There are a few places in btrfs where knowledge of the various
parameters of a replication type is needed. Factor this out into a
single function which can supply all the relevant information.

Signed-off-by: Hugo Mills <h...@carfax.org.uk>
---
 fs/btrfs/super.c   |   16 +++-----
 fs/btrfs/volumes.c |   97 +++++++++++++++++++++++++++++++++++-----------------
 fs/btrfs/volumes.h |   17 +++++++++
 3 files changed, 88 insertions(+), 42 deletions(-)

diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index d39a989..4341730 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -879,12 +879,12 @@ static int btrfs_calc_avail_data_space(struct btrfs_root 
*root, u64 *free_bytes)
        struct btrfs_device_info *devices_info;
        struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
        struct btrfs_device *device;
+       struct btrfs_replication_info repl_info;
        u64 skip_space;
        u64 type;
        u64 avail_space;
        u64 used_space;
        u64 min_stripe_size;
-       int min_stripes = 1;
        int i = 0, nr_devices;
        int ret;
 
@@ -898,12 +898,7 @@ static int btrfs_calc_avail_data_space(struct btrfs_root 
*root, u64 *free_bytes)
 
        /* calc min stripe number for data space alloction */
        type = btrfs_get_alloc_profile(root, 1);
-       if (type & BTRFS_BLOCK_GROUP_RAID0)
-               min_stripes = 2;
-       else if (type & BTRFS_BLOCK_GROUP_RAID1)
-               min_stripes = 2;
-       else if (type & BTRFS_BLOCK_GROUP_RAID10)
-               min_stripes = 4;
+       btrfs_get_replication_info(&repl_info, type);
 
        if (type & BTRFS_BLOCK_GROUP_DUP)
                min_stripe_size = 2 * BTRFS_STRIPE_LEN;
@@ -971,14 +966,15 @@ static int btrfs_calc_avail_data_space(struct btrfs_root 
*root, u64 *free_bytes)
 
        i = nr_devices - 1;
        avail_space = 0;
-       while (nr_devices >= min_stripes) {
+       while (nr_devices >= repl_info.devs_min) {
                if (devices_info[i].max_avail >= min_stripe_size) {
                        int j;
                        u64 alloc_size;
 
-                       avail_space += devices_info[i].max_avail * min_stripes;
+                       avail_space += devices_info[i].max_avail
+                         * repl_info.devs_min;
                        alloc_size = devices_info[i].max_avail;
-                       for (j = i + 1 - min_stripes; j <= i; j++)
+                       for (j = i + 1 - repl_info.devs_min; j <= i; j++)
                                devices_info[j].max_avail -= alloc_size;
                }
                i--;
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 230d100..9216ad85 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -141,6 +141,52 @@ static void requeue_list(struct btrfs_pending_bios 
*pending_bios,
                pending_bios->tail = tail;
 }
 
+void btrfs_get_replication_info(struct btrfs_replication_info *info,
+                                                               u64 type)
+{
+       info->sub_stripes = 1;
+       info->dev_stripes = 1;
+       info->devs_increment = 1;
+       info->num_copies = 1;
+       info->devs_max = 0;     /* 0 == as many as possible */
+       info->devs_min = 1;
+
+       if (type & BTRFS_BLOCK_GROUP_DUP) {
+               info->dev_stripes = 2;
+               info->num_copies = 2;
+               info->devs_max = 1;
+       } else if (type & BTRFS_BLOCK_GROUP_RAID0) {
+               info->devs_min = 2;
+       } else if (type & BTRFS_BLOCK_GROUP_RAID1) {
+               info->devs_increment = 2;
+               info->num_copies = 2;
+               info->devs_max = 2;
+               info->devs_min = 2;
+       } else if (type & BTRFS_BLOCK_GROUP_RAID10) {
+               info->sub_stripes = 2;
+               info->devs_increment = 2;
+               info->num_copies = 2;
+               info->devs_min = 4;
+       }
+
+       if (type & BTRFS_BLOCK_GROUP_DATA) {
+               info->max_stripe_size = 1024 * 1024 * 1024;
+               info->min_stripe_size = 64 * 1024 * 1024;
+               info->max_chunk_size = 10 * info->max_stripe_size;
+       } else if (type & BTRFS_BLOCK_GROUP_METADATA) {
+               info->max_stripe_size = 256 * 1024 * 1024;
+               info->min_stripe_size = 32 * 1024 * 1024;
+               info->max_chunk_size = info->max_stripe_size;
+       } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
+               info->max_stripe_size = 8 * 1024 * 1024;
+               info->min_stripe_size = 1 * 1024 * 1024;
+               info->max_chunk_size = 2 * info->max_stripe_size;
+       } else {
+               printk(KERN_ERR "Block group is of an unknown usage type: not 
data, metadata or system.\n");
+               BUG_ON(1);
+       }
+}
+
 /*
  * we try to collect pending bios for a device so we don't get a large
  * number of procs sending bios down to the same device.  This greatly
@@ -1248,6 +1294,7 @@ int btrfs_rm_device(struct btrfs_root *root, char 
*device_path)
        struct block_device *bdev;
        struct buffer_head *bh = NULL;
        struct btrfs_super_block *disk_super;
+       struct btrfs_replication_info repl_info;
        u64 all_avail;
        u64 devid;
        u64 num_devices;
@@ -1261,18 +1308,16 @@ int btrfs_rm_device(struct btrfs_root *root, char 
*device_path)
                root->fs_info->avail_system_alloc_bits |
                root->fs_info->avail_metadata_alloc_bits;
 
-       if ((all_avail & BTRFS_BLOCK_GROUP_RAID10) &&
-           root->fs_info->fs_devices->num_devices <= 4) {
-               printk(KERN_ERR "btrfs: unable to go below four devices "
-                      "on raid10\n");
-               ret = -EINVAL;
-               goto out;
-       }
+       btrfs_get_replication_info(&repl_info, all_avail);
 
-       if ((all_avail & BTRFS_BLOCK_GROUP_RAID1) &&
-           root->fs_info->fs_devices->num_devices <= 2) {
-               printk(KERN_ERR "btrfs: unable to go below two "
-                      "devices on raid1\n");
+       if (root->fs_info->fs_devices->num_devices <= repl_info.devs_min) {
+               if (all_avail & BTRFS_BLOCK_GROUP_RAID10) {
+                       printk(KERN_ERR "btrfs: unable to go below four devices 
"
+                                  "on raid10\n");
+               } else if (all_avail & BTRFS_BLOCK_GROUP_RAID1) {
+                       printk(KERN_ERR "btrfs: unable to go below two "
+                                  "devices on raid1\n");
+               }
                ret = -EINVAL;
                goto out;
        }
@@ -2037,6 +2082,7 @@ int balance_chunk_filter(struct btrfs_ioctl_balance_start 
*filter,
        struct extent_buffer *eb;
        struct btrfs_chunk *chunk;
        int i;
+       struct btrfs_replication_info replinfo;
 
        /* No filter defined, everything matches */
        if (!filter)
@@ -2050,6 +2096,8 @@ int balance_chunk_filter(struct btrfs_ioctl_balance_start 
*filter,
        chunk = btrfs_item_ptr(eb, path->slots[0],
                                                   struct btrfs_chunk);
 
+       btrfs_get_replication_info(&replinfo, btrfs_chunk_type(eb, chunk));
+
        if (filter->flags & BTRFS_BALANCE_FILTER_CHUNK_TYPE) {
                if ((btrfs_chunk_type(eb, chunk) & filter->chunk_type_mask)
                        != filter->chunk_type)
@@ -2492,34 +2540,19 @@ static u64 __btrfs_calc_stripe_size(struct 
btrfs_fs_devices *fs_devices,
                                    u64 proposed_size, u64 type,
                                    int num_stripes, int small_stripe)
 {
-       int min_stripe_size = 1 * 1024 * 1024;
+       struct btrfs_replication_info repl_info;
        u64 calc_size = proposed_size;
        u64 max_chunk_size = calc_size;
-       int ncopies = 1;
 
-       if (type & (BTRFS_BLOCK_GROUP_RAID1 |
-                   BTRFS_BLOCK_GROUP_DUP |
-                   BTRFS_BLOCK_GROUP_RAID10))
-               ncopies = 2;
-
-       if (type & BTRFS_BLOCK_GROUP_DATA) {
-               max_chunk_size = 10 * calc_size;
-               min_stripe_size = 64 * 1024 * 1024;
-       } else if (type & BTRFS_BLOCK_GROUP_METADATA) {
-               max_chunk_size = 256 * 1024 * 1024;
-               min_stripe_size = 32 * 1024 * 1024;
-       } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
-               calc_size = 8 * 1024 * 1024;
-               max_chunk_size = calc_size * 2;
-               min_stripe_size = 1 * 1024 * 1024;
-       }
+       btrfs_get_replication_info(&repl_info, type);
+       max_chunk_size = repl_info.max_chunk_size;
 
        /* we don't want a chunk larger than 10% of writeable space */
        max_chunk_size = min(div_factor(fs_devices->total_rw_bytes, 1),
                             max_chunk_size);
 
-       if (calc_size * num_stripes > max_chunk_size * ncopies) {
-               calc_size = max_chunk_size * ncopies;
+       if (calc_size * num_stripes > max_chunk_size * repl_info.num_copies) {
+               calc_size = max_chunk_size * repl_info.num_copies;
                do_div(calc_size, num_stripes);
                do_div(calc_size, BTRFS_STRIPE_LEN);
                calc_size *= BTRFS_STRIPE_LEN;
@@ -2527,7 +2560,7 @@ static u64 __btrfs_calc_stripe_size(struct 
btrfs_fs_devices *fs_devices,
 
        /* we don't want tiny stripes */
        if (!small_stripe)
-               calc_size = max_t(u64, min_stripe_size, calc_size);
+               calc_size = max_t(u64, repl_info.min_stripe_size, calc_size);
 
        /*
         * we're about to do_div by the BTRFS_STRIPE_LEN so lets make sure
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index 168771b..a94de82 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -146,6 +146,22 @@ struct btrfs_device_info {
        u64 max_avail;
 };
 
+/*
+ * Information about a the parameters of a replication strategy (RAID
+ * level)
+ */
+struct btrfs_replication_info {
+       u32 sub_stripes;
+       u32 dev_stripes;
+       u32 devs_increment;
+       u32 num_copies;
+       u32 devs_max;
+       u32 devs_min;
+       u64 max_stripe_size;
+       u64 min_stripe_size;
+       u64 max_chunk_size;
+};
+
 /* Used to sort the devices by max_avail(descending sort) */
 int btrfs_cmp_device_free_bytes(const void *dev_info1, const void *dev_info2);
 
@@ -214,4 +230,5 @@ int btrfs_chunk_readonly(struct btrfs_root *root, u64 
chunk_offset);
 int find_free_dev_extent(struct btrfs_trans_handle *trans,
                         struct btrfs_device *device, u64 num_bytes,
                         u64 *start, u64 *max_avail);
+void btrfs_get_replication_info(struct btrfs_replication_info *info, u64 type);
 #endif
-- 
1.7.2.5

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to