aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2010-03-23 06:06:58 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2010-05-21 18:31:16 -0400
commit01a05b337a5b647909e1d6670f57e7202318a5fb (patch)
tree7877f08db14877d06346c8e1ef52aa17f2483e93
parent35cf7ba0b46dc3582a01c3860b14bff122662aa3 (diff)
new helper: iterate_supers()
... and switch the simple "loop over superblocks and do something" loops to it. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/buffer.c24
-rw-r--r--fs/drop_caches.c25
-rw-r--r--fs/quota/quota.c33
-rw-r--r--fs/super.c30
-rw-r--r--fs/sync.c25
-rw-r--r--include/linux/fs.h1
6 files changed, 56 insertions, 82 deletions
diff --git a/fs/buffer.c b/fs/buffer.c
index ded29b0fdac3..2914d9adfb50 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -560,25 +560,17 @@ repeat:
560 return err; 560 return err;
561} 561}
562 562
563static void do_thaw_all(struct work_struct *work) 563static void do_thaw_one(struct super_block *sb, void *unused)
564{ 564{
565 struct super_block *sb, *n;
566 char b[BDEVNAME_SIZE]; 565 char b[BDEVNAME_SIZE];
566 while (sb->s_bdev && !thaw_bdev(sb->s_bdev, sb))
567 printk(KERN_WARNING "Emergency Thaw on %s\n",
568 bdevname(sb->s_bdev, b));
569}
567 570
568 spin_lock(&sb_lock); 571static void do_thaw_all(struct work_struct *work)
569 list_for_each_entry_safe(sb, n, &super_blocks, s_list) { 572{
570 if (list_empty(&sb->s_instances)) 573 iterate_supers(do_thaw_one, NULL);
571 continue;
572 sb->s_count++;
573 spin_unlock(&sb_lock);
574 down_read(&sb->s_umount);
575 while (sb->s_bdev && !thaw_bdev(sb->s_bdev, sb))
576 printk(KERN_WARNING "Emergency Thaw on %s\n",
577 bdevname(sb->s_bdev, b));
578 up_read(&sb->s_umount);
579 spin_lock(&sb_lock);
580 }
581 spin_unlock(&sb_lock);
582 kfree(work); 574 kfree(work);
583 printk(KERN_WARNING "Emergency Thaw complete\n"); 575 printk(KERN_WARNING "Emergency Thaw complete\n");
584} 576}
diff --git a/fs/drop_caches.c b/fs/drop_caches.c
index 52047cf4177f..83c4f600786a 100644
--- a/fs/drop_caches.c
+++ b/fs/drop_caches.c
@@ -8,12 +8,11 @@
8#include <linux/writeback.h> 8#include <linux/writeback.h>
9#include <linux/sysctl.h> 9#include <linux/sysctl.h>
10#include <linux/gfp.h> 10#include <linux/gfp.h>
11#include "internal.h"
12 11
13/* A global variable is a bit ugly, but it keeps the code simple */ 12/* A global variable is a bit ugly, but it keeps the code simple */
14int sysctl_drop_caches; 13int sysctl_drop_caches;
15 14
16static void drop_pagecache_sb(struct super_block *sb) 15static void drop_pagecache_sb(struct super_block *sb, void *unused)
17{ 16{
18 struct inode *inode, *toput_inode = NULL; 17 struct inode *inode, *toput_inode = NULL;
19 18
@@ -34,26 +33,6 @@ static void drop_pagecache_sb(struct super_block *sb)
34 iput(toput_inode); 33 iput(toput_inode);
35} 34}
36 35
37static void drop_pagecache(void)
38{
39 struct super_block *sb, *n;
40
41 spin_lock(&sb_lock);
42 list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
43 if (list_empty(&sb->s_instances))
44 continue;
45 sb->s_count++;
46 spin_unlock(&sb_lock);
47 down_read(&sb->s_umount);
48 if (sb->s_root)
49 drop_pagecache_sb(sb);
50 up_read(&sb->s_umount);
51 spin_lock(&sb_lock);
52 __put_super(sb);
53 }
54 spin_unlock(&sb_lock);
55}
56
57static void drop_slab(void) 36static void drop_slab(void)
58{ 37{
59 int nr_objects; 38 int nr_objects;
@@ -69,7 +48,7 @@ int drop_caches_sysctl_handler(ctl_table *table, int write,
69 proc_dointvec_minmax(table, write, buffer, length, ppos); 48 proc_dointvec_minmax(table, write, buffer, length, ppos);
70 if (write) { 49 if (write) {
71 if (sysctl_drop_caches & 1) 50 if (sysctl_drop_caches & 1)
72 drop_pagecache(); 51 iterate_supers(drop_pagecache_sb, NULL);
73 if (sysctl_drop_caches & 2) 52 if (sysctl_drop_caches & 2)
74 drop_slab(); 53 drop_slab();
75 } 54 }
diff --git a/fs/quota/quota.c b/fs/quota/quota.c
index 3ce1553ea7eb..ce3dfd066f59 100644
--- a/fs/quota/quota.c
+++ b/fs/quota/quota.c
@@ -18,7 +18,6 @@
18#include <linux/quotaops.h> 18#include <linux/quotaops.h>
19#include <linux/types.h> 19#include <linux/types.h>
20#include <linux/writeback.h> 20#include <linux/writeback.h>
21#include "../internal.h"
22 21
23static int check_quotactl_permission(struct super_block *sb, int type, int cmd, 22static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
24 qid_t id) 23 qid_t id)
@@ -46,36 +45,22 @@ static int check_quotactl_permission(struct super_block *sb, int type, int cmd,
46 return security_quotactl(cmd, type, id, sb); 45 return security_quotactl(cmd, type, id, sb);
47} 46}
48 47
48static void quota_sync_one(struct super_block *sb, void *arg)
49{
50 if (sb->s_qcop && sb->s_qcop->quota_sync)
51 sb->s_qcop->quota_sync(sb, *(int *)arg, 1);
52}
53
49static int quota_sync_all(int type) 54static int quota_sync_all(int type)
50{ 55{
51 struct super_block *sb, *n;
52 int ret; 56 int ret;
53 57
54 if (type >= MAXQUOTAS) 58 if (type >= MAXQUOTAS)
55 return -EINVAL; 59 return -EINVAL;
56 ret = security_quotactl(Q_SYNC, type, 0, NULL); 60 ret = security_quotactl(Q_SYNC, type, 0, NULL);
57 if (ret) 61 if (!ret)
58 return ret; 62 iterate_supers(quota_sync_one, &type);
59 63 return ret;
60 spin_lock(&sb_lock);
61 list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
62 if (list_empty(&sb->s_instances))
63 continue;
64 if (!sb->s_qcop || !sb->s_qcop->quota_sync)
65 continue;
66
67 sb->s_count++;
68 spin_unlock(&sb_lock);
69 down_read(&sb->s_umount);
70 if (sb->s_root)
71 sb->s_qcop->quota_sync(sb, type, 1);
72 up_read(&sb->s_umount);
73 spin_lock(&sb_lock);
74 __put_super(sb);
75 }
76 spin_unlock(&sb_lock);
77
78 return 0;
79} 64}
80 65
81static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id, 66static int quota_quotaon(struct super_block *sb, int type, int cmd, qid_t id,
diff --git a/fs/super.c b/fs/super.c
index 95adbb3d8e58..2c3e370c60d9 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -392,6 +392,36 @@ void sync_supers(void)
392} 392}
393 393
394/** 394/**
395 * iterate_supers - call function for all active superblocks
396 * @f: function to call
397 * @arg: argument to pass to it
398 *
399 * Scans the superblock list and calls given function, passing it
400 * locked superblock and given argument.
401 */
402void iterate_supers(void (*f)(struct super_block *, void *), void *arg)
403{
404 struct super_block *sb, *n;
405
406 spin_lock(&sb_lock);
407 list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
408 if (list_empty(&sb->s_instances))
409 continue;
410 sb->s_count++;
411 spin_unlock(&sb_lock);
412
413 down_read(&sb->s_umount);
414 if (sb->s_root)
415 f(sb, arg);
416 up_read(&sb->s_umount);
417
418 spin_lock(&sb_lock);
419 __put_super(sb);
420 }
421 spin_unlock(&sb_lock);
422}
423
424/**
395 * get_super - get the superblock of a device 425 * get_super - get the superblock of a device
396 * @bdev: device to get the superblock for 426 * @bdev: device to get the superblock for
397 * 427 *
diff --git a/fs/sync.c b/fs/sync.c
index f3f0a0e1948f..d5369203f8e4 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -77,31 +77,18 @@ int sync_filesystem(struct super_block *sb)
77} 77}
78EXPORT_SYMBOL_GPL(sync_filesystem); 78EXPORT_SYMBOL_GPL(sync_filesystem);
79 79
80static void sync_one_sb(struct super_block *sb, void *arg)
81{
82 if (!(sb->s_flags & MS_RDONLY) && sb->s_bdi)
83 __sync_filesystem(sb, *(int *)arg);
84}
80/* 85/*
81 * Sync all the data for all the filesystems (called by sys_sync() and 86 * Sync all the data for all the filesystems (called by sys_sync() and
82 * emergency sync) 87 * emergency sync)
83 */ 88 */
84static void sync_filesystems(int wait) 89static void sync_filesystems(int wait)
85{ 90{
86 struct super_block *sb, *n; 91 iterate_supers(sync_one_sb, &wait);
87
88 spin_lock(&sb_lock);
89 list_for_each_entry_safe(sb, n, &super_blocks, s_list) {
90 if (list_empty(&sb->s_instances))
91 continue;
92 sb->s_count++;
93 spin_unlock(&sb_lock);
94
95 down_read(&sb->s_umount);
96 if (!(sb->s_flags & MS_RDONLY) && sb->s_root && sb->s_bdi)
97 __sync_filesystem(sb, wait);
98 up_read(&sb->s_umount);
99
100 /* restart only when sb is no longer on the list */
101 spin_lock(&sb_lock);
102 __put_super(sb);
103 }
104 spin_unlock(&sb_lock);
105} 92}
106 93
107/* 94/*
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 523086714c74..eeb04ba17b63 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2324,6 +2324,7 @@ extern struct super_block *get_super(struct block_device *);
2324extern struct super_block *get_active_super(struct block_device *bdev); 2324extern struct super_block *get_active_super(struct block_device *bdev);
2325extern struct super_block *user_get_super(dev_t); 2325extern struct super_block *user_get_super(dev_t);
2326extern void drop_super(struct super_block *sb); 2326extern void drop_super(struct super_block *sb);
2327extern void iterate_supers(void (*)(struct super_block *, void *), void *);
2327 2328
2328extern int dcache_dir_open(struct inode *, struct file *); 2329extern int dcache_dir_open(struct inode *, struct file *);
2329extern int dcache_dir_close(struct inode *, struct file *); 2330extern int dcache_dir_close(struct inode *, struct file *);