summaryrefslogtreecommitdiff
path: root/fs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c47
1 files changed, 47 insertions, 0 deletions
diff --git a/fs/super.c b/fs/super.c
index ad57841f7..3446dc4fb 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1372,3 +1372,50 @@ out:
return 0;
}
EXPORT_SYMBOL(thaw_super);
+
+/**
+ * lock_supers -- Stop other processes from modifying the list of super blocks.
+ */
+void take_super_lock() {
+ spin_lock(&sb_lock);
+}
+
+/**
+ * unlock_supers -- Allow other processes to again modify the list of super blocks.
+ */
+void release_super_lock() {
+ spin_unlock(&sb_lock);
+}
+
+/**
+ * iterate_supers_no_sb_lock - call function for all active superblocks without using sb_lock
+ *
+ * Note that the callback must work with sb_lock taken and not unlock it.
+ *
+ * @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_no_sb_lock(void (*f)(struct super_block *, void *), void *arg)
+{
+ struct super_block *sb, *p = NULL;
+
+ list_for_each_entry(sb, &super_blocks, s_list) {
+ if (hlist_unhashed(&sb->s_instances))
+ continue;
+ sb->s_count++;
+
+ down_read(&sb->s_umount);
+ if (sb->s_root && (sb->s_flags & MS_BORN))
+ f(sb, arg);
+ up_read(&sb->s_umount);
+
+ if (p)
+ __put_super(p);
+ p = sb;
+ }
+ if (p)
+ __put_super(p);
+}