From: Zygo Blaxell Date: Wed, 14 Feb 2024 05:10:23 +0000 (-0500) Subject: zygo: btrfs: prefer aligned dev_extent holes when allocating chunks (v4, handle last... X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fd66ce7a8643932159cfee3fd539bfe8529ab35d;p=linux zygo: btrfs: prefer aligned dev_extent holes when allocating chunks (v4, handle last hole correctly when it is aligned) zygo: btrfs: prefer aligned dev_extent holes when allocating chunks (v2, right end of the hole) (cherry picked from commit ded252ea39093671390a526a76c6def61d7e6ac1) zygo: btrfs: prefer aligned dev_extent holes when allocating chunks (v3, handle last hole correctly) (cherry picked from commit 825cb15cd8a02a083042cc6fa12767ec1805f92d) (cherry picked from commit 4ca76de09f5ac2c9354df4effd4bcea41830eb47) --- diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 20a0ac1e1450..7a23feb068cb 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -1685,21 +1685,25 @@ again: dev_extent_hole_check(device, &search_start, &hole_size, num_bytes); - if (hole_size > max_hole_size) { + /* + * Once we find a hole of sufficient size we + * ignore any larger holes that may appear at + * higher device offsets. If we later find a + * hole that is sufficiently large, but aligned, + * we'll use that instead. + */ + if (hole_size > max_hole_size && max_hole_size < num_bytes) { max_hole_start = search_start; max_hole_size = hole_size; } /* - * If this free space is greater than which we need, - * it must be the max free space that we have found - * until now, so max_hole_start must point to the start - * of this free space and the length of this free space - * is stored in max_hole_size. Thus, we return - * max_hole_start and max_hole_size and go back to the - * caller. + * If we find a hole that is aligned and as large + * as we need, then exit early with that hole. */ - if (hole_size >= num_bytes) { + if (hole_size >= num_bytes && (search_start & (SZ_1G - 1)) == SZ_1M) { + max_hole_start = search_start; + max_hole_size = hole_size; ret = 0; goto out; } @@ -1728,9 +1732,24 @@ next: goto again; } - if (hole_size > max_hole_size) { + /* + * If this is a larger hole it might not be aligned. + * Keep the hole we found above if it was large enough. + */ + if (hole_size > max_hole_size && max_hole_size < num_bytes) { + max_hole_start = search_start; + max_hole_size = hole_size; + } + + /* + * The last hole may be aligned and longer than any other, + * so do the aligned check and exit early again. + */ + if (hole_size >= num_bytes && (search_start & (SZ_1G - 1)) == SZ_1M) { max_hole_start = search_start; max_hole_size = hole_size; + ret = 0; + goto out; } }