nilfs2: add norecovery mount option
authorRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Thu, 19 Nov 2009 18:28:01 +0000 (03:28 +0900)
committerRyusuke Konishi <konishi.ryusuke@lab.ntt.co.jp>
Fri, 20 Nov 2009 01:05:52 +0000 (10:05 +0900)
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>
Documentation/filesystems/nilfs2.txt
fs/nilfs2/super.c
fs/nilfs2/the_nilfs.c
include/linux/nilfs2_fs.h

index cbd877978c8065b9baa147fc4da931a3cc58585f..4949fcaa6b6a94f6d8b42d483a86c9a5984e0420 100644 (file)
@@ -70,6 +70,10 @@ order=strict         Apply strict in-order semantics that preserves sequence
                        blocks.  That means, it is guaranteed that no
                        overtaking of events occurs in the recovered file
                        system after a crash.
+norecovery             Disable recovery of the filesystem on mount.
+                       This disables every write access on the device for
+                       read-only mounts or snapshots.  This option will fail
+                       for r/w mounts on an unclean volume.
 
 NILFS2 usage
 ============
index 990ead43a833acfe34681aebda2dadbbc5d3cd75..5403b3ef3a42bd745b80b2e550a7f57a7c3d2c48 100644 (file)
@@ -479,6 +479,8 @@ static int nilfs_show_options(struct seq_file *seq, struct vfsmount *vfs)
                seq_printf(seq, ",errors=panic");
        if (nilfs_test_opt(sbi, STRICT_ORDER))
                seq_printf(seq, ",order=strict");
+       if (nilfs_test_opt(sbi, NORECOVERY))
+               seq_printf(seq, ",norecovery");
 
        return 0;
 }
@@ -547,7 +549,7 @@ static const struct export_operations nilfs_export_ops = {
 
 enum {
        Opt_err_cont, Opt_err_panic, Opt_err_ro,
-       Opt_nobarrier, Opt_snapshot, Opt_order,
+       Opt_nobarrier, Opt_snapshot, Opt_order, Opt_norecovery,
        Opt_err,
 };
 
@@ -558,6 +560,7 @@ static match_table_t tokens = {
        {Opt_nobarrier, "nobarrier"},
        {Opt_snapshot, "cp=%u"},
        {Opt_order, "order=%s"},
+       {Opt_norecovery, "norecovery"},
        {Opt_err, NULL}
 };
 
@@ -608,6 +611,9 @@ static int parse_options(char *options, struct super_block *sb)
                        sbi->s_snapshot_cno = option;
                        nilfs_set_opt(sbi, SNAPSHOT);
                        break;
+               case Opt_norecovery:
+                       nilfs_set_opt(sbi, NORECOVERY);
+                       break;
                default:
                        printk(KERN_ERR
                               "NILFS: Unrecognized mount option \"%s\"\n", p);
@@ -863,6 +869,14 @@ static int nilfs_remount(struct super_block *sb, int *flags, char *data)
                goto restore_opts;
        }
 
+       if (!nilfs_valid_fs(nilfs)) {
+               printk(KERN_WARNING "NILFS (device %s): couldn't "
+                      "remount because the filesystem is in an "
+                      "incomplete recovery state.\n", sb->s_id);
+               err = -EINVAL;
+               goto restore_opts;
+       }
+
        if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY))
                goto out;
        if (*flags & MS_RDONLY) {
index 890a8d3886cf6ac1c3e7590b702dc9e7bfec33d2..6241e1722efc570f3bb62c81f30a4b4e8f7092e3 100644 (file)
@@ -264,8 +264,14 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
        int valid_fs = nilfs_valid_fs(nilfs);
        int err;
 
-       if (nilfs_loaded(nilfs))
-               return 0;
+       if (nilfs_loaded(nilfs)) {
+               if (valid_fs ||
+                   ((s_flags & MS_RDONLY) && nilfs_test_opt(sbi, NORECOVERY)))
+                       return 0;
+               printk(KERN_ERR "NILFS: the filesystem is in an incomplete "
+                      "recovery state.\n");
+               return -EINVAL;
+       }
 
        if (!valid_fs) {
                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)
                goto skip_recovery;
 
        if (s_flags & MS_RDONLY) {
+               if (nilfs_test_opt(sbi, NORECOVERY)) {
+                       printk(KERN_INFO "NILFS: norecovery option specified. "
+                              "skipping roll-forward recovery\n");
+                       goto skip_recovery;
+               }
                if (really_read_only) {
                        printk(KERN_ERR "NILFS: write access "
                               "unavailable, cannot proceed.\n");
@@ -302,6 +313,11 @@ int load_nilfs(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi)
                        goto failed_unload;
                }
                sbi->s_super->s_flags &= ~MS_RDONLY;
+       } else if (nilfs_test_opt(sbi, NORECOVERY)) {
+               printk(KERN_ERR "NILFS: recovery cancelled because norecovery "
+                      "option was specified for a read/write mount\n");
+               err = -EINVAL;
+               goto failed_unload;
        }
 
        err = nilfs_recover_logical_segments(nilfs, sbi, &ri);
index 72289d2bb3414d03171a32d888fe0b13864223e1..3fe02cf8b65a3097785fd1543097b9cdadf3116e 100644 (file)
@@ -151,6 +151,8 @@ struct nilfs_super_root {
 #define NILFS_MOUNT_BARRIER            0x1000  /* Use block barriers */
 #define NILFS_MOUNT_STRICT_ORDER       0x2000  /* Apply strict in-order
                                                   semantics also for data */
+#define NILFS_MOUNT_NORECOVERY         0x4000  /* Disable write access during
+                                                  mount-time recovery */
 
 
 /**