diff options
author | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2009-11-19 13:28:01 -0500 |
---|---|---|
committer | Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp> | 2009-11-19 20:05:52 -0500 |
commit | 0234576d041b9b2cc7043691ea61d2c2ca597aaa (patch) | |
tree | 1fd5f397cf0a7cb010a3e383a715438e64582b65 | |
parent | a057d2c01161444c48b12a60351ae6c7135f6e61 (diff) |
nilfs2: add norecovery mount option
This adds "norecovery" mount option which disables temporal write
access to read-only mounts or snapshots during mount/recovery.
Without this option, write access will be even performed for those
types of mounts; the temporal write access is needed to mount root
file system read-only after an unclean shutdown.
This option will be helpful when user wants to prevent any write
access to the device.
Signed-off-by: Ryusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Cc: Eric Sandeen <sandeen@redhat.com>
-rw-r--r-- | Documentation/filesystems/nilfs2.txt | 4 | ||||
-rw-r--r-- | fs/nilfs2/super.c | 16 | ||||
-rw-r--r-- | fs/nilfs2/the_nilfs.c | 20 | ||||
-rw-r--r-- | include/linux/nilfs2_fs.h | 2 |
4 files changed, 39 insertions, 3 deletions
diff --git a/Documentation/filesystems/nilfs2.txt b/Documentation/filesystems/nilfs2.txt index cbd877978c80..4949fcaa6b6a 100644 --- a/Documentation/filesystems/nilfs2.txt +++ b/Documentation/filesystems/nilfs2.txt | |||
@@ -70,6 +70,10 @@ order=strict Apply strict in-order semantics that preserves sequence | |||
70 | blocks. That means, it is guaranteed that no | 70 | blocks. That means, it is guaranteed that no |
71 | overtaking of events occurs in the recovered file | 71 | overtaking of events occurs in the recovered file |
72 | system after a crash. | 72 | system after a crash. |
73 | norecovery Disable recovery of the filesystem on mount. | ||
74 | This disables every write access on the device for | ||
75 | read-only mounts or snapshots. This option will fail | ||
76 | for r/w mounts on an unclean volume. | ||
73 | 77 | ||
74 | NILFS2 usage | 78 | NILFS2 usage |
75 | ============ | 79 | ============ |
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c index 990ead43a833..5403b3ef3a42 100644 --- a/fs/nilfs2/super.c +++ b/fs/nilfs2/super.c | |||
@@ -479,6 +479,8 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs) | |||
479 | seq_printf(seq, ",errors=panic"); | 479 | seq_printf(seq, ",errors=panic"); |
480 | if (nilfs_test_opt(sbi, STRICT_ORDER)) | 480 | if (nilfs_test_opt(sbi, STRICT_ORDER)) |
481 | seq_printf(seq, ",order=strict"); | 481 | seq_printf(seq, ",order=strict"); |
482 | if (nilfs_test_opt(sbi, NORECOVERY)) | ||
483 | seq_printf(seq, ",norecovery"); | ||
482 | 484 | ||
483 | return 0; | 485 | return 0; |
484 | } | 486 | } |
@@ -547,7 +549,7 @@ static const struct export_operations nilfs_export_ops = { | |||
547 | 549 | ||
548 | enum { | 550 | enum { |
549 | Opt_err_cont, Opt_err_panic, Opt_err_ro, | 551 | Opt_err_cont, Opt_err_panic, Opt_err_ro, |
550 | Opt_nobarrier, Opt_snapshot, Opt_order, | 552 | Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery, |
551 | Opt_err, | 553 | Opt_err, |
552 | }; | 554 | }; |
553 | 555 | ||
@@ -558,6 +560,7 @@ static match_table_t tokens = { | |||
558 | {Opt_nobarrier, "nobarrier"}, | 560 | {Opt_nobarrier, "nobarrier"}, |
559 | {Opt_snapshot, "cp=%u"}, | 561 | {Opt_snapshot, "cp=%u"}, |
560 | {Opt_order, "order=%s"}, | 562 | {Opt_order, "order=%s"}, |
563 | {Opt_norecovery, "norecovery"}, | ||
561 | {Opt_err, NULL} | 564 | {Opt_err, NULL} |
562 | }; | 565 | }; |
563 | 566 | ||
@@ -608,6 +611,9 @@ static int parse_options(char *options, struct super_block *sb) | |||
608 | sbi->s_snapshot_cno = option; | 611 | sbi->s_snapshot_cno = option; |
609 | nilfs_set_opt(sbi, SNAPSHOT); | 612 | nilfs_set_opt(sbi, SNAPSHOT); |
610 | break; | 613 | break; |
614 | case Opt_norecovery: | ||
615 | nilfs_set_opt(sbi, NORECOVERY); | ||
616 | break; | ||
611 | default: | 617 | default: |
612 | printk(KERN_ERR | 618 | printk(KERN_ERR |
613 | "NILFS: Unrecognized mount option \"%s\"\n", p); | 619 | "NILFS: Unrecognized mount option \"%s\"\n", p); |
@@ -863,6 +869,14 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data) | |||
863 | goto restore_opts; | 869 | goto restore_opts; |
864 | } | 870 | } |
865 | 871 | ||
872 | if (!nilfs_valid_fs(nilfs)) { | ||
873 | printk(KERN_WARNING "NILFS (device %s): couldn't " | ||
874 | "remount because the filesystem is in an " | ||
875 | "incomplete recovery state.\n", sb->s_id); | ||
876 | err = -EINVAL; | ||
877 | goto restore_opts; | ||
878 | } | ||
879 | |||
866 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) | 880 | if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) |
867 | goto out; | 881 | goto out; |
868 | if (*flags & MS_RDONLY) { | 882 | if (*flags & MS_RDONLY) { |
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c index 890a8d3886cf..6241e1722efc 100644 --- a/fs/nilfs2/the_nilfs.c +++ b/fs/nilfs2/the_nilfs.c | |||
@@ -264,8 +264,14 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
264 | int valid_fs = nilfs_valid_fs(nilfs); | 264 | int valid_fs = nilfs_valid_fs(nilfs); |
265 | int err; | 265 | int err; |
266 | 266 | ||
267 | if (nilfs_loaded(nilfs)) | 267 | if (nilfs_loaded(nilfs)) { |
268 | return 0; | 268 | if (valid_fs || |
269 | ((s_flags & MS_RDONLY) && nilfs_test_opt(sbi, NORECOVERY))) | ||
270 | return 0; | ||
271 | printk(KERN_ERR "NILFS: the filesystem is in an incomplete " | ||
272 | "recovery state.\n"); | ||
273 | return -EINVAL; | ||
274 | } | ||
269 | 275 | ||
270 | if (!valid_fs) { | 276 | if (!valid_fs) { |
271 | printk(KERN_WARNING "NILFS warning: mounting unchecked fs\n"); | 277 | printk(KERN_WARNING "NILFS warning: mounting unchecked fs\n"); |
@@ -295,6 +301,11 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
295 | goto skip_recovery; | 301 | goto skip_recovery; |
296 | 302 | ||
297 | if (s_flags & MS_RDONLY) { | 303 | if (s_flags & MS_RDONLY) { |
304 | if (nilfs_test_opt(sbi, NORECOVERY)) { | ||
305 | printk(KERN_INFO "NILFS: norecovery option specified. " | ||
306 | "skipping roll-forward recovery\n"); | ||
307 | goto skip_recovery; | ||
308 | } | ||
298 | if (really_read_only) { | 309 | if (really_read_only) { |
299 | printk(KERN_ERR "NILFS: write access " | 310 | printk(KERN_ERR "NILFS: write access " |
300 | "unavailable, cannot proceed.\n"); | 311 | "unavailable, cannot proceed.\n"); |
@@ -302,6 +313,11 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi) | |||
302 | goto failed_unload; | 313 | goto failed_unload; |
303 | } | 314 | } |
304 | sbi->s_super->s_flags &= ~MS_RDONLY; | 315 | sbi->s_super->s_flags &= ~MS_RDONLY; |
316 | } else if (nilfs_test_opt(sbi, NORECOVERY)) { | ||
317 | printk(KERN_ERR "NILFS: recovery cancelled because norecovery " | ||
318 | "option was specified for a read/write mount\n"); | ||
319 | err = -EINVAL; | ||
320 | goto failed_unload; | ||
305 | } | 321 | } |
306 | 322 | ||
307 | err = nilfs_recover_logical_segments(nilfs, sbi, &ri); | 323 | err = nilfs_recover_logical_segments(nilfs, sbi, &ri); |
diff --git a/include/linux/nilfs2_fs.h b/include/linux/nilfs2_fs.h index 72289d2bb341..3fe02cf8b65a 100644 --- a/include/linux/nilfs2_fs.h +++ b/include/linux/nilfs2_fs.h | |||
@@ -151,6 +151,8 @@ struct nilfs_super_root { | |||
151 | #define NILFS_MOUNT_BARRIER 0x1000 /* Use block barriers */ | 151 | #define NILFS_MOUNT_BARRIER 0x1000 /* Use block barriers */ |
152 | #define NILFS_MOUNT_STRICT_ORDER 0x2000 /* Apply strict in-order | 152 | #define NILFS_MOUNT_STRICT_ORDER 0x2000 /* Apply strict in-order |
153 | semantics also for data */ | 153 | semantics also for data */ |
154 | #define NILFS_MOUNT_NORECOVERY 0x4000 /* Disable write access during | ||
155 | mount-time recovery */ | ||
154 | 156 | ||
155 | 157 | ||
156 | /** | 158 | /** |