Commit ad9e3359 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] (1/3) fs/super.c cleanups

* missing yield() added to grab_super() (on failure exit).  Without
  that we have a nasty race - if get_sb_bdev() happens just before
  we grab ->s_umount in kill_super(), we are going to have
  get_sb_bdev() spinning indefinitely long without yielding CPU,
  so that kill_super() could make progress (and break the loop).

* in kill_super() code that does actual superblock shutdown is
  wrapped in if (sb->s_root) {}.  That condition is true for
  all old callers of kill_super(), so we don't change existing
  behaviour.

* instances of deactivate_super()/remove_super() (after failed
  call of foo_fill_super()) are replaced with
	up_write(&s->s_umount);
	kill_super(s);
  - now it becomes legitimate (kill_super() works on such guys and
  does exactly what we want).
parent dbd56307
...@@ -355,6 +355,7 @@ static int grab_super(struct super_block *s) ...@@ -355,6 +355,7 @@ static int grab_super(struct super_block *s)
} }
up_write(&s->s_umount); up_write(&s->s_umount);
put_super(s); put_super(s);
yield();
return 0; return 0;
} }
...@@ -724,8 +725,8 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, ...@@ -724,8 +725,8 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type,
return s; return s;
failed: failed:
deactivate_super(s); up_write(&s->s_umount);
remove_super(s); kill_super(s);
goto out; goto out;
out1: out1:
blkdev_put(bdev, BDEV_FS); blkdev_put(bdev, BDEV_FS);
...@@ -748,8 +749,8 @@ struct super_block *get_sb_nodev(struct file_system_type *fs_type, ...@@ -748,8 +749,8 @@ struct super_block *get_sb_nodev(struct file_system_type *fs_type,
error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
if (error) { if (error) {
deactivate_super(s); up_write(&s->s_umount);
remove_super(s); kill_super(s);
return ERR_PTR(error); return ERR_PTR(error);
} }
s->s_flags |= MS_ACTIVE; s->s_flags |= MS_ACTIVE;
...@@ -774,8 +775,8 @@ struct super_block *get_sb_single(struct file_system_type *fs_type, ...@@ -774,8 +775,8 @@ struct super_block *get_sb_single(struct file_system_type *fs_type,
s->s_flags = flags; s->s_flags = flags;
error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0); error = fill_super(s, data, flags & MS_VERBOSE ? 1 : 0);
if (error) { if (error) {
deactivate_super(s); up_write(&s->s_umount);
remove_super(s); kill_super(s);
return ERR_PTR(error); return ERR_PTR(error);
} }
s->s_flags |= MS_ACTIVE; s->s_flags |= MS_ACTIVE;
...@@ -826,6 +827,7 @@ void kill_super(struct super_block *sb) ...@@ -826,6 +827,7 @@ void kill_super(struct super_block *sb)
return; return;
down_write(&sb->s_umount); down_write(&sb->s_umount);
if (sb->s_root) {
sb->s_root = NULL; sb->s_root = NULL;
/* Need to clean after the sucker */ /* Need to clean after the sucker */
if (fs->fs_flags & FS_LITTER) if (fs->fs_flags & FS_LITTER)
...@@ -836,7 +838,8 @@ void kill_super(struct super_block *sb) ...@@ -836,7 +838,8 @@ void kill_super(struct super_block *sb)
lock_super(sb); lock_super(sb);
lock_kernel(); lock_kernel();
sb->s_flags &= ~MS_ACTIVE; sb->s_flags &= ~MS_ACTIVE;
invalidate_inodes(sb); /* bad name - it should be evict_inodes() */ /* bad name - it should be evict_inodes() */
invalidate_inodes(sb);
if (sop) { if (sop) {
if (sop->write_super && sb->s_dirt) if (sop->write_super && sb->s_dirt)
sop->write_super(sb); sop->write_super(sb);
...@@ -852,6 +855,7 @@ void kill_super(struct super_block *sb) ...@@ -852,6 +855,7 @@ void kill_super(struct super_block *sb)
unlock_kernel(); unlock_kernel();
unlock_super(sb); unlock_super(sb);
}
remove_super(sb); remove_super(sb);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment