shmem: don't call put_super() when fill_super() failed.
diff mbox

Message ID 201805150027.w4F0RZ27055056@www262.sakura.ne.jp
State New
Headers show

Commit Message

Tetsuo Handa May 15, 2018, 12:27 a.m. UTC
Eric Biggers wrote:
> > I'm not following, since generic_shutdown_super() only calls ->put_super() if
> > ->s_root is set, which only happens at the end of shmem_fill_super().  Isn't the
> > real problem that s_shrink is registered too early, causing super_cache_count()
> > and shmem_unused_huge_count() to potentially run before shmem_fill_super() has
> > completed?  Or alternatively, the problem is that super_cache_count() doesn't
> > check for SB_ACTIVE.
> > 
> 
> Coincidentally, this is already going to be fixed by commit 79f546a696bff259
> ("fs: don't scan the inode cache before SB_BORN is set") in vfs/for-linus.
> 

Just an idea, but if shrinker registration is too early, can't we postpone it
like below?

Comments

Al Viro May 15, 2018, 12:39 a.m. UTC | #1
On Tue, May 15, 2018 at 09:27:35AM +0900, Tetsuo Handa wrote:
> Eric Biggers wrote:
> > > I'm not following, since generic_shutdown_super() only calls ->put_super() if
> > > ->s_root is set, which only happens at the end of shmem_fill_super().  Isn't the
> > > real problem that s_shrink is registered too early, causing super_cache_count()
> > > and shmem_unused_huge_count() to potentially run before shmem_fill_super() has
> > > completed?  Or alternatively, the problem is that super_cache_count() doesn't
> > > check for SB_ACTIVE.
> > > 
> > 
> > Coincidentally, this is already going to be fixed by commit 79f546a696bff259
> > ("fs: don't scan the inode cache before SB_BORN is set") in vfs/for-linus.
> > 
> 
> Just an idea, but if shrinker registration is too early, can't we postpone it
> like below?

Wonderful.  And when ->mount() returns you a subtree of the same filesystem again,
that will do what, exactly?
Tetsuo Handa May 15, 2018, 12:52 a.m. UTC | #2
> On Tue, May 15, 2018 at 09:27:35AM +0900, Tetsuo Handa wrote:
> > Eric Biggers wrote:
> > > > I'm not following, since generic_shutdown_super() only calls ->put_super() if
> > > > ->s_root is set, which only happens at the end of shmem_fill_super().  Isn't the
> > > > real problem that s_shrink is registered too early, causing super_cache_count()
> > > > and shmem_unused_huge_count() to potentially run before shmem_fill_super() has
> > > > completed?  Or alternatively, the problem is that super_cache_count() doesn't
> > > > check for SB_ACTIVE.
> > > > 
> > > 
> > > Coincidentally, this is already going to be fixed by commit 79f546a696bff259
> > > ("fs: don't scan the inode cache before SB_BORN is set") in vfs/for-linus.
> > > 
> > 
> > Just an idea, but if shrinker registration is too early, can't we postpone it
> > like below?
> 
> Wonderful.  And when ->mount() returns you a subtree of the same filesystem again,
> that will do what, exactly?
> 
Can't we detect it via list_empty(&sb->s_shrink.list) test
before calling register_shrinker_prepared(&sb->s_shrink) ?
Al Viro May 15, 2018, 1:13 a.m. UTC | #3
On Tue, May 15, 2018 at 09:52:37AM +0900, Tetsuo Handa wrote:
> > On Tue, May 15, 2018 at 09:27:35AM +0900, Tetsuo Handa wrote:
> > > Eric Biggers wrote:
> > > > > I'm not following, since generic_shutdown_super() only calls ->put_super() if
> > > > > ->s_root is set, which only happens at the end of shmem_fill_super().  Isn't the
> > > > > real problem that s_shrink is registered too early, causing super_cache_count()
> > > > > and shmem_unused_huge_count() to potentially run before shmem_fill_super() has
> > > > > completed?  Or alternatively, the problem is that super_cache_count() doesn't
> > > > > check for SB_ACTIVE.
> > > > > 
> > > > 
> > > > Coincidentally, this is already going to be fixed by commit 79f546a696bff259
> > > > ("fs: don't scan the inode cache before SB_BORN is set") in vfs/for-linus.
> > > > 
> > > 
> > > Just an idea, but if shrinker registration is too early, can't we postpone it
> > > like below?
> > 
> > Wonderful.  And when ->mount() returns you a subtree of the same filesystem again,
> > that will do what, exactly?
> > 
> Can't we detect it via list_empty(&sb->s_shrink.list) test
> before calling register_shrinker_prepared(&sb->s_shrink) ?

What for?  Seriously, what's the benefit of doing that in such a convoluted way?
Avoiding a trivial check in super_cache_count()?  The same check we normally
do in places where we are not holding an active reference to superblock and
want to make sure it's alive, at that...

Patch
diff mbox

--- a/fs/super.c
+++ b/fs/super.c
@@ -521,7 +521,6 @@  struct super_block *sget_userns(struct file_system_type *type,
 	hlist_add_head(&s->s_instances, &type->fs_supers);
 	spin_unlock(&sb_lock);
 	get_filesystem(type);
-	register_shrinker_prepared(&s->s_shrink);
 	return s;
 }
 
@@ -1287,6 +1286,7 @@  struct dentry *
 	WARN((sb->s_maxbytes < 0), "%s set sb->s_maxbytes to "
 		"negative value (%lld)\n", type->name, sb->s_maxbytes);
 
+	register_shrinker_prepared(&sb->s_shrink);
 	up_write(&sb->s_umount);
 	free_secdata(secdata);
 	return root;
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -313,6 +313,7 @@  int prealloc_shrinker(struct shrinker *shrinker)
 	shrinker->nr_deferred = kzalloc(size, GFP_KERNEL);
 	if (!shrinker->nr_deferred)
 		return -ENOMEM;
+	INIT_LIST_HEAD(&shrinker->list);
 	return 0;
 }