btrfs: Introduce new mount option to disable tree log replay
[sfrench/cifs-2.6.git] / fs / btrfs / super.c
index 9b9eab6d048e93d32963b0c66a6d9ab6c022ee63..e8a7a9f88195140351682d3559d70d052d67f27b 100644 (file)
@@ -303,7 +303,8 @@ enum {
        Opt_check_integrity_print_mask, Opt_fatal_errors, Opt_rescan_uuid_tree,
        Opt_commit_interval, Opt_barrier, Opt_nodefrag, Opt_nodiscard,
        Opt_noenospc_debug, Opt_noflushoncommit, Opt_acl, Opt_datacow,
-       Opt_datasum, Opt_treelog, Opt_noinode_cache,
+       Opt_datasum, Opt_treelog, Opt_noinode_cache, Opt_usebackuproot,
+       Opt_nologreplay,
 #ifdef CONFIG_BTRFS_DEBUG
        Opt_fragment_data, Opt_fragment_metadata, Opt_fragment_all,
 #endif
@@ -335,6 +336,7 @@ static const match_table_t tokens = {
        {Opt_noacl, "noacl"},
        {Opt_notreelog, "notreelog"},
        {Opt_treelog, "treelog"},
+       {Opt_nologreplay, "nologreplay"},
        {Opt_flushoncommit, "flushoncommit"},
        {Opt_noflushoncommit, "noflushoncommit"},
        {Opt_ratio, "metadata_ratio=%d"},
@@ -352,7 +354,8 @@ static const match_table_t tokens = {
        {Opt_inode_cache, "inode_cache"},
        {Opt_noinode_cache, "noinode_cache"},
        {Opt_no_space_cache, "nospace_cache"},
-       {Opt_recovery, "recovery"},
+       {Opt_recovery, "recovery"}, /* deprecated */
+       {Opt_usebackuproot, "usebackuproot"},
        {Opt_skip_balance, "skip_balance"},
        {Opt_check_integrity, "check_int"},
        {Opt_check_integrity_including_extent_data, "check_int_data"},
@@ -373,7 +376,8 @@ static const match_table_t tokens = {
  * reading in a new superblock is parsed here.
  * XXX JDM: This needs to be cleaned up for remount.
  */
-int btrfs_parse_options(struct btrfs_root *root, char *options)
+int btrfs_parse_options(struct btrfs_root *root, char *options,
+                       unsigned long new_flags)
 {
        struct btrfs_fs_info *info = root->fs_info;
        substring_t args[MAX_OPT_ARGS];
@@ -383,6 +387,9 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
        int ret = 0;
        char *compress_type;
        bool compress_force = false;
+       enum btrfs_compression_type saved_compress_type;
+       bool saved_compress_force;
+       int no_compress = 0;
 
        cache_gen = btrfs_super_cache_generation(root->fs_info->super_copy);
        if (btrfs_fs_compat_ro(root->fs_info, FREE_SPACE_TREE))
@@ -390,8 +397,12 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
        else if (cache_gen)
                btrfs_set_opt(info->mount_opt, SPACE_CACHE);
 
+       /*
+        * Even the options are empty, we still need to do extra check
+        * against new flags
+        */
        if (!options)
-               goto out;
+               goto check;
 
        /*
         * strsep changes the string, duplicate it because parse_options
@@ -462,6 +473,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                        /* Fallthrough */
                case Opt_compress:
                case Opt_compress_type:
+                       saved_compress_type = btrfs_test_opt(root, COMPRESS) ?
+                               info->compress_type : BTRFS_COMPRESS_NONE;
+                       saved_compress_force =
+                               btrfs_test_opt(root, FORCE_COMPRESS);
                        if (token == Opt_compress ||
                            token == Opt_compress_force ||
                            strcmp(args[0].from, "zlib") == 0) {
@@ -470,6 +485,7 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                                btrfs_set_opt(info->mount_opt, COMPRESS);
                                btrfs_clear_opt(info->mount_opt, NODATACOW);
                                btrfs_clear_opt(info->mount_opt, NODATASUM);
+                               no_compress = 0;
                        } else if (strcmp(args[0].from, "lzo") == 0) {
                                compress_type = "lzo";
                                info->compress_type = BTRFS_COMPRESS_LZO;
@@ -477,25 +493,21 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                                btrfs_clear_opt(info->mount_opt, NODATACOW);
                                btrfs_clear_opt(info->mount_opt, NODATASUM);
                                btrfs_set_fs_incompat(info, COMPRESS_LZO);
+                               no_compress = 0;
                        } else if (strncmp(args[0].from, "no", 2) == 0) {
                                compress_type = "no";
                                btrfs_clear_opt(info->mount_opt, COMPRESS);
                                btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
                                compress_force = false;
+                               no_compress++;
                        } else {
                                ret = -EINVAL;
                                goto out;
                        }
 
                        if (compress_force) {
-                               btrfs_set_and_info(root, FORCE_COMPRESS,
-                                                  "force %s compression",
-                                                  compress_type);
+                               btrfs_set_opt(info->mount_opt, FORCE_COMPRESS);
                        } else {
-                               if (!btrfs_test_opt(root, COMPRESS))
-                                       btrfs_info(root->fs_info,
-                                                  "btrfs: use %s compression",
-                                                  compress_type);
                                /*
                                 * If we remount from compress-force=xxx to
                                 * compress=xxx, we need clear FORCE_COMPRESS
@@ -504,6 +516,17 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                                 */
                                btrfs_clear_opt(info->mount_opt, FORCE_COMPRESS);
                        }
+                       if ((btrfs_test_opt(root, COMPRESS) &&
+                            (info->compress_type != saved_compress_type ||
+                             compress_force != saved_compress_force)) ||
+                           (!btrfs_test_opt(root, COMPRESS) &&
+                            no_compress == 1)) {
+                               btrfs_info(root->fs_info,
+                                          "%s %s compression",
+                                          (compress_force) ? "force" : "use",
+                                          compress_type);
+                       }
+                       compress_force = false;
                        break;
                case Opt_ssd:
                        btrfs_set_and_info(root, SSD,
@@ -591,6 +614,10 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                        btrfs_clear_and_info(root, NOTREELOG,
                                             "enabling tree log");
                        break;
+               case Opt_nologreplay:
+                       btrfs_set_and_info(root, NOLOGREPLAY,
+                                          "disabling log replay at mount time");
+                       break;
                case Opt_flushoncommit:
                        btrfs_set_and_info(root, FLUSHONCOMMIT,
                                           "turning on flush-on-commit");
@@ -681,8 +708,12 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                                             "disabling auto defrag");
                        break;
                case Opt_recovery:
-                       btrfs_info(root->fs_info, "enabling auto recovery");
-                       btrfs_set_opt(info->mount_opt, RECOVERY);
+                       btrfs_warn(root->fs_info,
+                                  "'recovery' is deprecated, use 'usebackuproot' instead");
+               case Opt_usebackuproot:
+                       btrfs_info(root->fs_info,
+                                  "trying to use backup root at mount time");
+                       btrfs_set_opt(info->mount_opt, USEBACKUPROOT);
                        break;
                case Opt_skip_balance:
                        btrfs_set_opt(info->mount_opt, SKIP_BALANCE);
@@ -777,6 +808,15 @@ int btrfs_parse_options(struct btrfs_root *root, char *options)
                        break;
                }
        }
+check:
+       /*
+        * Extra check for current option against current flag
+        */
+       if (btrfs_test_opt(root, NOLOGREPLAY) && !(new_flags & MS_RDONLY)) {
+               btrfs_err(root->fs_info,
+                         "nologreplay must be used with ro mount option");
+               ret = -EINVAL;
+       }
 out:
        if (btrfs_fs_compat_ro(root->fs_info, FREE_SPACE_TREE) &&
            !btrfs_test_opt(root, FREE_SPACE_TREE) &&
@@ -1187,6 +1227,8 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
                seq_puts(seq, ",ssd");
        if (btrfs_test_opt(root, NOTREELOG))
                seq_puts(seq, ",notreelog");
+       if (btrfs_test_opt(root, NOLOGREPLAY))
+               seq_puts(seq, ",nologreplay");
        if (btrfs_test_opt(root, FLUSHONCOMMIT))
                seq_puts(seq, ",flushoncommit");
        if (btrfs_test_opt(root, DISCARD))
@@ -1213,8 +1255,6 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
                seq_puts(seq, ",inode_cache");
        if (btrfs_test_opt(root, SKIP_BALANCE))
                seq_puts(seq, ",skip_balance");
-       if (btrfs_test_opt(root, RECOVERY))
-               seq_puts(seq, ",recovery");
 #ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
        if (btrfs_test_opt(root, CHECK_INTEGRITY_INCLUDING_EXTENT_DATA))
                seq_puts(seq, ",check_int_data");
@@ -1670,7 +1710,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                }
        }
 
-       ret = btrfs_parse_options(root, data);
+       ret = btrfs_parse_options(root, data, *flags);
        if (ret) {
                ret = -EINVAL;
                goto restore;