On (23/06/22 16:53), Qi Zheng wrote: > +/* > + * Remove one > + */ > +void unregister_shrinker(struct shrinker *shrinker) > +{ > + struct dentry *debugfs_entry; > + int debugfs_id; > + > + if (!(shrinker->flags & SHRINKER_REGISTERED)) > + return; > + > + shrinker_put(shrinker); > + wait_for_completion(&shrinker->completion_wait); > + > + mutex_lock(&shrinker_mutex); > + list_del_rcu(&shrinker->list); Should this function wait for RCU grace period(s) before it goes touching shrinker fields? > + shrinker->flags &= ~SHRINKER_REGISTERED; > + if (shrinker->flags & SHRINKER_MEMCG_AWARE) > + unregister_memcg_shrinker(shrinker); > + debugfs_entry = shrinker_debugfs_detach(shrinker, &debugfs_id); > + mutex_unlock(&shrinker_mutex); > + > + shrinker_debugfs_remove(debugfs_entry, debugfs_id); > + > + kfree(shrinker->nr_deferred); > + shrinker->nr_deferred = NULL; > +} > +EXPORT_SYMBOL(unregister_shrinker); [..] > +void shrinker_free(struct shrinker *shrinker) > +{ > + kfree(shrinker); > +} > +EXPORT_SYMBOL(shrinker_free); > + > +void unregister_and_free_shrinker(struct shrinker *shrinker) > +{ > + unregister_shrinker(shrinker); > + kfree_rcu(shrinker, rcu); > +} Seems like this unregister_shrinker(); shrinker_free(); is not exact equivalent of this unregister_and_free_shrinker();