summaryrefslogtreecommitdiffstats
path: root/fs/super.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2017-10-11 19:48:55 +0200
committerAl Viro <viro@zeniv.linux.org.uk>2017-10-11 19:55:42 +0200
commit0200894d11551a8abcff7872c2260d0801951f67 (patch)
treee9cbded380927b342f1fe282a31db62311753c6f /fs/super.c
parentfix address space warnings in ipc/ (diff)
downloadlinux-0200894d11551a8abcff7872c2260d0801951f67.tar.xz
linux-0200894d11551a8abcff7872c2260d0801951f67.zip
new helper: destroy_unused_super()
Used for disposal of super_block instances that had never been reachable via any shared data structures. No need for RCU delay in there, everything can be called directly. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c31
1 files changed, 19 insertions, 12 deletions
diff --git a/fs/super.c b/fs/super.c
index 166c4ee0d0ed..01b7e3fd09e8 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -171,6 +171,21 @@ static void destroy_super(struct super_block *s)
call_rcu(&s->rcu, destroy_super_rcu);
}
+/* Free a superblock that has never been seen by anyone */
+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);
+ /* no delays needed */
+ destroy_super_work(&s->destroy_work);
+}
+
/**
* alloc_super - create new superblock
* @type: filesystem type superblock should belong to
@@ -256,7 +271,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
return s;
fail:
- destroy_super(s);
+ destroy_unused_super(s);
return NULL;
}
@@ -484,19 +499,12 @@ retry:
continue;
if (user_ns != old->s_user_ns) {
spin_unlock(&sb_lock);
- if (s) {
- up_write(&s->s_umount);
- destroy_super(s);
- }
+ destroy_unused_super(s);
return ERR_PTR(-EBUSY);
}
if (!grab_super(old))
goto retry;
- if (s) {
- up_write(&s->s_umount);
- destroy_super(s);
- s = NULL;
- }
+ destroy_unused_super(s);
return old;
}
}
@@ -511,8 +519,7 @@ retry:
err = set(s, data);
if (err) {
spin_unlock(&sb_lock);
- up_write(&s->s_umount);
- destroy_super(s);
+ destroy_unused_super(s);
return ERR_PTR(err);
}
s->s_type = type;