All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] mm, page_alloc: disallow __GFP_COMP in alloc_pages_exact()
@ 2019-03-14  9:39 Vlastimil Babka
  2019-03-14  9:42 ` [PATCH v2] " Vlastimil Babka
  0 siblings, 1 reply; 19+ messages in thread
From: Vlastimil Babka @ 2019-03-14  9:39 UTC (permalink / raw)
  To: linux-mm
  Cc: Michal Hocko, Kirill A. Shutemov, Mel Gorman, Takashi Iwai,
	Vlastimil Babka

alloc_pages_exact*() allocates a page of sufficient order and then splits it
to return only the number of pages requested. That makes it incompatible with
__GFP_COMP, because compound pages cannot be split.

As shown by [1] things may silently work until the requested size (possibly
depending on user) stops being power of two. Then for CONFIG_DEBUG_VM, BUG_ON()
triggers in split_page(). Without CONFIG_DEBUG_VM, consequences are unclear.

There are several options here, none of them great:

1) Don't do the spliting when __GFP_COMP is passed, and return the whole
compound page. However if caller then returns it via free_pages_exact(),
that will be unexpected and the freeing actions there will be wrong.

2) Warn and remove __GFP_COMP from the flags. But the caller wanted it, so
things make break later somewhere.

3) Warn and return NULL. However NULL may be unexpected, especially for
small sizes.

This patch picks option 3, as it's best defined.

[1] https://lore.kernel.org/lkml/20181126002805.GI18977@shao2-debian/T/#u

Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
---
 mm/page_alloc.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 0b9f577b1a2a..3127d47afaa7 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -4752,7 +4752,7 @@ static void *make_alloc_exact(unsigned long addr, unsigned int order,
 /**
  * alloc_pages_exact - allocate an exact number physically-contiguous pages.
  * @size: the number of bytes to allocate
- * @gfp_mask: GFP flags for the allocation
+ * @gfp_mask: GFP flags for the allocation, must not contain __GFP_COMP
  *
  * This function is similar to alloc_pages(), except that it allocates the
  * minimum number of pages to satisfy the request.  alloc_pages() can only
@@ -4768,6 +4768,10 @@ void *alloc_pages_exact(size_t size, gfp_t gfp_mask)
 	unsigned long addr;
 
 	addr = __get_free_pages(gfp_mask, order);
+
+	if (WARN_ON_ONCE(gfp_mask & __GFP_COMP))
+		gfp_mask &= ~__GFP_COMP;
+
 	return make_alloc_exact(addr, order, size);
 }
 EXPORT_SYMBOL(alloc_pages_exact);
-- 
2.20.1


^ permalink raw reply related	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2019-03-19  9:47 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-14  9:39 [PATCH] mm, page_alloc: disallow __GFP_COMP in alloc_pages_exact() Vlastimil Babka
2019-03-14  9:42 ` [PATCH v2] " Vlastimil Babka
2019-03-14 10:15   ` Michal Hocko
2019-03-14 10:30     ` Vlastimil Babka
2019-03-14 11:36       ` Michal Hocko
2019-03-14 11:56         ` Takashi Iwai
2019-03-14 12:09           ` Michal Hocko
2019-03-14 13:15             ` Takashi Iwai
2019-03-14 13:29               ` Michal Hocko
2019-03-14 16:52                 ` Takashi Iwai
2019-03-14 17:37                   ` Hugh Dickins
2019-03-14 18:00                     ` Takashi Iwai
2019-03-14 18:15                       ` Hugh Dickins
2019-03-14 20:13                         ` Takashi Iwai
2019-03-14 18:51   ` Kirill A. Shutemov
2019-03-18 12:21   ` [PATCH v3] " Vlastimil Babka
2019-03-18 12:43     ` Michal Hocko
2019-03-19  8:45     ` Kirill A. Shutemov
2019-03-19  9:47     ` Mel Gorman

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.