Re: [PATCH 1/2] mm, page_alloc: Keep pcp count and list contents in sync if struct page is corrupted

2016-12-04 Thread Hillf Danton
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

2016-12-02 Thread Michal Hocko
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

2016-12-02 Thread Vlastimil Babka

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

2016-12-02 Thread Mel Gorman
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

2016-12-02 Thread Mel Gorman
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

2016-12-02 Thread Michal Hocko
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

2016-12-02 Thread Michal Hocko
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

2016-12-02 Thread Mel Gorman
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

2016-12-02 Thread Hillf Danton
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

2016-12-02 Thread Michal Hocko
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

2016-12-01 Thread Vlastimil Babka

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

2016-12-01 Thread Hillf Danton
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

2016-12-01 Thread Mel Gorman
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