diff options
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/fs/super.c b/fs/super.c index aff046b0fe78..903896ec7c73 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 | ||