aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
authorliubo <liubo2009@cn.fujitsu.com>2011-08-01 22:39:03 -0400
committerChris Mason <chris.mason@oracle.com>2011-08-16 21:09:15 -0400
commit38c01b9605923cfdff5413e0a12e58ee8d962257 (patch)
tree49f7197ee14581d800d927e5860de4d62b77f15b /fs/btrfs/volumes.c
parent34f3e4f23ca3d259fe078f62a128d97ca83508ef (diff)
Btrfs: fix a bug of balance on full multi-disk partitions
When balancing, we'll first try to shrink devices for some space, but if it is working on a full multi-disk partition with raid protection, we may encounter a bug, that is, while shrinking, total_bytes may be less than bytes_used, and btrfs may allocate a dev extent that accesses out of device's bounds. Then we will not be able to write or read the data which stores at the end of the device, and get the followings: device fsid 0939f071-7ea3-46c8-95df-f176d773bfb6 devid 1 transid 10 /dev/sdb5 Btrfs detected SSD devices, enabling SSD mode btrfs: relocating block group 476315648 flags 9 btrfs: found 4 extents attempt to access beyond end of device sdb5: rw=145, want=546176, limit=546147 attempt to access beyond end of device sdb5: rw=145, want=546304, limit=546147 attempt to access beyond end of device sdb5: rw=145, want=546432, limit=546147 attempt to access beyond end of device sdb5: rw=145, want=546560, limit=546147 attempt to access beyond end of device Signed-off-by: Liu Bo <liubo2009@cn.fujitsu.com> Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c17
1 files changed, 13 insertions, 4 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index a595f8775c37..46f9a208723d 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -863,6 +863,7 @@ int find_free_dev_extent(struct btrfs_trans_handle *trans,
863 863
864 max_hole_start = search_start; 864 max_hole_start = search_start;
865 max_hole_size = 0; 865 max_hole_size = 0;
866 hole_size = 0;
866 867
867 if (search_start >= search_end) { 868 if (search_start >= search_end) {
868 ret = -ENOSPC; 869 ret = -ENOSPC;
@@ -945,7 +946,14 @@ next:
945 cond_resched(); 946 cond_resched();
946 } 947 }
947 948
948 hole_size = search_end- search_start; 949 /*
950 * At this point, search_start should be the end of
951 * allocated dev extents, and when shrinking the device,
952 * search_end may be smaller than search_start.
953 */
954 if (search_end > search_start)
955 hole_size = search_end - search_start;
956
949 if (hole_size > max_hole_size) { 957 if (hole_size > max_hole_size) {
950 max_hole_start = search_start; 958 max_hole_start = search_start;
951 max_hole_size = hole_size; 959 max_hole_size = hole_size;
@@ -2447,9 +2455,10 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
2447 total_avail = device->total_bytes - device->bytes_used; 2455 total_avail = device->total_bytes - device->bytes_used;
2448 else 2456 else
2449 total_avail = 0; 2457 total_avail = 0;
2450 /* avail is off by max(alloc_start, 1MB), but that is the same 2458
2451 * for all devices, so it doesn't hurt the sorting later on 2459 /* If there is no space on this device, skip it. */
2452 */ 2460 if (total_avail == 0)
2461 continue;
2453 2462
2454 ret = find_free_dev_extent(trans, device, 2463 ret = find_free_dev_extent(trans, device,
2455 max_stripe_size * dev_stripes, 2464 max_stripe_size * dev_stripes,