Skip to contentSkip to conversation

btrfs: fix wrong calculation of stripe size

PATCH In review Miao Xie 2 participants 2 messages Jan 5, 2011 – Jan 12, 2011 Btrfs file system

lore
Share & tools
lore

Miao Xie

author
#0 lore raw

PATCH v3 3/6 btrfs: fix wrong calculation of stripe size

There are two tiny problem:
- One is When we check the chunk size is greater than the max chunk size or not, we should take mirrors into account, but the original code didn't.
- The other is btrfs shouldn't use the size of the residual free space as the length of of a dup chunk when doing chunk allocation. It is because the device space that a dup chunk needs is twice as large as the chunk size, if we use the size of the residual free space as the length of a dup chunk, we can not get enough free space. Fix it.

---
Changelog V1 -> V2:
- fix compiler errors x86_32 machines which were caused by u64 division.

 fs/btrfs/volumes.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)
fs/btrfs/volumes.c +8 -2
index 177b731..c50a85e 100644
@@ -2177,6 +2177,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
 	int num_stripes = 1;
 	int min_stripes = 1;
 	int sub_stripes = 0;
+	int ncopies = 1;
 	int looped = 0;
 	int ret;
 	int index;
@@ -2197,12 +2198,14 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
 	if (type & (BTRFS_BLOCK_GROUP_DUP)) {
 		num_stripes = 2;
 		min_stripes = 2;
+		ncopies = 2;
 	}
 	if (type & (BTRFS_BLOCK_GROUP_RAID1)) {
 		if (fs_devices->rw_devices < 2)
 			return -ENOSPC;
 		num_stripes = 2;
 		min_stripes = 2;
+		ncopies = 2;
 	}
 	if (type & (BTRFS_BLOCK_GROUP_RAID10)) {
 		num_stripes = fs_devices->rw_devices;
@@ -2210,6 +2213,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
 			return -ENOSPC;
 		num_stripes &= ~(u32)1;
 		sub_stripes = 2;
+		ncopies = 2;
 		min_stripes = 4;
 	}
 
@@ -2239,8 +2243,8 @@ again:
 		map->num_stripes = num_stripes;
 	}
 
-	if (calc_size * num_stripes > max_chunk_size) {
-		calc_size = max_chunk_size;
+	if (calc_size * num_stripes > max_chunk_size * ncopies) {
+		calc_size = max_chunk_size * ncopies;
 		do_div(calc_size, num_stripes);
 		do_div(calc_size, stripe_len);
 		calc_size *= stripe_len;
@@ -2321,6 +2325,8 @@ again:
 		if (!looped && max_avail > 0) {
 			looped = 1;
 			calc_size = max_avail;
+			if (type & BTRFS_BLOCK_GROUP_DUP)
+				do_div(calc_size, 2);
 			goto again;
 		}
 		kfree(map);
Signature · 1 line
1.7.2.3
Reviewed-by on v3 3/6
#1 lore raw
Quoted 10 lines · Miao Xie

There are two tiny problem:
- One is When we check the chunk size is greater than the max chunk size or not, we should take mirrors into account, but the original code didn't.
- The other is btrfs shouldn't use the size of the residual free space as the length of of a dup chunk when doing chunk allocation. It is because the device space that a dup chunk needs is twice as large as the chunk size, if we use the size of the residual free space as the length of a dup chunk, we can not get enough free space. Fix it.

Thanks,

Josef