btrfs: add dev maxs limit for __btrfs_alloc_chunk in kernel space
authorGui Hecheng <guihc.fnst@cn.fujitsu.com>
Mon, 21 Apr 2014 12:13:12 +0000 (20:13 +0800)
committerChris Mason <clm@fb.com>
Tue, 10 Jun 2014 00:20:36 +0000 (17:20 -0700)
For RAID0,5,6,10,
For system chunk, there shouldn't be too many stripes to
make a btrfs_chunk that exceeds BTRFS_SYSTEM_CHUNK_ARRAY_SIZE
For data/meta chunk, there shouldn't be too many stripes to
make a btrfs_chunk that exceeds a leaf.

Signed-off-by: Gui Hecheng <guihc.fnst@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
fs/btrfs/volumes.c

index 5864f05243c21cfa53079f5f2137d528093fc279..8113f4567084407841e3e9b8a13b6aa33f7ca160 100644 (file)
@@ -4027,6 +4027,16 @@ static void check_raid56_incompat_flag(struct btrfs_fs_info *info, u64 type)
        btrfs_set_fs_incompat(info, RAID56);
 }
 
+#define BTRFS_MAX_DEVS(r) ((BTRFS_LEAF_DATA_SIZE(r)            \
+                       - sizeof(struct btrfs_item)             \
+                       - sizeof(struct btrfs_chunk))           \
+                       / sizeof(struct btrfs_stripe) + 1)
+
+#define BTRFS_MAX_DEVS_SYS_CHUNK ((BTRFS_SYSTEM_CHUNK_ARRAY_SIZE       \
+                               - 2 * sizeof(struct btrfs_disk_key)     \
+                               - 2 * sizeof(struct btrfs_chunk))       \
+                               / sizeof(struct btrfs_stripe) + 1)
+
 static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
                               struct btrfs_root *extent_root, u64 start,
                               u64 type)
@@ -4076,6 +4086,8 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        if (type & BTRFS_BLOCK_GROUP_DATA) {
                max_stripe_size = 1024 * 1024 * 1024;
                max_chunk_size = 10 * max_stripe_size;
+               if (!devs_max)
+                       devs_max = BTRFS_MAX_DEVS(info->chunk_root);
        } else if (type & BTRFS_BLOCK_GROUP_METADATA) {
                /* for larger filesystems, use larger metadata chunks */
                if (fs_devices->total_rw_bytes > 50ULL * 1024 * 1024 * 1024)
@@ -4083,9 +4095,13 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
                else
                        max_stripe_size = 256 * 1024 * 1024;
                max_chunk_size = max_stripe_size;
+               if (!devs_max)
+                       devs_max = BTRFS_MAX_DEVS(info->chunk_root);
        } else if (type & BTRFS_BLOCK_GROUP_SYSTEM) {
                max_stripe_size = 32 * 1024 * 1024;
                max_chunk_size = 2 * max_stripe_size;
+               if (!devs_max)
+                       devs_max = BTRFS_MAX_DEVS_SYS_CHUNK;
        } else {
                btrfs_err(info, "invalid chunk type 0x%llx requested\n",
                       type);