Skip to content

Commit 3c538de

Browse files
josefbacikkdave
authored andcommitted
btrfs: limit device extents to the device size
There was a recent regression in btrfs/177 that started happening with the size class patches ("btrfs: introduce size class to block group allocator"). This however isn't a regression introduced by those patches, but rather the bug was uncovered by a change in behavior in these patches. The patches triggered more chunk allocations in the ^free-space-tree case, which uncovered a race with device shrink. The problem is we will set the device total size to the new size, and use this to find a hole for a device extent. However during shrink we may have device extents allocated past this range, so we could potentially find a hole in a range past our new shrink size. We don't actually limit our found extent to the device size anywhere, we assume that we will not find a hole past our device size. This isn't true with shrink as we're relocating block groups and thus creating holes past the device size. Fix this by making sure we do not search past the new device size, and if we wander into any device extents that start after our device size simply break from the loop and use whatever hole we've already found. CC: [email protected] # 4.14+ Signed-off-by: Josef Bacik <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent f7c11af commit 3c538de

File tree

1 file changed

+5
-1
lines changed

1 file changed

+5
-1
lines changed

fs/btrfs/volumes.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1600,7 +1600,7 @@ static int find_free_dev_extent_start(struct btrfs_device *device,
16001600
if (ret < 0)
16011601
goto out;
16021602

1603-
while (1) {
1603+
while (search_start < search_end) {
16041604
l = path->nodes[0];
16051605
slot = path->slots[0];
16061606
if (slot >= btrfs_header_nritems(l)) {
@@ -1623,6 +1623,9 @@ static int find_free_dev_extent_start(struct btrfs_device *device,
16231623
if (key.type != BTRFS_DEV_EXTENT_KEY)
16241624
goto next;
16251625

1626+
if (key.offset > search_end)
1627+
break;
1628+
16261629
if (key.offset > search_start) {
16271630
hole_size = key.offset - search_start;
16281631
dev_extent_hole_check(device, &search_start, &hole_size,
@@ -1683,6 +1686,7 @@ static int find_free_dev_extent_start(struct btrfs_device *device,
16831686
else
16841687
ret = 0;
16851688

1689+
ASSERT(max_hole_start + max_hole_size <= search_end);
16861690
out:
16871691
btrfs_free_path(path);
16881692
*start = max_hole_start;

0 commit comments

Comments
 (0)