Commit 23f2ac44 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] (3/14) resync

sget()/generic_shutdown_super() cleaned up; fixed error handling
in sget()
parent 9279e3b6
...@@ -151,47 +151,17 @@ static int grab_super(struct super_block *s) ...@@ -151,47 +151,17 @@ static int grab_super(struct super_block *s)
yield(); yield();
return 0; return 0;
} }
/**
* insert_super - put superblock on the lists
* @s: superblock in question
* @type: filesystem type it will belong to
*
* Associates superblock with fs type and puts it on per-type and global
* superblocks' lists. Should be called with sb_lock held; drops it.
*
* NOTE: the super_blocks ordering here is important: writeback wants
* the blockdev superblock to be at super_blocks.next.
*/
static void insert_super(struct super_block *s, struct file_system_type *type)
{
s->s_type = type;
list_add(&s->s_list, super_blocks.prev);
list_add(&s->s_instances, &type->fs_supers);
spin_unlock(&sb_lock);
get_filesystem(type);
}
/** /**
* remove_super - makes superblock unreachable * generic_shutdown_super - common helper for ->kill_sb()
* @s: superblock in question * @sb: superblock to kill
* *
* Removes superblock from the lists, and unlocks it. @s should have * generic_shutdown_super() does all fs-independent work on superblock
* no active references by that time and after remove_super() it's * shutdown. Typical ->kill_sb() should pick all fs-specific objects
* essentially in rundown mode - all remaining references are temporary, * that need destruction out of superblock, call generic_shutdown_super()
* no new references of any sort are going to appear and all holders * and release aforementioned objects. Note: dentries and inodes _are_
* of temporary ones will eventually drop them. At that point superblock * taken care of and do not need specific handling.
* itself will be destroyed; all its contents is already gone.
*/ */
static void remove_super(struct super_block *s)
{
spin_lock(&sb_lock);
list_del(&s->s_list);
list_del(&s->s_instances);
spin_unlock(&sb_lock);
up_write(&s->s_umount);
}
void generic_shutdown_super(struct super_block *sb) void generic_shutdown_super(struct super_block *sb)
{ {
struct dentry *root = sb->s_root; struct dentry *root = sb->s_root;
...@@ -224,9 +194,20 @@ void generic_shutdown_super(struct super_block *sb) ...@@ -224,9 +194,20 @@ void generic_shutdown_super(struct super_block *sb)
unlock_kernel(); unlock_kernel();
unlock_super(sb); unlock_super(sb);
} }
remove_super(sb); spin_lock(&sb_lock);
list_del(&sb->s_list);
list_del(&sb->s_instances);
spin_unlock(&sb_lock);
up_write(&sb->s_umount);
} }
/**
* sget - find or create a superblock
* @type: filesystem type superblock should belong to
* @test: comparison callback
* @set: setup callback
* @data: argument to each of them
*/
struct super_block *sget(struct file_system_type *type, struct super_block *sget(struct file_system_type *type,
int (*test)(struct super_block *,void *), int (*test)(struct super_block *,void *),
int (*set)(struct super_block *,void *), int (*set)(struct super_block *,void *),
...@@ -253,10 +234,15 @@ struct super_block *sget(struct file_system_type *type, ...@@ -253,10 +234,15 @@ struct super_block *sget(struct file_system_type *type,
} }
err = set(s, data); err = set(s, data);
if (err) { if (err) {
spin_unlock(&sb_lock);
destroy_super(s); destroy_super(s);
return ERR_PTR(err); return ERR_PTR(err);
} }
insert_super(s, type); s->s_type = type;
list_add(&s->s_list, super_blocks.prev);
list_add(&s->s_instances, &type->fs_supers);
spin_unlock(&sb_lock);
get_filesystem(type);
return s; return s;
} }
...@@ -427,12 +413,6 @@ int set_anon_super(struct super_block *s, void *data) ...@@ -427,12 +413,6 @@ int set_anon_super(struct super_block *s, void *data)
return 0; return 0;
} }
struct super_block *get_anon_super(struct file_system_type *type,
int (*compare)(struct super_block *,void *), void *data)
{
return sget(type, compare, set_anon_super, data);
}
void kill_anon_super(struct super_block *sb) void kill_anon_super(struct super_block *sb)
{ {
int slot = minor(sb->s_dev); int slot = minor(sb->s_dev);
...@@ -512,7 +492,10 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, ...@@ -512,7 +492,10 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
goto out1; goto out1;
s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); s = sget(fs_type, test_bdev_super, set_bdev_super, bdev);
if (s->s_root) { if (IS_ERR(s)) {
bd_release(bdev);
blkdev_put(bdev, BDEV_FS);
} else if (s->s_root) {
if ((flags ^ s->s_flags) & MS_RDONLY) { if ((flags ^ s->s_flags) & MS_RDONLY) {
up_write(&s->s_umount); up_write(&s->s_umount);
deactivate_super(s); deactivate_super(s);
...@@ -557,7 +540,7 @@ struct super_block *get_sb_nodev(struct file_system_type *fs_type, ...@@ -557,7 +540,7 @@ struct super_block *get_sb_nodev(struct file_system_type *fs_type,
int (*fill_super)(struct super_block *, void *, int)) int (*fill_super)(struct super_block *, void *, int))
{ {
int error; int error;
struct super_block *s = get_anon_super(fs_type, NULL, NULL); struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL);
if (IS_ERR(s)) if (IS_ERR(s))
return s; return s;
...@@ -583,9 +566,10 @@ struct super_block *get_sb_single(struct file_system_type *fs_type, ...@@ -583,9 +566,10 @@ struct super_block *get_sb_single(struct file_system_type *fs_type,
int flags, void *data, int flags, void *data,
int (*fill_super)(struct super_block *, void *, int)) int (*fill_super)(struct super_block *, void *, int))
{ {
struct super_block *s;
int error; int error;
struct super_block *s = get_anon_super(fs_type, compare_single, NULL);
s = sget(fs_type, compare_single, set_anon_super, NULL);
if (IS_ERR(s)) if (IS_ERR(s))
return s; return s;
if (!s->s_root) { if (!s->s_root) {
......
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