btrfs: alloc_chunk: fix DUP stripe size handling
[sfrench/cifs-2.6.git] / fs / btrfs / volumes.c
index 34c889a66240f331fc1edafb49129b1897007c24..b2d05c6b1c5672a638ba8752333c10508e366885 100644 (file)
@@ -645,6 +645,7 @@ static void btrfs_free_stale_devices(const char *path,
                                btrfs_sysfs_remove_fsid(fs_devs);
                                list_del(&fs_devs->list);
                                free_fs_devices(fs_devs);
+                               break;
                        } else {
                                fs_devs->num_devices--;
                                list_del(&dev->dev_list);
@@ -728,12 +729,13 @@ error_brelse:
  * error pointer when failed
  */
 static noinline struct btrfs_device *device_list_add(const char *path,
-                          struct btrfs_super_block *disk_super, u64 devid)
+                          struct btrfs_super_block *disk_super)
 {
        struct btrfs_device *device;
        struct btrfs_fs_devices *fs_devices;
        struct rcu_string *name;
        u64 found_transid = btrfs_super_generation(disk_super);
+       u64 devid = btrfs_stack_device_id(&disk_super->dev_item);
 
        fs_devices = find_fsid(disk_super->fsid);
        if (!fs_devices) {
@@ -1181,7 +1183,6 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
        struct block_device *bdev;
        struct page *page;
        int ret = 0;
-       u64 devid;
        u64 bytenr;
 
        /*
@@ -1205,9 +1206,7 @@ int btrfs_scan_one_device(const char *path, fmode_t flags, void *holder,
                goto error_bdev_put;
        }
 
-       devid = btrfs_stack_device_id(&disk_super->dev_item);
-
-       device = device_list_add(path, disk_super, devid);
+       device = device_list_add(path, disk_super);
        if (IS_ERR(device))
                ret = PTR_ERR(device);
        else
@@ -4830,10 +4829,13 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        ndevs = min(ndevs, devs_max);
 
        /*
-        * the primary goal is to maximize the number of stripes, so use as many
-        * devices as possible, even if the stripes are not maximum sized.
+        * The primary goal is to maximize the number of stripes, so use as
+        * many devices as possible, even if the stripes are not maximum sized.
+        *
+        * The DUP profile stores more than one stripe per device, the
+        * max_avail is the total size so we have to adjust.
         */
-       stripe_size = devices_info[ndevs-1].max_avail;
+       stripe_size = div_u64(devices_info[ndevs - 1].max_avail, dev_stripes);
        num_stripes = ndevs * dev_stripes;
 
        /*
@@ -4868,8 +4870,6 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
                        stripe_size = devices_info[ndevs-1].max_avail;
        }
 
-       stripe_size = div_u64(stripe_size, dev_stripes);
-
        /* align to BTRFS_STRIPE_LEN */
        stripe_size = round_down(stripe_size, BTRFS_STRIPE_LEN);