Merge branches 'irq-urgent-for-linus' and 'timers-urgent-for-linus' of git://git...
[firefly-linux-kernel-4.4.55.git] / fs / btrfs / volumes.c
index 6fc735869c186c35fb79fa66decc7d3519ed2e93..a6df8fdc1312ce78e97f9f90037ff5b236a58a92 100644 (file)
 #include "dev-replace.h"
 #include "sysfs.h"
 
+const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
+       [BTRFS_RAID_RAID10] = {
+               .sub_stripes    = 2,
+               .dev_stripes    = 1,
+               .devs_max       = 0,    /* 0 == as many as possible */
+               .devs_min       = 4,
+               .tolerated_failures = 1,
+               .devs_increment = 2,
+               .ncopies        = 2,
+       },
+       [BTRFS_RAID_RAID1] = {
+               .sub_stripes    = 1,
+               .dev_stripes    = 1,
+               .devs_max       = 2,
+               .devs_min       = 2,
+               .tolerated_failures = 1,
+               .devs_increment = 2,
+               .ncopies        = 2,
+       },
+       [BTRFS_RAID_DUP] = {
+               .sub_stripes    = 1,
+               .dev_stripes    = 2,
+               .devs_max       = 1,
+               .devs_min       = 1,
+               .tolerated_failures = 0,
+               .devs_increment = 1,
+               .ncopies        = 2,
+       },
+       [BTRFS_RAID_RAID0] = {
+               .sub_stripes    = 1,
+               .dev_stripes    = 1,
+               .devs_max       = 0,
+               .devs_min       = 2,
+               .tolerated_failures = 0,
+               .devs_increment = 1,
+               .ncopies        = 1,
+       },
+       [BTRFS_RAID_SINGLE] = {
+               .sub_stripes    = 1,
+               .dev_stripes    = 1,
+               .devs_max       = 1,
+               .devs_min       = 1,
+               .tolerated_failures = 0,
+               .devs_increment = 1,
+               .ncopies        = 1,
+       },
+       [BTRFS_RAID_RAID5] = {
+               .sub_stripes    = 1,
+               .dev_stripes    = 1,
+               .devs_max       = 0,
+               .devs_min       = 2,
+               .tolerated_failures = 1,
+               .devs_increment = 1,
+               .ncopies        = 2,
+       },
+       [BTRFS_RAID_RAID6] = {
+               .sub_stripes    = 1,
+               .dev_stripes    = 1,
+               .devs_max       = 0,
+               .devs_min       = 3,
+               .tolerated_failures = 2,
+               .devs_increment = 1,
+               .ncopies        = 3,
+       },
+};
+
+const u64 const btrfs_raid_group[BTRFS_NR_RAID_TYPES] = {
+       [BTRFS_RAID_RAID10] = BTRFS_BLOCK_GROUP_RAID10,
+       [BTRFS_RAID_RAID1]  = BTRFS_BLOCK_GROUP_RAID1,
+       [BTRFS_RAID_DUP]    = BTRFS_BLOCK_GROUP_DUP,
+       [BTRFS_RAID_RAID0]  = BTRFS_BLOCK_GROUP_RAID0,
+       [BTRFS_RAID_SINGLE] = 0,
+       [BTRFS_RAID_RAID5]  = BTRFS_BLOCK_GROUP_RAID5,
+       [BTRFS_RAID_RAID6]  = BTRFS_BLOCK_GROUP_RAID6,
+};
+
 static int init_first_rw_device(struct btrfs_trans_handle *trans,
                                struct btrfs_root *root,
                                struct btrfs_device *device);
@@ -156,8 +232,8 @@ static struct btrfs_device *__alloc_device(void)
        spin_lock_init(&dev->reada_lock);
        atomic_set(&dev->reada_in_flight, 0);
        atomic_set(&dev->dev_stats_ccnt, 0);
-       INIT_RADIX_TREE(&dev->reada_zones, GFP_NOFS & ~__GFP_WAIT);
-       INIT_RADIX_TREE(&dev->reada_extents, GFP_NOFS & ~__GFP_WAIT);
+       INIT_RADIX_TREE(&dev->reada_zones, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
+       INIT_RADIX_TREE(&dev->reada_extents, GFP_NOFS & ~__GFP_DIRECT_RECLAIM);
 
        return dev;
 }
@@ -198,7 +274,6 @@ btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder,
 
        if (IS_ERR(*bdev)) {
                ret = PTR_ERR(*bdev);
-               printk(KERN_INFO "BTRFS: open %s failed\n", device_path);
                goto error;
        }
 
@@ -211,8 +286,8 @@ btrfs_get_bdev_and_sb(const char *device_path, fmode_t flags, void *holder,
        }
        invalidate_bdev(*bdev);
        *bh = btrfs_read_dev_super(*bdev);
-       if (!*bh) {
-               ret = -EINVAL;
+       if (IS_ERR(*bh)) {
+               ret = PTR_ERR(*bh);
                blkdev_put(*bdev, flags);
                goto error;
        }
@@ -345,6 +420,9 @@ loop_lock:
                pending = pending->bi_next;
                cur->bi_next = NULL;
 
+               /*
+                * atomic_dec_return implies a barrier for waitqueue_active
+                */
                if (atomic_dec_return(&fs_info->nr_async_bios) < limit &&
                    waitqueue_active(&fs_info->async_submit_wait))
                        wake_up(&fs_info->async_submit_wait);
@@ -765,36 +843,7 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
 
        mutex_lock(&fs_devices->device_list_mutex);
        list_for_each_entry_safe(device, tmp, &fs_devices->devices, dev_list) {
-               struct btrfs_device *new_device;
-               struct rcu_string *name;
-
-               if (device->bdev)
-                       fs_devices->open_devices--;
-
-               if (device->writeable &&
-                   device->devid != BTRFS_DEV_REPLACE_DEVID) {
-                       list_del_init(&device->dev_alloc_list);
-                       fs_devices->rw_devices--;
-               }
-
-               if (device->missing)
-                       fs_devices->missing_devices--;
-
-               new_device = btrfs_alloc_device(NULL, &device->devid,
-                                               device->uuid);
-               BUG_ON(IS_ERR(new_device)); /* -ENOMEM */
-
-               /* Safe because we are under uuid_mutex */
-               if (device->name) {
-                       name = rcu_string_strdup(device->name->str, GFP_NOFS);
-                       BUG_ON(!name); /* -ENOMEM */
-                       rcu_assign_pointer(new_device->name, name);
-               }
-
-               list_replace_rcu(&device->dev_list, &new_device->dev_list);
-               new_device->fs_devices = device->fs_devices;
-
-               call_rcu(&device->rcu, free_device);
+               btrfs_close_one_device(device);
        }
        mutex_unlock(&fs_devices->device_list_mutex);
 
@@ -1402,7 +1451,7 @@ again:
                extent = btrfs_item_ptr(leaf, path->slots[0],
                                        struct btrfs_dev_extent);
        } else {
-               btrfs_error(root->fs_info, ret, "Slot search failed");
+               btrfs_std_error(root->fs_info, ret, "Slot search failed");
                goto out;
        }
 
@@ -1410,10 +1459,10 @@ again:
 
        ret = btrfs_del_item(trans, root, path);
        if (ret) {
-               btrfs_error(root->fs_info, ret,
+               btrfs_std_error(root->fs_info, ret,
                            "Failed to remove dev extent item");
        } else {
-               trans->transaction->have_free_bgs = 1;
+               set_bit(BTRFS_TRANS_HAVE_FREE_BGS, &trans->transaction->flags);
        }
 out:
        btrfs_free_path(path);
@@ -1801,7 +1850,7 @@ int btrfs_rm_device(struct btrfs_root *root, char *device_path)
        if (device->bdev) {
                device->fs_devices->open_devices--;
                /* remove sysfs entry */
-               btrfs_kobj_rm_device(root->fs_info->fs_devices, device);
+               btrfs_sysfs_rm_device_link(root->fs_info->fs_devices, device);
        }
 
        call_rcu(&device->rcu, free_device);
@@ -1924,7 +1973,8 @@ void btrfs_rm_dev_replace_remove_srcdev(struct btrfs_fs_info *fs_info,
        if (srcdev->writeable) {
                fs_devices->rw_devices--;
                /* zero out the old super if it is writable */
-               btrfs_scratch_superblock(srcdev);
+               btrfs_scratch_superblocks(srcdev->bdev,
+                                       rcu_str_deref(srcdev->name));
        }
 
        if (srcdev->bdev)
@@ -1971,10 +2021,11 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
        WARN_ON(!tgtdev);
        mutex_lock(&fs_info->fs_devices->device_list_mutex);
 
-       btrfs_kobj_rm_device(fs_info->fs_devices, tgtdev);
+       btrfs_sysfs_rm_device_link(fs_info->fs_devices, tgtdev);
 
        if (tgtdev->bdev) {
-               btrfs_scratch_superblock(tgtdev);
+               btrfs_scratch_superblocks(tgtdev->bdev,
+                                       rcu_str_deref(tgtdev->name));
                fs_info->fs_devices->open_devices--;
        }
        fs_info->fs_devices->num_devices--;
@@ -2041,10 +2092,8 @@ int btrfs_find_device_missing_or_by_path(struct btrfs_root *root,
                        }
                }
 
-               if (!*device) {
-                       btrfs_err(root->fs_info, "no missing device found");
-                       return -ENOENT;
-               }
+               if (!*device)
+                       return BTRFS_ERROR_DEV_MISSING_NOT_FOUND;
 
                return 0;
        } else {
@@ -2309,7 +2358,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
                                    tmp + 1);
 
        /* add sysfs device entry */
-       btrfs_kobj_add_device(root->fs_info->fs_devices, device);
+       btrfs_sysfs_add_device_link(root->fs_info->fs_devices, device);
 
        /*
         * we've got more storage, clear any full flags on the space
@@ -2350,9 +2399,10 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
                 */
                snprintf(fsid_buf, BTRFS_UUID_UNPARSED_SIZE, "%pU",
                                                root->fs_info->fsid);
-               if (kobject_rename(&root->fs_info->fs_devices->super_kobj,
+               if (kobject_rename(&root->fs_info->fs_devices->fsid_kobj,
                                                                fsid_buf))
-                       pr_warn("BTRFS: sysfs: failed to create fsid for sprout\n");
+                       btrfs_warn(root->fs_info,
+                               "sysfs: failed to create fsid for sprout");
        }
 
        root->fs_info->num_tolerated_disk_barrier_failures =
@@ -2368,7 +2418,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
 
                ret = btrfs_relocate_sys_chunks(root);
                if (ret < 0)
-                       btrfs_error(root->fs_info, ret,
+                       btrfs_std_error(root->fs_info, ret,
                                    "Failed to relocate sys chunks after "
                                    "device initialization. This can be fixed "
                                    "using the \"btrfs balance\" command.");
@@ -2388,7 +2438,7 @@ int btrfs_init_new_device(struct btrfs_root *root, char *device_path)
 error_trans:
        btrfs_end_transaction(trans, root);
        rcu_string_free(device->name);
-       btrfs_kobj_rm_device(root->fs_info->fs_devices, device);
+       btrfs_sysfs_rm_device_link(root->fs_info->fs_devices, device);
        kfree(device);
 error:
        blkdev_put(bdev, FMODE_EXCL);
@@ -2613,7 +2663,7 @@ static int btrfs_free_chunk(struct btrfs_trans_handle *trans,
        if (ret < 0)
                goto out;
        else if (ret > 0) { /* Logic error or corruption */
-               btrfs_error(root->fs_info, -ENOENT,
+               btrfs_std_error(root->fs_info, -ENOENT,
                            "Failed lookup while freeing chunk.");
                ret = -ENOENT;
                goto out;
@@ -2621,7 +2671,7 @@ static int btrfs_free_chunk(struct btrfs_trans_handle *trans,
 
        ret = btrfs_del_item(trans, root, path);
        if (ret < 0)
-               btrfs_error(root->fs_info, ret,
+               btrfs_std_error(root->fs_info, ret,
                            "Failed to delete chunk item.");
 out:
        btrfs_free_path(path);
@@ -2806,7 +2856,7 @@ static int btrfs_relocate_chunk(struct btrfs_root *root, u64 chunk_offset)
        trans = btrfs_start_transaction(root, 0);
        if (IS_ERR(trans)) {
                ret = PTR_ERR(trans);
-               btrfs_std_error(root->fs_info, ret);
+               btrfs_std_error(root->fs_info, ret, NULL);
                return ret;
        }
 
@@ -3009,16 +3059,19 @@ static void update_balance_args(struct btrfs_balance_control *bctl)
         * (albeit full) chunks.
         */
        if (!(bctl->data.flags & BTRFS_BALANCE_ARGS_USAGE) &&
+           !(bctl->data.flags & BTRFS_BALANCE_ARGS_USAGE_RANGE) &&
            !(bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT)) {
                bctl->data.flags |= BTRFS_BALANCE_ARGS_USAGE;
                bctl->data.usage = 90;
        }
        if (!(bctl->sys.flags & BTRFS_BALANCE_ARGS_USAGE) &&
+           !(bctl->sys.flags & BTRFS_BALANCE_ARGS_USAGE_RANGE) &&
            !(bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT)) {
                bctl->sys.flags |= BTRFS_BALANCE_ARGS_USAGE;
                bctl->sys.usage = 90;
        }
        if (!(bctl->meta.flags & BTRFS_BALANCE_ARGS_USAGE) &&
+           !(bctl->meta.flags & BTRFS_BALANCE_ARGS_USAGE_RANGE) &&
            !(bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT)) {
                bctl->meta.flags |= BTRFS_BALANCE_ARGS_USAGE;
                bctl->meta.usage = 90;
@@ -3072,6 +3125,39 @@ static int chunk_profiles_filter(u64 chunk_type,
 
 static int chunk_usage_filter(struct btrfs_fs_info *fs_info, u64 chunk_offset,
                              struct btrfs_balance_args *bargs)
+{
+       struct btrfs_block_group_cache *cache;
+       u64 chunk_used;
+       u64 user_thresh_min;
+       u64 user_thresh_max;
+       int ret = 1;
+
+       cache = btrfs_lookup_block_group(fs_info, chunk_offset);
+       chunk_used = btrfs_block_group_used(&cache->item);
+
+       if (bargs->usage_min == 0)
+               user_thresh_min = 0;
+       else
+               user_thresh_min = div_factor_fine(cache->key.offset,
+                                       bargs->usage_min);
+
+       if (bargs->usage_max == 0)
+               user_thresh_max = 1;
+       else if (bargs->usage_max > 100)
+               user_thresh_max = cache->key.offset;
+       else
+               user_thresh_max = div_factor_fine(cache->key.offset,
+                                       bargs->usage_max);
+
+       if (user_thresh_min <= chunk_used && chunk_used < user_thresh_max)
+               ret = 0;
+
+       btrfs_put_block_group(cache);
+       return ret;
+}
+
+static int chunk_usage_range_filter(struct btrfs_fs_info *fs_info,
+               u64 chunk_offset, struct btrfs_balance_args *bargs)
 {
        struct btrfs_block_group_cache *cache;
        u64 chunk_used, user_thresh;
@@ -3080,7 +3166,7 @@ static int chunk_usage_filter(struct btrfs_fs_info *fs_info, u64 chunk_offset,
        cache = btrfs_lookup_block_group(fs_info, chunk_offset);
        chunk_used = btrfs_block_group_used(&cache->item);
 
-       if (bargs->usage == 0)
+       if (bargs->usage_min == 0)
                user_thresh = 1;
        else if (bargs->usage > 100)
                user_thresh = cache->key.offset;
@@ -3170,6 +3256,19 @@ static int chunk_vrange_filter(struct extent_buffer *leaf,
        return 1;
 }
 
+static int chunk_stripes_range_filter(struct extent_buffer *leaf,
+                              struct btrfs_chunk *chunk,
+                              struct btrfs_balance_args *bargs)
+{
+       int num_stripes = btrfs_chunk_num_stripes(leaf, chunk);
+
+       if (bargs->stripes_min <= num_stripes
+                       && num_stripes <= bargs->stripes_max)
+               return 0;
+
+       return 1;
+}
+
 static int chunk_soft_convert_filter(u64 chunk_type,
                                     struct btrfs_balance_args *bargs)
 {
@@ -3216,6 +3315,9 @@ static int should_balance_chunk(struct btrfs_root *root,
        if ((bargs->flags & BTRFS_BALANCE_ARGS_USAGE) &&
            chunk_usage_filter(bctl->fs_info, chunk_offset, bargs)) {
                return 0;
+       } else if ((bargs->flags & BTRFS_BALANCE_ARGS_USAGE_RANGE) &&
+           chunk_usage_range_filter(bctl->fs_info, chunk_offset, bargs)) {
+               return 0;
        }
 
        /* devid filter */
@@ -3236,6 +3338,12 @@ static int should_balance_chunk(struct btrfs_root *root,
                return 0;
        }
 
+       /* stripes filter */
+       if ((bargs->flags & BTRFS_BALANCE_ARGS_STRIPES_RANGE) &&
+           chunk_stripes_range_filter(leaf, chunk, bargs)) {
+               return 0;
+       }
+
        /* soft profile changing mode */
        if ((bargs->flags & BTRFS_BALANCE_ARGS_SOFT) &&
            chunk_soft_convert_filter(chunk_type, bargs)) {
@@ -3250,6 +3358,16 @@ static int should_balance_chunk(struct btrfs_root *root,
                        return 0;
                else
                        bargs->limit--;
+       } else if ((bargs->flags & BTRFS_BALANCE_ARGS_LIMIT_RANGE)) {
+               /*
+                * Same logic as the 'limit' filter; the minimum cannot be
+                * determined here because we do not have the global informatoin
+                * about the count of all chunks that satisfy the filters.
+                */
+               if (bargs->limit_max == 0)
+                       return 0;
+               else
+                       bargs->limit_max--;
        }
 
        return 1;
@@ -3264,6 +3382,7 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
        struct btrfs_device *device;
        u64 old_size;
        u64 size_to_free;
+       u64 chunk_type;
        struct btrfs_chunk *chunk;
        struct btrfs_path *path;
        struct btrfs_key key;
@@ -3274,9 +3393,14 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
        int ret;
        int enospc_errors = 0;
        bool counting = true;
+       /* The single value limit and min/max limits use the same bytes in the */
        u64 limit_data = bctl->data.limit;
        u64 limit_meta = bctl->meta.limit;
        u64 limit_sys = bctl->sys.limit;
+       u32 count_data = 0;
+       u32 count_meta = 0;
+       u32 count_sys = 0;
+       int chunk_reserved = 0;
 
        /* step one make some room on all the devices */
        devices = &fs_info->fs_devices->devices;
@@ -3317,6 +3441,10 @@ static int __btrfs_balance(struct btrfs_fs_info *fs_info)
        spin_unlock(&fs_info->balance_lock);
 again:
        if (!counting) {
+               /*
+                * The single value limit and min/max limits use the same bytes
+                * in the
+                */
                bctl->data.limit = limit_data;
                bctl->meta.limit = limit_meta;
                bctl->sys.limit = limit_sys;
@@ -3364,6 +3492,7 @@ again:
                }
 
                chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk);
+               chunk_type = btrfs_chunk_type(leaf, chunk);
 
                if (!counting) {
                        spin_lock(&fs_info->balance_lock);
@@ -3373,6 +3502,7 @@ again:
 
                ret = should_balance_chunk(chunk_root, leaf, chunk,
                                           found_key.offset);
+
                btrfs_release_path(path);
                if (!ret) {
                        mutex_unlock(&fs_info->delete_unused_bgs_mutex);
@@ -3384,9 +3514,50 @@ again:
                        spin_lock(&fs_info->balance_lock);
                        bctl->stat.expected++;
                        spin_unlock(&fs_info->balance_lock);
+
+                       if (chunk_type & BTRFS_BLOCK_GROUP_DATA)
+                               count_data++;
+                       else if (chunk_type & BTRFS_BLOCK_GROUP_SYSTEM)
+                               count_sys++;
+                       else if (chunk_type & BTRFS_BLOCK_GROUP_METADATA)
+                               count_meta++;
+
                        goto loop;
                }
 
+               /*
+                * Apply limit_min filter, no need to check if the LIMITS
+                * filter is used, limit_min is 0 by default
+                */
+               if (((chunk_type & BTRFS_BLOCK_GROUP_DATA) &&
+                                       count_data < bctl->data.limit_min)
+                               || ((chunk_type & BTRFS_BLOCK_GROUP_METADATA) &&
+                                       count_meta < bctl->meta.limit_min)
+                               || ((chunk_type & BTRFS_BLOCK_GROUP_SYSTEM) &&
+                                       count_sys < bctl->sys.limit_min)) {
+                       mutex_unlock(&fs_info->delete_unused_bgs_mutex);
+                       goto loop;
+               }
+
+               if ((chunk_type & BTRFS_BLOCK_GROUP_DATA) && !chunk_reserved) {
+                       trans = btrfs_start_transaction(chunk_root, 0);
+                       if (IS_ERR(trans)) {
+                               mutex_unlock(&fs_info->delete_unused_bgs_mutex);
+                               ret = PTR_ERR(trans);
+                               goto error;
+                       }
+
+                       ret = btrfs_force_chunk_alloc(trans, chunk_root,
+                                                     BTRFS_BLOCK_GROUP_DATA);
+                       if (ret < 0) {
+                               mutex_unlock(&fs_info->delete_unused_bgs_mutex);
+                               goto error;
+                       }
+
+                       btrfs_end_transaction(trans, chunk_root);
+                       chunk_reserved = 1;
+               }
+
                ret = btrfs_relocate_chunk(chunk_root,
                                           found_key.offset);
                mutex_unlock(&fs_info->delete_unused_bgs_mutex);
@@ -3461,11 +3632,20 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info)
        unset_balance_control(fs_info);
        ret = del_balance_item(fs_info->tree_root);
        if (ret)
-               btrfs_std_error(fs_info, ret);
+               btrfs_std_error(fs_info, ret, NULL);
 
        atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
 }
 
+/* Non-zero return value signifies invalidity */
+static inline int validate_convert_profile(struct btrfs_balance_args *bctl_arg,
+               u64 allowed)
+{
+       return ((bctl_arg->flags & BTRFS_BALANCE_ARGS_CONVERT) &&
+               (!alloc_profile_is_valid(bctl_arg->target, 1) ||
+                (bctl_arg->target & ~allowed)));
+}
+
 /*
  * Should be called with both balance and volume mutexes held
  */
@@ -3523,27 +3703,21 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
        if (num_devices > 3)
                allowed |= (BTRFS_BLOCK_GROUP_RAID10 |
                            BTRFS_BLOCK_GROUP_RAID6);
-       if ((bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
-           (!alloc_profile_is_valid(bctl->data.target, 1) ||
-            (bctl->data.target & ~allowed))) {
+       if (validate_convert_profile(&bctl->data, allowed)) {
                btrfs_err(fs_info, "unable to start balance with target "
                           "data profile %llu",
                       bctl->data.target);
                ret = -EINVAL;
                goto out;
        }
-       if ((bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
-           (!alloc_profile_is_valid(bctl->meta.target, 1) ||
-            (bctl->meta.target & ~allowed))) {
+       if (validate_convert_profile(&bctl->meta, allowed)) {
                btrfs_err(fs_info,
                           "unable to start balance with target metadata profile %llu",
                       bctl->meta.target);
                ret = -EINVAL;
                goto out;
        }
-       if ((bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) &&
-           (!alloc_profile_is_valid(bctl->sys.target, 1) ||
-            (bctl->sys.target & ~allowed))) {
+       if (validate_convert_profile(&bctl->sys, allowed)) {
                btrfs_err(fs_info,
                           "unable to start balance with target system profile %llu",
                       bctl->sys.target);
@@ -4285,65 +4459,6 @@ static int btrfs_cmp_device_info(const void *a, const void *b)
        return 0;
 }
 
-static const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
-       [BTRFS_RAID_RAID10] = {
-               .sub_stripes    = 2,
-               .dev_stripes    = 1,
-               .devs_max       = 0,    /* 0 == as many as possible */
-               .devs_min       = 4,
-               .devs_increment = 2,
-               .ncopies        = 2,
-       },
-       [BTRFS_RAID_RAID1] = {
-               .sub_stripes    = 1,
-               .dev_stripes    = 1,
-               .devs_max       = 2,
-               .devs_min       = 2,
-               .devs_increment = 2,
-               .ncopies        = 2,
-       },
-       [BTRFS_RAID_DUP] = {
-               .sub_stripes    = 1,
-               .dev_stripes    = 2,
-               .devs_max       = 1,
-               .devs_min       = 1,
-               .devs_increment = 1,
-               .ncopies        = 2,
-       },
-       [BTRFS_RAID_RAID0] = {
-               .sub_stripes    = 1,
-               .dev_stripes    = 1,
-               .devs_max       = 0,
-               .devs_min       = 2,
-               .devs_increment = 1,
-               .ncopies        = 1,
-       },
-       [BTRFS_RAID_SINGLE] = {
-               .sub_stripes    = 1,
-               .dev_stripes    = 1,
-               .devs_max       = 1,
-               .devs_min       = 1,
-               .devs_increment = 1,
-               .ncopies        = 1,
-       },
-       [BTRFS_RAID_RAID5] = {
-               .sub_stripes    = 1,
-               .dev_stripes    = 1,
-               .devs_max       = 0,
-               .devs_min       = 2,
-               .devs_increment = 1,
-               .ncopies        = 2,
-       },
-       [BTRFS_RAID_RAID6] = {
-               .sub_stripes    = 1,
-               .dev_stripes    = 1,
-               .devs_max       = 0,
-               .devs_min       = 3,
-               .devs_increment = 1,
-               .ncopies        = 3,
-       },
-};
-
 static u32 find_raid56_stripe_len(u32 data_devices, u32 dev_stripe_target)
 {
        /* TODO allow them to set a preferred stripe size */
@@ -6594,8 +6709,8 @@ static int update_dev_stat_item(struct btrfs_trans_handle *trans,
        BUG_ON(!path);
        ret = btrfs_search_slot(trans, dev_root, &key, path, -1, 1);
        if (ret < 0) {
-               printk_in_rcu(KERN_WARNING "BTRFS: "
-                       "error %d while searching for dev_stats item for device %s!\n",
+               btrfs_warn_in_rcu(dev_root->fs_info,
+                       "error %d while searching for dev_stats item for device %s",
                              ret, rcu_str_deref(device->name));
                goto out;
        }
@@ -6605,8 +6720,8 @@ static int update_dev_stat_item(struct btrfs_trans_handle *trans,
                /* need to delete old one and insert a new one */
                ret = btrfs_del_item(trans, dev_root, path);
                if (ret != 0) {
-                       printk_in_rcu(KERN_WARNING "BTRFS: "
-                               "delete too small dev_stats item for device %s failed %d!\n",
+                       btrfs_warn_in_rcu(dev_root->fs_info,
+                               "delete too small dev_stats item for device %s failed %d",
                                      rcu_str_deref(device->name), ret);
                        goto out;
                }
@@ -6619,9 +6734,9 @@ static int update_dev_stat_item(struct btrfs_trans_handle *trans,
                ret = btrfs_insert_empty_item(trans, dev_root, path,
                                              &key, sizeof(*ptr));
                if (ret < 0) {
-                       printk_in_rcu(KERN_WARNING "BTRFS: "
-                                         "insert dev_stats item for device %s failed %d!\n",
-                                     rcu_str_deref(device->name), ret);
+                       btrfs_warn_in_rcu(dev_root->fs_info,
+                               "insert dev_stats item for device %s failed %d",
+                               rcu_str_deref(device->name), ret);
                        goto out;
                }
        }
@@ -6675,8 +6790,8 @@ static void btrfs_dev_stat_print_on_error(struct btrfs_device *dev)
 {
        if (!dev->dev_stats_valid)
                return;
-       printk_ratelimited_in_rcu(KERN_ERR "BTRFS: "
-                          "bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u\n",
+       btrfs_err_rl_in_rcu(dev->dev_root->fs_info,
+               "bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u",
                           rcu_str_deref(dev->name),
                           btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_WRITE_ERRS),
                           btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_READ_ERRS),
@@ -6695,8 +6810,8 @@ static void btrfs_dev_stat_print_on_load(struct btrfs_device *dev)
        if (i == BTRFS_DEV_STAT_VALUES_MAX)
                return; /* all values == 0, suppress message */
 
-       printk_in_rcu(KERN_INFO "BTRFS: "
-                  "bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u\n",
+       btrfs_info_in_rcu(dev->dev_root->fs_info,
+               "bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u",
               rcu_str_deref(dev->name),
               btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_WRITE_ERRS),
               btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_READ_ERRS),
@@ -6740,22 +6855,34 @@ int btrfs_get_dev_stats(struct btrfs_root *root,
        return 0;
 }
 
-int btrfs_scratch_superblock(struct btrfs_device *device)
+void btrfs_scratch_superblocks(struct block_device *bdev, char *device_path)
 {
        struct buffer_head *bh;
        struct btrfs_super_block *disk_super;
+       int copy_num;
 
-       bh = btrfs_read_dev_super(device->bdev);
-       if (!bh)
-               return -EINVAL;
-       disk_super = (struct btrfs_super_block *)bh->b_data;
+       if (!bdev)
+               return;
 
-       memset(&disk_super->magic, 0, sizeof(disk_super->magic));
-       set_buffer_dirty(bh);
-       sync_dirty_buffer(bh);
-       brelse(bh);
+       for (copy_num = 0; copy_num < BTRFS_SUPER_MIRROR_MAX;
+               copy_num++) {
 
-       return 0;
+               if (btrfs_read_dev_one_super(bdev, copy_num, &bh))
+                       continue;
+
+               disk_super = (struct btrfs_super_block *)bh->b_data;
+
+               memset(&disk_super->magic, 0, sizeof(disk_super->magic));
+               set_buffer_dirty(bh);
+               sync_dirty_buffer(bh);
+               brelse(bh);
+       }
+
+       /* Notify udev that device has changed */
+       btrfs_kobject_uevent(bdev, KOBJ_CHANGE);
+
+       /* Update ctime/mtime for device path for libblkid */
+       update_dev_time(device_path);
 }
 
 /*
@@ -6823,3 +6950,38 @@ void btrfs_reset_fs_info_ptr(struct btrfs_fs_info *fs_info)
                fs_devices = fs_devices->seed;
        }
 }
+
+void btrfs_close_one_device(struct btrfs_device *device)
+{
+       struct btrfs_fs_devices *fs_devices = device->fs_devices;
+       struct btrfs_device *new_device;
+       struct rcu_string *name;
+
+       if (device->bdev)
+               fs_devices->open_devices--;
+
+       if (device->writeable &&
+           device->devid != BTRFS_DEV_REPLACE_DEVID) {
+               list_del_init(&device->dev_alloc_list);
+               fs_devices->rw_devices--;
+       }
+
+       if (device->missing)
+               fs_devices->missing_devices--;
+
+       new_device = btrfs_alloc_device(NULL, &device->devid,
+                                       device->uuid);
+       BUG_ON(IS_ERR(new_device)); /* -ENOMEM */
+
+       /* Safe because we are under uuid_mutex */
+       if (device->name) {
+               name = rcu_string_strdup(device->name->str, GFP_NOFS);
+               BUG_ON(!name); /* -ENOMEM */
+               rcu_assign_pointer(new_device->name, name);
+       }
+
+       list_replace_rcu(&device->dev_list, &new_device->dev_list);
+       new_device->fs_devices = device->fs_devices;
+
+       call_rcu(&device->rcu, free_device);
+}