btrfs: Remove superfluous check form btrfs_remove_chunk
[sfrench/cifs-2.6.git] / fs / btrfs / volumes.c
index e392ca5103cc7b54902b0d4d0fb2092baa01dab1..0839fae337f6fbc1bbdeee28b667d2021fe83e8e 100644 (file)
@@ -37,6 +37,7 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
                .tolerated_failures = 1,
                .devs_increment = 2,
                .ncopies        = 2,
+               .nparity        = 0,
                .raid_name      = "raid10",
                .bg_flag        = BTRFS_BLOCK_GROUP_RAID10,
                .mindev_error   = BTRFS_ERROR_DEV_RAID10_MIN_NOT_MET,
@@ -49,6 +50,7 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
                .tolerated_failures = 1,
                .devs_increment = 2,
                .ncopies        = 2,
+               .nparity        = 0,
                .raid_name      = "raid1",
                .bg_flag        = BTRFS_BLOCK_GROUP_RAID1,
                .mindev_error   = BTRFS_ERROR_DEV_RAID1_MIN_NOT_MET,
@@ -61,6 +63,7 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
                .tolerated_failures = 0,
                .devs_increment = 1,
                .ncopies        = 2,
+               .nparity        = 0,
                .raid_name      = "dup",
                .bg_flag        = BTRFS_BLOCK_GROUP_DUP,
                .mindev_error   = 0,
@@ -73,6 +76,7 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
                .tolerated_failures = 0,
                .devs_increment = 1,
                .ncopies        = 1,
+               .nparity        = 0,
                .raid_name      = "raid0",
                .bg_flag        = BTRFS_BLOCK_GROUP_RAID0,
                .mindev_error   = 0,
@@ -85,6 +89,7 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
                .tolerated_failures = 0,
                .devs_increment = 1,
                .ncopies        = 1,
+               .nparity        = 0,
                .raid_name      = "single",
                .bg_flag        = 0,
                .mindev_error   = 0,
@@ -96,7 +101,8 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
                .devs_min       = 2,
                .tolerated_failures = 1,
                .devs_increment = 1,
-               .ncopies        = 2,
+               .ncopies        = 1,
+               .nparity        = 1,
                .raid_name      = "raid5",
                .bg_flag        = BTRFS_BLOCK_GROUP_RAID5,
                .mindev_error   = BTRFS_ERROR_DEV_RAID5_MIN_NOT_MET,
@@ -108,7 +114,8 @@ const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = {
                .devs_min       = 3,
                .tolerated_failures = 2,
                .devs_increment = 1,
-               .ncopies        = 3,
+               .ncopies        = 1,
+               .nparity        = 2,
                .raid_name      = "raid6",
                .bg_flag        = BTRFS_BLOCK_GROUP_RAID6,
                .mindev_error   = BTRFS_ERROR_DEV_RAID6_MIN_NOT_MET,
@@ -850,6 +857,35 @@ static noinline struct btrfs_device *device_list_add(const char *path,
                        return ERR_PTR(-EEXIST);
                }
 
+               /*
+                * We are going to replace the device path for a given devid,
+                * make sure it's the same device if the device is mounted
+                */
+               if (device->bdev) {
+                       struct block_device *path_bdev;
+
+                       path_bdev = lookup_bdev(path);
+                       if (IS_ERR(path_bdev)) {
+                               mutex_unlock(&fs_devices->device_list_mutex);
+                               return ERR_CAST(path_bdev);
+                       }
+
+                       if (device->bdev != path_bdev) {
+                               bdput(path_bdev);
+                               mutex_unlock(&fs_devices->device_list_mutex);
+                               btrfs_warn_in_rcu(device->fs_info,
+                       "duplicate device fsid:devid for %pU:%llu old:%s new:%s",
+                                       disk_super->fsid, devid,
+                                       rcu_str_deref(device->name), path);
+                               return ERR_PTR(-EEXIST);
+                       }
+                       bdput(path_bdev);
+                       btrfs_info_in_rcu(device->fs_info,
+                               "device fsid %pU devid %llu moved old:%s new:%s",
+                               disk_super->fsid, devid,
+                               rcu_str_deref(device->name), path);
+               }
+
                name = rcu_string_strdup(path, GFP_NOFS);
                if (!name) {
                        mutex_unlock(&fs_devices->device_list_mutex);
@@ -2812,13 +2848,11 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans, u64 chunk_offset)
                        mutex_unlock(&fs_info->chunk_mutex);
                }
 
-               if (map->stripes[i].dev) {
-                       ret = btrfs_update_device(trans, map->stripes[i].dev);
-                       if (ret) {
-                               mutex_unlock(&fs_devices->device_list_mutex);
-                               btrfs_abort_transaction(trans, ret);
-                               goto out;
-                       }
+               ret = btrfs_update_device(trans, device);
+               if (ret) {
+                       mutex_unlock(&fs_devices->device_list_mutex);
+                       btrfs_abort_transaction(trans, ret);
+                       goto out;
                }
        }
        mutex_unlock(&fs_devices->device_list_mutex);
@@ -4628,11 +4662,13 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        int devs_min;           /* min devs needed */
        int devs_increment;     /* ndevs has to be a multiple of this */
        int ncopies;            /* how many copies to data has */
+       int nparity;            /* number of stripes worth of bytes to
+                                  store parity information */
        int ret;
        u64 max_stripe_size;
        u64 max_chunk_size;
        u64 stripe_size;
-       u64 num_bytes;
+       u64 chunk_size;
        int ndevs;
        int i;
        int j;
@@ -4654,6 +4690,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        devs_min = btrfs_raid_array[index].devs_min;
        devs_increment = btrfs_raid_array[index].devs_increment;
        ncopies = btrfs_raid_array[index].ncopies;
+       nparity = btrfs_raid_array[index].nparity;
 
        if (type & BTRFS_BLOCK_GROUP_DATA) {
                max_stripe_size = SZ_1G;
@@ -4783,30 +4820,22 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
         * this will have to be fixed for RAID1 and RAID10 over
         * more drives
         */
-       data_stripes = num_stripes / ncopies;
-
-       if (type & BTRFS_BLOCK_GROUP_RAID5)
-               data_stripes = num_stripes - 1;
-
-       if (type & BTRFS_BLOCK_GROUP_RAID6)
-               data_stripes = num_stripes - 2;
+       data_stripes = (num_stripes - nparity) / ncopies;
 
        /*
         * Use the number of data stripes to figure out how big this chunk
         * is really going to be in terms of logical address space,
-        * and compare that answer with the max chunk size
+        * and compare that answer with the max chunk size. If it's higher,
+        * we try to reduce stripe_size.
         */
        if (stripe_size * data_stripes > max_chunk_size) {
-               stripe_size = div_u64(max_chunk_size, data_stripes);
-
-               /* bump the answer up to a 16MB boundary */
-               stripe_size = round_up(stripe_size, SZ_16M);
-
                /*
-                * But don't go higher than the limits we found while searching
-                * for free extents
+                * Reduce stripe_size, round it up to a 16MB boundary again and
+                * then use it, unless it ends up being even bigger than the
+                * previous value we had already.
                 */
-               stripe_size = min(devices_info[ndevs - 1].max_avail,
+               stripe_size = min(round_up(div_u64(max_chunk_size,
+                                                  data_stripes), SZ_16M),
                                  stripe_size);
        }
 
@@ -4834,9 +4863,9 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        map->type = type;
        map->sub_stripes = sub_stripes;
 
-       num_bytes = stripe_size * data_stripes;
+       chunk_size = stripe_size * data_stripes;
 
-       trace_btrfs_chunk_alloc(info, map, start, num_bytes);
+       trace_btrfs_chunk_alloc(info, map, start, chunk_size);
 
        em = alloc_extent_map();
        if (!em) {
@@ -4847,7 +4876,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        set_bit(EXTENT_FLAG_FS_MAPPING, &em->flags);
        em->map_lookup = map;
        em->start = start;
-       em->len = num_bytes;
+       em->len = chunk_size;
        em->block_start = 0;
        em->block_len = em->len;
        em->orig_block_len = stripe_size;
@@ -4865,14 +4894,13 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        refcount_inc(&em->refs);
        write_unlock(&em_tree->lock);
 
-       ret = btrfs_make_block_group(trans, 0, type, start, num_bytes);
+       ret = btrfs_make_block_group(trans, 0, type, start, chunk_size);
        if (ret)
                goto error_del_extent;
 
-       for (i = 0; i < map->num_stripes; i++) {
-               num_bytes = map->stripes[i].dev->bytes_used + stripe_size;
-               btrfs_device_set_bytes_used(map->stripes[i].dev, num_bytes);
-       }
+       for (i = 0; i < map->num_stripes; i++)
+               btrfs_device_set_bytes_used(map->stripes[i].dev,
+                               map->stripes[i].dev->bytes_used + stripe_size);
 
        atomic64_sub(stripe_size * map->num_stripes, &info->free_chunk_space);
 
@@ -6109,12 +6137,6 @@ static noinline void btrfs_schedule_bio(struct btrfs_device *device,
        int should_queue = 1;
        struct btrfs_pending_bios *pending_bios;
 
-       if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state) ||
-           !device->bdev) {
-               bio_io_error(bio);
-               return;
-       }
-
        /* don't bother with additional async steps for reads, right now */
        if (bio_op(bio) == REQ_OP_READ) {
                btrfsic_submit_bio(bio);
@@ -6243,7 +6265,8 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
 
        for (dev_nr = 0; dev_nr < total_devs; dev_nr++) {
                dev = bbio->stripes[dev_nr].dev;
-               if (!dev || !dev->bdev ||
+               if (!dev || !dev->bdev || test_bit(BTRFS_DEV_STATE_MISSING,
+                                                  &dev->dev_state) ||
                    (bio_op(first_bio) == REQ_OP_WRITE &&
                    !test_bit(BTRFS_DEV_STATE_WRITEABLE, &dev->dev_state))) {
                        bbio_error(bbio, first_bio, logical);