[PATCH 4.14 28/67] percpu: add __GFP_NORETRY semantics to the percpu balancing path

2018-04-06 Thread Greg Kroah-Hartman
4.14-stable review patch.  If anyone has any objections, please let me know.

--

From: Dennis Zhou 

commit 47504ee04b9241548ae2c28be7d0b01cff3b7aa6 upstream.

Percpu memory using the vmalloc area based chunk allocator lazily
populates chunks by first requesting the full virtual address space
required for the chunk and subsequently adding pages as allocations come
through. To ensure atomic allocations can succeed, a workqueue item is
used to maintain a minimum number of empty pages. In certain scenarios,
such as reported in [1], it is possible that physical memory becomes
quite scarce which can result in either a rather long time spent trying
to find free pages or worse, a kernel panic.

This patch adds support for __GFP_NORETRY and __GFP_NOWARN passing them
through to the underlying allocators. This should prevent any
unnecessary panics potentially caused by the workqueue item. The passing
of gfp around is as additional flags rather than a full set of flags.
The next patch will change these to caller passed semantics.

V2:
Added const modifier to gfp flags in the balance path.
Removed an extra whitespace.

[1] https://lkml.org/lkml/2018/2/12/551

Signed-off-by: Dennis Zhou 
Suggested-by: Daniel Borkmann 
Reported-by: syzbot+adb03f3f0bb57ce3a...@syzkaller.appspotmail.com
Acked-by: Christoph Lameter 
Signed-off-by: Tejun Heo 
Signed-off-by: Greg Kroah-Hartman 

---
 mm/percpu-km.c |8 
 mm/percpu-vm.c |   18 +++---
 mm/percpu.c|   45 -
 3 files changed, 43 insertions(+), 28 deletions(-)

--- a/mm/percpu-km.c
+++ b/mm/percpu-km.c
@@ -34,7 +34,7 @@
 #include 
 
 static int pcpu_populate_chunk(struct pcpu_chunk *chunk,
-  int page_start, int page_end)
+  int page_start, int page_end, gfp_t gfp)
 {
return 0;
 }
@@ -45,18 +45,18 @@ static void pcpu_depopulate_chunk(struct
/* nada */
 }
 
-static struct pcpu_chunk *pcpu_create_chunk(void)
+static struct pcpu_chunk *pcpu_create_chunk(gfp_t gfp)
 {
const int nr_pages = pcpu_group_sizes[0] >> PAGE_SHIFT;
struct pcpu_chunk *chunk;
struct page *pages;
int i;
 
-   chunk = pcpu_alloc_chunk();
+   chunk = pcpu_alloc_chunk(gfp);
if (!chunk)
return NULL;
 
-   pages = alloc_pages(GFP_KERNEL, order_base_2(nr_pages));
+   pages = alloc_pages(gfp | GFP_KERNEL, order_base_2(nr_pages));
if (!pages) {
pcpu_free_chunk(chunk);
return NULL;
--- a/mm/percpu-vm.c
+++ b/mm/percpu-vm.c
@@ -37,7 +37,7 @@ static struct page **pcpu_get_pages(void
lockdep_assert_held(_alloc_mutex);
 
if (!pages)
-   pages = pcpu_mem_zalloc(pages_size);
+   pages = pcpu_mem_zalloc(pages_size, 0);
return pages;
 }
 
@@ -73,18 +73,21 @@ static void pcpu_free_pages(struct pcpu_
  * @pages: array to put the allocated pages into, indexed by pcpu_page_idx()
  * @page_start: page index of the first page to be allocated
  * @page_end: page index of the last page to be allocated + 1
+ * @gfp: allocation flags passed to the underlying allocator
  *
  * Allocate pages [@page_start,@page_end) into @pages for all units.
  * The allocation is for @chunk.  Percpu core doesn't care about the
  * content of @pages and will pass it verbatim to pcpu_map_pages().
  */
 static int pcpu_alloc_pages(struct pcpu_chunk *chunk,
-   struct page **pages, int page_start, int page_end)
+   struct page **pages, int page_start, int page_end,
+   gfp_t gfp)
 {
-   const gfp_t gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD;
unsigned int cpu, tcpu;
int i;
 
+   gfp |= GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD;
+
for_each_possible_cpu(cpu) {
for (i = page_start; i < page_end; i++) {
struct page **pagep = [pcpu_page_idx(cpu, i)];
@@ -262,6 +265,7 @@ static void pcpu_post_map_flush(struct p
  * @chunk: chunk of interest
  * @page_start: the start page
  * @page_end: the end page
+ * @gfp: allocation flags passed to the underlying memory allocator
  *
  * For each cpu, populate and map pages [@page_start,@page_end) into
  * @chunk.
@@ -270,7 +274,7 @@ static void pcpu_post_map_flush(struct p
  * pcpu_alloc_mutex, does GFP_KERNEL allocation.
  */
 static int pcpu_populate_chunk(struct pcpu_chunk *chunk,
-  int page_start, int page_end)
+  int page_start, int page_end, gfp_t gfp)
 {
struct page **pages;
 
@@ -278,7 +282,7 @@ static int pcpu_populate_chunk(struct pc
if (!pages)
return -ENOMEM;
 
-   if (pcpu_alloc_pages(chunk, pages, page_start, page_end))
+   if 

[PATCH 4.14 28/67] percpu: add __GFP_NORETRY semantics to the percpu balancing path

2018-04-06 Thread Greg Kroah-Hartman
4.14-stable review patch.  If anyone has any objections, please let me know.

--

From: Dennis Zhou 

commit 47504ee04b9241548ae2c28be7d0b01cff3b7aa6 upstream.

Percpu memory using the vmalloc area based chunk allocator lazily
populates chunks by first requesting the full virtual address space
required for the chunk and subsequently adding pages as allocations come
through. To ensure atomic allocations can succeed, a workqueue item is
used to maintain a minimum number of empty pages. In certain scenarios,
such as reported in [1], it is possible that physical memory becomes
quite scarce which can result in either a rather long time spent trying
to find free pages or worse, a kernel panic.

This patch adds support for __GFP_NORETRY and __GFP_NOWARN passing them
through to the underlying allocators. This should prevent any
unnecessary panics potentially caused by the workqueue item. The passing
of gfp around is as additional flags rather than a full set of flags.
The next patch will change these to caller passed semantics.

V2:
Added const modifier to gfp flags in the balance path.
Removed an extra whitespace.

[1] https://lkml.org/lkml/2018/2/12/551

Signed-off-by: Dennis Zhou 
Suggested-by: Daniel Borkmann 
Reported-by: syzbot+adb03f3f0bb57ce3a...@syzkaller.appspotmail.com
Acked-by: Christoph Lameter 
Signed-off-by: Tejun Heo 
Signed-off-by: Greg Kroah-Hartman 

---
 mm/percpu-km.c |8 
 mm/percpu-vm.c |   18 +++---
 mm/percpu.c|   45 -
 3 files changed, 43 insertions(+), 28 deletions(-)

--- a/mm/percpu-km.c
+++ b/mm/percpu-km.c
@@ -34,7 +34,7 @@
 #include 
 
 static int pcpu_populate_chunk(struct pcpu_chunk *chunk,
-  int page_start, int page_end)
+  int page_start, int page_end, gfp_t gfp)
 {
return 0;
 }
@@ -45,18 +45,18 @@ static void pcpu_depopulate_chunk(struct
/* nada */
 }
 
-static struct pcpu_chunk *pcpu_create_chunk(void)
+static struct pcpu_chunk *pcpu_create_chunk(gfp_t gfp)
 {
const int nr_pages = pcpu_group_sizes[0] >> PAGE_SHIFT;
struct pcpu_chunk *chunk;
struct page *pages;
int i;
 
-   chunk = pcpu_alloc_chunk();
+   chunk = pcpu_alloc_chunk(gfp);
if (!chunk)
return NULL;
 
-   pages = alloc_pages(GFP_KERNEL, order_base_2(nr_pages));
+   pages = alloc_pages(gfp | GFP_KERNEL, order_base_2(nr_pages));
if (!pages) {
pcpu_free_chunk(chunk);
return NULL;
--- a/mm/percpu-vm.c
+++ b/mm/percpu-vm.c
@@ -37,7 +37,7 @@ static struct page **pcpu_get_pages(void
lockdep_assert_held(_alloc_mutex);
 
if (!pages)
-   pages = pcpu_mem_zalloc(pages_size);
+   pages = pcpu_mem_zalloc(pages_size, 0);
return pages;
 }
 
@@ -73,18 +73,21 @@ static void pcpu_free_pages(struct pcpu_
  * @pages: array to put the allocated pages into, indexed by pcpu_page_idx()
  * @page_start: page index of the first page to be allocated
  * @page_end: page index of the last page to be allocated + 1
+ * @gfp: allocation flags passed to the underlying allocator
  *
  * Allocate pages [@page_start,@page_end) into @pages for all units.
  * The allocation is for @chunk.  Percpu core doesn't care about the
  * content of @pages and will pass it verbatim to pcpu_map_pages().
  */
 static int pcpu_alloc_pages(struct pcpu_chunk *chunk,
-   struct page **pages, int page_start, int page_end)
+   struct page **pages, int page_start, int page_end,
+   gfp_t gfp)
 {
-   const gfp_t gfp = GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD;
unsigned int cpu, tcpu;
int i;
 
+   gfp |= GFP_KERNEL | __GFP_HIGHMEM | __GFP_COLD;
+
for_each_possible_cpu(cpu) {
for (i = page_start; i < page_end; i++) {
struct page **pagep = [pcpu_page_idx(cpu, i)];
@@ -262,6 +265,7 @@ static void pcpu_post_map_flush(struct p
  * @chunk: chunk of interest
  * @page_start: the start page
  * @page_end: the end page
+ * @gfp: allocation flags passed to the underlying memory allocator
  *
  * For each cpu, populate and map pages [@page_start,@page_end) into
  * @chunk.
@@ -270,7 +274,7 @@ static void pcpu_post_map_flush(struct p
  * pcpu_alloc_mutex, does GFP_KERNEL allocation.
  */
 static int pcpu_populate_chunk(struct pcpu_chunk *chunk,
-  int page_start, int page_end)
+  int page_start, int page_end, gfp_t gfp)
 {
struct page **pages;
 
@@ -278,7 +282,7 @@ static int pcpu_populate_chunk(struct pc
if (!pages)
return -ENOMEM;
 
-   if (pcpu_alloc_pages(chunk, pages, page_start, page_end))
+   if (pcpu_alloc_pages(chunk, pages, page_start, page_end, gfp))
return -ENOMEM;
 
if (pcpu_map_pages(chunk, pages,