On Wed, May 31, 2023 at 09:57:37AM +0000, Qi Zheng wrote: > From: Kirill Tkhai <tkhai@xxxxx> > > The patch makes s_dentry_lru and s_inode_lru be destroyed > later from the workqueue. This is preparation to split > unregister_shrinker(super_block::s_shrink) in two stages, > and to call finalize stage from destroy_super_work(). > > Note, that generic filesystem shrinker unregistration > is safe to be split in two stages right after this > patch, since super_cache_count() and super_cache_scan() > have a deal with s_dentry_lru and s_inode_lru only. > > But there are two exceptions: XFS and SHMEM, which > define .nr_cached_objects() and .free_cached_objects() > callbacks. These two do not allow us to do the splitting > right after this patch. They touch fs-specific data, > which is destroyed earlier, than destroy_super_work(). > So, we can't call unregister_shrinker_delayed_finalize() > from destroy_super_work() because of them, and next > patches make preparations to make this possible. > > Signed-off-by: Kirill Tkhai <tkhai@xxxxx> > Signed-off-by: Qi Zheng <zhengqi.arch@xxxxxxxxxxxxx> > --- > fs/super.c | 17 +++++------------ > 1 file changed, 5 insertions(+), 12 deletions(-) > > diff --git a/fs/super.c b/fs/super.c > index 8d8d68799b34..2ce4c72720f3 100644 > --- a/fs/super.c > +++ b/fs/super.c > @@ -159,6 +159,11 @@ static void destroy_super_work(struct work_struct *work) > destroy_work); > int i; > > + WARN_ON(list_lru_count(&s->s_dentry_lru)); > + WARN_ON(list_lru_count(&s->s_inode_lru)); > + list_lru_destroy(&s->s_dentry_lru); > + list_lru_destroy(&s->s_inode_lru); > + > for (i = 0; i < SB_FREEZE_LEVELS; i++) > percpu_free_rwsem(&s->s_writers.rw_sem[i]); > kfree(s); > @@ -177,8 +182,6 @@ static void destroy_unused_super(struct super_block *s) > if (!s) > return; > up_write(&s->s_umount); > - list_lru_destroy(&s->s_dentry_lru); > - list_lru_destroy(&s->s_inode_lru); > security_sb_free(s); > put_user_ns(s->s_user_ns); > kfree(s->s_subtype); > @@ -287,8 +290,6 @@ static void __put_super(struct super_block *s) > { > if (!--s->s_count) { > list_del_init(&s->s_list); > - WARN_ON(s->s_dentry_lru.node); > - WARN_ON(s->s_inode_lru.node); Why are you removing the wanrings from here? Regardless of where we tear down the lru lists, they *must* be empty here otherwise we have a memory leak. Hence I don't think these warnings should be moved at all. Cheers, Dave. -- Dave Chinner david@xxxxxxxxxxxxx