diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2010-03-22 20:15:33 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2010-05-21 18:31:15 -0400 |
commit | 1494583de59dfad2e3a6788ce9817e658d32df22 (patch) | |
tree | 6f0a0fe022af703aa18ecc5f65a616fe44b9f8ad /fs/super.c | |
parent | e7fe0585ca8793e2d43c57e77d4ca79042806acf (diff) | |
download | linux-3.10-1494583de59dfad2e3a6788ce9817e658d32df22.tar.gz linux-3.10-1494583de59dfad2e3a6788ce9817e658d32df22.tar.bz2 linux-3.10-1494583de59dfad2e3a6788ce9817e658d32df22.zip |
fix get_active_super()/umount() race
This one needs restarts...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/fs/super.c b/fs/super.c index 4df8233dfb6..44971d7df1c 100644 --- a/fs/super.c +++ b/fs/super.c @@ -471,17 +471,17 @@ struct super_block *get_active_super(struct block_device *bdev) if (!bdev) return NULL; +restart: spin_lock(&sb_lock); list_for_each_entry(sb, &super_blocks, s_list) { if (list_empty(&sb->s_instances)) continue; - if (sb->s_bdev != bdev) - continue; - - if (grab_super(sb)) /* drops sb_lock */ - return sb; - - spin_lock(&sb_lock); + if (sb->s_bdev == bdev) { + if (grab_super(sb)) /* drops sb_lock */ + return sb; + else + goto restart; + } } spin_unlock(&sb_lock); return NULL; |