On Tue, 26 Sep 2023 03:37:22 +0300 Dmitry Osipenko <dmitry.osipenko@xxxxxxxxxxxxx> wrote: > On 9/15/23 11:46, Boris Brezillon wrote: > >> -static int drm_gem_shmem_get_pages_locked(struct drm_gem_shmem_object *shmem) > >> +static int > >> +drm_gem_shmem_acquire_pages(struct drm_gem_shmem_object *shmem, bool init) > >> { > >> struct drm_gem_object *obj = &shmem->base; > >> struct page **pages; > >> > >> dma_resv_assert_held(shmem->base.resv); > >> > >> - if (refcount_inc_not_zero(&shmem->pages_use_count)) > >> + if (shmem->madv < 0) { > >> + drm_WARN_ON(obj->dev, shmem->pages); > >> + return -ENOMEM; > >> + } > >> + > >> + if (shmem->pages) { > >> + drm_WARN_ON(obj->dev, !shmem->evicted); > >> return 0; > >> + } > >> + > >> + if (drm_WARN_ON(obj->dev, !(init ^ refcount_read(&shmem->pages_use_count)))) > >> + return -EINVAL; > > OOC, why do we care? Is there any difference between initial and re-pin > > that make the page allocation impossible? Feels like, if there's a > > check to do, it should be done in the caller instead, and you can drop > > the init param here. > > This is a sanity check that addresses additional refcnt tracking > complexity imposed by shrinker. > > This function is used by both init and re-pin that is invoked from > several places in the code. It's not trivial to move that check to the > callers. drm_gem_shmem_acquire_pages() is called twice, once with init=false, once with init=true. If you really care about this check, it can be moved to the callers so 1/ it's clearer (the XOR operation between init and refcount to check if refcount is zero on init and non-zero otherwise is convoluted) 2/ it doesn't leak to the function whose purpose it to [re-]acquire pages