On 6/19/2026 6:15 PM, Matthew Auld wrote:
On 18/06/2026 13:47, Arunpravin Paneer Selvam wrote:
The try_harder contiguous fallback could return a range whose start
offset did not match the caller's min_block_size. Check each candidate
against the requested alignment and reject the allocation when no
candidate satisfies it, instead of handing back a misaligned range.

Suggested-by: Christian König <[email protected]>
Fixes: 0a1844bf0b53 ("drm/buddy: Improve contiguous memory allocation")
Cc: Matthew Auld <[email protected]>
Cc: Christian König <[email protected]>
Cc: Timur Kristóf <[email protected]>
Cc: John Olender <[email protected]>
Cc: [email protected]
Signed-off-by: Arunpravin Paneer Selvam <[email protected]>
---
  drivers/gpu/buddy.c | 33 +++++++++++++++++++++------------
  1 file changed, 21 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/buddy.c b/drivers/gpu/buddy.c
index dc81fe0301ce..28ed3250ac57 100644
--- a/drivers/gpu/buddy.c
+++ b/drivers/gpu/buddy.c
@@ -1127,13 +1127,11 @@ static int __alloc_contig_try_harder(struct gpu_buddy *mm,
      struct gpu_buddy_block *block;
      unsigned int tree, order;
      LIST_HEAD(blocks_lhs);
-    unsigned long pages;
      u64 modify_size;
      int err;
        modify_size = rounddown_pow_of_two(size);
-    pages = modify_size >> ilog2(mm->chunk_size);
-    order = fls(pages) - 1;
+    order = ilog2(modify_size) - ilog2(mm->chunk_size);
      if (order == 0)
          return -ENOSPC;
  @@ -1149,31 +1147,42 @@ static int __alloc_contig_try_harder(struct gpu_buddy *mm,
          while (iter) {
              block = rbtree_get_free_block(iter);
  -            /* Allocate blocks traversing RHS */
              rhs_offset = gpu_buddy_block_offset(block);
+
+            /* Allocate blocks traversing RHS */
              err =  __gpu_buddy_alloc_range(mm, rhs_offset, size,
                                 &filled, blocks);
-            if (!err || err != -ENOSPC)
+            if (err && err != -ENOSPC)
                  return err;
+            if (!err && IS_ALIGNED(rhs_offset, min_block_size))
+                return 0;
+            if (!err)

Should we do some kind of rhs = round_down(rhs, min_block_size) at the start? Just wondering if we can get something misaligned here, that should have succeeded if we just applied the round_down first, in some edge case?
 Done - when the whole size fits at rhs_offset but the start is misaligned, we drop it and realign to the min_block_size boundary below instead of bailing.

+                goto next;
  -            lhs_size = max((size - filled), min_block_size);
-            if (!IS_ALIGNED(lhs_size, min_block_size))
-                lhs_size = round_up(lhs_size, min_block_size);
+            lhs_size = round_up(max((size - filled), min_block_size),
+                        min_block_size);

Can this be simplified as: round_up(size - filled, min_block_size) ?
Dropped round_up/lhs_size entirely, we realign and allocate exactly size, so the max/round_up is gone.

+
+            if (lhs_size > rhs_offset)

What is the idea with this check?
We reach here only on a partial RHS fill, so the leftover size - filled must be taken from the space left of rhs_offset;
if that leftover exceeds rhs_offset there isn't room, so we skip.
It also prevents the next line's u64 rhs_offset - (size - filled) from underflowing.


+                goto next;
                /* Allocate blocks traversing LHS */
-            lhs_offset = gpu_buddy_block_offset(block) - lhs_size;
+            lhs_offset = rhs_offset - lhs_size;
+
+            if (!IS_ALIGNED(lhs_offset, min_block_size))
+                goto next;

Would it make sense to just align the lhs down, if misaligned, instead of baling? If the final size we get back is slightly too large, we can just apply a trim at the end?
Done -  we realign lhs_offset (round_down) and request exactly size, so there is no surplus to trim.
Please review the v2.

Regards,
Arun.

+
              err =  __gpu_buddy_alloc_range(mm, lhs_offset, lhs_size,
                                 NULL, &blocks_lhs);
              if (!err) {
                  list_splice(&blocks_lhs, blocks);
                  return 0;
-            } else if (err != -ENOSPC) {
+            }
+            if (err != -ENOSPC) {
                  gpu_buddy_free_list_internal(mm, blocks);
                  return err;
              }
-            /* Free blocks for the next iteration */
+next:
              gpu_buddy_free_list_internal(mm, blocks);
-
              iter = rb_prev(iter);
          }
      }

base-commit: b9e2d5cdaab05c997be3a69d9b372d7676683e1b


Reply via email to