Skip to content

Commit 0614784

Browse files
chucklevertorvalds
authored andcommitted
mm/page_alloc: further fix __alloc_pages_bulk() return value
The author of commit b3b64eb ("mm/page_alloc: do bulk array bounds check after checking populated elements") was possibly confused by the mixture of return values throughout the function. The API contract is clear that the function "Returns the number of pages on the list or array." It does not list zero as a unique return value with a special meaning. Therefore zero is a plausible return value only if @nr_pages is zero or less. Clean up the return logic to make it clear that the returned value is always the total number of pages in the array/list, not the number of pages that were allocated during this call. The only change in behavior with this patch is the value returned if prepare_alloc_pages() fails. To match the API contract, the number of pages currently in the array/list is returned in this case. The call site in __page_pool_alloc_pages_slow() also seems to be confused on this matter. It should be attended to by someone who is familiar with that code. [[email protected]: Return nr_populated if 0 pages are requested] Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Chuck Lever <[email protected]> Signed-off-by: Mel Gorman <[email protected]> Acked-by: Jesper Dangaard Brouer <[email protected]> Cc: Desmond Cheong Zhi Xi <[email protected]> Cc: Zhang Qiang <[email protected]> Cc: Yanfei Xu <[email protected]> Cc: Matteo Croce <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent e5c15ce commit 0614784

File tree

1 file changed

+8
-6
lines changed

1 file changed

+8
-6
lines changed

mm/page_alloc.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5221,19 +5221,20 @@ unsigned long __alloc_pages_bulk(gfp_t gfp, int preferred_nid,
52215221
unsigned int alloc_flags = ALLOC_WMARK_LOW;
52225222
int nr_populated = 0, nr_account = 0;
52235223

5224-
if (unlikely(nr_pages <= 0))
5225-
return 0;
5226-
52275224
/*
52285225
* Skip populated array elements to determine if any pages need
52295226
* to be allocated before disabling IRQs.
52305227
*/
52315228
while (page_array && nr_populated < nr_pages && page_array[nr_populated])
52325229
nr_populated++;
52335230

5231+
/* No pages requested? */
5232+
if (unlikely(nr_pages <= 0))
5233+
goto out;
5234+
52345235
/* Already populated array? */
52355236
if (unlikely(page_array && nr_pages - nr_populated == 0))
5236-
return nr_populated;
5237+
goto out;
52375238

52385239
/* Use the single page allocator for one page. */
52395240
if (nr_pages - nr_populated == 1)
@@ -5255,7 +5256,7 @@ unsigned long __alloc_pages_bulk(gfp_t gfp, int preferred_nid,
52555256
gfp &= gfp_allowed_mask;
52565257
alloc_gfp = gfp;
52575258
if (!prepare_alloc_pages(gfp, 0, preferred_nid, nodemask, &ac, &alloc_gfp, &alloc_flags))
5258-
return nr_populated;
5259+
goto out;
52595260
gfp = alloc_gfp;
52605261

52615262
/* Find an allowed local zone that meets the low watermark. */
@@ -5323,6 +5324,7 @@ unsigned long __alloc_pages_bulk(gfp_t gfp, int preferred_nid,
53235324
__count_zid_vm_events(PGALLOC, zone_idx(zone), nr_account);
53245325
zone_statistics(ac.preferred_zoneref->zone, zone, nr_account);
53255326

5327+
out:
53265328
return nr_populated;
53275329

53285330
failed_irq:
@@ -5338,7 +5340,7 @@ unsigned long __alloc_pages_bulk(gfp_t gfp, int preferred_nid,
53385340
nr_populated++;
53395341
}
53405342

5341-
return nr_populated;
5343+
goto out;
53425344
}
53435345
EXPORT_SYMBOL_GPL(__alloc_pages_bulk);
53445346

0 commit comments

Comments
 (0)