Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] mm: gpu/buddy try-harder fails range allocation when free space exceeds range_end - [High] mm: gpu/buddy try-harder misses higher-order blocks for range allocations --
commit 3089b8dadc6718a57b0162914961a76a654e9d6b Author: Arunpravin Paneer Selvam <[email protected]> Subject: gpu/buddy: add range-restricted contiguous allocation fallback This commit adds support for range-restricted contiguous allocation fallback in the GPU buddy allocator. It extends __alloc_contig_try_harder to confine candidate placements to a specified [range_start, range_end) window. > diff --git a/drivers/gpu/buddy.c b/drivers/gpu/buddy.c > index 6566bad4fef15..1f648bcfce574 100644 > --- a/drivers/gpu/buddy.c > +++ b/drivers/gpu/buddy.c > @@ -1682,26 +1682,14 @@ static int __gpu_buddy_alloc_range(struct gpu_buddy > *mm, [ ... ] > static int __alloc_contig_try_harder(struct gpu_buddy *mm, > + u64 range_start, u64 range_end, > u64 size, > u64 min_block_size, > unsigned long flags, > struct list_head *blocks) > { [Severity: High] Does the try-harder fallback miss higher-order blocks for range allocations? When this function is called as a fallback, it derives an order based on the unrounded size and searches exclusively in mm->free_tree[order]: modify_size = rounddown_pow_of_two(size); pages = modify_size >> ilog2(mm->chunk_size); order = fls(pages) - 1; ... root = &mm->free_tree[order]; if (RB_EMPTY_ROOT(root)) return -ENOSPC; However, for range contiguous allocations, the normal allocation pass rounds up the requested size. If a higher-order block intersects the range but cannot fit the rounded-up size within the bounds, it gets skipped and is not split. If this occurs, the valid contiguous space remains in a higher-order tree. Since the try-harder fallback only checks the single derived order's tree, will it fail immediately with -ENOSPC, missing the free space that resides in the unsplit, higher-order blocks? > - u64 rhs_offset, lhs_offset, filled; > + u64 rhs_offset, lhs_offset, filled, aligned; > struct gpu_buddy_block *block; > struct rb_root *root; > struct rb_node *iter; > @@ -1726,25 +1714,36 @@ static int __alloc_contig_try_harder(struct gpu_buddy > *mm, > > rhs_offset = gpu_buddy_block_offset(block); > > + if (rhs_offset >= range_end) { > + iter = rb_prev(iter); > + continue; > + } > + if (rhs_offset < range_start) > + break; > + > /* Allocate blocks traversing RHS */ > err = __gpu_buddy_alloc_range(mm, rhs_offset, size, > flags, &filled, blocks); > if (err && err != -ENOSPC) > return err; > - if (!err && IS_ALIGNED(rhs_offset, min_block_size)) > + if (!err && IS_ALIGNED(rhs_offset, min_block_size) && > + rhs_offset >= range_start && rhs_offset + size <= range_end) > return 0; > if (!err) { > /* Allocate the unaligned RHS offset using round_down */ > gpu_buddy_free_list_internal(mm, blocks); > - err = __alloc_contig_aligned_retry(mm, rhs_offset, > - size, > - min_block_size, > - flags, blocks); > - if (!err) > - return 0; > - if (err != -ENOSPC) { > - gpu_buddy_free_list_internal(mm, blocks); > - return err; > + > + aligned = round_down(rhs_offset, min_block_size); > + if (aligned >= range_start && > + aligned + size <= range_end) { > + err = __gpu_buddy_alloc_range(mm, aligned, size, > + flags, NULL, > blocks); > + if (!err) > + return 0; > + if (err != -ENOSPC) { > + gpu_buddy_free_list_internal(mm, > blocks); > + return err; > + } > } > goto next; > } [Severity: High] Does this bypass the left-shift fallback when free space exceeds range_end? __alloc_contig_try_harder() attempts to place a contiguous block by calling __gpu_buddy_alloc_range() without passing range_end. If the contiguous free space extends beyond range_end, this allocation fully succeeds and returns err == 0. Because the allocation succeeded, the condition aligned + size <= range_end will evaluate to false if the memory exceeds the requested range, and the code hits goto next: if (aligned >= range_start && aligned + size <= range_end) { ... } goto next; } This completely skips the lhs_offset fallback path that normally follows: if (size - filled > rhs_offset) goto next; lhs_offset = rhs_offset - (size - filled); ... Had the allocator been bounded by range_end, it would have returned -ENOSPC with filled set, triggering the left-shift fallback to perfectly slide the allocation into the requested range. Will the presence of extra free memory outside the range cause valid contiguous allocations to spuriously fail? -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=2
