Commit 0200894d authored by Al Viro's avatar Al Viro

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: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 6aa211e8
...@@ -171,6 +171,21 @@ static void destroy_super(struct super_block *s) ...@@ -171,6 +171,21 @@ static void destroy_super(struct super_block *s)
call_rcu(&s->rcu, destroy_super_rcu); 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 * alloc_super - create new superblock
* @type: filesystem type superblock should belong to * @type: filesystem type superblock should belong to
...@@ -256,7 +271,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags, ...@@ -256,7 +271,7 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags,
return s; return s;
fail: fail:
destroy_super(s); destroy_unused_super(s);
return NULL; return NULL;
} }
...@@ -484,19 +499,12 @@ struct super_block *sget_userns(struct file_system_type *type, ...@@ -484,19 +499,12 @@ struct super_block *sget_userns(struct file_system_type *type,
continue; continue;
if (user_ns != old->s_user_ns) { if (user_ns != old->s_user_ns) {
spin_unlock(&sb_lock); spin_unlock(&sb_lock);
if (s) { destroy_unused_super(s);
up_write(&s->s_umount);
destroy_super(s);
}
return ERR_PTR(-EBUSY); return ERR_PTR(-EBUSY);
} }
if (!grab_super(old)) if (!grab_super(old))
goto retry; goto retry;
if (s) { destroy_unused_super(s);
up_write(&s->s_umount);
destroy_super(s);
s = NULL;
}
return old; return old;
} }
} }
...@@ -511,8 +519,7 @@ struct super_block *sget_userns(struct file_system_type *type, ...@@ -511,8 +519,7 @@ struct super_block *sget_userns(struct file_system_type *type,
err = set(s, data); err = set(s, data);
if (err) { if (err) {
spin_unlock(&sb_lock); spin_unlock(&sb_lock);
up_write(&s->s_umount); destroy_unused_super(s);
destroy_super(s);
return ERR_PTR(err); return ERR_PTR(err);
} }
s->s_type = type; s->s_type = type;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment