All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <20170511021240.GA22319@js1304-desktop>

diff --git a/a/1.txt b/N1/1.txt
index fdbdf29..8e1a869 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -138,3 +138,243 @@ Thanks.
 
 
 ------------------->8----------------------
+>From bd8baee10fd83121b4172375524b97c3296a61e1 Mon Sep 17 00:00:00 2001
+From: Joonsoo Kim <iamjoonsoo.kim@lge.com>
+Date: Wed, 10 May 2017 15:12:26 +0900
+Subject: [RFC PATCH] mm/cma: don't use one more bit on page flags for ZONE_CMA
+
+This is just for showing my idea to solve the page flags problem
+due to ZONE_CMA. There is some consensus that ZONE_CMA is a nicer
+solution than MIGRATETYPE approach but there is also a worry about
+using one more bit on page flags. This patch tries to solve this
+worry. This patch is a temporary implementation and I will
+optimize it more if everyone agree with this approach.
+
+Adding a new zone (ZONE_CMA) needs one more bit on page flags
+in some configuration. This resource is very precious so that
+it's better not to consume it as much as possible. Therefore,
+this patch implements following tricky magic not to use one more bit.
+
+1. If the number of the zone are five due to the ZONE_CMA, start
+encoding magic.
+2. ZONE_MOVABLE is written on the pages for ZONE_CMA. Since we don't
+use ZONE_CMA (enum value 4) that needs one more bit for encoding,
+we can save one bit on page flags.
+3. Check ZONE_MOVABLE when retrieving page's zone index.
+If the zone index is ZONE_MOVABLE, we use a special handler function
+to get the actual zone index.
+
+I found no regression on kernel build test with applying this magic.
+
+Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>
+---
+ include/linux/cma.h               | 24 ++++++++++++++++++++++++
+ include/linux/gfp.h               | 24 ++++++++++++++++++++++--
+ include/linux/mm.h                |  8 +++++++-
+ include/linux/page-flags-layout.h | 15 ++++++++++++++-
+ mm/cma.c                          | 19 +++++++++++++++++++
+ mm/page_alloc.c                   | 10 +++++++++-
+ 6 files changed, 95 insertions(+), 5 deletions(-)
+
+diff --git a/include/linux/cma.h b/include/linux/cma.h
+index 2433d5e..d36695c 100644
+--- a/include/linux/cma.h
++++ b/include/linux/cma.h
+@@ -3,6 +3,7 @@
+ 
+ #include <linux/init.h>
+ #include <linux/types.h>
++#include <linux/mmzone.h>
+ 
+ /*
+  * There is always at least global CMA area and a few optional
+@@ -34,9 +35,32 @@ extern struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align,
+ extern bool cma_release(struct cma *cma, const struct page *pages, unsigned int count);
+ 
+ #ifdef CONFIG_CMA
++extern unsigned cma_area_count;
+ extern unsigned long cma_get_free(void);
++extern bool is_zone_cma_page(const struct page *page);
++
++static inline enum zone_type page_zonenum_special(const struct page *page,
++			enum zone_type zone_type)
++{
++	if (!cma_area_count)
++		return zone_type;
++
++	if (zone_type != ZONE_MOVABLE)
++		return zone_type;
++
++	if (is_zone_cma_page(page))
++		return ZONE_CMA;
++
++	return ZONE_MOVABLE;
++}
++
+ #else
+ static inline unsigned long cma_get_free(void) { return 0; }
++static inline enum zone_type page_zonenum_special(const struct page *page,
++			enum zone_type zone_type)
++{
++	return zone_type;
++}
+ #endif
+ 
+ #endif
+diff --git a/include/linux/gfp.h b/include/linux/gfp.h
+index 15987cc..bc5e443 100644
+--- a/include/linux/gfp.h
++++ b/include/linux/gfp.h
+@@ -348,13 +348,33 @@ static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags)
+  *       0xf    => BAD (MOVABLE+DMA32+HIGHMEM+DMA)
+  */
+ 
+-#if defined(CONFIG_ZONE_DEVICE) && (MAX_NR_ZONES-1) <= 4
++#if MAX_NR_ZONES <= 4
++#define GFP_ZONES_SHIFT ZONES_SHIFT
++#elif (MAX_NR_ZONES-1) == 4
++
++/*
++ * ZONE_CMA is encoded as ZONE_MOVABLE and ZONES_SHIFT would be one less
++ * than what GFP_ZONES_SHIFT usually needs.
++ */
++#if defined(CONFIG_ZONE_DEVICE) && defined(CONFIG_CMA)
++#define GFP_ZONES_SHIFT ZONES_SHIFT
++
+ /* ZONE_DEVICE is not a valid GFP zone specifier */
+-#define GFP_ZONES_SHIFT 2
++#elif defined(CONFIG_ZONE_DEVICE)
++#define GFP_ZONES_SHIFT Z
++
++#elif defined(CONFIG_CMA)
++#define GFP_ZONES_SHIFT (ZONES_SHIFT + 1)
++
++#else
++#define GFP_ZONES_SHIFT ZONES_SHIFT
++#endif
++
+ #else
+ #define GFP_ZONES_SHIFT ZONES_SHIFT
+ #endif
+ 
++
+ #if !defined(CONFIG_64BITS) && GFP_ZONES_SHIFT > 2
+ typedef unsigned long long GFP_ZONE_TABLE_TYPE;
+ #else
+diff --git a/include/linux/mm.h b/include/linux/mm.h
+index 693dc6e..50228ef 100644
+--- a/include/linux/mm.h
++++ b/include/linux/mm.h
+@@ -23,6 +23,7 @@
+ #include <linux/page_ext.h>
+ #include <linux/err.h>
+ #include <linux/page_ref.h>
++#include <linux/cma.h>
+ 
+ struct mempolicy;
+ struct anon_vma;
+@@ -780,7 +781,12 @@ int finish_mkwrite_fault(struct vm_fault *vmf);
+ 
+ static inline enum zone_type page_zonenum(const struct page *page)
+ {
+-	return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK;
++	enum zone_type zone_type = (page->flags >> ZONES_PGSHIFT) & ZONES_MASK;
++
++	if (ZONE_CMA_IN_PAGE_FLAGS)
++		return zone_type;
++
++	return page_zonenum_special(page, zone_type);
+ }
+ 
+ #ifdef CONFIG_ZONE_DEVICE
+diff --git a/include/linux/page-flags-layout.h b/include/linux/page-flags-layout.h
+index 77b078c..8a4ae38 100644
+--- a/include/linux/page-flags-layout.h
++++ b/include/linux/page-flags-layout.h
+@@ -17,12 +17,25 @@
+ #define ZONES_SHIFT 1
+ #elif MAX_NR_ZONES <= 4
+ #define ZONES_SHIFT 2
++
+ #elif MAX_NR_ZONES <= 8
+-#define ZONES_SHIFT 3
++
++#if defined(CONFIG_CMA) && (MAX_NR_ZONES-1) <= 4
++#define ZONES_SHIFT 2
++#define ZONE_CMA_IN_PAGE_FLAGS 0
+ #else
++#define ZONES_SHIFT 3
++#endif
++
++#else /* MAX_NR_ZONES <= 8 */
++
+ #error ZONES_SHIFT -- too many zones configured adjust calculation
+ #endif
+ 
++#ifndef ZONE_CMA_IN_PAGE_FLAGS
++#define ZONE_CMA_IN_PAGE_FLAGS 1
++#endif
++
+ #ifdef CONFIG_SPARSEMEM
+ #include <asm/sparsemem.h>
+ 
+diff --git a/mm/cma.c b/mm/cma.c
+index adfda1c..1833973 100644
+--- a/mm/cma.c
++++ b/mm/cma.c
+@@ -110,6 +110,25 @@ static void cma_clear_bitmap(struct cma *cma, unsigned long pfn,
+ 	mutex_unlock(&cma->lock);
+ }
+ 
++bool is_zone_cma_page(const struct page *page)
++{
++	struct cma *cma;
++	int i;
++	unsigned long pfn = page_to_pfn(page);
++
++	for (i = 0; i < cma_area_count; i++) {
++		cma = &cma_areas[i];
++
++		if (pfn < cma->base_pfn)
++			continue;
++
++		if (pfn < cma->base_pfn + cma->count)
++			return true;
++	}
++
++	return false;
++}
++
+ static int __init cma_activate_area(struct cma *cma)
+ {
+ 	int bitmap_size = BITS_TO_LONGS(cma_bitmap_maxno(cma)) * sizeof(long);
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index cf29227..9399cc4 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -1596,6 +1596,14 @@ void __init init_cma_reserved_pageblock(struct page *page)
+ 	unsigned long pfn = page_to_pfn(page);
+ 	struct page *p = page;
+ 	int nid = page_to_nid(page);
++	enum zone_type zone_type;
++
++	/*
++	 * In some cases, we don't have enough place to encode ZONE_CMA
++	 * in page flags. Use ZONE_MOVABLE in this case and do
++	 * post-processing when getting the page's zone.
++	 */
++	zone_type = ZONE_CMA_IN_PAGE_FLAGS ? ZONE_CMA : ZONE_MOVABLE;
+ 
+ 	/*
+ 	 * ZONE_CMA will steal present pages from other zones by changing
+@@ -1609,7 +1617,7 @@ void __init init_cma_reserved_pageblock(struct page *page)
+ 		set_page_count(p, 0);
+ 
+ 		/* Steal pages from other zones */
+-		set_page_links(p, ZONE_CMA, nid, pfn);
++		set_page_links(p, zone_type, nid, pfn);
+ 	} while (++p, ++pfn, --i);
+ 
+ 	adjust_present_page_count(page, pageblock_nr_pages);
+-- 
+2.7.4
diff --git a/a/content_digest b/N1/content_digest
index 2bd011b..c08ffc3 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -168,6 +168,246 @@
  "Thanks.\n"
  "\n"
  "\n"
- ------------------->8----------------------
+ "------------------->8----------------------\n"
+ ">From bd8baee10fd83121b4172375524b97c3296a61e1 Mon Sep 17 00:00:00 2001\n"
+ "From: Joonsoo Kim <iamjoonsoo.kim@lge.com>\n"
+ "Date: Wed, 10 May 2017 15:12:26 +0900\n"
+ "Subject: [RFC PATCH] mm/cma: don't use one more bit on page flags for ZONE_CMA\n"
+ "\n"
+ "This is just for showing my idea to solve the page flags problem\n"
+ "due to ZONE_CMA. There is some consensus that ZONE_CMA is a nicer\n"
+ "solution than MIGRATETYPE approach but there is also a worry about\n"
+ "using one more bit on page flags. This patch tries to solve this\n"
+ "worry. This patch is a temporary implementation and I will\n"
+ "optimize it more if everyone agree with this approach.\n"
+ "\n"
+ "Adding a new zone (ZONE_CMA) needs one more bit on page flags\n"
+ "in some configuration. This resource is very precious so that\n"
+ "it's better not to consume it as much as possible. Therefore,\n"
+ "this patch implements following tricky magic not to use one more bit.\n"
+ "\n"
+ "1. If the number of the zone are five due to the ZONE_CMA, start\n"
+ "encoding magic.\n"
+ "2. ZONE_MOVABLE is written on the pages for ZONE_CMA. Since we don't\n"
+ "use ZONE_CMA (enum value 4) that needs one more bit for encoding,\n"
+ "we can save one bit on page flags.\n"
+ "3. Check ZONE_MOVABLE when retrieving page's zone index.\n"
+ "If the zone index is ZONE_MOVABLE, we use a special handler function\n"
+ "to get the actual zone index.\n"
+ "\n"
+ "I found no regression on kernel build test with applying this magic.\n"
+ "\n"
+ "Signed-off-by: Joonsoo Kim <iamjoonsoo.kim@lge.com>\n"
+ "---\n"
+ " include/linux/cma.h               | 24 ++++++++++++++++++++++++\n"
+ " include/linux/gfp.h               | 24 ++++++++++++++++++++++--\n"
+ " include/linux/mm.h                |  8 +++++++-\n"
+ " include/linux/page-flags-layout.h | 15 ++++++++++++++-\n"
+ " mm/cma.c                          | 19 +++++++++++++++++++\n"
+ " mm/page_alloc.c                   | 10 +++++++++-\n"
+ " 6 files changed, 95 insertions(+), 5 deletions(-)\n"
+ "\n"
+ "diff --git a/include/linux/cma.h b/include/linux/cma.h\n"
+ "index 2433d5e..d36695c 100644\n"
+ "--- a/include/linux/cma.h\n"
+ "+++ b/include/linux/cma.h\n"
+ "@@ -3,6 +3,7 @@\n"
+ " \n"
+ " #include <linux/init.h>\n"
+ " #include <linux/types.h>\n"
+ "+#include <linux/mmzone.h>\n"
+ " \n"
+ " /*\n"
+ "  * There is always at least global CMA area and a few optional\n"
+ "@@ -34,9 +35,32 @@ extern struct page *cma_alloc(struct cma *cma, size_t count, unsigned int align,\n"
+ " extern bool cma_release(struct cma *cma, const struct page *pages, unsigned int count);\n"
+ " \n"
+ " #ifdef CONFIG_CMA\n"
+ "+extern unsigned cma_area_count;\n"
+ " extern unsigned long cma_get_free(void);\n"
+ "+extern bool is_zone_cma_page(const struct page *page);\n"
+ "+\n"
+ "+static inline enum zone_type page_zonenum_special(const struct page *page,\n"
+ "+\t\t\tenum zone_type zone_type)\n"
+ "+{\n"
+ "+\tif (!cma_area_count)\n"
+ "+\t\treturn zone_type;\n"
+ "+\n"
+ "+\tif (zone_type != ZONE_MOVABLE)\n"
+ "+\t\treturn zone_type;\n"
+ "+\n"
+ "+\tif (is_zone_cma_page(page))\n"
+ "+\t\treturn ZONE_CMA;\n"
+ "+\n"
+ "+\treturn ZONE_MOVABLE;\n"
+ "+}\n"
+ "+\n"
+ " #else\n"
+ " static inline unsigned long cma_get_free(void) { return 0; }\n"
+ "+static inline enum zone_type page_zonenum_special(const struct page *page,\n"
+ "+\t\t\tenum zone_type zone_type)\n"
+ "+{\n"
+ "+\treturn zone_type;\n"
+ "+}\n"
+ " #endif\n"
+ " \n"
+ " #endif\n"
+ "diff --git a/include/linux/gfp.h b/include/linux/gfp.h\n"
+ "index 15987cc..bc5e443 100644\n"
+ "--- a/include/linux/gfp.h\n"
+ "+++ b/include/linux/gfp.h\n"
+ "@@ -348,13 +348,33 @@ static inline bool gfpflags_allow_blocking(const gfp_t gfp_flags)\n"
+ "  *       0xf    => BAD (MOVABLE+DMA32+HIGHMEM+DMA)\n"
+ "  */\n"
+ " \n"
+ "-#if defined(CONFIG_ZONE_DEVICE) && (MAX_NR_ZONES-1) <= 4\n"
+ "+#if MAX_NR_ZONES <= 4\n"
+ "+#define GFP_ZONES_SHIFT ZONES_SHIFT\n"
+ "+#elif (MAX_NR_ZONES-1) == 4\n"
+ "+\n"
+ "+/*\n"
+ "+ * ZONE_CMA is encoded as ZONE_MOVABLE and ZONES_SHIFT would be one less\n"
+ "+ * than what GFP_ZONES_SHIFT usually needs.\n"
+ "+ */\n"
+ "+#if defined(CONFIG_ZONE_DEVICE) && defined(CONFIG_CMA)\n"
+ "+#define GFP_ZONES_SHIFT ZONES_SHIFT\n"
+ "+\n"
+ " /* ZONE_DEVICE is not a valid GFP zone specifier */\n"
+ "-#define GFP_ZONES_SHIFT 2\n"
+ "+#elif defined(CONFIG_ZONE_DEVICE)\n"
+ "+#define GFP_ZONES_SHIFT Z\n"
+ "+\n"
+ "+#elif defined(CONFIG_CMA)\n"
+ "+#define GFP_ZONES_SHIFT (ZONES_SHIFT + 1)\n"
+ "+\n"
+ "+#else\n"
+ "+#define GFP_ZONES_SHIFT ZONES_SHIFT\n"
+ "+#endif\n"
+ "+\n"
+ " #else\n"
+ " #define GFP_ZONES_SHIFT ZONES_SHIFT\n"
+ " #endif\n"
+ " \n"
+ "+\n"
+ " #if !defined(CONFIG_64BITS) && GFP_ZONES_SHIFT > 2\n"
+ " typedef unsigned long long GFP_ZONE_TABLE_TYPE;\n"
+ " #else\n"
+ "diff --git a/include/linux/mm.h b/include/linux/mm.h\n"
+ "index 693dc6e..50228ef 100644\n"
+ "--- a/include/linux/mm.h\n"
+ "+++ b/include/linux/mm.h\n"
+ "@@ -23,6 +23,7 @@\n"
+ " #include <linux/page_ext.h>\n"
+ " #include <linux/err.h>\n"
+ " #include <linux/page_ref.h>\n"
+ "+#include <linux/cma.h>\n"
+ " \n"
+ " struct mempolicy;\n"
+ " struct anon_vma;\n"
+ "@@ -780,7 +781,12 @@ int finish_mkwrite_fault(struct vm_fault *vmf);\n"
+ " \n"
+ " static inline enum zone_type page_zonenum(const struct page *page)\n"
+ " {\n"
+ "-\treturn (page->flags >> ZONES_PGSHIFT) & ZONES_MASK;\n"
+ "+\tenum zone_type zone_type = (page->flags >> ZONES_PGSHIFT) & ZONES_MASK;\n"
+ "+\n"
+ "+\tif (ZONE_CMA_IN_PAGE_FLAGS)\n"
+ "+\t\treturn zone_type;\n"
+ "+\n"
+ "+\treturn page_zonenum_special(page, zone_type);\n"
+ " }\n"
+ " \n"
+ " #ifdef CONFIG_ZONE_DEVICE\n"
+ "diff --git a/include/linux/page-flags-layout.h b/include/linux/page-flags-layout.h\n"
+ "index 77b078c..8a4ae38 100644\n"
+ "--- a/include/linux/page-flags-layout.h\n"
+ "+++ b/include/linux/page-flags-layout.h\n"
+ "@@ -17,12 +17,25 @@\n"
+ " #define ZONES_SHIFT 1\n"
+ " #elif MAX_NR_ZONES <= 4\n"
+ " #define ZONES_SHIFT 2\n"
+ "+\n"
+ " #elif MAX_NR_ZONES <= 8\n"
+ "-#define ZONES_SHIFT 3\n"
+ "+\n"
+ "+#if defined(CONFIG_CMA) && (MAX_NR_ZONES-1) <= 4\n"
+ "+#define ZONES_SHIFT 2\n"
+ "+#define ZONE_CMA_IN_PAGE_FLAGS 0\n"
+ " #else\n"
+ "+#define ZONES_SHIFT 3\n"
+ "+#endif\n"
+ "+\n"
+ "+#else /* MAX_NR_ZONES <= 8 */\n"
+ "+\n"
+ " #error ZONES_SHIFT -- too many zones configured adjust calculation\n"
+ " #endif\n"
+ " \n"
+ "+#ifndef ZONE_CMA_IN_PAGE_FLAGS\n"
+ "+#define ZONE_CMA_IN_PAGE_FLAGS 1\n"
+ "+#endif\n"
+ "+\n"
+ " #ifdef CONFIG_SPARSEMEM\n"
+ " #include <asm/sparsemem.h>\n"
+ " \n"
+ "diff --git a/mm/cma.c b/mm/cma.c\n"
+ "index adfda1c..1833973 100644\n"
+ "--- a/mm/cma.c\n"
+ "+++ b/mm/cma.c\n"
+ "@@ -110,6 +110,25 @@ static void cma_clear_bitmap(struct cma *cma, unsigned long pfn,\n"
+ " \tmutex_unlock(&cma->lock);\n"
+ " }\n"
+ " \n"
+ "+bool is_zone_cma_page(const struct page *page)\n"
+ "+{\n"
+ "+\tstruct cma *cma;\n"
+ "+\tint i;\n"
+ "+\tunsigned long pfn = page_to_pfn(page);\n"
+ "+\n"
+ "+\tfor (i = 0; i < cma_area_count; i++) {\n"
+ "+\t\tcma = &cma_areas[i];\n"
+ "+\n"
+ "+\t\tif (pfn < cma->base_pfn)\n"
+ "+\t\t\tcontinue;\n"
+ "+\n"
+ "+\t\tif (pfn < cma->base_pfn + cma->count)\n"
+ "+\t\t\treturn true;\n"
+ "+\t}\n"
+ "+\n"
+ "+\treturn false;\n"
+ "+}\n"
+ "+\n"
+ " static int __init cma_activate_area(struct cma *cma)\n"
+ " {\n"
+ " \tint bitmap_size = BITS_TO_LONGS(cma_bitmap_maxno(cma)) * sizeof(long);\n"
+ "diff --git a/mm/page_alloc.c b/mm/page_alloc.c\n"
+ "index cf29227..9399cc4 100644\n"
+ "--- a/mm/page_alloc.c\n"
+ "+++ b/mm/page_alloc.c\n"
+ "@@ -1596,6 +1596,14 @@ void __init init_cma_reserved_pageblock(struct page *page)\n"
+ " \tunsigned long pfn = page_to_pfn(page);\n"
+ " \tstruct page *p = page;\n"
+ " \tint nid = page_to_nid(page);\n"
+ "+\tenum zone_type zone_type;\n"
+ "+\n"
+ "+\t/*\n"
+ "+\t * In some cases, we don't have enough place to encode ZONE_CMA\n"
+ "+\t * in page flags. Use ZONE_MOVABLE in this case and do\n"
+ "+\t * post-processing when getting the page's zone.\n"
+ "+\t */\n"
+ "+\tzone_type = ZONE_CMA_IN_PAGE_FLAGS ? ZONE_CMA : ZONE_MOVABLE;\n"
+ " \n"
+ " \t/*\n"
+ " \t * ZONE_CMA will steal present pages from other zones by changing\n"
+ "@@ -1609,7 +1617,7 @@ void __init init_cma_reserved_pageblock(struct page *page)\n"
+ " \t\tset_page_count(p, 0);\n"
+ " \n"
+ " \t\t/* Steal pages from other zones */\n"
+ "-\t\tset_page_links(p, ZONE_CMA, nid, pfn);\n"
+ "+\t\tset_page_links(p, zone_type, nid, pfn);\n"
+ " \t} while (++p, ++pfn, --i);\n"
+ " \n"
+ " \tadjust_present_page_count(page, pageblock_nr_pages);\n"
+ "-- \n"
+ 2.7.4
 
-a4dedc790f601473980d9afe59146703ef6e416994b11421a585e4cdaddb74d5
+f9ccae06b246d98b27835183f3c1667e320f5ef08a2663d0a840ebf2c053f576

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.