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,32 +827,35 @@ void kill_super(struct super_block *sb) ...@@ -826,32 +827,35 @@ void kill_super(struct super_block *sb)
return; return;
down_write(&sb->s_umount); down_write(&sb->s_umount);
sb->s_root = NULL; if (sb->s_root) {
/* Need to clean after the sucker */ sb->s_root = NULL;
if (fs->fs_flags & FS_LITTER) /* Need to clean after the sucker */
d_genocide(root); if (fs->fs_flags & FS_LITTER)
shrink_dcache_parent(root); d_genocide(root);
dput(root); shrink_dcache_parent(root);
fsync_super(sb); dput(root);
lock_super(sb); fsync_super(sb);
lock_kernel(); lock_super(sb);
sb->s_flags &= ~MS_ACTIVE; lock_kernel();
invalidate_inodes(sb); /* bad name - it should be evict_inodes() */ sb->s_flags &= ~MS_ACTIVE;
if (sop) { /* bad name - it should be evict_inodes() */
if (sop->write_super && sb->s_dirt) invalidate_inodes(sb);
sop->write_super(sb); if (sop) {
if (sop->put_super) if (sop->write_super && sb->s_dirt)
sop->put_super(sb); sop->write_super(sb);
} if (sop->put_super)
sop->put_super(sb);
}
/* Forget any remaining inodes */ /* Forget any remaining inodes */
if (invalidate_inodes(sb)) { if (invalidate_inodes(sb)) {
printk("VFS: Busy inodes after unmount. " printk("VFS: Busy inodes after unmount. "
"Self-destruct in 5 seconds. Have a nice day...\n"); "Self-destruct in 5 seconds. Have a nice day...\n");
} }
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