On Thu, Apr 11, 2019 at 11:34:40AM +1000, Tobin C. Harding wrote: > +/* > + * d_isolate() - Dentry isolation callback function. > + * @s: The dentry cache. > + * @v: Vector of pointers to the objects to isolate. > + * @nr: Number of objects in @v. > + * > + * The slab allocator is holding off frees. We can safely examine > + * the object without the danger of it vanishing from under us. > + */ > +static void *d_isolate(struct kmem_cache *s, void **v, int nr) > +{ > + struct dentry *dentry; > + int i; > + > + for (i = 0; i < nr; i++) { > + dentry = v[i]; > + __dget(dentry); > + } > + > + return NULL; /* No need for private data */ > +} Huh? This is compeletely wrong; what you need is collecting the ones with zero refcount (and not on shrink lists) into a private list. *NOT* bumping the refcounts at all. And do it in your isolate thing. > +static void d_partial_shrink(struct kmem_cache *s, void **v, int nr, > + int node, void *_unused) > +{ > + struct dentry *dentry; > + LIST_HEAD(dispose); > + int i; > + > + for (i = 0; i < nr; i++) { > + dentry = v[i]; > + spin_lock(&dentry->d_lock); > + dentry->d_lockref.count--; > + > + if (dentry->d_lockref.count > 0 || > + dentry->d_flags & DCACHE_SHRINK_LIST) { > + spin_unlock(&dentry->d_lock); > + continue; > + } > + > + if (dentry->d_flags & DCACHE_LRU_LIST) > + d_lru_del(dentry); > + > + d_shrink_add(dentry, &dispose); > + > + spin_unlock(&dentry->d_lock); > + } Basically, that loop (sans jerking the refcount up and down) should get moved into d_isolate(). > + > + if (!list_empty(&dispose)) > + shrink_dentry_list(&dispose); > +} ... with this left in d_partial_shrink(). And you obviously need some way to pass the list from the former to the latter...