All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dan Carpenter <dan.carpenter@oracle.com>
To: mgorman@techsingularity.net
Cc: linux-mm@kvack.org
Subject: [bug report] mm/page_alloc: add an array-based interface to the bulk page allocator
Date: Fri, 18 Jun 2021 12:03:45 +0300	[thread overview]
Message-ID: <YMCqxktRfwqOmluS@mwanda> (raw)

Hello Mel Gorman,

The patch 0f87d9d30f21: "mm/page_alloc: add an array-based interface
to the bulk page allocator" from Apr 29, 2021, leads to the following
static checker warning:

	mm/page_alloc.c:5338 __alloc_pages_bulk()
	warn: potentially one past the end of array 'page_array[nr_populated]'

mm/page_alloc.c
  5225  unsigned long __alloc_pages_bulk(gfp_t gfp, int preferred_nid,
  5226                          nodemask_t *nodemask, int nr_pages,
  5227                          struct list_head *page_list,
  5228                          struct page **page_array)
  5229  {
  5230          struct page *page;
  5231          unsigned long flags;
  5232          struct zone *zone;
  5233          struct zoneref *z;
  5234          struct per_cpu_pages *pcp;
  5235          struct list_head *pcp_list;
  5236          struct alloc_context ac;
  5237          gfp_t alloc_gfp;
  5238          unsigned int alloc_flags = ALLOC_WMARK_LOW;
  5239          int nr_populated = 0, nr_account = 0;
  5240  
  5241          if (unlikely(nr_pages <= 0))
  5242                  return 0;
  5243  
  5244          /*
  5245           * Skip populated array elements to determine if any pages need
  5246           * to be allocated before disabling IRQs.
  5247           */
  5248          while (page_array && nr_populated < nr_pages && page_array[nr_populated])
                                     ^^^^^^^^^^^^^^^^^^^^^^^
Presumably we can have all the pages populated.

  5249                  nr_populated++;
  5250  
  5251          /* Use the single page allocator for one page. */
  5252          if (nr_pages - nr_populated == 1)
  5253                  goto failed;
  5254  
  5255          /* May set ALLOC_NOFRAGMENT, fragmentation will return 1 page. */
  5256          gfp &= gfp_allowed_mask;
  5257          alloc_gfp = gfp;
  5258          if (!prepare_alloc_pages(gfp, 0, preferred_nid, nodemask, &ac, &alloc_gfp, &alloc_flags))
  5259                  return 0;
  5260          gfp = alloc_gfp;
  5261  
  5262          /* Find an allowed local zone that meets the low watermark. */
  5263          for_each_zone_zonelist_nodemask(zone, z, ac.zonelist, ac.highest_zoneidx, ac.nodemask) {
  5264                  unsigned long mark;
  5265  
  5266                  if (cpusets_enabled() && (alloc_flags & ALLOC_CPUSET) &&
  5267                      !__cpuset_zone_allowed(zone, gfp)) {
  5268                          continue;
  5269                  }
  5270  
  5271                  if (nr_online_nodes > 1 && zone != ac.preferred_zoneref->zone &&
  5272                      zone_to_nid(zone) != zone_to_nid(ac.preferred_zoneref->zone)) {
  5273                          goto failed;
  5274                  }
  5275  
  5276                  mark = wmark_pages(zone, alloc_flags & ALLOC_WMARK_MASK) + nr_pages;
  5277                  if (zone_watermark_fast(zone, 0,  mark,
  5278                                  zonelist_zone_idx(ac.preferred_zoneref),
  5279                                  alloc_flags, gfp)) {
  5280                          break;
  5281                  }
  5282          }
  5283  
  5284          /*
  5285           * If there are no allowed local zones that meets the watermarks then
  5286           * try to allocate a single page and reclaim if necessary.
  5287           */
  5288          if (unlikely(!zone))
  5289                  goto failed;
                        ^^^^^^^^^^^^
If we hit a goto then it puts the new page beyond the end of the array.

  5290  
  5291          /* Attempt the batch allocation */
  5292          local_lock_irqsave(&pagesets.lock, flags);
  5293          pcp = this_cpu_ptr(zone->per_cpu_pageset);
  5294          pcp_list = &pcp->lists[ac.migratetype];
  5295  
  5296          while (nr_populated < nr_pages) {
  5297  
  5298                  /* Skip existing pages */
  5299                  if (page_array && page_array[nr_populated]) {
  5300                          nr_populated++;
  5301                          continue;
  5302                  }
  5303  
  5304                  page = __rmqueue_pcplist(zone, 0, ac.migratetype, alloc_flags,
  5305                                                                  pcp, pcp_list);
  5306                  if (unlikely(!page)) {
  5307                          /* Try and get at least one page */
  5308                          if (!nr_populated)
  5309                                  goto failed_irq;
  5310                          break;
  5311                  }
  5312                  nr_account++;
  5313  
  5314                  prep_new_page(page, 0, gfp, 0);
  5315                  if (page_list)
  5316                          list_add(&page->lru, page_list);
  5317                  else
  5318                          page_array[nr_populated] = page;
  5319                  nr_populated++;
  5320          }
  5321  
  5322          local_unlock_irqrestore(&pagesets.lock, flags);
  5323  
  5324          __count_zid_vm_events(PGALLOC, zone_idx(zone), nr_account);
  5325          zone_statistics(ac.preferred_zoneref->zone, zone, nr_account);
  5326  
  5327          return nr_populated;
  5328  
  5329  failed_irq:
  5330          local_unlock_irqrestore(&pagesets.lock, flags);
  5331  
  5332  failed:
  5333          page = __alloc_pages(gfp, 0, preferred_nid, nodemask);
  5334          if (page) {
  5335                  if (page_list)
  5336                          list_add(&page->lru, page_list);
  5337                  else
  5338                          page_array[nr_populated] = page;
                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

  5339                  nr_populated++;
  5340          }
  5341  
  5342          return nr_populated;
  5343  }

regards,
dan carpenter


             reply	other threads:[~2021-06-18  9:04 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-18  9:03 Dan Carpenter [this message]
2021-06-18 10:14 ` [bug report] mm/page_alloc: add an array-based interface to the bulk page allocator Mel Gorman
2021-06-18 11:59   ` Dan Carpenter
2021-06-18 12:49     ` Mel Gorman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=YMCqxktRfwqOmluS@mwanda \
    --to=dan.carpenter@oracle.com \
    --cc=linux-mm@kvack.org \
    --cc=mgorman@techsingularity.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.