summaryrefslogtreecommitdiffstats
path: root/fs/super.c
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2010-03-23 00:36:35 +0100
committerAl Viro <viro@zeniv.linux.org.uk>2010-05-22 00:31:14 +0200
commit551de6f34dfeefbeeadb32909c387d393114ecc8 (patch)
tree822af803e7e75ed476b0a176639c162e0395910d /fs/super.c
parentSaner locking around deactivate_super() (diff)
downloadlinux-551de6f34dfeefbeeadb32909c387d393114ecc8.tar.xz
linux-551de6f34dfeefbeeadb32909c387d393114ecc8.zip
Leave superblocks on s_list until the end
We used to remove from s_list and s_instances at the same time. So let's *not* do the former and skip superblocks that have empty s_instances in the loops over s_list. The next step, of course, will be to get rid of rescan logics in those loops. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/fs/super.c b/fs/super.c
index 157657b32798..0390461dfca0 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -135,6 +135,7 @@ static int __put_super(struct super_block *sb)
int ret = 0;
if (!--sb->s_count) {
+ list_del_init(&sb->s_list);
destroy_super(sb);
ret = 1;
}
@@ -151,7 +152,7 @@ static int __put_super(struct super_block *sb)
int __put_super_and_need_restart(struct super_block *sb)
{
/* check for race with generic_shutdown_super() */
- if (list_empty(&sb->s_list)) {
+ if (list_empty(&sb->s_instances)) {
/* super block is removed, need to restart... */
__put_super(sb);
return 1;
@@ -308,8 +309,7 @@ void generic_shutdown_super(struct super_block *sb)
}
spin_lock(&sb_lock);
/* should be initialized for __put_super_and_need_restart() */
- list_del_init(&sb->s_list);
- list_del(&sb->s_instances);
+ list_del_init(&sb->s_instances);
spin_unlock(&sb_lock);
up_write(&sb->s_umount);
}
@@ -400,6 +400,8 @@ void sync_supers(void)
spin_lock(&sb_lock);
restart:
list_for_each_entry(sb, &super_blocks, s_list) {
+ if (list_empty(&sb->s_instances))
+ continue;
if (sb->s_op->write_super && sb->s_dirt) {
sb->s_count++;
spin_unlock(&sb_lock);
@@ -435,6 +437,8 @@ struct super_block * get_super(struct block_device *bdev)
spin_lock(&sb_lock);
rescan:
list_for_each_entry(sb, &super_blocks, s_list) {
+ if (list_empty(&sb->s_instances))
+ continue;
if (sb->s_bdev == bdev) {
sb->s_count++;
spin_unlock(&sb_lock);
@@ -471,6 +475,8 @@ struct super_block *get_active_super(struct block_device *bdev)
spin_lock(&sb_lock);
list_for_each_entry(sb, &super_blocks, s_list) {
+ if (list_empty(&sb->s_instances))
+ continue;
if (sb->s_bdev != bdev)
continue;
@@ -490,6 +496,8 @@ struct super_block * user_get_super(dev_t dev)
spin_lock(&sb_lock);
rescan:
list_for_each_entry(sb, &super_blocks, s_list) {
+ if (list_empty(&sb->s_instances))
+ continue;
if (sb->s_dev == dev) {
sb->s_count++;
spin_unlock(&sb_lock);
@@ -600,6 +608,8 @@ static void do_emergency_remount(struct work_struct *work)
spin_lock(&sb_lock);
list_for_each_entry(sb, &super_blocks, s_list) {
+ if (list_empty(&sb->s_instances))
+ continue;
sb->s_count++;
spin_unlock(&sb_lock);
down_write(&sb->s_umount);