Merge tag 'f2fs-for-4.17' of git://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk...
[linux-2.6-microblaze.git] / fs / btrfs / super.c
index 4b81794..170baef 100644 (file)
@@ -41,6 +41,7 @@
 #include <linux/slab.h>
 #include <linux/cleancache.h>
 #include <linux/ratelimit.h>
+#include <linux/crc32c.h>
 #include <linux/btrfs.h>
 #include "delayed-inode.h"
 #include "ctree.h"
@@ -48,7 +49,6 @@
 #include "transaction.h"
 #include "btrfs_inode.h"
 #include "print-tree.h"
-#include "hash.h"
 #include "props.h"
 #include "xattr.h"
 #include "volumes.h"
@@ -308,21 +308,50 @@ static void btrfs_put_super(struct super_block *sb)
 }
 
 enum {
-       Opt_degraded, Opt_subvol, Opt_subvolid, Opt_device, Opt_nodatasum,
-       Opt_nodatacow, Opt_max_inline, Opt_alloc_start, Opt_nobarrier, Opt_ssd,
-       Opt_nossd, Opt_ssd_spread, Opt_thread_pool, Opt_noacl, Opt_compress,
-       Opt_compress_type, Opt_compress_force, Opt_compress_force_type,
-       Opt_notreelog, Opt_ratio, Opt_flushoncommit, Opt_discard,
-       Opt_space_cache, Opt_space_cache_version, Opt_clear_cache,
-       Opt_user_subvol_rm_allowed, Opt_enospc_debug, Opt_subvolrootid,
-       Opt_defrag, Opt_inode_cache, Opt_no_space_cache, Opt_recovery,
-       Opt_skip_balance, Opt_check_integrity,
+       Opt_acl, Opt_noacl,
+       Opt_clear_cache,
+       Opt_commit_interval,
+       Opt_compress,
+       Opt_compress_force,
+       Opt_compress_force_type,
+       Opt_compress_type,
+       Opt_degraded,
+       Opt_device,
+       Opt_fatal_errors,
+       Opt_flushoncommit, Opt_noflushoncommit,
+       Opt_inode_cache, Opt_noinode_cache,
+       Opt_max_inline,
+       Opt_barrier, Opt_nobarrier,
+       Opt_datacow, Opt_nodatacow,
+       Opt_datasum, Opt_nodatasum,
+       Opt_defrag, Opt_nodefrag,
+       Opt_discard, Opt_nodiscard,
+       Opt_nologreplay,
+       Opt_norecovery,
+       Opt_ratio,
+       Opt_rescan_uuid_tree,
+       Opt_skip_balance,
+       Opt_space_cache, Opt_no_space_cache,
+       Opt_space_cache_version,
+       Opt_ssd, Opt_nossd,
+       Opt_ssd_spread, Opt_nossd_spread,
+       Opt_subvol,
+       Opt_subvolid,
+       Opt_thread_pool,
+       Opt_treelog, Opt_notreelog,
+       Opt_usebackuproot,
+       Opt_user_subvol_rm_allowed,
+
+       /* Deprecated options */
+       Opt_alloc_start,
+       Opt_recovery,
+       Opt_subvolrootid,
+
+       /* Debugging options */
+       Opt_check_integrity,
        Opt_check_integrity_including_extent_data,
-       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_usebackuproot,
-       Opt_nologreplay, Opt_norecovery,
+       Opt_check_integrity_print_mask,
+       Opt_enospc_debug, Opt_noenospc_debug,
 #ifdef CONFIG_BTRFS_DEBUG
        Opt_fragment_data, Opt_fragment_metadata, Opt_fragment_all,
 #endif
@@ -333,58 +362,63 @@ enum {
 };
 
 static const match_table_t tokens = {
-       {Opt_degraded, "degraded"},
-       {Opt_subvol, "subvol=%s"},
-       {Opt_subvolid, "subvolid=%s"},
-       {Opt_device, "device=%s"},
-       {Opt_nodatasum, "nodatasum"},
-       {Opt_datasum, "datasum"},
-       {Opt_nodatacow, "nodatacow"},
-       {Opt_datacow, "datacow"},
-       {Opt_nobarrier, "nobarrier"},
-       {Opt_barrier, "barrier"},
-       {Opt_max_inline, "max_inline=%s"},
-       {Opt_alloc_start, "alloc_start=%s"},
-       {Opt_thread_pool, "thread_pool=%d"},
+       {Opt_acl, "acl"},
+       {Opt_noacl, "noacl"},
+       {Opt_clear_cache, "clear_cache"},
+       {Opt_commit_interval, "commit=%u"},
        {Opt_compress, "compress"},
        {Opt_compress_type, "compress=%s"},
        {Opt_compress_force, "compress-force"},
        {Opt_compress_force_type, "compress-force=%s"},
-       {Opt_ssd, "ssd"},
-       {Opt_ssd_spread, "ssd_spread"},
-       {Opt_nossd, "nossd"},
-       {Opt_acl, "acl"},
-       {Opt_noacl, "noacl"},
-       {Opt_notreelog, "notreelog"},
-       {Opt_treelog, "treelog"},
-       {Opt_nologreplay, "nologreplay"},
-       {Opt_norecovery, "norecovery"},
+       {Opt_degraded, "degraded"},
+       {Opt_device, "device=%s"},
+       {Opt_fatal_errors, "fatal_errors=%s"},
        {Opt_flushoncommit, "flushoncommit"},
        {Opt_noflushoncommit, "noflushoncommit"},
-       {Opt_ratio, "metadata_ratio=%d"},
+       {Opt_inode_cache, "inode_cache"},
+       {Opt_noinode_cache, "noinode_cache"},
+       {Opt_max_inline, "max_inline=%s"},
+       {Opt_barrier, "barrier"},
+       {Opt_nobarrier, "nobarrier"},
+       {Opt_datacow, "datacow"},
+       {Opt_nodatacow, "nodatacow"},
+       {Opt_datasum, "datasum"},
+       {Opt_nodatasum, "nodatasum"},
+       {Opt_defrag, "autodefrag"},
+       {Opt_nodefrag, "noautodefrag"},
        {Opt_discard, "discard"},
        {Opt_nodiscard, "nodiscard"},
+       {Opt_nologreplay, "nologreplay"},
+       {Opt_norecovery, "norecovery"},
+       {Opt_ratio, "metadata_ratio=%u"},
+       {Opt_rescan_uuid_tree, "rescan_uuid_tree"},
+       {Opt_skip_balance, "skip_balance"},
        {Opt_space_cache, "space_cache"},
+       {Opt_no_space_cache, "nospace_cache"},
        {Opt_space_cache_version, "space_cache=%s"},
-       {Opt_clear_cache, "clear_cache"},
+       {Opt_ssd, "ssd"},
+       {Opt_nossd, "nossd"},
+       {Opt_ssd_spread, "ssd_spread"},
+       {Opt_nossd_spread, "nossd_spread"},
+       {Opt_subvol, "subvol=%s"},
+       {Opt_subvolid, "subvolid=%s"},
+       {Opt_thread_pool, "thread_pool=%u"},
+       {Opt_treelog, "treelog"},
+       {Opt_notreelog, "notreelog"},
+       {Opt_usebackuproot, "usebackuproot"},
        {Opt_user_subvol_rm_allowed, "user_subvol_rm_allowed"},
-       {Opt_enospc_debug, "enospc_debug"},
-       {Opt_noenospc_debug, "noenospc_debug"},
+
+       /* Deprecated options */
+       {Opt_alloc_start, "alloc_start=%s"},
+       {Opt_recovery, "recovery"},
        {Opt_subvolrootid, "subvolrootid=%d"},
-       {Opt_defrag, "autodefrag"},
-       {Opt_nodefrag, "noautodefrag"},
-       {Opt_inode_cache, "inode_cache"},
-       {Opt_noinode_cache, "noinode_cache"},
-       {Opt_no_space_cache, "nospace_cache"},
-       {Opt_recovery, "recovery"}, /* deprecated */
-       {Opt_usebackuproot, "usebackuproot"},
-       {Opt_skip_balance, "skip_balance"},
+
+       /* Debugging options */
        {Opt_check_integrity, "check_int"},
        {Opt_check_integrity_including_extent_data, "check_int_data"},
-       {Opt_check_integrity_print_mask, "check_int_print_mask=%d"},
-       {Opt_rescan_uuid_tree, "rescan_uuid_tree"},
-       {Opt_fatal_errors, "fatal_errors=%s"},
-       {Opt_commit_interval, "commit=%d"},
+       {Opt_check_integrity_print_mask, "check_int_print_mask=%u"},
+       {Opt_enospc_debug, "enospc_debug"},
+       {Opt_noenospc_debug, "noenospc_debug"},
 #ifdef CONFIG_BTRFS_DEBUG
        {Opt_fragment_data, "fragment=data"},
        {Opt_fragment_metadata, "fragment=metadata"},
@@ -579,6 +613,8 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                        btrfs_set_opt(info->mount_opt, NOSSD);
                        btrfs_clear_and_info(info, SSD,
                                             "not using ssd optimizations");
+                       /* Fallthrough */
+               case Opt_nossd_spread:
                        btrfs_clear_and_info(info, SSD_SPREAD,
                                             "not using spread ssd allocation scheme");
                        break;
@@ -594,12 +630,11 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                        ret = match_int(&args[0], &intarg);
                        if (ret) {
                                goto out;
-                       } else if (intarg > 0) {
-                               info->thread_pool_size = intarg;
-                       } else {
+                       } else if (intarg == 0) {
                                ret = -EINVAL;
                                goto out;
                        }
+                       info->thread_pool_size = intarg;
                        break;
                case Opt_max_inline:
                        num = match_strdup(&args[0]);
@@ -658,16 +693,11 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                        break;
                case Opt_ratio:
                        ret = match_int(&args[0], &intarg);
-                       if (ret) {
+                       if (ret)
                                goto out;
-                       } else if (intarg >= 0) {
-                               info->metadata_ratio = intarg;
-                               btrfs_info(info, "metadata ratio %d",
-                                          info->metadata_ratio);
-                       } else {
-                               ret = -EINVAL;
-                               goto out;
-                       }
+                       info->metadata_ratio = intarg;
+                       btrfs_info(info, "metadata ratio %u",
+                                  info->metadata_ratio);
                        break;
                case Opt_discard:
                        btrfs_set_and_info(info, DISCARD,
@@ -762,17 +792,11 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                        break;
                case Opt_check_integrity_print_mask:
                        ret = match_int(&args[0], &intarg);
-                       if (ret) {
+                       if (ret)
                                goto out;
-                       } else if (intarg >= 0) {
-                               info->check_integrity_print_mask = intarg;
-                               btrfs_info(info,
-                                          "check_integrity_print_mask 0x%x",
-                                          info->check_integrity_print_mask);
-                       } else {
-                               ret = -EINVAL;
-                               goto out;
-                       }
+                       info->check_integrity_print_mask = intarg;
+                       btrfs_info(info, "check_integrity_print_mask 0x%x",
+                                  info->check_integrity_print_mask);
                        break;
 #else
                case Opt_check_integrity_including_extent_data:
@@ -798,24 +822,18 @@ int btrfs_parse_options(struct btrfs_fs_info *info, char *options,
                case Opt_commit_interval:
                        intarg = 0;
                        ret = match_int(&args[0], &intarg);
-                       if (ret < 0) {
-                               btrfs_err(info, "invalid commit interval");
-                               ret = -EINVAL;
+                       if (ret)
                                goto out;
-                       }
-                       if (intarg > 0) {
-                               if (intarg > 300) {
-                                       btrfs_warn(info,
-                                               "excessive commit interval %d",
-                                               intarg);
-                               }
-                               info->commit_interval = intarg;
-                       } else {
+                       if (intarg == 0) {
                                btrfs_info(info,
-                                          "using default commit interval %ds",
+                                          "using default commit interval %us",
                                           BTRFS_DEFAULT_COMMIT_INTERVAL);
-                               info->commit_interval = BTRFS_DEFAULT_COMMIT_INTERVAL;
+                               intarg = BTRFS_DEFAULT_COMMIT_INTERVAL;
+                       } else if (intarg > 300) {
+                               btrfs_warn(info, "excessive commit interval %d",
+                                          intarg);
                        }
+                       info->commit_interval = intarg;
                        break;
 #ifdef CONFIG_BTRFS_DEBUG
                case Opt_fragment_all:
@@ -932,8 +950,8 @@ static int btrfs_parse_subvol_options(const char *options, fmode_t flags,
 {
        substring_t args[MAX_OPT_ARGS];
        char *opts, *orig, *p;
-       char *num = NULL;
        int error = 0;
+       u64 subvolid;
 
        if (!options)
                return 0;
@@ -963,18 +981,15 @@ static int btrfs_parse_subvol_options(const char *options, fmode_t flags,
                        }
                        break;
                case Opt_subvolid:
-                       num = match_strdup(&args[0]);
-                       if (num) {
-                               *subvol_objectid = memparse(num, NULL);
-                               kfree(num);
-                               /* we want the original fs_tree */
-                               if (!*subvol_objectid)
-                                       *subvol_objectid =
-                                               BTRFS_FS_TREE_OBJECTID;
-                       } else {
-                               error = -EINVAL;
+                       error = match_u64(&args[0], &subvolid);
+                       if (error)
                                goto out;
-                       }
+
+                       /* we want the original fs_tree */
+                       if (subvolid == 0)
+                               subvolid = BTRFS_FS_TREE_OBJECTID;
+
+                       *subvol_objectid = subvolid;
                        break;
                case Opt_subvolrootid:
                        pr_warn("BTRFS: 'subvolrootid' mount option is deprecated and has no effect\n");
@@ -1284,7 +1299,7 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
                seq_printf(seq, ",max_inline=%llu", info->max_inline);
        if (info->thread_pool_size !=  min_t(unsigned long,
                                             num_online_cpus() + 2, 8))
-               seq_printf(seq, ",thread_pool=%d", info->thread_pool_size);
+               seq_printf(seq, ",thread_pool=%u", info->thread_pool_size);
        if (btrfs_test_opt(info, COMPRESS)) {
                compress_type = btrfs_compress_type2str(info->compress_type);
                if (btrfs_test_opt(info, FORCE_COMPRESS))
@@ -1340,12 +1355,11 @@ static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
                                info->check_integrity_print_mask);
 #endif
        if (info->metadata_ratio)
-               seq_printf(seq, ",metadata_ratio=%d",
-                               info->metadata_ratio);
+               seq_printf(seq, ",metadata_ratio=%u", info->metadata_ratio);
        if (btrfs_test_opt(info, PANIC_ON_FATAL_ERROR))
                seq_puts(seq, ",fatal_errors=panic");
        if (info->commit_interval != BTRFS_DEFAULT_COMMIT_INTERVAL)
-               seq_printf(seq, ",commit=%d", info->commit_interval);
+               seq_printf(seq, ",commit=%u", info->commit_interval);
 #ifdef CONFIG_BTRFS_DEBUG
        if (btrfs_test_opt(info, FRAGMENT_DATA))
                seq_puts(seq, ",fragment=data");
@@ -1690,7 +1704,7 @@ out:
 }
 
 static void btrfs_resize_thread_pool(struct btrfs_fs_info *fs_info,
-                                    int new_pool_size, int old_pool_size)
+                                    u32 new_pool_size, u32 old_pool_size)
 {
        if (new_pool_size == old_pool_size)
                return;
@@ -1758,8 +1772,8 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
        unsigned long old_opts = fs_info->mount_opt;
        unsigned long old_compress_type = fs_info->compress_type;
        u64 old_max_inline = fs_info->max_inline;
-       int old_thread_pool_size = fs_info->thread_pool_size;
-       unsigned int old_metadata_ratio = fs_info->metadata_ratio;
+       u32 old_thread_pool_size = fs_info->thread_pool_size;
+       u32 old_metadata_ratio = fs_info->metadata_ratio;
        int ret;
 
        sync_filesystem(sb);
@@ -2290,11 +2304,18 @@ static int btrfs_show_devname(struct seq_file *m, struct dentry *root)
        struct list_head *head;
        struct rcu_string *name;
 
-       mutex_lock(&fs_info->fs_devices->device_list_mutex);
+       /*
+        * Lightweight locking of the devices. We should not need
+        * device_list_mutex here as we only read the device data and the list
+        * is protected by RCU.  Even if a device is deleted during the list
+        * traversals, we'll get valid data, the freeing callback will wait at
+        * least until until the rcu_read_unlock.
+        */
+       rcu_read_lock();
        cur_devices = fs_info->fs_devices;
        while (cur_devices) {
                head = &cur_devices->devices;
-               list_for_each_entry(dev, head, dev_list) {
+               list_for_each_entry_rcu(dev, head, dev_list) {
                        if (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state))
                                continue;
                        if (!dev->name)
@@ -2306,14 +2327,12 @@ static int btrfs_show_devname(struct seq_file *m, struct dentry *root)
        }
 
        if (first_dev) {
-               rcu_read_lock();
                name = rcu_dereference(first_dev->name);
                seq_escape(m, name->str, " \t\n\\");
-               rcu_read_unlock();
        } else {
                WARN_ON(1);
        }
-       mutex_unlock(&fs_info->fs_devices->device_list_mutex);
+       rcu_read_unlock();
        return 0;
 }
 
@@ -2355,7 +2374,7 @@ static int __init btrfs_interface_init(void)
        return misc_register(&btrfs_misc);
 }
 
-static void btrfs_interface_exit(void)
+static __cold void btrfs_interface_exit(void)
 {
        misc_deregister(&btrfs_misc);
 }
@@ -2376,22 +2395,18 @@ static void __init btrfs_print_mod_info(void)
                        ", ref-verify=on"
 #endif
                        "\n",
-                       btrfs_crc32c_impl());
+                       crc32c_impl());
 }
 
 static int __init init_btrfs_fs(void)
 {
        int err;
 
-       err = btrfs_hash_init();
-       if (err)
-               return err;
-
        btrfs_props_init();
 
        err = btrfs_init_sysfs();
        if (err)
-               goto free_hash;
+               return err;
 
        btrfs_init_compress();
 
@@ -2472,8 +2487,7 @@ free_cachep:
 free_compress:
        btrfs_exit_compress();
        btrfs_exit_sysfs();
-free_hash:
-       btrfs_hash_exit();
+
        return err;
 }
 
@@ -2493,7 +2507,6 @@ static void __exit exit_btrfs_fs(void)
        btrfs_exit_sysfs();
        btrfs_cleanup_fs_uuids();
        btrfs_exit_compress();
-       btrfs_hash_exit();
 }
 
 late_initcall(init_btrfs_fs);