Re: [PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted
On Friday, December 02, 2016 7:30 PM Mel Gorman wrote: > Vlastimil Babka pointed out that commit 479f854a207c ("mm, page_alloc: > defer debugging checks of pages allocated from the PCP") will allow the > per-cpu list counter to be out of sync with the per-cpu list contents > if a struct page is corrupted. > > The consequence is an infinite loop if the per-cpu lists get fully drained > by free_pcppages_bulk because all the lists are empty but the count is > positive. The infinite loop occurs here > > do { > batch_free++; > if (++migratetype == MIGRATE_PCPTYPES) > migratetype = 0; > list = &pcp->lists[migratetype]; > } while (list_empty(list)); > > From a user perspective, it's a bad page warning followed by a soft lockup > with interrupts disabled in free_pcppages_bulk(). > > This patch keeps the accounting in sync. > > Fixes: 479f854a207c ("mm, page_alloc: defer debugging checks of pages > allocated from the PCP") > Signed-off-by: Mel Gorman > cc: sta...@vger.kernel.org [4.7+] > --- Acked-by: Hillf Danton > mm/page_alloc.c | 12 ++-- > 1 file changed, 10 insertions(+), 2 deletions(-) > > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index 6de9440e3ae2..34ada718ef47 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -2192,7 +2192,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int > order, > unsigned long count, struct list_head *list, > int migratetype, bool cold) > { > - int i; > + int i, alloced = 0; > > spin_lock(&zone->lock); > for (i = 0; i < count; ++i) { > @@ -2217,13 +2217,21 @@ static int rmqueue_bulk(struct zone *zone, unsigned > int order, > else > list_add_tail(&page->lru, list); > list = &page->lru; > + alloced++; > if (is_migrate_cma(get_pcppage_migratetype(page))) > __mod_zone_page_state(zone, NR_FREE_CMA_PAGES, > -(1 << order)); > } > + > + /* > + * i pages were removed from the buddy list even if some leak due > + * to check_pcp_refill failing so adjust NR_FREE_PAGES based > + * on i. Do not confuse with 'alloced' which is the number of > + * pages added to the pcp list. > + */ > __mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order)); > spin_unlock(&zone->lock); > - return i; > + return alloced; > } > > #ifdef CONFIG_NUMA > -- > 2.10.2
Re: [PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted
On Fri 02-12-16 11:29:50, Mel Gorman wrote: > Vlastimil Babka pointed out that commit 479f854a207c ("mm, page_alloc: > defer debugging checks of pages allocated from the PCP") will allow the > per-cpu list counter to be out of sync with the per-cpu list contents > if a struct page is corrupted. > > The consequence is an infinite loop if the per-cpu lists get fully drained > by free_pcppages_bulk because all the lists are empty but the count is > positive. The infinite loop occurs here > > do { > batch_free++; > if (++migratetype == MIGRATE_PCPTYPES) > migratetype = 0; > list = &pcp->lists[migratetype]; > } while (list_empty(list)); > > >From a user perspective, it's a bad page warning followed by a soft lockup > with interrupts disabled in free_pcppages_bulk(). > > This patch keeps the accounting in sync. > > Fixes: 479f854a207c ("mm, page_alloc: defer debugging checks of pages > allocated from the PCP") > Signed-off-by: Mel Gorman > cc: sta...@vger.kernel.org [4.7+] Thanks for adding the comment it should really make the code more clear. Acked-by: Michal Hocko > --- > mm/page_alloc.c | 12 ++-- > 1 file changed, 10 insertions(+), 2 deletions(-) > > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index 6de9440e3ae2..34ada718ef47 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -2192,7 +2192,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int > order, > unsigned long count, struct list_head *list, > int migratetype, bool cold) > { > - int i; > + int i, alloced = 0; > > spin_lock(&zone->lock); > for (i = 0; i < count; ++i) { > @@ -2217,13 +2217,21 @@ static int rmqueue_bulk(struct zone *zone, unsigned > int order, > else > list_add_tail(&page->lru, list); > list = &page->lru; > + alloced++; > if (is_migrate_cma(get_pcppage_migratetype(page))) > __mod_zone_page_state(zone, NR_FREE_CMA_PAGES, > -(1 << order)); > } > + > + /* > + * i pages were removed from the buddy list even if some leak due > + * to check_pcp_refill failing so adjust NR_FREE_PAGES based > + * on i. Do not confuse with 'alloced' which is the number of > + * pages added to the pcp list. > + */ > __mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order)); > spin_unlock(&zone->lock); > - return i; > + return alloced; > } > > #ifdef CONFIG_NUMA > -- > 2.10.2 > -- Michal Hocko SUSE Labs
Re: [PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted
On 12/02/2016 12:29 PM, Mel Gorman wrote: Vlastimil Babka pointed out that commit 479f854a207c ("mm, page_alloc: defer debugging checks of pages allocated from the PCP") will allow the per-cpu list counter to be out of sync with the per-cpu list contents if a struct page is corrupted. The consequence is an infinite loop if the per-cpu lists get fully drained by free_pcppages_bulk because all the lists are empty but the count is positive. The infinite loop occurs here do { batch_free++; if (++migratetype == MIGRATE_PCPTYPES) migratetype = 0; list = &pcp->lists[migratetype]; } while (list_empty(list)); From a user perspective, it's a bad page warning followed by a soft lockup with interrupts disabled in free_pcppages_bulk(). This patch keeps the accounting in sync. Fixes: 479f854a207c ("mm, page_alloc: defer debugging checks of pages allocated from the PCP") Signed-off-by: Mel Gorman cc: sta...@vger.kernel.org [4.7+] Acked-by: Vlastimil Babka --- mm/page_alloc.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6de9440e3ae2..34ada718ef47 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2192,7 +2192,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, unsigned long count, struct list_head *list, int migratetype, bool cold) { - int i; + int i, alloced = 0; spin_lock(&zone->lock); for (i = 0; i < count; ++i) { @@ -2217,13 +2217,21 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, else list_add_tail(&page->lru, list); list = &page->lru; + alloced++; if (is_migrate_cma(get_pcppage_migratetype(page))) __mod_zone_page_state(zone, NR_FREE_CMA_PAGES, -(1 << order)); } + + /* +* i pages were removed from the buddy list even if some leak due +* to check_pcp_refill failing so adjust NR_FREE_PAGES based +* on i. Do not confuse with 'alloced' which is the number of +* pages added to the pcp list. +*/ __mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order)); spin_unlock(&zone->lock); - return i; + return alloced; } #ifdef CONFIG_NUMA
[PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted
Vlastimil Babka pointed out that commit 479f854a207c ("mm, page_alloc: defer debugging checks of pages allocated from the PCP") will allow the per-cpu list counter to be out of sync with the per-cpu list contents if a struct page is corrupted. The consequence is an infinite loop if the per-cpu lists get fully drained by free_pcppages_bulk because all the lists are empty but the count is positive. The infinite loop occurs here do { batch_free++; if (++migratetype == MIGRATE_PCPTYPES) migratetype = 0; list = &pcp->lists[migratetype]; } while (list_empty(list)); >From a user perspective, it's a bad page warning followed by a soft lockup with interrupts disabled in free_pcppages_bulk(). This patch keeps the accounting in sync. Fixes: 479f854a207c ("mm, page_alloc: defer debugging checks of pages allocated from the PCP") Signed-off-by: Mel Gorman cc: sta...@vger.kernel.org [4.7+] --- mm/page_alloc.c | 12 ++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6de9440e3ae2..34ada718ef47 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2192,7 +2192,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, unsigned long count, struct list_head *list, int migratetype, bool cold) { - int i; + int i, alloced = 0; spin_lock(&zone->lock); for (i = 0; i < count; ++i) { @@ -2217,13 +2217,21 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, else list_add_tail(&page->lru, list); list = &page->lru; + alloced++; if (is_migrate_cma(get_pcppage_migratetype(page))) __mod_zone_page_state(zone, NR_FREE_CMA_PAGES, -(1 << order)); } + + /* +* i pages were removed from the buddy list even if some leak due +* to check_pcp_refill failing so adjust NR_FREE_PAGES based +* on i. Do not confuse with 'alloced' which is the number of +* pages added to the pcp list. +*/ __mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order)); spin_unlock(&zone->lock); - return i; + return alloced; } #ifdef CONFIG_NUMA -- 2.10.2
Re: [PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted
On Fri, Dec 02, 2016 at 11:04:11AM +0100, Michal Hocko wrote: > On Fri 02-12-16 17:30:07, Hillf Danton wrote: > [...] > > > >> @@ -2217,13 +2217,14 @@ static int rmqueue_bulk(struct zone *zone, > > > >> unsigned int order, > > > >>else > > > >>list_add_tail(&page->lru, list); > > > >>list = &page->lru; > > > >> + alloced++; > > > >>if (is_migrate_cma(get_pcppage_migratetype(page))) > > > >>__mod_zone_page_state(zone, NR_FREE_CMA_PAGES, > > > >> -(1 << order)); > > > >>} > > > >>__mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order)); > > > > > > > > Now i is a pure index, yes? > > > > > > No, even if a page fails the check_pcp_refill() check and is not > > > "allocated", it is also no longer a free page, so it's correct to > > > subtract it from NR_FREE_PAGES. > > > > > Yes, we can allocate free page next time. > > No we cannot. The page is gone from the free list. We have effectively > leaked it. And deliberately so. It's in an unknown state, possibly due to memory corruption or a use-after free bug. The machine can continue limping on with warnings in the kernel log but the VM stops going near the page itself as much as possible. -- Mel Gorman SUSE Labs
Re: [PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted
On Fri 02-12-16 17:30:07, Hillf Danton wrote: [...] > > >> @@ -2217,13 +2217,14 @@ static int rmqueue_bulk(struct zone *zone, > > >> unsigned int order, > > >> else > > >> list_add_tail(&page->lru, list); > > >> list = &page->lru; > > >> +alloced++; > > >> if (is_migrate_cma(get_pcppage_migratetype(page))) > > >> __mod_zone_page_state(zone, NR_FREE_CMA_PAGES, > > >>-(1 << order)); > > >> } > > >> __mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order)); > > > > > > Now i is a pure index, yes? > > > > No, even if a page fails the check_pcp_refill() check and is not > > "allocated", it is also no longer a free page, so it's correct to > > subtract it from NR_FREE_PAGES. > > > Yes, we can allocate free page next time. No we cannot. The page is gone from the free list. We have effectively leaked it. -- Michal Hocko SUSE Labs
Re: [PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted
On Fri 02-12-16 09:49:33, Mel Gorman wrote: > On Fri, Dec 02, 2016 at 09:12:17AM +0100, Michal Hocko wrote: > > On Fri 02-12-16 00:22:43, Mel Gorman wrote: > > > Vlastimil Babka pointed out that commit 479f854a207c ("mm, page_alloc: > > > defer debugging checks of pages allocated from the PCP") will allow the > > > per-cpu list counter to be out of sync with the per-cpu list contents > > > if a struct page is corrupted. This patch keeps the accounting in sync. > > > > > > Fixes: 479f854a207c ("mm, page_alloc: defer debugging checks of pages > > > allocated from the PCP") > > > Signed-off-by: Mel Gorman > > > cc: sta...@vger.kernel.org [4.7+] > > > > I am trying to think about what would happen if we did go out of sync > > and cannot spot a problem. Vlastimil has mentioned something about > > free_pcppages_bulk looping for ever but I cannot see it happening right > > now. > > free_pcppages_bulk can infinite loop if the page count is positive and > there are no pages. While I've only seen this during development, a > corrupted count loops here > > do { > batch_free++; > if (++pindex == NR_PCP_LISTS) > pindex = 0; > list = &pcp->lists[pindex]; > } while (list_empty(list)); > > It would only be seen in a situation where struct page corruption was > detected so it's rare. OK, I was apparently sleeping when responding. I focused on t he outer loop and that should just converge. But it is true that this inner loop can just runaway... Could you add that to the changelog please? This definitely warrants stable backport. Thanks! -- Michal Hocko SUSE Labs
Re: [PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted
On Fri, Dec 02, 2016 at 09:12:17AM +0100, Michal Hocko wrote: > On Fri 02-12-16 00:22:43, Mel Gorman wrote: > > Vlastimil Babka pointed out that commit 479f854a207c ("mm, page_alloc: > > defer debugging checks of pages allocated from the PCP") will allow the > > per-cpu list counter to be out of sync with the per-cpu list contents > > if a struct page is corrupted. This patch keeps the accounting in sync. > > > > Fixes: 479f854a207c ("mm, page_alloc: defer debugging checks of pages > > allocated from the PCP") > > Signed-off-by: Mel Gorman > > cc: sta...@vger.kernel.org [4.7+] > > I am trying to think about what would happen if we did go out of sync > and cannot spot a problem. Vlastimil has mentioned something about > free_pcppages_bulk looping for ever but I cannot see it happening right > now. free_pcppages_bulk can infinite loop if the page count is positive and there are no pages. While I've only seen this during development, a corrupted count loops here do { batch_free++; if (++pindex == NR_PCP_LISTS) pindex = 0; list = &pcp->lists[pindex]; } while (list_empty(list)); It would only be seen in a situation where struct page corruption was detected so it's rare. -- Mel Gorman SUSE Labs
Re: [PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted
On Friday, December 02, 2016 2:19 PM Vlastimil Babka wrote: > On 12/02/2016 04:47 AM, Hillf Danton wrote: > > On Friday, December 02, 2016 8:23 AM Mel Gorman wrote: > >> Vlastimil Babka pointed out that commit 479f854a207c ("mm, page_alloc: > >> defer debugging checks of pages allocated from the PCP") will allow the > >> per-cpu list counter to be out of sync with the per-cpu list contents > >> if a struct page is corrupted. This patch keeps the accounting in sync. > >> > >> Fixes: 479f854a207c ("mm, page_alloc: defer debugging checks of pages > >> allocated from the PCP") > >> Signed-off-by: Mel Gorman > >> cc: sta...@vger.kernel.org [4.7+] > > Acked-by: Vlastimil Babka > > >> --- > >> mm/page_alloc.c | 5 +++-- > >> 1 file changed, 3 insertions(+), 2 deletions(-) > >> > >> diff --git a/mm/page_alloc.c b/mm/page_alloc.c > >> index 6de9440e3ae2..777ed59570df 100644 > >> --- a/mm/page_alloc.c > >> +++ b/mm/page_alloc.c > >> @@ -2192,7 +2192,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned > >> int order, > >>unsigned long count, struct list_head *list, > >>int migratetype, bool cold) > >> { > >> - int i; > >> + int i, alloced = 0; > >> > >>spin_lock(&zone->lock); > >>for (i = 0; i < count; ++i) { > >> @@ -2217,13 +2217,14 @@ static int rmqueue_bulk(struct zone *zone, > >> unsigned int order, > >>else > >>list_add_tail(&page->lru, list); > >>list = &page->lru; > >> + alloced++; > >>if (is_migrate_cma(get_pcppage_migratetype(page))) > >>__mod_zone_page_state(zone, NR_FREE_CMA_PAGES, > >> -(1 << order)); > >>} > >>__mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order)); > > > > Now i is a pure index, yes? > > No, even if a page fails the check_pcp_refill() check and is not > "allocated", it is also no longer a free page, so it's correct to > subtract it from NR_FREE_PAGES. > Yes, we can allocate free page next time. thanks Hillf
Re: [PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted
On Fri 02-12-16 00:22:43, Mel Gorman wrote: > Vlastimil Babka pointed out that commit 479f854a207c ("mm, page_alloc: > defer debugging checks of pages allocated from the PCP") will allow the > per-cpu list counter to be out of sync with the per-cpu list contents > if a struct page is corrupted. This patch keeps the accounting in sync. > > Fixes: 479f854a207c ("mm, page_alloc: defer debugging checks of pages > allocated from the PCP") > Signed-off-by: Mel Gorman > cc: sta...@vger.kernel.org [4.7+] I am trying to think about what would happen if we did go out of sync and cannot spot a problem. Vlastimil has mentioned something about free_pcppages_bulk looping for ever but I cannot see it happening right now. So why is this worth stable backport? Anyway the patch looks correct Acked-by: Michal Hocko > --- > mm/page_alloc.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index 6de9440e3ae2..777ed59570df 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -2192,7 +2192,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int > order, > unsigned long count, struct list_head *list, > int migratetype, bool cold) > { > - int i; > + int i, alloced = 0; > > spin_lock(&zone->lock); > for (i = 0; i < count; ++i) { > @@ -2217,13 +2217,14 @@ static int rmqueue_bulk(struct zone *zone, unsigned > int order, > else > list_add_tail(&page->lru, list); > list = &page->lru; > + alloced++; > if (is_migrate_cma(get_pcppage_migratetype(page))) > __mod_zone_page_state(zone, NR_FREE_CMA_PAGES, > -(1 << order)); > } > __mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order)); I guess this deserves a comment (i vs. alloced is confusing and I bet somebody will come up with a cleanup...). We leak corrupted pages intentionally so we should uncharge them from the NR_FREE_PAGES. > spin_unlock(&zone->lock); > - return i; > + return alloced; > } > > #ifdef CONFIG_NUMA > -- > 2.10.2 > -- Michal Hocko SUSE Labs
Re: [PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted
On 12/02/2016 04:47 AM, Hillf Danton wrote: On Friday, December 02, 2016 8:23 AM Mel Gorman wrote: Vlastimil Babka pointed out that commit 479f854a207c ("mm, page_alloc: defer debugging checks of pages allocated from the PCP") will allow the per-cpu list counter to be out of sync with the per-cpu list contents if a struct page is corrupted. This patch keeps the accounting in sync. Fixes: 479f854a207c ("mm, page_alloc: defer debugging checks of pages allocated from the PCP") Signed-off-by: Mel Gorman cc: sta...@vger.kernel.org [4.7+] Acked-by: Vlastimil Babka --- mm/page_alloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6de9440e3ae2..777ed59570df 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2192,7 +2192,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, unsigned long count, struct list_head *list, int migratetype, bool cold) { - int i; + int i, alloced = 0; spin_lock(&zone->lock); for (i = 0; i < count; ++i) { @@ -2217,13 +2217,14 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, else list_add_tail(&page->lru, list); list = &page->lru; + alloced++; if (is_migrate_cma(get_pcppage_migratetype(page))) __mod_zone_page_state(zone, NR_FREE_CMA_PAGES, -(1 << order)); } __mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order)); Now i is a pure index, yes? No, even if a page fails the check_pcp_refill() check and is not "allocated", it is also no longer a free page, so it's correct to subtract it from NR_FREE_PAGES. spin_unlock(&zone->lock); - return i; + return alloced; } #ifdef CONFIG_NUMA -- 2.10.2
Re: [PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted
On Friday, December 02, 2016 8:23 AM Mel Gorman wrote: > Vlastimil Babka pointed out that commit 479f854a207c ("mm, page_alloc: > defer debugging checks of pages allocated from the PCP") will allow the > per-cpu list counter to be out of sync with the per-cpu list contents > if a struct page is corrupted. This patch keeps the accounting in sync. > > Fixes: 479f854a207c ("mm, page_alloc: defer debugging checks of pages > allocated from the PCP") > Signed-off-by: Mel Gorman > cc: sta...@vger.kernel.org [4.7+] > --- > mm/page_alloc.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/mm/page_alloc.c b/mm/page_alloc.c > index 6de9440e3ae2..777ed59570df 100644 > --- a/mm/page_alloc.c > +++ b/mm/page_alloc.c > @@ -2192,7 +2192,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int > order, > unsigned long count, struct list_head *list, > int migratetype, bool cold) > { > - int i; > + int i, alloced = 0; > > spin_lock(&zone->lock); > for (i = 0; i < count; ++i) { > @@ -2217,13 +2217,14 @@ static int rmqueue_bulk(struct zone *zone, unsigned > int order, > else > list_add_tail(&page->lru, list); > list = &page->lru; > + alloced++; > if (is_migrate_cma(get_pcppage_migratetype(page))) > __mod_zone_page_state(zone, NR_FREE_CMA_PAGES, > -(1 << order)); > } > __mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order)); Now i is a pure index, yes? > spin_unlock(&zone->lock); > - return i; > + return alloced; > } > > #ifdef CONFIG_NUMA > -- > 2.10.2
[PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted
Vlastimil Babka pointed out that commit 479f854a207c ("mm, page_alloc: defer debugging checks of pages allocated from the PCP") will allow the per-cpu list counter to be out of sync with the per-cpu list contents if a struct page is corrupted. This patch keeps the accounting in sync. Fixes: 479f854a207c ("mm, page_alloc: defer debugging checks of pages allocated from the PCP") Signed-off-by: Mel Gorman cc: sta...@vger.kernel.org [4.7+] --- mm/page_alloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6de9440e3ae2..777ed59570df 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2192,7 +2192,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, unsigned long count, struct list_head *list, int migratetype, bool cold) { - int i; + int i, alloced = 0; spin_lock(&zone->lock); for (i = 0; i < count; ++i) { @@ -2217,13 +2217,14 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order, else list_add_tail(&page->lru, list); list = &page->lru; + alloced++; if (is_migrate_cma(get_pcppage_migratetype(page))) __mod_zone_page_state(zone, NR_FREE_CMA_PAGES, -(1 << order)); } __mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order)); spin_unlock(&zone->lock); - return i; + return alloced; } #ifdef CONFIG_NUMA -- 2.10.2