diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2010-03-23 01:11:53 +0100 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-05-22 00:31:15 +0200 |
commit | e7fe0585ca8793e2d43c57e77d4ca79042806acf (patch) | |
tree | a68234ce86f5ff221f3f6260374f3a6437d77ce3 | |
parent | Convert simple loops over superblocks to list_for_each_entry_safe (diff) | |
download | linux-e7fe0585ca8793e2d43c57e77d4ca79042806acf.tar.xz linux-e7fe0585ca8793e2d43c57e77d4ca79042806acf.zip |
fix do_emergency_remount()/umount() races
need list_for_each_entry_safe() here. Original didn't even
have restart logics, so if you race with umount() it blew up.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r-- | fs/super.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/fs/super.c b/fs/super.c index ccb2b5fa89bd..4df8233dfb61 100644 --- a/fs/super.c +++ b/fs/super.c @@ -602,10 +602,10 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) static void do_emergency_remount(struct work_struct *work) { - struct super_block *sb; + struct super_block *sb, *n; spin_lock(&sb_lock); - list_for_each_entry(sb, &super_blocks, s_list) { + list_for_each_entry_safe(sb, n, &super_blocks, s_list) { if (list_empty(&sb->s_instances)) continue; sb->s_count++; @@ -618,8 +618,8 @@ static void do_emergency_remount(struct work_struct *work) do_remount_sb(sb, MS_RDONLY, NULL, 1); } up_write(&sb->s_umount); - put_super(sb); spin_lock(&sb_lock); + __put_super(sb); } spin_unlock(&sb_lock); kfree(work); |