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 | |
parent | e7fe0585ca8793e2d43c57e77d4ca79042806acf (diff) |
fix get_active_super()/umount() race
This one needs restarts...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-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 4df8233dfb61..44971d7df1ce 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -471,17 +471,17 @@ struct super_block *get_active_super(struct block_device *bdev) | |||
471 | if (!bdev) | 471 | if (!bdev) |
472 | return NULL; | 472 | return NULL; |
473 | 473 | ||
474 | restart: | ||
474 | spin_lock(&sb_lock); | 475 | spin_lock(&sb_lock); |
475 | list_for_each_entry(sb, &super_blocks, s_list) { | 476 | list_for_each_entry(sb, &super_blocks, s_list) { |
476 | if (list_empty(&sb->s_instances)) | 477 | if (list_empty(&sb->s_instances)) |
477 | continue; | 478 | continue; |
478 | if (sb->s_bdev != bdev) | 479 | if (sb->s_bdev == bdev) { |
479 | continue; | 480 | if (grab_super(sb)) /* drops sb_lock */ |
480 | 481 | return sb; | |
481 | if (grab_super(sb)) /* drops sb_lock */ | 482 | else |
482 | return sb; | 483 | goto restart; |
483 | 484 | } | |
484 | spin_lock(&sb_lock); | ||
485 | } | 485 | } |
486 | spin_unlock(&sb_lock); | 486 | spin_unlock(&sb_lock); |
487 | return NULL; | 487 | return NULL; |