提交 15ae4878 编写于 作者: J Josef Bacik 提交者: zhaoxiaoqiang11

btrfs: limit device extents to the device size

stable inclusion
from stable-v5.10.168
commit a1406d5aa39361b4f62edde1dfd8f86e1bdf1323
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I7URR4

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=a1406d5aa39361b4f62edde1dfd8f86e1bdf1323

----------------------------------------------------

commit 3c538de0 upstream.

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: stable@vger.kernel.org # 4.14+
Signed-off-by: NJosef Bacik <josef@toxicpanda.com>
Signed-off-by: NDavid Sterba <dsterba@suse.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Nzhaoxiaoqiang11 <zhaoxiaoqiang11@jd.com>
上级 e6f478f9
...@@ -1580,7 +1580,7 @@ static int find_free_dev_extent_start(struct btrfs_device *device, ...@@ -1580,7 +1580,7 @@ static int find_free_dev_extent_start(struct btrfs_device *device,
goto out; goto out;
} }
while (1) { while (search_start < search_end) {
l = path->nodes[0]; l = path->nodes[0];
slot = path->slots[0]; slot = path->slots[0];
if (slot >= btrfs_header_nritems(l)) { if (slot >= btrfs_header_nritems(l)) {
...@@ -1603,6 +1603,9 @@ static int find_free_dev_extent_start(struct btrfs_device *device, ...@@ -1603,6 +1603,9 @@ static int find_free_dev_extent_start(struct btrfs_device *device,
if (key.type != BTRFS_DEV_EXTENT_KEY) if (key.type != BTRFS_DEV_EXTENT_KEY)
goto next; goto next;
if (key.offset > search_end)
break;
if (key.offset > search_start) { if (key.offset > search_start) {
hole_size = key.offset - search_start; hole_size = key.offset - search_start;
dev_extent_hole_check(device, &search_start, &hole_size, dev_extent_hole_check(device, &search_start, &hole_size,
...@@ -1663,6 +1666,7 @@ static int find_free_dev_extent_start(struct btrfs_device *device, ...@@ -1663,6 +1666,7 @@ static int find_free_dev_extent_start(struct btrfs_device *device,
else else
ret = 0; ret = 0;
ASSERT(max_hole_start + max_hole_size <= search_end);
out: out:
btrfs_free_path(path); btrfs_free_path(path);
*start = max_hole_start; *start = max_hole_start;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册