aboutsummaryrefslogtreecommitdiffstats
path: root/fs/super.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/super.c')
-rw-r--r--fs/super.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/fs/super.c b/fs/super.c
index ddba069d7a99..645e5403f2a0 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -38,6 +38,7 @@
38#include <linux/kobject.h> 38#include <linux/kobject.h>
39#include <linux/mutex.h> 39#include <linux/mutex.h>
40#include <linux/file.h> 40#include <linux/file.h>
41#include <linux/async.h>
41#include <asm/uaccess.h> 42#include <asm/uaccess.h>
42#include "internal.h" 43#include "internal.h"
43 44
@@ -71,6 +72,7 @@ static struct super_block *alloc_super(struct file_system_type *type)
71 INIT_HLIST_HEAD(&s->s_anon); 72 INIT_HLIST_HEAD(&s->s_anon);
72 INIT_LIST_HEAD(&s->s_inodes); 73 INIT_LIST_HEAD(&s->s_inodes);
73 INIT_LIST_HEAD(&s->s_dentry_lru); 74 INIT_LIST_HEAD(&s->s_dentry_lru);
75 INIT_LIST_HEAD(&s->s_async_list);
74 init_rwsem(&s->s_umount); 76 init_rwsem(&s->s_umount);
75 mutex_init(&s->s_lock); 77 mutex_init(&s->s_lock);
76 lockdep_set_class(&s->s_umount, &type->s_umount_key); 78 lockdep_set_class(&s->s_umount, &type->s_umount_key);
@@ -289,11 +291,18 @@ void generic_shutdown_super(struct super_block *sb)
289{ 291{
290 const struct super_operations *sop = sb->s_op; 292 const struct super_operations *sop = sb->s_op;
291 293
294
292 if (sb->s_root) { 295 if (sb->s_root) {
293 shrink_dcache_for_umount(sb); 296 shrink_dcache_for_umount(sb);
294 fsync_super(sb); 297 fsync_super(sb);
295 lock_super(sb); 298 lock_super(sb);
296 sb->s_flags &= ~MS_ACTIVE; 299 sb->s_flags &= ~MS_ACTIVE;
300
301 /*
302 * wait for asynchronous fs operations to finish before going further
303 */
304 async_synchronize_full_special(&sb->s_async_list);
305
297 /* bad name - it should be evict_inodes() */ 306 /* bad name - it should be evict_inodes() */
298 invalidate_inodes(sb); 307 invalidate_inodes(sb);
299 lock_kernel(); 308 lock_kernel();
@@ -461,6 +470,7 @@ restart:
461 sb->s_count++; 470 sb->s_count++;
462 spin_unlock(&sb_lock); 471 spin_unlock(&sb_lock);
463 down_read(&sb->s_umount); 472 down_read(&sb->s_umount);
473 async_synchronize_full_special(&sb->s_async_list);
464 if (sb->s_root && (wait || sb->s_dirt)) 474 if (sb->s_root && (wait || sb->s_dirt))
465 sb->s_op->sync_fs(sb, wait); 475 sb->s_op->sync_fs(sb, wait);
466 up_read(&sb->s_umount); 476 up_read(&sb->s_umount);
@@ -534,7 +544,7 @@ rescan:
534 return NULL; 544 return NULL;
535} 545}
536 546
537asmlinkage long sys_ustat(unsigned dev, struct ustat __user * ubuf) 547SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf)
538{ 548{
539 struct super_block *s; 549 struct super_block *s;
540 struct ustat tmp; 550 struct ustat tmp;
@@ -800,6 +810,7 @@ int get_sb_bdev(struct file_system_type *fs_type,
800 } 810 }
801 811
802 s->s_flags |= MS_ACTIVE; 812 s->s_flags |= MS_ACTIVE;
813 bdev->bd_super = s;
803 } 814 }
804 815
805 return simple_set_mnt(mnt, s); 816 return simple_set_mnt(mnt, s);
@@ -819,6 +830,7 @@ void kill_block_super(struct super_block *sb)
819 struct block_device *bdev = sb->s_bdev; 830 struct block_device *bdev = sb->s_bdev;
820 fmode_t mode = sb->s_mode; 831 fmode_t mode = sb->s_mode;
821 832
833 bdev->bd_super = 0;
822 generic_shutdown_super(sb); 834 generic_shutdown_super(sb);
823 sync_blockdev(bdev); 835 sync_blockdev(bdev);
824 close_bdev_exclusive(bdev, mode); 836 close_bdev_exclusive(bdev, mode);