Leave superblocks on s_list until the end
Al Viro [Mon, 22 Mar 2010 23:36:35 +0000 (19:36 -0400)]
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>

fs/buffer.c
fs/dcache.c
fs/drop_caches.c
fs/quota/quota.c
fs/super.c
fs/sync.c

index c9c266d..021ec4d 100644 (file)
@@ -568,6 +568,8 @@ static void do_thaw_all(struct work_struct *work)
        spin_lock(&sb_lock);
 restart:
        list_for_each_entry(sb, &super_blocks, s_list) {
+               if (list_empty(&sb->s_instances))
+                       continue;
                sb->s_count++;
                spin_unlock(&sb_lock);
                down_read(&sb->s_umount);
index 2b6f09a..5afc499 100644 (file)
@@ -552,6 +552,8 @@ restart:
                prune_ratio = unused / count;
        spin_lock(&sb_lock);
        list_for_each_entry(sb, &super_blocks, s_list) {
+               if (list_empty(&sb->s_instances))
+                       continue;
                if (sb->s_nr_dentry_unused == 0)
                        continue;
                sb->s_count++;
index 31f4b0e..9cd4e4a 100644 (file)
@@ -40,6 +40,8 @@ static void drop_pagecache(void)
        spin_lock(&sb_lock);
 restart:
        list_for_each_entry(sb, &super_blocks, s_list) {
+               if (list_empty(&sb->s_instances))
+                       continue;
                sb->s_count++;
                spin_unlock(&sb_lock);
                down_read(&sb->s_umount);
index cfc7882..4669e7e 100644 (file)
@@ -59,6 +59,8 @@ static int quota_sync_all(int type)
        spin_lock(&sb_lock);
 restart:
        list_for_each_entry(sb, &super_blocks, s_list) {
+               if (list_empty(&sb->s_instances))
+                       continue;
                if (!sb->s_qcop || !sb->s_qcop->quota_sync)
                        continue;
 
index 157657b..0390461 100644 (file)
@@ -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);
index 92b2281..ad6691b 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -99,10 +99,13 @@ static void sync_filesystems(int wait)
        mutex_lock(&mutex);             /* Could be down_interruptible */
        spin_lock(&sb_lock);
        list_for_each_entry(sb, &super_blocks, s_list)
-               sb->s_need_sync = 1;
+               if (!list_empty(&sb->s_instances))
+                       sb->s_need_sync = 1;
 
 restart:
        list_for_each_entry(sb, &super_blocks, s_list) {
+               if (list_empty(&sb->s_instances))
+                       continue;
                if (!sb->s_need_sync)
                        continue;
                sb->s_need_sync = 0;