diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 47 |
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); +} |