diff options
Diffstat (limited to 'fs/super.c')
| -rw-r--r-- | fs/super.c | 25 |
1 files changed, 10 insertions, 15 deletions
diff --git a/fs/super.c b/fs/super.c index 7465d4364208..68307c029228 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -336,19 +336,19 @@ EXPORT_SYMBOL(deactivate_super); | |||
| 336 | * and want to turn it into a full-blown active reference. grab_super() | 336 | * and want to turn it into a full-blown active reference. grab_super() |
| 337 | * is called with sb_lock held and drops it. Returns 1 in case of | 337 | * is called with sb_lock held and drops it. Returns 1 in case of |
| 338 | * success, 0 if we had failed (superblock contents was already dead or | 338 | * success, 0 if we had failed (superblock contents was already dead or |
| 339 | * dying when grab_super() had been called). | 339 | * dying when grab_super() had been called). Note that this is only |
| 340 | * called for superblocks not in rundown mode (== ones still on ->fs_supers | ||
| 341 | * of their type), so increment of ->s_count is OK here. | ||
| 340 | */ | 342 | */ |
| 341 | static int grab_super(struct super_block *s) __releases(sb_lock) | 343 | static int grab_super(struct super_block *s) __releases(sb_lock) |
| 342 | { | 344 | { |
| 343 | if (atomic_inc_not_zero(&s->s_active)) { | ||
| 344 | spin_unlock(&sb_lock); | ||
| 345 | return 1; | ||
| 346 | } | ||
| 347 | /* it's going away */ | ||
| 348 | s->s_count++; | 345 | s->s_count++; |
| 349 | spin_unlock(&sb_lock); | 346 | spin_unlock(&sb_lock); |
| 350 | /* wait for it to die */ | ||
| 351 | down_write(&s->s_umount); | 347 | down_write(&s->s_umount); |
| 348 | if ((s->s_flags & MS_BORN) && atomic_inc_not_zero(&s->s_active)) { | ||
| 349 | put_super(s); | ||
| 350 | return 1; | ||
| 351 | } | ||
| 352 | up_write(&s->s_umount); | 352 | up_write(&s->s_umount); |
| 353 | put_super(s); | 353 | put_super(s); |
| 354 | return 0; | 354 | return 0; |
| @@ -463,11 +463,6 @@ retry: | |||
| 463 | destroy_super(s); | 463 | destroy_super(s); |
| 464 | s = NULL; | 464 | s = NULL; |
| 465 | } | 465 | } |
| 466 | down_write(&old->s_umount); | ||
| 467 | if (unlikely(!(old->s_flags & MS_BORN))) { | ||
| 468 | deactivate_locked_super(old); | ||
| 469 | goto retry; | ||
| 470 | } | ||
| 471 | return old; | 466 | return old; |
| 472 | } | 467 | } |
| 473 | } | 468 | } |
| @@ -660,10 +655,10 @@ restart: | |||
| 660 | if (hlist_unhashed(&sb->s_instances)) | 655 | if (hlist_unhashed(&sb->s_instances)) |
| 661 | continue; | 656 | continue; |
| 662 | if (sb->s_bdev == bdev) { | 657 | if (sb->s_bdev == bdev) { |
| 663 | if (grab_super(sb)) /* drops sb_lock */ | 658 | if (!grab_super(sb)) |
| 664 | return sb; | ||
| 665 | else | ||
| 666 | goto restart; | 659 | goto restart; |
| 660 | up_write(&sb->s_umount); | ||
| 661 | return sb; | ||
| 667 | } | 662 | } |
| 668 | } | 663 | } |
| 669 | spin_unlock(&sb_lock); | 664 | spin_unlock(&sb_lock); |
