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.