]> git.hungrycats.org Git - linux/commitdiff
zygo: btrfs: prefer aligned dev_extent holes when allocating chunks (v4, handle last...
authorZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Wed, 14 Feb 2024 05:10:23 +0000 (00:10 -0500)
committerZygo Blaxell <ce3g8jdj@umail.furryterror.org>
Fri, 18 Sep 2026 21:36:34 +0000 (17:36 -0400)
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)

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)
(cherry picked from commit fd66ce7a8643932159cfee3fd539bfe8529ab35d)
(cherry picked from commit f2dd2c8c2401075b679971b4fc28379b6760fec3)

fs/btrfs/volumes.c

index bb7f9feec8c77736f3169d094e37d291af93574d..fad59c407a1abf5bf346aa2f385d57ebfed61ccd 100644 (file)
@@ -1925,21 +1925,25 @@ static int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes,
                        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;
                        }
@@ -1964,9 +1968,24 @@ next:
                hole_size = search_end - search_start;
                dev_extent_hole_check(device, &search_start, &hole_size, num_bytes);
 
-               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;
                }
        }