new helper: iterate_supers()
authorAl Viro <viro@zeniv.linux.org.uk>
Tue, 23 Mar 2010 10:06:58 +0000 (06:06 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 21 May 2010 22:31:16 +0000 (18:31 -0400)
... and switch the simple "loop over superblocks and do something"
loops to it.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/buffer.c
fs/drop_caches.c
fs/quota/quota.c
fs/super.c
fs/sync.c
include/linux/fs.h

index ded29b0fdac3a0db8ee6be49f7a970e3a42dce6b..2914d9adfb5031416e5127c022762815c88f4ade 100644 (file)
@@ -560,25 +560,17 @@ repeat:
        return err;
 }
 
-static void do_thaw_all(struct work_struct *work)
+static void do_thaw_one(struct super_block *sb, void *unused)
 {
-       struct super_block *sb, *n;
        char b[BDEVNAME_SIZE];
+       while (sb->s_bdev && !thaw_bdev(sb->s_bdev, sb))
+               printk(KERN_WARNING "Emergency Thaw on %s\n",
+                      bdevname(sb->s_bdev, b));
+}
 
-       spin_lock(&sb_lock);
-       list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
-               if (list_empty(&sb->s_instances))
-                       continue;
-               sb->s_count++;
-               spin_unlock(&sb_lock);
-               down_read(&sb->s_umount);
-               while (sb->s_bdev && !thaw_bdev(sb->s_bdev, sb))
-                       printk(KERN_WARNING "Emergency Thaw on %s\n",
-                              bdevname(sb->s_bdev, b));
-               up_read(&sb->s_umount);
-               spin_lock(&sb_lock);
-       }
-       spin_unlock(&sb_lock);
+static void do_thaw_all(struct work_struct *work)
+{
+       iterate_supers(do_thaw_one, NULL);
        kfree(work);
        printk(KERN_WARNING "Emergency Thaw complete\n");
 }
index 52047cf4177f46033b906a59eeca90aa9f8390db..83c4f600786a84cde81efde7fe6163ea66df9d04 100644 (file)
@@ -8,12 +8,11 @@
 #include <linux/writeback.h>
 #include <linux/sysctl.h>
 #include <linux/gfp.h>
-#include "internal.h"
 
 /* A global variable is a bit ugly, but it keeps the code simple */
 int sysctl_drop_caches;
 
-static void drop_pagecache_sb(struct super_block *sb)
+static void drop_pagecache_sb(struct super_block *sb, void *unused)
 {
        struct inode *inode, *toput_inode = NULL;
 
@@ -34,26 +33,6 @@ static void drop_pagecache_sb(struct super_block *sb)
        iput(toput_inode);
 }
 
-static void drop_pagecache(void)
-{
-       struct super_block *sb, *n;
-
-       spin_lock(&sb_lock);
-       list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
-               if (list_empty(&sb->s_instances))
-                       continue;
-               sb->s_count++;
-               spin_unlock(&sb_lock);
-               down_read(&sb->s_umount);
-               if (sb->s_root)
-                       drop_pagecache_sb(sb);
-               up_read(&sb->s_umount);
-               spin_lock(&sb_lock);
-               __put_super(sb);
-       }
-       spin_unlock(&sb_lock);
-}
-
 static void drop_slab(void)
 {
        int nr_objects;
@@ -69,7 +48,7 @@ int drop_caches_sysctl_handler(ctl_table *table, int write,
        proc_dointvec_minmax(table, write, buffer, length, ppos);
        if (write) {
                if (sysctl_drop_caches & 1)
-                       drop_pagecache();
+                       iterate_supers(drop_pagecache_sb, NULL);
                if (sysctl_drop_caches & 2)
                        drop_slab();
        }
index 3ce1553ea7ebc557b265b70a5a4efeab07e567b3..ce3dfd066f590a2b35a22fa14f01a60b2bc1d650 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/quotaops.h>
 #include <linux/types.h>
 #include <linux/writeback.h>
-#include "../internal.h"
 
 static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
                                     qid_t id)
@@ -46,36 +45,22 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
        return security_quotactl(cmd, type, id, sb);
 }
 
+static void quota_sync_one(struct super_block *sb, void *arg)
+{
+       if (sb->s_qcop && sb->s_qcop->quota_sync)
+               sb->s_qcop->quota_sync(sb, *(int *)arg, 1);
+}
+
 static int quota_sync_all(int type)
 {
-       struct super_block *sb, *n;
        int ret;
 
        if (type >= MAXQUOTAS)
                return -EINVAL;
        ret = security_quotactl(Q_SYNC, type, 0, NULL);
-       if (ret)
-               return ret;
-
-       spin_lock(&sb_lock);
-       list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
-               if (list_empty(&sb->s_instances))
-                       continue;
-               if (!sb->s_qcop || !sb->s_qcop->quota_sync)
-                       continue;
-
-               sb->s_count++;
-               spin_unlock(&sb_lock);
-               down_read(&sb->s_umount);
-               if (sb->s_root)
-                       sb->s_qcop->quota_sync(sb, type, 1);
-               up_read(&sb->s_umount);
-               spin_lock(&sb_lock);
-               __put_super(sb);
-       }
-       spin_unlock(&sb_lock);
-
-       return 0;
+       if (!ret)
+               iterate_supers(quota_sync_one, &type);
+       return ret;
 }
 
 static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id,
index 95adbb3d8e581e2e8755e4601554a3dfe8ce10ef..2c3e370c60d9ca83f1a8619586b65d833e8e0e61 100644 (file)
@@ -391,6 +391,36 @@ void sync_supers(void)
        spin_unlock(&sb_lock);
 }
 
+/**
+ *     iterate_supers - call function for all active superblocks
+ *     @f: function to call
+ *     @arg: argument to pass to it
+ *
+ *     Scans the superblock list and calls given function, passing it
+ *     locked superblock and given argument.
+ */
+void iterate_supers(void (*f)(struct super_block *, void *), void *arg)
+{
+       struct super_block *sb, *n;
+
+       spin_lock(&sb_lock);
+       list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
+               if (list_empty(&sb->s_instances))
+                       continue;
+               sb->s_count++;
+               spin_unlock(&sb_lock);
+
+               down_read(&sb->s_umount);
+               if (sb->s_root)
+                       f(sb, arg);
+               up_read(&sb->s_umount);
+
+               spin_lock(&sb_lock);
+               __put_super(sb);
+       }
+       spin_unlock(&sb_lock);
+}
+
 /**
  *     get_super - get the superblock of a device
  *     @bdev: device to get the superblock for
index f3f0a0e1948f0eb87389af19376dddf19c9c17b3..d5369203f8e46bda1cb18336517091862eb98bce 100644 (file)
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -77,31 +77,18 @@ int sync_filesystem(struct super_block *sb)
 }
 EXPORT_SYMBOL_GPL(sync_filesystem);
 
+static void sync_one_sb(struct super_block *sb, void *arg)
+{
+       if (!(sb->s_flags & MS_RDONLY) && sb->s_bdi)
+               __sync_filesystem(sb, *(int *)arg);
+}
 /*
  * Sync all the data for all the filesystems (called by sys_sync() and
  * emergency sync)
  */
 static void sync_filesystems(int wait)
 {
-       struct super_block *sb, *n;
-
-       spin_lock(&sb_lock);
-       list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
-               if (list_empty(&sb->s_instances))
-                       continue;
-               sb->s_count++;
-               spin_unlock(&sb_lock);
-
-               down_read(&sb->s_umount);
-               if (!(sb->s_flags & MS_RDONLY) && sb->s_root && sb->s_bdi)
-                       __sync_filesystem(sb, wait);
-               up_read(&sb->s_umount);
-
-               /* restart only when sb is no longer on the list */
-               spin_lock(&sb_lock);
-               __put_super(sb);
-       }
-       spin_unlock(&sb_lock);
+       iterate_supers(sync_one_sb, &wait);
 }
 
 /*
index 523086714c7483766e5a9a4fac9ea41f8b708919..eeb04ba17b63e3e5340697a3d7d68afe2ba347fa 100644 (file)
@@ -2324,6 +2324,7 @@ extern struct super_block *get_super(struct block_device *);
 extern struct super_block *get_active_super(struct block_device *bdev);
 extern struct super_block *user_get_super(dev_t);
 extern void drop_super(struct super_block *sb);
+extern void iterate_supers(void (*)(struct super_block *, void *), void *);
 
 extern int dcache_dir_open(struct inode *, struct file *);
 extern int dcache_dir_close(struct inode *, struct file *);