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)
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 @@ struct super_block *sget_userns(struct file_system_type *type,
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 @@ struct super_block *sget_userns(struct file_system_type *type,
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;
......
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