diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/fs/super.c b/fs/super.c index aff046b0fe78..dc72491a19f9 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -568,7 +568,7 @@ out: | |||
568 | int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | 568 | int do_remount_sb(struct super_block *sb, int flags, void *data, int force) |
569 | { | 569 | { |
570 | int retval; | 570 | int retval; |
571 | int remount_rw; | 571 | int remount_rw, remount_ro; |
572 | 572 | ||
573 | if (sb->s_frozen != SB_UNFROZEN) | 573 | if (sb->s_frozen != SB_UNFROZEN) |
574 | return -EBUSY; | 574 | return -EBUSY; |
@@ -583,9 +583,12 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
583 | shrink_dcache_sb(sb); | 583 | shrink_dcache_sb(sb); |
584 | sync_filesystem(sb); | 584 | sync_filesystem(sb); |
585 | 585 | ||
586 | remount_ro = (flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY); | ||
587 | remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY); | ||
588 | |||
586 | /* If we are remounting RDONLY and current sb is read/write, | 589 | /* If we are remounting RDONLY and current sb is read/write, |
587 | make sure there are no rw files opened */ | 590 | make sure there are no rw files opened */ |
588 | if ((flags & MS_RDONLY) && !(sb->s_flags & MS_RDONLY)) { | 591 | if (remount_ro) { |
589 | if (force) | 592 | if (force) |
590 | mark_files_ro(sb); | 593 | mark_files_ro(sb); |
591 | else if (!fs_may_remount_ro(sb)) | 594 | else if (!fs_may_remount_ro(sb)) |
@@ -594,7 +597,6 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
594 | if (retval < 0 && retval != -ENOSYS) | 597 | if (retval < 0 && retval != -ENOSYS) |
595 | return -EBUSY; | 598 | return -EBUSY; |
596 | } | 599 | } |
597 | remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY); | ||
598 | 600 | ||
599 | if (sb->s_op->remount_fs) { | 601 | if (sb->s_op->remount_fs) { |
600 | retval = sb->s_op->remount_fs(sb, &flags, data); | 602 | retval = sb->s_op->remount_fs(sb, &flags, data); |
@@ -604,6 +606,16 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) | |||
604 | sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); | 606 | sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); |
605 | if (remount_rw) | 607 | if (remount_rw) |
606 | vfs_dq_quota_on_remount(sb); | 608 | vfs_dq_quota_on_remount(sb); |
609 | /* | ||
610 | * Some filesystems modify their metadata via some other path than the | ||
611 | * bdev buffer cache (eg. use a private mapping, or directories in | ||
612 | * pagecache, etc). Also file data modifications go via their own | ||
613 | * mappings. So If we try to mount readonly then copy the filesystem | ||
614 | * from bdev, we could get stale data, so invalidate it to give a best | ||
615 | * effort at coherency. | ||
616 | */ | ||
617 | if (remount_ro && sb->s_bdev) | ||
618 | invalidate_bdev(sb->s_bdev); | ||
607 | return 0; | 619 | return 0; |
608 | } | 620 | } |
609 | 621 | ||
@@ -681,6 +693,7 @@ int set_anon_super(struct super_block *s, void *data) | |||
681 | return -EMFILE; | 693 | return -EMFILE; |
682 | } | 694 | } |
683 | s->s_dev = MKDEV(0, dev & MINORMASK); | 695 | s->s_dev = MKDEV(0, dev & MINORMASK); |
696 | s->s_bdi = &noop_backing_dev_info; | ||
684 | return 0; | 697 | return 0; |
685 | } | 698 | } |
686 | 699 | ||
@@ -925,6 +938,9 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void | |||
925 | if (!mnt) | 938 | if (!mnt) |
926 | goto out; | 939 | goto out; |
927 | 940 | ||
941 | if (flags & MS_KERNMOUNT) | ||
942 | mnt->mnt_flags = MNT_INTERNAL; | ||
943 | |||
928 | if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { | 944 | if (data && !(type->fs_flags & FS_BINARY_MOUNTDATA)) { |
929 | secdata = alloc_secdata(); | 945 | secdata = alloc_secdata(); |
930 | if (!secdata) | 946 | if (!secdata) |
@@ -939,10 +955,11 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void | |||
939 | if (error < 0) | 955 | if (error < 0) |
940 | goto out_free_secdata; | 956 | goto out_free_secdata; |
941 | BUG_ON(!mnt->mnt_sb); | 957 | BUG_ON(!mnt->mnt_sb); |
958 | WARN_ON(!mnt->mnt_sb->s_bdi); | ||
942 | 959 | ||
943 | error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); | 960 | error = security_sb_kern_mount(mnt->mnt_sb, flags, secdata); |
944 | if (error) | 961 | if (error) |
945 | goto out_sb; | 962 | goto out_sb; |
946 | 963 | ||
947 | /* | 964 | /* |
948 | * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE | 965 | * filesystems should never set s_maxbytes larger than MAX_LFS_FILESIZE |