Skip to contentSkip to conversation

mm: mirrored memory support for page buddy allocations

RFC PATCH Superseded Xishi Qiu 7 participants 62 messages Jun 4, 2015 – Jun 26, 2015

Subsystems (10)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore

Xishi Qiu

author
#0 lore raw

cover mm: mirrored memory support for page buddy allocations

Intel Xeon processor E7 v3 product family-based platforms introduces support for partial memory mirroring called as 'Address Range Mirroring'. This feature allows BIOS to specify a subset of total available memory to be mirrored (and optionally also specify whether to mirror the range 0-4 GB). This capability allows user to make an appropriate tradeoff between non-mirrored memory range and mirrored memory range thus optimizing total available memory and still achieving highly reliable memory range for mission critical workloads and/or kernel space.

Tony has already send a patchset to supprot this feature at boot time.
https://lkml.org/lkml/2015/5/8/521

This patchset can support the feature after boot time. It introduces mirror_info to save the mirrored memory range. Then use __GFP_MIRROR to allocate mirrored pages.

I think add a new migratetype is btter and easier than a new zone, so I use MIGRATE_MIRROR to manage the mirrored pages. However it changed some code in the core file, please review and comment, thanks.

TBD:
1) call add_mirror_info() to fill mirrored memory info.
2) add compatibility with memory online/offline.
3) add more interface? others?

Xishi Qiu (12):
mm: add a new config to manage the code
mm: introduce mirror_info
mm: introduce MIGRATE_MIRROR to manage the mirrored pages
mm: add mirrored pages to buddy system
mm: introduce a new zone_stat_item NR_FREE_MIRROR_PAGES
mm: add free mirrored pages info
mm: introduce __GFP_MIRROR to allocate mirrored pages
mm: use mirrorable to switch allocate mirrored memory
mm: enable allocate mirrored memory at boot time
mm: add the buddy system interface
mm: add the PCP interface
mm: let slab/slub/slob use mirrored memory

 arch/x86/mm/numa.c     |   3 ++
 drivers/base/node.c    |  17 ++++---
 fs/proc/meminfo.c      |   6 +++
 include/linux/gfp.h    |   5 +-
 include/linux/mmzone.h |  23 +++++++++
 include/linux/vmstat.h |   2 +
 kernel/sysctl.c        |   9 ++++
 mm/Kconfig             |   8 +++
 mm/page_alloc.c        | 134 ++++++++++++++++++++++++++++++++++++++++++++++---
 mm/slab.c              |   3 +-
 mm/slob.c              |   2 +-
 mm/slub.c              |   2 +-
 mm/vmstat.c            |   4 ++
 13 files changed, 202 insertions(+), 16 deletions(-)
Signature · 1 line
2.0.0
author
#1 lore raw

RFC PATCH 1/12 mm: add a new config to manage the code

This patch introduces a new config called "CONFIG_ACPI_MIRROR_MEMORY", it is used to on/off the feature.

---
 mm/Kconfig | 8 ++++++++
 1 file changed, 8 insertions(+)
mm/Kconfig +8 -0
index 390214d..4f2a726 100644
@@ -200,6 +200,14 @@ config MEMORY_HOTREMOVE
 	depends on MEMORY_HOTPLUG && ARCH_ENABLE_MEMORY_HOTREMOVE
 	depends on MIGRATION
 
+config MEMORY_MIRROR
+	bool "Address range mirroring support"
+	depends on X86 && NUMA
+	default y
+	help
+	  This feature depends on hardware and firmware support.
+	  ACPI or EFI records the mirror info.
+
 #
 # If we have space for more page flags then we can enable additional
 # optimizations and functionality.
Signature · 1 line
2.0.0
#2 lore raw

Re: [RFC PATCH 01/12] mm: add a new config to manage the code

Quoted 13 lines · Xishi Qiu

This patch introduces a new config called "CONFIG_ACPI_MIRROR_MEMORY", it is used to on/off the feature.

---
 mm/Kconfig | 8 ++++++++
 1 file changed, 8 insertions(+)
mm/Kconfig +0 -0
index 390214d..4f2a726 100644

mm/Kconfig config MEMORY_HOTREMOVE · line 206

Quoted 7 lines
mm/Kconfig +4 -0
@@ -200,6 +200,14 @@ config MEMORY_HOTREMOVE
        depends on MEMORY_HOTPLUG && ARCH_ENABLE_MEMORY_HOTREMOVE
        depends on MIGRATION
 
+config MEMORY_MIRROR
+       bool "Address range mirroring support"
+       depends on X86 && NUMA
+       default y

Is it correct for the systems (NOT xeon) without memory support built in?

Quoted 16 lines
mm/Kconfig +4 -1
+       help
+         This feature depends on hardware and firmware support.
+         ACPI or EFI records the mirror info.
+
 #
 # If we have space for more page flags then we can enable additional
 # optimizations and functionality.
--

2.0.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

Signature · 8 lines
Leon Romanovsky | Independent Linux Consultant
        www.leon.nu | [email protected]

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#3 lore raw

RE: [RFC PATCH 01/12] mm: add a new config to manage the code

PiA+ICtjb25maWcgTUVNT1JZX01JUlJPUg0KPiA+ICsgICAgICAgYm9vbCAiQWRkcmVzcyByYW5n ZSBtaXJyb3Jpbmcgc3VwcG9ydCINCj4gPiArICAgICAgIGRlcGVuZHMgb24gWDg2ICYmIE5VTUEN Cj4gPiArICAgICAgIGRlZmF1bHQgeQ0KPiBJcyBpdCBjb3JyZWN0IGZvciB0aGUgc3lzdGVtcyAo Tk9UIHhlb24pIHdpdGhvdXQgbWVtb3J5IHN1cHBvcnQgYnVpbHQgaW4/DQoNCklzIHRoZSAiJiYg TlVNQSIgZG9pbmcgdGhhdD8gIElmIHlvdSBzdXBwb3J0IE5VTUEsIHRoZW4geW91IGFyZSBub3Qg YSBtaW5pbWFsDQpjb25maWcgZm9yIGEgdGFibGV0IG9yIGxhcHRvcC4NCg0KSWYgeW91IHdhbnQg YSBzeW1ib2wgdGhhdCBoYXMgYSBzdHJvbmdlciBjb3JyZWxhdGlvbiB0byBoaWdoIGVuZCBYZW9u IGZlYXR1cmVzDQp0aGVuIHBlcmhhcHMgTUVNT1JZX0ZBSUxVUkU/DQoNCi1Ub255DQo=

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#4 lore raw

Re: [RFC PATCH 01/12] mm: add a new config to manage the code

Quoted 11 lines · Tony
Quoted 5 lines

mm/Kconfig config MEMORY_HOTREMOVE · line 206

Quoted 4 lines
mm/Kconfig +4 -0
+config MEMORY_MIRROR
+       bool "Address range mirroring support"
+       depends on X86 && NUMA
+       default y

Is it correct for the systems (NOT xeon) without memory support built in?

Is the "&& NUMA" doing that? If you support NUMA, then you are not a minimal config for a tablet or laptop.

If you want a symbol that has a stronger correlation to high end Xeon features then perhaps MEMORY_FAILURE?

I would like to see the default set to be "n".
On my machine (x86_64) defconfig enables this feature and I don't know if this feature can work there.

➜ linux-mm git:(dev) ✗ make defconfig ARCH=x86

  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/basic/bin2c
  HOSTCC  scripts/kconfig/conf.o
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
*** Default configuration is based on 'x86_64_defconfig'
#
# configuration written to .config
#
➜  linux-mm git:(dev) ✗ grep CONFIG_MEMORY_MIRROR .config
CONFIG_MEMORY_MIRROR=y
Quoted 2 lines

-Tony

Signature · 8 lines
Leon Romanovsky | Independent Linux Consultant
        www.leon.nu | [email protected]

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
#5 lore raw

Re: [RFC PATCH 01/12] mm: add a new config to manage the code

In reply to Xishi Qiu
Quoted 13 lines · Xishi Qiu

This patch introduces a new config called "CONFIG_ACPI_MIRROR_MEMORY", it is used to on/off the feature.

---
  mm/Kconfig | 8 ++++++++
  1 file changed, 8 insertions(+)
mm/Kconfig +0 -0
index 390214d..4f2a726 100644

mm/Kconfig config MEMORY_HOTREMOVE · line 209

Quoted 10 lines
mm/Kconfig +7 -0
@@ -200,6 +200,14 @@ config MEMORY_HOTREMOVE
  	depends on MEMORY_HOTPLUG && ARCH_ENABLE_MEMORY_HOTREMOVE
  	depends on MIGRATION
 
+config MEMORY_MIRROR
+	bool "Address range mirroring support"
+	depends on X86 && NUMA
+	default y
+	help
+	  This feature depends on hardware and firmware support.
+	  ACPI or EFI records the mirror info.

default y...no runtime influence when the user doesn't use memory mirror ?

Thanks,
-Kame

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#6 lore raw

Re: [RFC PATCH 01/12] mm: add a new config to manage the code

Quoted 17 lines · Kamezawa Hiroyuki
Quoted 16 lines · Xishi Qiu

This patch introduces a new config called "CONFIG_ACPI_MIRROR_MEMORY", it is used to on/off the feature.

---
  mm/Kconfig | 8 ++++++++
  1 file changed, 8 insertions(+)
mm/Kconfig +0 -0
index 390214d..4f2a726 100644
@@ -200,6 +200,14 @@ config MEMORY_HOTREMOVE
      depends on MEMORY_HOTPLUG && ARCH_ENABLE_MEMORY_HOTREMOVE
      depends on MIGRATION
 
Quoted 10 lines

mm/Kconfig config MEMORY_HOTREMOVE · line 209

Quoted 7 lines
mm/Kconfig +7 -0
+config MEMORY_MIRROR
+    bool "Address range mirroring support"
+    depends on X86 && NUMA
+    default y
+    help
+      This feature depends on hardware and firmware support.
+      ACPI or EFI records the mirror info.

default y...no runtime influence when the user doesn't use memory mirror ?

It is a new feature, so how about like this: default y -> n?

Thanks,
Xishi Qiu

Quoted 8 lines

Thanks,
-Kame

.

#7 lore raw

Re: [RFC PATCH 01/12] mm: add a new config to manage the code

Quoted 30 lines · Xishi Qiu
Quoted 17 lines · Kamezawa Hiroyuki
Quoted 16 lines · Xishi Qiu

This patch introduces a new config called "CONFIG_ACPI_MIRROR_MEMORY", it is used to on/off the feature.

---
   mm/Kconfig | 8 ++++++++
   1 file changed, 8 insertions(+)
mm/Kconfig +0 -0
index 390214d..4f2a726 100644
@@ -200,6 +200,14 @@ config MEMORY_HOTREMOVE
       depends on MEMORY_HOTPLUG && ARCH_ENABLE_MEMORY_HOTREMOVE
       depends on MIGRATION
 
Quoted 10 lines

mm/Kconfig config MEMORY_HOTREMOVE · line 209

Quoted 7 lines
mm/Kconfig +7 -0
+config MEMORY_MIRROR
+    bool "Address range mirroring support"
+    depends on X86 && NUMA
+    default y
+    help
+      This feature depends on hardware and firmware support.
+      ACPI or EFI records the mirror info.

default y...no runtime influence when the user doesn't use memory mirror ?

Quoted 2 lines

It is a new feature, so how about like this: default y -> n?

It's okay to me. But it's better to check performance impact before merge because you modified core code of memory management.

Thanks,
-Kame

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#8 lore raw

RFC PATCH 2/12 mm: introduce mirror_info

In reply to Xishi Qiu

This patch introduces a new struct called "mirror_info", it is used to storage the mirror address range which reported by EFI or ACPI.

TBD: call add_mirror_info() to fill it.

---
 arch/x86/mm/numa.c     |  3 +++
 include/linux/mmzone.h | 15 +++++++++++++++
 mm/page_alloc.c        | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 51 insertions(+)
arch/x86/mm/numa.c +3 -0
index 4053bb5..781fd68 100644
@@ -619,6 +619,9 @@ static int __init numa_init(int (*init_func)(void))
 	/* In case that parsing SRAT failed. */
 	WARN_ON(memblock_clear_hotplug(0, ULLONG_MAX));
 	numa_reset_distance();
+#ifdef CONFIG_MEMORY_MIRROR
+	memset(&mirror_info, 0, sizeof(mirror_info));
+#endif
 
 	ret = init_func();
 	if (ret < 0)
include/linux/mmzone.h +15 -0
index 54d74f6..1fae07b 100644
@@ -69,6 +69,21 @@ enum {
 #  define is_migrate_cma(migratetype) false
 #endif
 
+#ifdef CONFIG_MEMORY_MIRROR
+struct numa_mirror_info {
+	int node;
+	unsigned long start;
+	unsigned long size;
+};
+
+struct mirror_info {
+	int count;
+	struct numa_mirror_info info[MAX_NUMNODES];
+};
+
+extern struct mirror_info mirror_info;
+#endif
+
 #define for_each_migratetype_order(order, type) \
 	for (order = 0; order < MAX_ORDER; order++) \
 		for (type = 0; type < MIGRATE_TYPES; type++)
mm/page_alloc.c +33 -0
index ebffa0e..41a95a7 100644
@@ -210,6 +210,10 @@ static char * const zone_names[MAX_NR_ZONES] = {
 int min_free_kbytes = 1024;
 int user_min_free_kbytes = -1;
 
+#ifdef CONFIG_MEMORY_MIRROR
+struct mirror_info mirror_info;
+#endif
+
 static unsigned long __meminitdata nr_kernel_pages;
 static unsigned long __meminitdata nr_all_pages;
 static unsigned long __meminitdata dma_reserve;
@@ -545,6 +549,31 @@ static inline int page_is_buddy(struct page *page, struct page *buddy,
 	return 0;
 }
 
+#ifdef CONFIG_MEMORY_MIRROR
+static void __init add_mirror_info(int node,
+			unsigned long start, unsigned long size)
+{
+	mirror_info.info[mirror_info.count].node = node;
+	mirror_info.info[mirror_info.count].start = start;
+	mirror_info.info[mirror_info.count].size = size;
+
+	mirror_info.count++;
+}
+
+static void __init print_mirror_info(void)
+{
+	int i;
+
+	printk("Mirror info\n");
+	for (i = 0; i < mirror_info.count; i++)
+		printk("  node %3d: [mem %#010lx-%#010lx]\n",
+			mirror_info.info[i].node,
+			mirror_info.info[i].start,
+			mirror_info.info[i].start +
+				mirror_info.info[i].size - 1);
+}
+#endif
+
 /*
  * Freeing function for a buddy system allocator.
  *
@@ -5438,6 +5467,10 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
 			       (u64)zone_movable_pfn[i] << PAGE_SHIFT);
 	}
 
+#ifdef CONFIG_MEMORY_MIRROR
+	print_mirror_info();
+#endif
+
 	/* Print out the early node map */
 	pr_info("Early memory node ranges\n");
 	for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid)
Signature · 1 line
2.0.0
#9 lore raw

RE: [RFC PATCH 02/12] mm: introduce mirror_info

+#ifdef CONFIG_MEMORY_MIRROR
+struct numa_mirror_info {
+ int node;
+ unsigned long start;
+ unsigned long size;
+};
+
+struct mirror_info {
+ int count;
+ struct numa_mirror_info info[MAX_NUMNODES];
+};

Do we really need this? My patch series leaves all the mirrored memory in the memblock allocator tagged with the MEMBLOCK_MIRROR flag. Can't we use that information when freeing the boot memory into the runtime free lists?

If we can't ... then [MAX_NUMNODES] may not be enough. We may have more than one mirrored range on each node. Current h/w allows two ranges per node.

-Tony

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#10 lore raw

Re: [RFC PATCH 02/12] mm: introduce mirror_info

Quoted 12 lines · Tony
include/linux/mmzone.h +11 -0
+#ifdef CONFIG_MEMORY_MIRROR
+struct numa_mirror_info {
+	int node;
+	unsigned long start;
+	unsigned long size;
+};
+
+struct mirror_info {
+	int count;
+	struct numa_mirror_info info[MAX_NUMNODES];
+};
Quoted 5 lines

Do we really need this? My patch series leaves all the mirrored memory in the memblock allocator tagged with the MEMBLOCK_MIRROR flag. Can't we use that information when freeing the boot memory into the runtime free lists?

Hi Tony,

I used this code for testing before, so when your patchset added to mainline, I'll rewrite it, use MEMBLOCK_MIRROR, not mirror_info.

I find Andrew has added your patches to mm-tree, right?

Thanks,
Xishi Qiu

Quoted 8 lines

If we can't ... then [MAX_NUMNODES] may not be enough. We may have more than one mirrored range on each node. Current h/w allows two ranges per node.

-Tony

.

#11 lore raw

Re: [RFC PATCH 02/12] mm: introduce mirror_info

In reply to Xishi Qiu
Quoted 35 lines · Xishi Qiu

This patch introduces a new struct called "mirror_info", it is used to storage the mirror address range which reported by EFI or ACPI.

TBD: call add_mirror_info() to fill it.

---
  arch/x86/mm/numa.c     |  3 +++
  include/linux/mmzone.h | 15 +++++++++++++++
  mm/page_alloc.c        | 33 +++++++++++++++++++++++++++++++++
  3 files changed, 51 insertions(+)
arch/x86/mm/numa.c +3 -0
index 4053bb5..781fd68 100644
@@ -619,6 +619,9 @@ static int __init numa_init(int (*init_func)(void))
  	/* In case that parsing SRAT failed. */
  	WARN_ON(memblock_clear_hotplug(0, ULLONG_MAX));
  	numa_reset_distance();
+#ifdef CONFIG_MEMORY_MIRROR
+	memset(&mirror_info, 0, sizeof(mirror_info));
+#endif
 
  	ret = init_func();
  	if (ret < 0)
include/linux/mmzone.h +1 -0
index 54d74f6..1fae07b 100644
@@ -69,6 +69,21 @@ enum {
  #  define is_migrate_cma(migratetype) false
  #endif
 
+#ifdef CONFIG_MEMORY_MIRROR

include/linux/mmzone.h enum { · line 82

Quoted 10 lines
include/linux/mmzone.h +10 -0
+struct numa_mirror_info {
+	int node;
+	unsigned long start;
+	unsigned long size;
+};
+
+struct mirror_info {
+	int count;
+	struct numa_mirror_info info[MAX_NUMNODES];
+};

MAX_NUMNODE may not be enough when the firmware cannot use contiguous address for mirroing.

include/linux/mmzone.h enum { · line 85

Quoted 3 lines
include/linux/mmzone.h +3 -0
+
+extern struct mirror_info mirror_info;
+#endif

If this structure will not be updated after boot, read_mostly should be helpful.

Quoted 53 lines
include/linux/mmzone.h +1 -0
+
  #define for_each_migratetype_order(order, type) \
  	for (order = 0; order < MAX_ORDER; order++) \
  		for (type = 0; type < MIGRATE_TYPES; type++)
mm/page_alloc.c +29 -0
index ebffa0e..41a95a7 100644
@@ -210,6 +210,10 @@ static char * const zone_names[MAX_NR_ZONES] = {
  int min_free_kbytes = 1024;
  int user_min_free_kbytes = -1;
 
+#ifdef CONFIG_MEMORY_MIRROR
+struct mirror_info mirror_info;
+#endif
+
  static unsigned long __meminitdata nr_kernel_pages;
  static unsigned long __meminitdata nr_all_pages;
  static unsigned long __meminitdata dma_reserve;
@@ -545,6 +549,31 @@ static inline int page_is_buddy(struct page *page, struct page *buddy,
  	return 0;
  }
 
+#ifdef CONFIG_MEMORY_MIRROR
+static void __init add_mirror_info(int node,
+			unsigned long start, unsigned long size)
+{
+	mirror_info.info[mirror_info.count].node = node;
+	mirror_info.info[mirror_info.count].start = start;
+	mirror_info.info[mirror_info.count].size = size;
+
+	mirror_info.count++;
+}
+
+static void __init print_mirror_info(void)
+{
+	int i;
+
+	printk("Mirror info\n");
+	for (i = 0; i < mirror_info.count; i++)
+		printk("  node %3d: [mem %#010lx-%#010lx]\n",
+			mirror_info.info[i].node,
+			mirror_info.info[i].start,
+			mirror_info.info[i].start +
+				mirror_info.info[i].size - 1);
+}
+#endif
+
  /*
   * Freeing function for a buddy system allocator.
   *

mm/page_alloc.c void __init free_area_init_nodes(unsigned long *max_zone_pfn) · line 5476

Quoted 10 lines
mm/page_alloc.c +4 -0
@@ -5438,6 +5467,10 @@ void __init free_area_init_nodes(unsigned long *max_zone_pfn)
  			       (u64)zone_movable_pfn[i] << PAGE_SHIFT);
  	}
 
+#ifdef CONFIG_MEMORY_MIRROR
+	print_mirror_info();
+#endif
+
  	/* Print out the early node map */
  	pr_info("Early memory node ranges\n");
  	for_each_mem_pfn_range(i, MAX_NUMNODES, &start_pfn, &end_pfn, &nid)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#12 lore raw

RFC PATCH 3/12 mm: introduce MIGRATE_MIRROR to manage the mirrored, pages

In reply to Xishi Qiu

This patch introduces a new MIGRATE_TYPES called "MIGRATE_MIRROR", it is used to storage the mirrored pages list.
When cat /proc/pagetypeinfo, you can see the count of free mirrored blocks.

e.g.
euler-linux:~ # cat /proc/pagetypeinfo

Page block order: 9
Pages per block:  512
Free pages count per migrate type at order       0      1      2      3      4      5      6      7      8      9     10
Node    0, zone      DMA, type    Unmovable      1      1      0      0      2      1      1      0      1      0      0
Node    0, zone      DMA, type  Reclaimable      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone      DMA, type      Movable      0      0      0      0      0      0      0      0      0      0      3
Node    0, zone      DMA, type       Mirror      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone      DMA, type      Reserve      0      0      0      0      0      0      0      0      0      1      0
Node    0, zone      DMA, type      Isolate      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone    DMA32, type    Unmovable      0      0      1      0      0      0      0      1      1      1      0
Node    0, zone    DMA32, type  Reclaimable      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone    DMA32, type      Movable      1      2      6      6      6      4      5      3      3      2    738
Node    0, zone    DMA32, type       Mirror      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone    DMA32, type      Reserve      0      0      0      0      0      0      0      0      0      0      1
Node    0, zone    DMA32, type      Isolate      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone   Normal, type    Unmovable      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone   Normal, type  Reclaimable      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone   Normal, type      Movable      0      0      1      1      0      0      0      2      1      0   4254
Node    0, zone   Normal, type       Mirror    148    104     63     70     26     11      2      2      1      1    973
Node    0, zone   Normal, type      Reserve      0      0      0      0      0      0      0      0      0      0      1
Node    0, zone   Normal, type      Isolate      0      0      0      0      0      0      0      0      0      0      0

Number of blocks type Unmovable Reclaimable Movable Mirror Reserve Isolate

Node 0, zone      DMA            1            0            6            0            1            0
Node 0, zone    DMA32            2            0         1525            0            1            0
Node 0, zone   Normal            0            0         8702         2048            2            0
Page block order: 9
Pages per block:  512
Free pages count per migrate type at order       0      1      2      3      4      5      6      7      8      9     10
Node    1, zone   Normal, type    Unmovable      0      0      0      0      0      0      0      0      0      0      0
Node    1, zone   Normal, type  Reclaimable      0      0      0      0      0      0      0      0      0      0      0
Node    1, zone   Normal, type      Movable      2      2      1      1      2      1      2      2      2      3   3996
Node    1, zone   Normal, type       Mirror     68     94     57      6      8      1      0      0      3      1   2003
Node    1, zone   Normal, type      Reserve      0      0      0      0      0      0      0      0      0      0      1
Node    1, zone   Normal, type      Isolate      0      0      0      0      0      0      0      0      0      0      0

Number of blocks type Unmovable Reclaimable Movable Mirror Reserve Isolate
Node 1, zone Normal 0 0 8190 4096 2 0

---
 include/linux/mmzone.h | 6 ++++++
 mm/page_alloc.c        | 3 +++
 mm/vmstat.c            | 3 +++
 3 files changed, 12 insertions(+)
include/linux/mmzone.h +6 -0
index 1fae07b..b444335 100644
@@ -39,6 +39,9 @@ enum {
 	MIGRATE_UNMOVABLE,
 	MIGRATE_RECLAIMABLE,
 	MIGRATE_MOVABLE,
+#ifdef CONFIG_MEMORY_MIRROR
+	MIGRATE_MIRROR,
+#endif
 	MIGRATE_PCPTYPES,	/* the number of types on the pcp lists */
 	MIGRATE_RESERVE = MIGRATE_PCPTYPES,
 #ifdef CONFIG_CMA
@@ -82,6 +85,9 @@ struct mirror_info {
 };
 
 extern struct mirror_info mirror_info;
+#  define is_migrate_mirror(migratetype) unlikely((migratetype) == MIGRATE_MIRROR)
+#else
+#  define is_migrate_mirror(migratetype) false
 #endif
 
 #define for_each_migratetype_order(order, type) \
mm/page_alloc.c +3 -0
index 41a95a7..3b2ff46 100644
@@ -3245,6 +3245,9 @@ static void show_migration_types(unsigned char type)
 		[MIGRATE_UNMOVABLE]	= 'U',
 		[MIGRATE_RECLAIMABLE]	= 'E',
 		[MIGRATE_MOVABLE]	= 'M',
+#ifdef CONFIG_MEMORY_MIRROR
+		[MIGRATE_MIRROR]	= 'O',
+#endif
 		[MIGRATE_RESERVE]	= 'R',
 #ifdef CONFIG_CMA
 		[MIGRATE_CMA]		= 'C',
mm/vmstat.c +3 -0
index 4f5cd97..d0323e0 100644
@@ -901,6 +901,9 @@ static char * const migratetype_names[MIGRATE_TYPES] = {
 	"Unmovable",
 	"Reclaimable",
 	"Movable",
+#ifdef CONFIG_MEMORY_MIRROR
+	"Mirror",
+#endif
 	"Reserve",
 #ifdef CONFIG_CMA
 	"CMA",
Signature · 1 line
2.0.0
#13 lore raw

Re: [RFC PATCH 03/12] mm: introduce MIGRATE_MIRROR to manage the mirrored, pages

Quoted 4 lines · Xishi Qiu

This patch introduces a new MIGRATE_TYPES called "MIGRATE_MIRROR", it is used to storage the mirrored pages list.
When cat /proc/pagetypeinfo, you can see the count of free mirrored blocks.

I guess you need to add Mel to CC.

Quoted 59 lines

e.g.
euler-linux:~ # cat /proc/pagetypeinfo

Page block order: 9
Pages per block:  512
Free pages count per migrate type at order       0      1      2      3      4      5      6      7      8      9     10
Node    0, zone      DMA, type    Unmovable      1      1      0      0      2      1      1      0      1      0      0
Node    0, zone      DMA, type  Reclaimable      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone      DMA, type      Movable      0      0      0      0      0      0      0      0      0      0      3
Node    0, zone      DMA, type       Mirror      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone      DMA, type      Reserve      0      0      0      0      0      0      0      0      0      1      0
Node    0, zone      DMA, type      Isolate      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone    DMA32, type    Unmovable      0      0      1      0      0      0      0      1      1      1      0
Node    0, zone    DMA32, type  Reclaimable      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone    DMA32, type      Movable      1      2      6      6      6      4      5      3      3      2    738
Node    0, zone    DMA32, type       Mirror      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone    DMA32, type      Reserve      0      0      0      0      0      0      0      0      0      0      1
Node    0, zone    DMA32, type      Isolate      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone   Normal, type    Unmovable      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone   Normal, type  Reclaimable      0      0      0      0      0      0      0      0      0      0      0
Node    0, zone   Normal, type      Movable      0      0      1      1      0      0      0      2      1      0   4254
Node    0, zone   Normal, type       Mirror    148    104     63     70     26     11      2      2      1      1    973
Node    0, zone   Normal, type      Reserve      0      0      0      0      0      0      0      0      0      0      1
Node    0, zone   Normal, type      Isolate      0      0      0      0      0      0      0      0      0      0      0

Number of blocks type Unmovable Reclaimable Movable Mirror Reserve Isolate

Node 0, zone      DMA            1            0            6            0            1            0
Node 0, zone    DMA32            2            0         1525            0            1            0
Node 0, zone   Normal            0            0         8702         2048            2            0
Page block order: 9
Pages per block:  512
Free pages count per migrate type at order       0      1      2      3      4      5      6      7      8      9     10
Node    1, zone   Normal, type    Unmovable      0      0      0      0      0      0      0      0      0      0      0
Node    1, zone   Normal, type  Reclaimable      0      0      0      0      0      0      0      0      0      0      0
Node    1, zone   Normal, type      Movable      2      2      1      1      2      1      2      2      2      3   3996
Node    1, zone   Normal, type       Mirror     68     94     57      6      8      1      0      0      3      1   2003
Node    1, zone   Normal, type      Reserve      0      0      0      0      0      0      0      0      0      0      1
Node    1, zone   Normal, type      Isolate      0      0      0      0      0      0      0      0      0      0      0

Number of blocks type Unmovable Reclaimable Movable Mirror Reserve Isolate
Node 1, zone Normal 0 0 8190 4096 2 0

---
  include/linux/mmzone.h | 6 ++++++
  mm/page_alloc.c        | 3 +++
  mm/vmstat.c            | 3 +++
  3 files changed, 12 insertions(+)
include/linux/mmzone.h +0 -0
index 1fae07b..b444335 100644

include/linux/mmzone.h enum { · line 44

Quoted 6 lines
include/linux/mmzone.h +3 -0
@@ -39,6 +39,9 @@ enum {
  	MIGRATE_UNMOVABLE,
  	MIGRATE_RECLAIMABLE,
  	MIGRATE_MOVABLE,
+#ifdef CONFIG_MEMORY_MIRROR
+	MIGRATE_MIRROR,
+#endif

I can't imagine how the fallback logic will work at reading this patch. I think an update for fallback order array should be in this patch...

Quoted 33 lines
include/linux/mmzone.h +3 -0
  	MIGRATE_PCPTYPES,	/* the number of types on the pcp lists */
  	MIGRATE_RESERVE = MIGRATE_PCPTYPES,
  #ifdef CONFIG_CMA
@@ -82,6 +85,9 @@ struct mirror_info {
  };
 
  extern struct mirror_info mirror_info;
+#  define is_migrate_mirror(migratetype) unlikely((migratetype) == MIGRATE_MIRROR)
+#else
+#  define is_migrate_mirror(migratetype) false
  #endif
 
  #define for_each_migratetype_order(order, type) \
mm/page_alloc.c +3 -0
index 41a95a7..3b2ff46 100644
@@ -3245,6 +3245,9 @@ static void show_migration_types(unsigned char type)
  		[MIGRATE_UNMOVABLE]	= 'U',
  		[MIGRATE_RECLAIMABLE]	= 'E',
  		[MIGRATE_MOVABLE]	= 'M',
+#ifdef CONFIG_MEMORY_MIRROR
+		[MIGRATE_MIRROR]	= 'O',
+#endif
  		[MIGRATE_RESERVE]	= 'R',
  #ifdef CONFIG_CMA
  		[MIGRATE_CMA]		= 'C',
mm/vmstat.c +0 -0
index 4f5cd97..d0323e0 100644

mm/vmstat.c static char * const migratetype_names[MIGRATE_TYPES] = { · line 909

Quoted 9 lines
mm/vmstat.c +3 -0
@@ -901,6 +901,9 @@ static char * const migratetype_names[MIGRATE_TYPES] = {
  	"Unmovable",
  	"Reclaimable",
  	"Movable",
+#ifdef CONFIG_MEMORY_MIRROR
+	"Mirror",
+#endif
  	"Reserve",
  #ifdef CONFIG_CMA
  	"CMA",

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#14 lore raw

RFC PATCH 4/12 mm: add mirrored pages to buddy system

In reply to Xishi Qiu

Set mirrored pageblock's migratetype to MIGRATE_MIRROR, so they could free to buddy system's MIGRATE_MIRROR list when free bootmem.

---
 mm/page_alloc.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
mm/page_alloc.c +27 -0
index 3b2ff46..8fe0187 100644
@@ -572,6 +572,25 @@ static void __init print_mirror_info(void)
 			mirror_info.info[i].start +
 				mirror_info.info[i].size - 1);
 }
+
+static inline bool is_mirror_pfn(unsigned long pfn)
+{
+	int i;
+	unsigned long addr = pfn << PAGE_SHIFT;
+
+	/* 0-4G is always mirrored, so ignore it */
+	if (addr < (4UL << 30))
+		return false;
+
+	for (i = 0; i < mirror_info.count; i++) {
+		if (addr >= mirror_info.info[i].start &&
+		    addr < mirror_info.info[i].start +
+			   mirror_info.info[i].size)
+			return true;
+	}
+
+	return false;
+}
 #endif
 
 /*
@@ -4147,6 +4166,9 @@ static void setup_zone_migrate_reserve(struct zone *zone)
 
 		block_migratetype = get_pageblock_migratetype(page);
 
+		if (is_migrate_mirror(block_migratetype))
+			continue;
+
 		/* Only test what is necessary when the reserves are not met */
 		if (reserve > 0) {
 			/*
@@ -4246,6 +4268,11 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
 		    && !(pfn & (pageblock_nr_pages - 1)))
 			set_pageblock_migratetype(page, MIGRATE_MOVABLE);
 
+#ifdef CONFIG_MEMORY_MIRROR
+		if (is_mirror_pfn(pfn))
+			set_pageblock_migratetype(page, MIGRATE_MIRROR);
+#endif
+
 		INIT_LIST_HEAD(&page->lru);
 #ifdef WANT_PAGE_VIRTUAL
 		/* The shift won't overflow because ZONE_NORMAL is below 4G. */
Signature · 1 line
2.0.0
author
#15 lore raw

RFC PATCH 5/12 mm: introduce a new zone_stat_item NR_FREE_MIRROR_PAGES

In reply to Xishi Qiu

This patch introduces a new zone_stat_item called "NR_FREE_MIRROR_PAGES", it is used to storage free mirrored pages count.

---
 include/linux/mmzone.h | 1 +
 include/linux/vmstat.h | 2 ++
 mm/vmstat.c            | 1 +
 3 files changed, 4 insertions(+)
include/linux/mmzone.h +1 -0
index b444335..f82e3ae 100644
@@ -178,6 +178,7 @@ enum zone_stat_item {
 	WORKINGSET_NODERECLAIM,
 	NR_ANON_TRANSPARENT_HUGEPAGES,
 	NR_FREE_CMA_PAGES,
+	NR_FREE_MIRROR_PAGES,
 	NR_VM_ZONE_STAT_ITEMS };
 
 /*
include/linux/vmstat.h +2 -0
index 82e7db7..d0a7268 100644
@@ -283,6 +283,8 @@ static inline void __mod_zone_freepage_state(struct zone *zone, int nr_pages,
 	__mod_zone_page_state(zone, NR_FREE_PAGES, nr_pages);
 	if (is_migrate_cma(migratetype))
 		__mod_zone_page_state(zone, NR_FREE_CMA_PAGES, nr_pages);
+	if (is_migrate_mirror(migratetype))
+		__mod_zone_page_state(zone, NR_FREE_MIRROR_PAGES, nr_pages);
 }
 
 extern const char * const vmstat_text[];
mm/vmstat.c +1 -0
index d0323e0..7ee11ca 100644
@@ -739,6 +739,7 @@ const char * const vmstat_text[] = {
 	"workingset_nodereclaim",
 	"nr_anon_transparent_hugepages",
 	"nr_free_cma",
+	"nr_free_mirror",
 
 	/* enum writeback_stat_item counters */
 	"nr_dirty_threshold",
Signature · 1 line
2.0.0
author
#16 lore raw

RFC PATCH 6/12 mm: add free mirrored pages info

In reply to Xishi Qiu

Add the count of free mirrored pages in the following paths:
/proc/meminfo
/proc/zoneinfo
/sys/devices/system/node/node XX/meminfo /sys/devices/system/node/node XX/vmstat

---
 drivers/base/node.c | 17 +++++++++++------
 fs/proc/meminfo.c   |  6 ++++++
 mm/page_alloc.c     |  7 +++++--
 3 files changed, 22 insertions(+), 8 deletions(-)
drivers/base/node.c +11 -6
index a2aa65b..d1a3556 100644
@@ -114,6 +114,9 @@ static ssize_t node_read_meminfo(struct device *dev,
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
 		       "Node %d AnonHugePages:  %8lu kB\n"
 #endif
+#ifdef CONFIG_MEMORY_MIRROR
+		       "Node %d MirrorFree:     %8lu kB\n"
+#endif
 			,
 		       nid, K(node_page_state(nid, NR_FILE_DIRTY)),
 		       nid, K(node_page_state(nid, NR_WRITEBACK)),
@@ -130,14 +133,16 @@ static ssize_t node_read_meminfo(struct device *dev,
 		       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE) +
 				node_page_state(nid, NR_SLAB_UNRECLAIMABLE)),
 		       nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)),
-#ifdef CONFIG_TRANSPARENT_HUGEPAGE
 		       nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))
-			, nid,
-			K(node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
-			HPAGE_PMD_NR));
-#else
-		       nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE)));
+#ifdef CONFIG_TRANSPARENT_HUGEPAGE
+		     , nid, K(node_page_state(nid, NR_ANON_TRANSPARENT_HUGEPAGES) *
+				HPAGE_PMD_NR)
+#endif
+#ifdef CONFIG_MEMORY_MIRROR
+		     , nid, K(node_page_state(nid, NR_FREE_MIRROR_PAGES))
 #endif
+			);
+
 	n += hugetlb_report_node_meminfo(nid, buf + n);
 	return n;
 }
fs/proc/meminfo.c +6 -0
index d3ebf2e..d1ebb20 100644
@@ -145,6 +145,9 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
 		"CmaTotal:       %8lu kB\n"
 		"CmaFree:        %8lu kB\n"
 #endif
+#ifdef CONFIG_MEMORY_MIRROR
+		"MirrorFree:     %8lu kB\n"
+#endif
 		,
 		K(i.totalram),
 		K(i.freeram),
@@ -204,6 +207,9 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
 		, K(totalcma_pages)
 		, K(global_page_state(NR_FREE_CMA_PAGES))
 #endif
+#ifdef CONFIG_MEMORY_MIRROR
+		, K(global_page_state(NR_FREE_MIRROR_PAGES))
+#endif
 		);
 
 	hugetlb_report_meminfo(m);
mm/page_alloc.c +5 -2
index 8fe0187..249a8f6 100644
@@ -3316,7 +3316,7 @@ void show_free_areas(unsigned int filter)
 		" unevictable:%lu dirty:%lu writeback:%lu unstable:%lu\n"
 		" slab_reclaimable:%lu slab_unreclaimable:%lu\n"
 		" mapped:%lu shmem:%lu pagetables:%lu bounce:%lu\n"
-		" free:%lu free_pcp:%lu free_cma:%lu\n",
+		" free:%lu free_pcp:%lu free_cma:%lu free_mirror:%lu\n",
 		global_page_state(NR_ACTIVE_ANON),
 		global_page_state(NR_INACTIVE_ANON),
 		global_page_state(NR_ISOLATED_ANON),
@@ -3335,7 +3335,8 @@ void show_free_areas(unsigned int filter)
 		global_page_state(NR_BOUNCE),
 		global_page_state(NR_FREE_PAGES),
 		free_pcp,
-		global_page_state(NR_FREE_CMA_PAGES));
+		global_page_state(NR_FREE_CMA_PAGES),
+		global_page_state(NR_FREE_MIRROR_PAGES));
 
 	for_each_populated_zone(zone) {
 		int i;
@@ -3376,6 +3377,7 @@ void show_free_areas(unsigned int filter)
 			" free_pcp:%lukB"
 			" local_pcp:%ukB"
 			" free_cma:%lukB"
+			" free_mirror:%lukB"
 			" writeback_tmp:%lukB"
 			" pages_scanned:%lu"
 			" all_unreclaimable? %s"
@@ -3409,6 +3411,7 @@ void show_free_areas(unsigned int filter)
 			K(free_pcp),
 			K(this_cpu_read(zone->pageset->pcp.count)),
 			K(zone_page_state(zone, NR_FREE_CMA_PAGES)),
+			K(zone_page_state(zone, NR_FREE_MIRROR_PAGES)),
 			K(zone_page_state(zone, NR_WRITEBACK_TEMP)),
 			K(zone_page_state(zone, NR_PAGES_SCANNED)),
 			(!zone_reclaimable(zone) ? "yes" : "no")
Signature · 1 line
2.0.0
author
#17 lore raw

RFC PATCH 7/12 mm: introduce __GFP_MIRROR to allocate mirrored pages

In reply to Xishi Qiu

This patch introduces a new gfp flag called "__GFP_MIRROR", it is used to allocate mirrored pages through buddy system.

---
 include/linux/gfp.h | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
include/linux/gfp.h +4 -1
index 15928f0..89d0091 100644
@@ -35,6 +35,7 @@ struct vm_area_struct;
 #define ___GFP_NO_KSWAPD	0x400000u
 #define ___GFP_OTHER_NODE	0x800000u
 #define ___GFP_WRITE		0x1000000u
+#define ___GFP_MIRROR		0x2000000u
 /* If the above are modified, __GFP_BITS_SHIFT may need updating */
 
 /*
@@ -95,13 +96,15 @@ struct vm_area_struct;
 #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */
 #define __GFP_WRITE	((__force gfp_t)___GFP_WRITE)	/* Allocator intends to dirty page */
 
+#define __GFP_MIRROR	((__force gfp_t)___GFP_MIRROR)	/* Allocate mirrored memory */
+
 /*
  * This may seem redundant, but it's a way of annotating false positives vs.
  * allocations that simply cannot be supported (e.g. page tables).
  */
 #define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK)
 
-#define __GFP_BITS_SHIFT 25	/* Room for N __GFP_FOO bits */
+#define __GFP_BITS_SHIFT 26	/* Room for N __GFP_FOO bits */
 #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
 
 /* This equals 0, but use constants in case they ever change */
Signature · 1 line
2.0.0
#18 lore raw

Re: [RFC PATCH 07/12] mm: introduce __GFP_MIRROR to allocate mirrored pages

Quoted 4 lines · Xishi Qiu

This patch introduces a new gfp flag called "__GFP_MIRROR", it is used to allocate mirrored pages through buddy system.

In Tony's original proposal, the motivation was to mirror all kernel memory.

Is the purpose of this patch making mirrored range available for user space ?

But, hmm... I don't think adding a new GFP flag is a good idea. It adds many conditional jumps.

How about using GFP_KERNEL for user memory if the user wants mirrored memory with mirroring all kernel memory?

Thanks,
-Kame

Quoted 24 lines
---
  include/linux/gfp.h | 5 ++++-
  1 file changed, 4 insertions(+), 1 deletion(-)
include/linux/gfp.h +3 -0
index 15928f0..89d0091 100644
@@ -35,6 +35,7 @@ struct vm_area_struct;
  #define ___GFP_NO_KSWAPD	0x400000u
  #define ___GFP_OTHER_NODE	0x800000u
  #define ___GFP_WRITE		0x1000000u
+#define ___GFP_MIRROR		0x2000000u
  /* If the above are modified, __GFP_BITS_SHIFT may need updating */
 
  /*
@@ -95,13 +96,15 @@ struct vm_area_struct;
  #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */
  #define __GFP_WRITE	((__force gfp_t)___GFP_WRITE)	/* Allocator intends to dirty page */
 
+#define __GFP_MIRROR	((__force gfp_t)___GFP_MIRROR)	/* Allocate mirrored memory */
+
  /*

include/linux/gfp.h struct vm_area_struct; · line 110

Quoted 10 lines
include/linux/gfp.h +1 -1
   * This may seem redundant, but it's a way of annotating false positives vs.
   * allocations that simply cannot be supported (e.g. page tables).
   */
  #define __GFP_NOTRACK_FALSE_POSITIVE (__GFP_NOTRACK)
 
-#define __GFP_BITS_SHIFT 25	/* Room for N __GFP_FOO bits */
+#define __GFP_BITS_SHIFT 26	/* Room for N __GFP_FOO bits */
  #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
 
  /* This equals 0, but use constants in case they ever change */

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#19 lore raw

RFC PATCH 8/12 mm: use mirrorable to switch allocate mirrored memory

In reply to Xishi Qiu

Add a new interface in path /proc/sys/vm/mirrorable. When set to 1, it means we should allocate mirrored memory for both user and kernel processes.

---
 include/linux/mmzone.h | 1 +
 kernel/sysctl.c        | 9 +++++++++
 mm/page_alloc.c        | 1 +
 3 files changed, 11 insertions(+)
include/linux/mmzone.h +1 -0
index f82e3ae..20888dd 100644
@@ -85,6 +85,7 @@ struct mirror_info {
 };
 
 extern struct mirror_info mirror_info;
+extern int sysctl_mirrorable;
 #  define is_migrate_mirror(migratetype) unlikely((migratetype) == MIGRATE_MIRROR)
 #else
 #  define is_migrate_mirror(migratetype) false
kernel/sysctl.c +9 -0
index 2082b1a..dc2625e 100644
@@ -1514,6 +1514,15 @@ static struct ctl_table vm_table[] = {
 		.extra2		= &one,
 	},
 #endif
+#ifdef CONFIG_MEMORY_MIRROR
+	{
+		.procname	= "mirrorable",
+		.data		= &sysctl_mirrorable,
+		.maxlen		= sizeof(sysctl_mirrorable),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+	},
+#endif
 	{
 		.procname	= "user_reserve_kbytes",
 		.data		= &sysctl_user_reserve_kbytes,
mm/page_alloc.c +1 -0
index 249a8f6..63b90ca 100644
@@ -212,6 +212,7 @@ int user_min_free_kbytes = -1;
 
 #ifdef CONFIG_MEMORY_MIRROR
 struct mirror_info mirror_info;
+int sysctl_mirrorable = 0;
 #endif
 
 static unsigned long __meminitdata nr_kernel_pages;
Signature · 1 line
2.0.0
#20 lore raw

RE: [RFC PATCH 08/12] mm: use mirrorable to switch allocate mirrored memory

Quoted 2 lines

Add a new interface in path /proc/sys/vm/mirrorable. When set to 1, it means we should allocate mirrored memory for both user and kernel processes.

With some "to be defined later" mechanism for how the user requests mirror vs. not mirror. Plus some capability/ulimit pieces that restrict who can do this and how much they can get???

-Tony

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#21 lore raw

Re: [RFC PATCH 08/12] mm: use mirrorable to switch allocate mirrored memory

In reply to Xishi Qiu
Quoted 2 lines · Xishi Qiu

Add a new interface in path /proc/sys/vm/mirrorable. When set to 1, it means we should allocate mirrored memory for both user and kernel processes.

That's a pretty dangerously short name. :)

How would this end up getting used? It seems like it would be dangerous to use once userspace was very far along. So would the kernel set it to 1 and then let (early??) userspace set it back to 0? That would let important userspace like /bin/init get mirrored memory without having to actually change much in userspace.

This definitely needs some good documentation.

Also, if it's insane to turn it back *on*, maybe it should be a one-way trip to turn off.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#22 lore raw

Re: [RFC PATCH 08/12] mm: use mirrorable to switch allocate mirrored memory

Quoted 6 lines · Dave Hansen
Quoted 2 lines · Xishi Qiu

Add a new interface in path /proc/sys/vm/mirrorable. When set to 1, it means we should allocate mirrored memory for both user and kernel processes.

That's a pretty dangerously short name. :)

Hi Dave,

Thanks for your comment. I'm not sure whether we should add this interface for user processes. However some important userspace(e.g. /bin/init, key business like datebase) may be want mirrored memory to improve reliability.

If we want this interface, I think the code need more change.

Thanks,
Xishi Qiu

Quoted 13 lines

How would this end up getting used? It seems like it would be dangerous to use once userspace was very far along. So would the kernel set it to 1 and then let (early??) userspace set it back to 0? That would let important userspace like /bin/init get mirrored memory without having to actually change much in userspace.

This definitely needs some good documentation.

Also, if it's insane to turn it back *on*, maybe it should be a one-way trip to turn off.

.

#23 lore raw

Re: [RFC PATCH 08/12] mm: use mirrorable to switch allocate mirrored memory

In reply to Xishi Qiu
Quoted 4 lines · Xishi Qiu

Add a new interface in path /proc/sys/vm/mirrorable. When set to 1, it means we should allocate mirrored memory for both user and kernel processes.

I can't see why do we need this switch. If this is set, all GFP_HIGHUSER will use mirrored memory ?

Or will you add special MMAP/madvise flag to use mirrored memory ?

Thanks,
-Kame

Quoted 44 lines
---
  include/linux/mmzone.h | 1 +
  kernel/sysctl.c        | 9 +++++++++
  mm/page_alloc.c        | 1 +
  3 files changed, 11 insertions(+)
include/linux/mmzone.h +1 -0
index f82e3ae..20888dd 100644
@@ -85,6 +85,7 @@ struct mirror_info {
  };
 
  extern struct mirror_info mirror_info;
+extern int sysctl_mirrorable;
  #  define is_migrate_mirror(migratetype) unlikely((migratetype) == MIGRATE_MIRROR)
  #else
  #  define is_migrate_mirror(migratetype) false
kernel/sysctl.c +9 -0
index 2082b1a..dc2625e 100644
@@ -1514,6 +1514,15 @@ static struct ctl_table vm_table[] = {
  		.extra2		= &one,
  	},
  #endif
+#ifdef CONFIG_MEMORY_MIRROR
+	{
+		.procname	= "mirrorable",
+		.data		= &sysctl_mirrorable,
+		.maxlen		= sizeof(sysctl_mirrorable),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+	},
+#endif
  	{
  		.procname	= "user_reserve_kbytes",
  		.data		= &sysctl_user_reserve_kbytes,
mm/page_alloc.c +0 -0
index 249a8f6..63b90ca 100644

mm/page_alloc.c int user_min_free_kbytes = -1; · line 218

Quoted 7 lines
mm/page_alloc.c +1 -0
@@ -212,6 +212,7 @@ int user_min_free_kbytes = -1;
 
  #ifdef CONFIG_MEMORY_MIRROR
  struct mirror_info mirror_info;
+int sysctl_mirrorable = 0;
  #endif
 
  static unsigned long __meminitdata nr_kernel_pages;

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#24 lore raw

Re: [RFC PATCH 08/12] mm: use mirrorable to switch allocate mirrored memory

Quoted 11 lines · Kamezawa Hiroyuki
Quoted 4 lines · Xishi Qiu

Add a new interface in path /proc/sys/vm/mirrorable. When set to 1, it means we should allocate mirrored memory for both user and kernel processes.

I can't see why do we need this switch. If this is set, all GFP_HIGHUSER will use mirrored memory ?

Or will you add special MMAP/madvise flag to use mirrored memory ?

Hi Kame,

Yes,

MMAP/madvise

	-> add VM_MIRROR 
		-> add GFP_MIRROR
			-> use MIGRATE_MIRROR list to alloc mirrored pages

So user can use mirrored memory. What do you think?

Thanks,
Xishi Qiu

Quoted 59 lines

Thanks,
-Kame

Quoted 44 lines
---
  include/linux/mmzone.h | 1 +
  kernel/sysctl.c        | 9 +++++++++
  mm/page_alloc.c        | 1 +
  3 files changed, 11 insertions(+)
include/linux/mmzone.h +1 -0
index f82e3ae..20888dd 100644
@@ -85,6 +85,7 @@ struct mirror_info {
  };
 
  extern struct mirror_info mirror_info;
+extern int sysctl_mirrorable;
  #  define is_migrate_mirror(migratetype) unlikely((migratetype) == MIGRATE_MIRROR)
  #else
  #  define is_migrate_mirror(migratetype) false
kernel/sysctl.c +9 -0
index 2082b1a..dc2625e 100644
@@ -1514,6 +1514,15 @@ static struct ctl_table vm_table[] = {
          .extra2        = &one,
      },
  #endif
+#ifdef CONFIG_MEMORY_MIRROR
+    {
+        .procname    = "mirrorable",
+        .data        = &sysctl_mirrorable,
+        .maxlen        = sizeof(sysctl_mirrorable),
+        .mode        = 0644,
+        .proc_handler    = proc_dointvec_minmax,
+    },
+#endif
      {
          .procname    = "user_reserve_kbytes",
          .data        = &sysctl_user_reserve_kbytes,
mm/page_alloc.c +0 -0
index 249a8f6..63b90ca 100644

mm/page_alloc.c int user_min_free_kbytes = -1; · line 218

Quoted 7 lines
mm/page_alloc.c +1 -0
@@ -212,6 +212,7 @@ int user_min_free_kbytes = -1;
 
  #ifdef CONFIG_MEMORY_MIRROR
  struct mirror_info mirror_info;
+int sysctl_mirrorable = 0;
  #endif
 
  static unsigned long __meminitdata nr_kernel_pages;

.

#25 lore raw

Re: [RFC PATCH 08/12] mm: use mirrorable to switch allocate mirrored memory

Quoted 16 lines · Xishi Qiu
Quoted 11 lines · Kamezawa Hiroyuki
Quoted 4 lines · Xishi Qiu

Add a new interface in path /proc/sys/vm/mirrorable. When set to 1, it means we should allocate mirrored memory for both user and kernel processes.

I can't see why do we need this switch. If this is set, all GFP_HIGHUSER will use mirrored memory ?

Or will you add special MMAP/madvise flag to use mirrored memory ?

Hi Kame,

Quoted 9 lines

Yes,

MMAP/madvise

	-> add VM_MIRROR
		-> add GFP_MIRROR
			-> use MIGRATE_MIRROR list to alloc mirrored pages

So user can use mirrored memory. What do you think?

I see. please explain it (your final plan) in patch description or in cover page of patches.

Thanks,
-Kame

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#26 lore raw

Re: [RFC PATCH 08/12] mm: use mirrorable to switch allocate mirrored memory

In reply to Xishi Qiu
Quoted 2 lines · Xishi Qiu

Add a new interface in path /proc/sys/vm/mirrorable. When set to 1, it means we should allocate mirrored memory for both user and kernel processes.

As Dave and Kamezawa-san commented, documentation is not enough, so please add a section in Documentation/sysctl/vm.txt for this new tuning parameter.

Thanks,
Naoya Horiguchi

Quoted 61 lines
---
 include/linux/mmzone.h | 1 +
 kernel/sysctl.c        | 9 +++++++++
 mm/page_alloc.c        | 1 +
 3 files changed, 11 insertions(+)
include/linux/mmzone.h +1 -0
index f82e3ae..20888dd 100644
@@ -85,6 +85,7 @@ struct mirror_info {
 };
 
 extern struct mirror_info mirror_info;
+extern int sysctl_mirrorable;
 #  define is_migrate_mirror(migratetype) unlikely((migratetype) == MIGRATE_MIRROR)
 #else
 #  define is_migrate_mirror(migratetype) false
kernel/sysctl.c +9 -0
index 2082b1a..dc2625e 100644
@@ -1514,6 +1514,15 @@ static struct ctl_table vm_table[] = {
 		.extra2		= &one,
 	},
 #endif
+#ifdef CONFIG_MEMORY_MIRROR
+	{
+		.procname	= "mirrorable",
+		.data		= &sysctl_mirrorable,
+		.maxlen		= sizeof(sysctl_mirrorable),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec_minmax,
+	},
+#endif
 	{
 		.procname	= "user_reserve_kbytes",
 		.data		= &sysctl_user_reserve_kbytes,
mm/page_alloc.c +1 -0
index 249a8f6..63b90ca 100644
@@ -212,6 +212,7 @@ int user_min_free_kbytes = -1;
 
 #ifdef CONFIG_MEMORY_MIRROR
 struct mirror_info mirror_info;
+int sysctl_mirrorable = 0;
 #endif
 
 static unsigned long __meminitdata nr_kernel_pages;
Signature · 8 lines
2.0.0


--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to [email protected].  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#27 lore raw

RFC PATCH 9/12 mm: enable allocate mirrored memory at boot time

In reply to Xishi Qiu

Add a boot option called "mirrorable" to allocate mirrored memory at boot time (after bootmem free).

---
 mm/page_alloc.c | 7 +++++++
 1 file changed, 7 insertions(+)
mm/page_alloc.c +7 -0
index 63b90ca..d4d2066 100644
@@ -213,6 +213,13 @@ int user_min_free_kbytes = -1;
 #ifdef CONFIG_MEMORY_MIRROR
 struct mirror_info mirror_info;
 int sysctl_mirrorable = 0;
+
+static int __init set_mirrorable(char *p)
+{
+	sysctl_mirrorable = 1;
+	return 0;
+}
+early_param("mirrorable", set_mirrorable);
 #endif
 
 static unsigned long __meminitdata nr_kernel_pages;
Signature · 1 line
2.0.0
author
#28 lore raw

RFC PATCH 10/12 mm: add the buddy system interface

In reply to Xishi Qiu

Add the buddy system interface for address range mirroring feature. Allocate mirrored pages in MIGRATE_MIRROR list. If there is no mirrored pages left, use other types pages.

---
 mm/page_alloc.c | 40 +++++++++++++++++++++++++++++++++++++++-
 1 file changed, 39 insertions(+), 1 deletion(-)
mm/page_alloc.c +39 -1
index d4d2066..0fb55288 100644
@@ -599,6 +599,26 @@ static inline bool is_mirror_pfn(unsigned long pfn)
 
 	return false;
 }
+
+static inline bool change_to_mirror(gfp_t gfp_flags, int high_zoneidx)
+{
+	/*
+	 * Do not alloc mirrored memory below 4G, because 0-4G is
+	 * all mirrored by default, and the list is always empty.
+	 */
+	if (high_zoneidx < ZONE_NORMAL)
+		return false;
+
+	/* Alloc mirrored memory for only kernel */
+	if (gfp_flags & __GFP_MIRROR)
+		return true;
+
+	/* Alloc mirrored memory for both user and kernel */
+	if (sysctl_mirrorable)
+		return true;
+
+	return false;
+}
 #endif
 
 /*
@@ -1796,7 +1816,10 @@ struct page *buffered_rmqueue(struct zone *preferred_zone,
 			WARN_ON_ONCE(order > 1);
 		}
 		spin_lock_irqsave(&zone->lock, flags);
-		page = __rmqueue(zone, order, migratetype);
+		if (is_migrate_mirror(migratetype))
+			page = __rmqueue_smallest(zone, order, migratetype);
+		else
+			page = __rmqueue(zone, order, migratetype);
 		spin_unlock(&zone->lock);
 		if (!page)
 			goto failed;
@@ -2928,6 +2951,11 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
 	if (IS_ENABLED(CONFIG_CMA) && ac.migratetype == MIGRATE_MOVABLE)
 		alloc_flags |= ALLOC_CMA;
 
+#ifdef CONFIG_MEMORY_MIRROR
+	if (change_to_mirror(gfp_mask, ac.high_zoneidx))
+		ac.migratetype = MIGRATE_MIRROR;
+#endif
+
 retry_cpuset:
 	cpuset_mems_cookie = read_mems_allowed_begin();
 
@@ -2943,9 +2971,19 @@ retry_cpuset:
 
 	/* First allocation attempt */
 	alloc_mask = gfp_mask|__GFP_HARDWALL;
+retry:
 	page = get_page_from_freelist(alloc_mask, order, alloc_flags, &ac);
 	if (unlikely(!page)) {
 		/*
+		 * If there is no mirrored memory, we will alloc other
+		 * types memory.
+		 */
+		if (is_migrate_mirror(ac.migratetype)) {
+			ac.migratetype = gfpflags_to_migratetype(gfp_mask);
+			goto retry;
+		}
+
+		/*
 		 * Runtime PM, block IO and its error handling path
 		 * can deadlock because I/O on the device might not
 		 * complete.
Signature · 1 line
2.0.0
#29 lore raw

RE: [RFC PATCH 10/12] mm: add the buddy system interface

+#ifdef CONFIG_MEMORY_MIRROR
+ if (change_to_mirror(gfp_mask, ac.high_zoneidx))
+ ac.migratetype = MIGRATE_MIRROR;
+#endif

We may have to be smarter than this here. I'd like to encourage the enterprise Linux distributions to set CONFIG_MEMORY_MIRROR=y But the reality is that most systems will not configure any mirrored memory - so we don't want the common code path for memory allocation to call functions that set the migrate type, try to allocate and then fall back to a non-mirror when that may be a complete waste of time.

Maybe a global "got_mirror" that is true if we have some mirrored memory. Then code is

	if (got_mirror && change_to_mirror(...))

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#30 lore raw

Re: [RFC PATCH 10/12] mm: add the buddy system interface

Quoted 13 lines · Tony
mm/page_alloc.c +4 -0
+#ifdef CONFIG_MEMORY_MIRROR
+	if (change_to_mirror(gfp_mask, ac.high_zoneidx))
+		ac.migratetype = MIGRATE_MIRROR;
+#endif

We may have to be smarter than this here. I'd like to encourage the enterprise Linux distributions to set CONFIG_MEMORY_MIRROR=y But the reality is that most systems will not configure any mirrored memory - so we don't want the common code path for memory allocation to call functions that set the migrate type, try to allocate and then fall back to a non-mirror when that may be a complete waste of time.

Quoted 5 lines

Maybe a global "got_mirror" that is true if we have some mirrored memory. Then code is

	if (got_mirror && change_to_mirror(...))

Yes, I will change next time.

Thanks,

Quoted 2 lines

.

#31 lore raw

Re: [RFC PATCH 10/12] mm: add the buddy system interface

In reply to Xishi Qiu
Quoted 20 lines · Xishi Qiu

Add the buddy system interface for address range mirroring feature. Allocate mirrored pages in MIGRATE_MIRROR list. If there is no mirrored pages left, use other types pages.

---
  mm/page_alloc.c | 40 +++++++++++++++++++++++++++++++++++++++-
  1 file changed, 39 insertions(+), 1 deletion(-)
mm/page_alloc.c +3 -0
index d4d2066..0fb55288 100644
@@ -599,6 +599,26 @@ static inline bool is_mirror_pfn(unsigned long pfn)
 
  	return false;
  }
+
+static inline bool change_to_mirror(gfp_t gfp_flags, int high_zoneidx)
+{

mm/page_alloc.c static inline bool is_mirror_pfn(unsigned long pfn) · line 614

Quoted 10 lines
mm/page_alloc.c +10 -0
+	/*
+	 * Do not alloc mirrored memory below 4G, because 0-4G is
+	 * all mirrored by default, and the list is always empty.
+	 */
+	if (high_zoneidx < ZONE_NORMAL)
+		return false;
+
+	/* Alloc mirrored memory for only kernel */
+	if (gfp_flags & __GFP_MIRROR)
+		return true;

GFP_KERNEL itself should imply mirror, I think.

mm/page_alloc.c static inline bool is_mirror_pfn(unsigned long pfn) · line 618

Quoted 4 lines
mm/page_alloc.c +4 -0
+
+	/* Alloc mirrored memory for both user and kernel */
+	if (sysctl_mirrorable)
+		return true;

Reading this, I think this sysctl is not good. The user cannot know what is mirrored because memory may not be mirrored until the sysctl is set.

Thanks,
-Kame

Quoted 41 lines
mm/page_alloc.c +15 -1
+
+	return false;
+}
  #endif
 
  /*
@@ -1796,7 +1816,10 @@ struct page *buffered_rmqueue(struct zone *preferred_zone,
  			WARN_ON_ONCE(order > 1);
  		}
  		spin_lock_irqsave(&zone->lock, flags);
-		page = __rmqueue(zone, order, migratetype);
+		if (is_migrate_mirror(migratetype))
+			page = __rmqueue_smallest(zone, order, migratetype);
+		else
+			page = __rmqueue(zone, order, migratetype);
  		spin_unlock(&zone->lock);
  		if (!page)
  			goto failed;
@@ -2928,6 +2951,11 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
  	if (IS_ENABLED(CONFIG_CMA) && ac.migratetype == MIGRATE_MOVABLE)
  		alloc_flags |= ALLOC_CMA;
 
+#ifdef CONFIG_MEMORY_MIRROR
+	if (change_to_mirror(gfp_mask, ac.high_zoneidx))
+		ac.migratetype = MIGRATE_MIRROR;
+#endif
+
  retry_cpuset:
  	cpuset_mems_cookie = read_mems_allowed_begin();
 
@@ -2943,9 +2971,19 @@ retry_cpuset:
 
  	/* First allocation attempt */
  	alloc_mask = gfp_mask|__GFP_HARDWALL;
+retry:
  	page = get_page_from_freelist(alloc_mask, order, alloc_flags, &ac);
  	if (unlikely(!page)) {
  		/*
+		 * If there is no mirrored memory, we will alloc other
+		 * types memory.

mm/page_alloc.c retry_cpuset: · line 2989

Quoted 10 lines
mm/page_alloc.c +7 -0
+		 */
+		if (is_migrate_mirror(ac.migratetype)) {
+			ac.migratetype = gfpflags_to_migratetype(gfp_mask);
+			goto retry;
+		}
+
+		/*
  		 * Runtime PM, block IO and its error handling path
  		 * can deadlock because I/O on the device might not
  		 * complete.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#32 lore raw

Re: [RFC PATCH 10/12] mm: add the buddy system interface

Quoted 25 lines · Kamezawa Hiroyuki
Quoted 24 lines · Xishi Qiu

Add the buddy system interface for address range mirroring feature. Allocate mirrored pages in MIGRATE_MIRROR list. If there is no mirrored pages left, use other types pages.

---
  mm/page_alloc.c | 40 +++++++++++++++++++++++++++++++++++++++-
  1 file changed, 39 insertions(+), 1 deletion(-)
mm/page_alloc.c +7 -0
index d4d2066..0fb55288 100644
@@ -599,6 +599,26 @@ static inline bool is_mirror_pfn(unsigned long pfn)
 
      return false;
  }
+
+static inline bool change_to_mirror(gfp_t gfp_flags, int high_zoneidx)
+{
+    /*
+     * Do not alloc mirrored memory below 4G, because 0-4G is
+     * all mirrored by default, and the list is always empty.
+     */
Quoted 9 lines

mm/page_alloc.c static inline bool is_mirror_pfn(unsigned long pfn) · line 614

Quoted 6 lines
mm/page_alloc.c +6 -0
+    if (high_zoneidx < ZONE_NORMAL)
+        return false;
+
+    /* Alloc mirrored memory for only kernel */
+    if (gfp_flags & __GFP_MIRROR)
+        return true;

GFP_KERNEL itself should imply mirror, I think.

Hi Kame,

How about like this: #define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_MIRROR) ?

Thanks,
Xishi Qiu

Quoted 68 lines

mm/page_alloc.c static inline bool is_mirror_pfn(unsigned long pfn) · line 618

Quoted 4 lines
mm/page_alloc.c +4 -0
+
+    /* Alloc mirrored memory for both user and kernel */
+    if (sysctl_mirrorable)
+        return true;

Reading this, I think this sysctl is not good. The user cannot know what is mirrored because memory may not be mirrored until the sysctl is set.

Thanks,
-Kame

Quoted 41 lines
mm/page_alloc.c +15 -1
+
+    return false;
+}
  #endif
 
  /*
@@ -1796,7 +1816,10 @@ struct page *buffered_rmqueue(struct zone *preferred_zone,
              WARN_ON_ONCE(order > 1);
          }
          spin_lock_irqsave(&zone->lock, flags);
-        page = __rmqueue(zone, order, migratetype);
+        if (is_migrate_mirror(migratetype))
+            page = __rmqueue_smallest(zone, order, migratetype);
+        else
+            page = __rmqueue(zone, order, migratetype);
          spin_unlock(&zone->lock);
          if (!page)
              goto failed;
@@ -2928,6 +2951,11 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
      if (IS_ENABLED(CONFIG_CMA) && ac.migratetype == MIGRATE_MOVABLE)
          alloc_flags |= ALLOC_CMA;
 
+#ifdef CONFIG_MEMORY_MIRROR
+    if (change_to_mirror(gfp_mask, ac.high_zoneidx))
+        ac.migratetype = MIGRATE_MIRROR;
+#endif
+
  retry_cpuset:
      cpuset_mems_cookie = read_mems_allowed_begin();
 
@@ -2943,9 +2971,19 @@ retry_cpuset:
 
      /* First allocation attempt */
      alloc_mask = gfp_mask|__GFP_HARDWALL;
+retry:
      page = get_page_from_freelist(alloc_mask, order, alloc_flags, &ac);
      if (unlikely(!page)) {
          /*
+         * If there is no mirrored memory, we will alloc other
+         * types memory.

mm/page_alloc.c retry_cpuset: · line 2989

Quoted 10 lines
mm/page_alloc.c +7 -0
+         */
+        if (is_migrate_mirror(ac.migratetype)) {
+            ac.migratetype = gfpflags_to_migratetype(gfp_mask);
+            goto retry;
+        }
+
+        /*
           * Runtime PM, block IO and its error handling path
           * can deadlock because I/O on the device might not
           * complete.

.

#33 lore raw

Re: [RFC PATCH 10/12] mm: add the buddy system interface

Quoted 37 lines · Xishi Qiu
Quoted 25 lines · Kamezawa Hiroyuki
Quoted 24 lines · Xishi Qiu

Add the buddy system interface for address range mirroring feature. Allocate mirrored pages in MIGRATE_MIRROR list. If there is no mirrored pages left, use other types pages.

---
   mm/page_alloc.c | 40 +++++++++++++++++++++++++++++++++++++++-
   1 file changed, 39 insertions(+), 1 deletion(-)
mm/page_alloc.c +7 -0
index d4d2066..0fb55288 100644
@@ -599,6 +599,26 @@ static inline bool is_mirror_pfn(unsigned long pfn)
 
       return false;
   }
+
+static inline bool change_to_mirror(gfp_t gfp_flags, int high_zoneidx)
+{
+    /*
+     * Do not alloc mirrored memory below 4G, because 0-4G is
+     * all mirrored by default, and the list is always empty.
+     */
Quoted 9 lines

mm/page_alloc.c static inline bool is_mirror_pfn(unsigned long pfn) · line 614

Quoted 6 lines
mm/page_alloc.c +6 -0
+    if (high_zoneidx < ZONE_NORMAL)
+        return false;
+
+    /* Alloc mirrored memory for only kernel */
+    if (gfp_flags & __GFP_MIRROR)
+        return true;

GFP_KERNEL itself should imply mirror, I think.

Quoted 4 lines

Hi Kame,

How about like this: #define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_MIRROR) ?

Hm.... it cannot cover GFP_ATOMIC at el.

I guess, mirrored memory should be allocated if !__GFP_HIGHMEM or !__GFP_MOVABLE

thanks,
-Kame

Thanks,
-Kame

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#34 lore raw

RE: [RFC PATCH 10/12] mm: add the buddy system interface

Quoted 1 line

I guess, mirrored memory should be allocated if !__GFP_HIGHMEM or !__GFP_MOVABLE

HIGHMEM shouldn't matter - partial memory mirror only makes any sense on X86_64 systems ... 32-bit kernels don't even boot on systems with 64GB, and the minimum rational configuration for a machine that supports mirror is 128GB (4 cpu sockets * 2 memory controller per socket * 4 channels per controller * 4GB DIMM ... leaving any channels empty likely leaves you short of memory bandwidth for these high core count processors).

MOVABLE is mostly the opposite of MIRROR - we never want to fill a kernel allocation from a MOVABLE page. I want all kernel allocations to be from MIRROR.

-Tony

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#35 lore raw

Re: [RFC PATCH 10/12] mm: add the buddy system interface

Quoted 10 lines · Tony
Quoted 1 line

I guess, mirrored memory should be allocated if !__GFP_HIGHMEM or !__GFP_MOVABLE

HIGHMEM shouldn't matter - partial memory mirror only makes any sense on X86_64 systems ... 32-bit kernels don't even boot on systems with 64GB, and the minimum rational configuration for a machine that supports mirror is 128GB (4 cpu sockets * 2 memory controller per socket * 4 channels per controller * 4GB DIMM ... leaving any channels empty likely leaves you short of memory bandwidth for these high core count processors).

MOVABLE is mostly the opposite of MIRROR - we never want to fill a kernel allocation from a MOVABLE page. I want all kernel allocations to be from MIRROR.

So, there are 3 ideas.

(1) kernel only from MIRROR / user only from MOVABLE (Tony)
(2) kernel only from MIRROR / user from MOVABLE + MIRROR(ASAP) (AKPM suggested) This makes use of the fact MOVABLE memory is reclaimable but Tony pointed out the memory reclaim can be critical for GFP_ATOMIC.
(3) kernel only from MIRROR / user from MOVABLE, special user from MIRROR (Xishi)

2 Implementation ideas.
- creating ZONE
- creating new alloation attribute

I don't convince whether we need some new structure in mm. Isn't it good to use ZONE_MOVABLE for not-mirrored memory ?
Then, disable fallback from ZONE_MOVABLE -> ZONE_NORMAL for (1) and (3)

Thanks,
-Kame

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#36 lore raw

Re: [RFC PATCH 10/12] mm: add the buddy system interface

Quoted 8 lines · Kamezawa Hiroyuki

So, there are 3 ideas.

(1) kernel only from MIRROR / user only from MOVABLE (Tony)
(2) kernel only from MIRROR / user from MOVABLE + MIRROR(ASAP) (AKPM suggested) This makes use of the fact MOVABLE memory is reclaimable but Tony pointed out the memory reclaim can be critical for GFP_ATOMIC.
(3) kernel only from MIRROR / user from MOVABLE, special user from MIRROR (Xishi)

Quoted 7 lines

2 Implementation ideas.
- creating ZONE
- creating new alloation attribute

I don't convince whether we need some new structure in mm. Isn't it good to use ZONE_MOVABLE for not-mirrored memory ?
Then, disable fallback from ZONE_MOVABLE -> ZONE_NORMAL for (1) and (3)

We might need to rename it ... right now the memory hotplug people use ZONE_MOVABLE to indicate regions of physical memory that can be removed from the system. I'm wondering whether people will want systems that have both removable and mirrored areas? Then we have four attribute combinations:

mirror=no removable=no - prefer to use for user, could use for kernel if we run out of mirror
mirror=no removable=yes - can only be used for user (kernel allocation makes it not-removable)
mirror=yes removable=no - use for kernel, possibly for special users if we define some interface
mirror=yes removable=yes - must not use for kernel ... would have to give to user ... seems like a bad idea to configure a system this way

-Tony

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#37 lore raw

Re: [RFC PATCH 10/12] mm: add the buddy system interface

Quoted 23 lines · Tony
Quoted 8 lines · Kamezawa Hiroyuki

So, there are 3 ideas.

(1) kernel only from MIRROR / user only from MOVABLE (Tony)
(2) kernel only from MIRROR / user from MOVABLE + MIRROR(ASAP) (AKPM suggested) This makes use of the fact MOVABLE memory is reclaimable but Tony pointed out the memory reclaim can be critical for GFP_ATOMIC.
(3) kernel only from MIRROR / user from MOVABLE, special user from MIRROR (Xishi)

Quoted 7 lines

2 Implementation ideas.
- creating ZONE
- creating new alloation attribute

I don't convince whether we need some new structure in mm. Isn't it good to use ZONE_MOVABLE for not-mirrored memory ?
Then, disable fallback from ZONE_MOVABLE -> ZONE_NORMAL for (1) and (3)

We might need to rename it ... right now the memory hotplug people use ZONE_MOVABLE to indicate regions of physical memory that can be removed from the system. I'm wondering whether people will want systems that have both removable and mirrored areas? Then we have four attribute combinations:

Quoted 5 lines

mirror=no removable=no - prefer to use for user, could use for kernel if we run out of mirror
mirror=no removable=yes - can only be used for user (kernel allocation makes it not-removable)
mirror=yes removable=no - use for kernel, possibly for special users if we define some interface
mirror=yes removable=yes - must not use for kernel ... would have to give to user ... seems like a bad idea to configure a system this way

Thank you for clarification. I see "mirror=no, removable=no" case may require a new name.

IMHO, the value of Address-Based-Memory-Mirror is that users can protect their system's important functions without using full-memory mirror. So, I feel thinking "mirror=no, removable=no" just makes our discussion/implemenation complex without real user value.

Shouldn't we start with just thiking 2 cases of
mirror=no removable=yes
mirror=yes removable=no
?

And then, if the naming is problem, alias name can be added.

Thanks,
-Kame

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#38 lore raw

Re: [RFC PATCH 10/12] mm: add the buddy system interface

In reply to Kamezawa Hiroyuki
Quoted 38 lines · Kamezawa Hiroyuki
Quoted 37 lines · Xishi Qiu
Quoted 34 lines · Kamezawa Hiroyuki
Quoted 20 lines · Xishi Qiu

Add the buddy system interface for address range mirroring feature. Allocate mirrored pages in MIGRATE_MIRROR list. If there is no mirrored pages left, use other types pages.

---
   mm/page_alloc.c | 40 +++++++++++++++++++++++++++++++++++++++-
   1 file changed, 39 insertions(+), 1 deletion(-)
mm/page_alloc.c +3 -0
index d4d2066..0fb55288 100644
@@ -599,6 +599,26 @@ static inline bool is_mirror_pfn(unsigned long pfn)
 
       return false;
   }
+
+static inline bool change_to_mirror(gfp_t gfp_flags, int high_zoneidx)
+{

mm/page_alloc.c static inline bool is_mirror_pfn(unsigned long pfn) · line 614

Quoted 10 lines
mm/page_alloc.c +10 -0
+    /*
+     * Do not alloc mirrored memory below 4G, because 0-4G is
+     * all mirrored by default, and the list is always empty.
+     */
+    if (high_zoneidx < ZONE_NORMAL)
+        return false;
+
+    /* Alloc mirrored memory for only kernel */
+    if (gfp_flags & __GFP_MIRROR)
+        return true;

GFP_KERNEL itself should imply mirror, I think.

Quoted 8 lines
Quoted 4 lines

Hi Kame,

How about like this: #define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_MIRROR) ?

Hm.... it cannot cover GFP_ATOMIC at el.

I guess, mirrored memory should be allocated if !__GFP_HIGHMEM or !__GFP_MOVABLE

Hi Kame,

Can we distinguish allocations form user or kernel only by GFP flags?

Thanks,
Xishi Qiu

#39 lore raw

Re: [RFC PATCH 10/12] mm: add the buddy system interface

Quoted 45 lines · Xishi Qiu
Quoted 43 lines · Kamezawa Hiroyuki
Quoted 41 lines · Xishi Qiu
Quoted 25 lines · Kamezawa Hiroyuki
Quoted 24 lines · Xishi Qiu

Add the buddy system interface for address range mirroring feature. Allocate mirrored pages in MIGRATE_MIRROR list. If there is no mirrored pages left, use other types pages.

---
    mm/page_alloc.c | 40 +++++++++++++++++++++++++++++++++++++++-
    1 file changed, 39 insertions(+), 1 deletion(-)
mm/page_alloc.c +7 -0
index d4d2066..0fb55288 100644
@@ -599,6 +599,26 @@ static inline bool is_mirror_pfn(unsigned long pfn)
 
        return false;
    }
+
+static inline bool change_to_mirror(gfp_t gfp_flags, int high_zoneidx)
+{
+    /*
+     * Do not alloc mirrored memory below 4G, because 0-4G is
+     * all mirrored by default, and the list is always empty.
+     */
Quoted 9 lines

mm/page_alloc.c static inline bool is_mirror_pfn(unsigned long pfn) · line 614

Quoted 6 lines
mm/page_alloc.c +6 -0
+    if (high_zoneidx < ZONE_NORMAL)
+        return false;
+
+    /* Alloc mirrored memory for only kernel */
+    if (gfp_flags & __GFP_MIRROR)
+        return true;

GFP_KERNEL itself should imply mirror, I think.

Hi Kame,

How about like this: #define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_MIRROR) ?

Quoted 9 lines
Quoted 3 lines

Hm.... it cannot cover GFP_ATOMIC at el.

I guess, mirrored memory should be allocated if !__GFP_HIGHMEM or !__GFP_MOVABLE

Hi Kame,

Can we distinguish allocations form user or kernel only by GFP flags?

Allocation from user and file caches are now *always* done with __GFP_MOVABLE.

By this, pages will be allocated from MIGRATE_MOVABLE migration type. MOVABLE migration type means it's can
be the target for page compaction or memory-hot-remove.

Thanks,
-Kame

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#40 lore raw

Re: [RFC PATCH 10/12] mm: add the buddy system interface

Quoted 56 lines · Kamezawa Hiroyuki
Quoted 45 lines · Xishi Qiu
Quoted 43 lines · Kamezawa Hiroyuki
Quoted 41 lines · Xishi Qiu
Quoted 25 lines · Kamezawa Hiroyuki
Quoted 24 lines · Xishi Qiu

Add the buddy system interface for address range mirroring feature. Allocate mirrored pages in MIGRATE_MIRROR list. If there is no mirrored pages left, use other types pages.

---
    mm/page_alloc.c | 40 +++++++++++++++++++++++++++++++++++++++-
    1 file changed, 39 insertions(+), 1 deletion(-)
mm/page_alloc.c +7 -0
index d4d2066..0fb55288 100644
@@ -599,6 +599,26 @@ static inline bool is_mirror_pfn(unsigned long pfn)
 
        return false;
    }
+
+static inline bool change_to_mirror(gfp_t gfp_flags, int high_zoneidx)
+{
+    /*
+     * Do not alloc mirrored memory below 4G, because 0-4G is
+     * all mirrored by default, and the list is always empty.
+     */
Quoted 9 lines

mm/page_alloc.c static inline bool is_mirror_pfn(unsigned long pfn) · line 614

Quoted 6 lines
mm/page_alloc.c +6 -0
+    if (high_zoneidx < ZONE_NORMAL)
+        return false;
+
+    /* Alloc mirrored memory for only kernel */
+    if (gfp_flags & __GFP_MIRROR)
+        return true;

GFP_KERNEL itself should imply mirror, I think.

Hi Kame,

How about like this: #define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_MIRROR) ?

Quoted 9 lines
Quoted 3 lines

Hm.... it cannot cover GFP_ATOMIC at el.

I guess, mirrored memory should be allocated if !__GFP_HIGHMEM or !__GFP_MOVABLE

Hi Kame,

Can we distinguish allocations form user or kernel only by GFP flags?

Quoted 9 lines

Allocation from user and file caches are now *always* done with __GFP_MOVABLE.

By this, pages will be allocated from MIGRATE_MOVABLE migration type. MOVABLE migration type means it's can
be the target for page compaction or memory-hot-remove.

Thanks,
-Kame

So if we want all kernel memory allocated from mirror, how about change like this? __alloc_pages_nodemask()
gfpflags_to_migratetype()

    if (!(gfp_mask & __GFP_MOVABLE))
	return MIGRATE_MIRROR

Thanks,
Xishi Qiu

Quoted 9 lines

.

#41 lore raw

Re: [RFC PATCH 10/12] mm: add the buddy system interface

Quoted 68 lines · Xishi Qiu
Quoted 56 lines · Kamezawa Hiroyuki
Quoted 45 lines · Xishi Qiu
Quoted 43 lines · Kamezawa Hiroyuki
Quoted 41 lines · Xishi Qiu
Quoted 25 lines · Kamezawa Hiroyuki
Quoted 24 lines · Xishi Qiu

Add the buddy system interface for address range mirroring feature. Allocate mirrored pages in MIGRATE_MIRROR list. If there is no mirrored pages left, use other types pages.

---
     mm/page_alloc.c | 40 +++++++++++++++++++++++++++++++++++++++-
     1 file changed, 39 insertions(+), 1 deletion(-)
mm/page_alloc.c +7 -0
index d4d2066..0fb55288 100644
@@ -599,6 +599,26 @@ static inline bool is_mirror_pfn(unsigned long pfn)
 
         return false;
     }
+
+static inline bool change_to_mirror(gfp_t gfp_flags, int high_zoneidx)
+{
+    /*
+     * Do not alloc mirrored memory below 4G, because 0-4G is
+     * all mirrored by default, and the list is always empty.
+     */
Quoted 9 lines

mm/page_alloc.c static inline bool is_mirror_pfn(unsigned long pfn) · line 614

Quoted 6 lines
mm/page_alloc.c +6 -0
+    if (high_zoneidx < ZONE_NORMAL)
+        return false;
+
+    /* Alloc mirrored memory for only kernel */
+    if (gfp_flags & __GFP_MIRROR)
+        return true;

GFP_KERNEL itself should imply mirror, I think.

Hi Kame,

How about like this: #define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_MIRROR) ?

Quoted 9 lines
Quoted 3 lines

Hm.... it cannot cover GFP_ATOMIC at el.

I guess, mirrored memory should be allocated if !__GFP_HIGHMEM or !__GFP_MOVABLE

Hi Kame,

Can we distinguish allocations form user or kernel only by GFP flags?

Quoted 9 lines

Allocation from user and file caches are now *always* done with __GFP_MOVABLE.

By this, pages will be allocated from MIGRATE_MOVABLE migration type. MOVABLE migration type means it's can
be the target for page compaction or memory-hot-remove.

Thanks,
-Kame

Quoted 5 lines

So if we want all kernel memory allocated from mirror, how about change like this? __alloc_pages_nodemask()
gfpflags_to_migratetype()

     if (!(gfp_mask & __GFP_MOVABLE))
	return MIGRATE_MIRROR

Maybe used with jump label can reduce performance impact. ==
static inline bool memory_mirror_enabled(void)

{
        return static_key_false(&memory_mirror_enabled);
}

gfpflags_to_migratetype()
if (memory_mirror_enabled()) { /* We want to mirror all unmovable pages */

      if (!(gfp_mask & __GFP_MOVABLE))
           return MIGRATE_MIRROR

}
==

BTW, I think current memory compaction code scans ranges of MOVABLE migrate type. So, if you use other migration type than MOVABLE for user pages, you may see page fragmentation. If you want to expand this MIRROR to user pages, please check mm/compaction.c

Thanks,
-Kame

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#42 lore raw

Re: [RFC PATCH 10/12] mm: add the buddy system interface

Quoted 69 lines · Kamezawa Hiroyuki
Quoted 68 lines · Xishi Qiu
Quoted 65 lines · Kamezawa Hiroyuki
Quoted 45 lines · Xishi Qiu
Quoted 43 lines · Kamezawa Hiroyuki
Quoted 41 lines · Xishi Qiu
Quoted 25 lines · Kamezawa Hiroyuki
Quoted 24 lines · Xishi Qiu

Add the buddy system interface for address range mirroring feature. Allocate mirrored pages in MIGRATE_MIRROR list. If there is no mirrored pages left, use other types pages.

---
     mm/page_alloc.c | 40 +++++++++++++++++++++++++++++++++++++++-
     1 file changed, 39 insertions(+), 1 deletion(-)
mm/page_alloc.c +7 -0
index d4d2066..0fb55288 100644
@@ -599,6 +599,26 @@ static inline bool is_mirror_pfn(unsigned long pfn)
 
         return false;
     }
+
+static inline bool change_to_mirror(gfp_t gfp_flags, int high_zoneidx)
+{
+    /*
+     * Do not alloc mirrored memory below 4G, because 0-4G is
+     * all mirrored by default, and the list is always empty.
+     */
Quoted 9 lines

mm/page_alloc.c static inline bool is_mirror_pfn(unsigned long pfn) · line 614

Quoted 6 lines
mm/page_alloc.c +6 -0
+    if (high_zoneidx < ZONE_NORMAL)
+        return false;
+
+    /* Alloc mirrored memory for only kernel */
+    if (gfp_flags & __GFP_MIRROR)
+        return true;

GFP_KERNEL itself should imply mirror, I think.

Hi Kame,

How about like this: #define GFP_KERNEL (__GFP_WAIT | __GFP_IO | __GFP_FS | __GFP_MIRROR) ?

Quoted 9 lines
Quoted 3 lines

Hm.... it cannot cover GFP_ATOMIC at el.

I guess, mirrored memory should be allocated if !__GFP_HIGHMEM or !__GFP_MOVABLE

Hi Kame,

Can we distinguish allocations form user or kernel only by GFP flags?

Allocation from user and file caches are now *always* done with __GFP_MOVABLE.

By this, pages will be allocated from MIGRATE_MOVABLE migration type. MOVABLE migration type means it's can
be the target for page compaction or memory-hot-remove.

Thanks,
-Kame

Quoted 7 lines
Quoted 5 lines

So if we want all kernel memory allocated from mirror, how about change like this? __alloc_pages_nodemask()
gfpflags_to_migratetype()

     if (!(gfp_mask & __GFP_MOVABLE))
    return MIGRATE_MIRROR

Maybe used with jump label can reduce performance impact.

Hi Kame,

I am not understand jump label, but I wil try.

Quoted 12 lines

==
static inline bool memory_mirror_enabled(void)

{
        return static_key_false(&memory_mirror_enabled);
}

gfpflags_to_migratetype()
if (memory_mirror_enabled()) { /* We want to mirror all unmovable pages */

      if (!(gfp_mask & __GFP_MOVABLE))
           return MIGRATE_MIRROR
Quoted 8 lines

}
==

BTW, I think current memory compaction code scans ranges of MOVABLE migrate type. So, if you use other migration type than MOVABLE for user pages, you may see page fragmentation. If you want to expand this MIRROR to user pages, please check mm/compaction.c

As Tony said "how can we minimize the run-time impact on systems that don't have any mirrored memory.", I think the idea "kernel only from MIRROR / user only from MOVABLE" may be better.

Thanks,
Xishi Qiu

#43 lore raw

RE: [RFC PATCH 10/12] mm: add the buddy system interface

Quoted 5 lines

gfpflags_to_migratetype()
if (memory_mirror_enabled()) { /* We want to mirror all unmovable pages */

      if (!(gfp_mask & __GFP_MOVABLE))
           return MIGRATE_MIRROR

}

I'm not sure that we can divide memory into just two buckets of "mirrored" and "movable".

My expectation is that there will be memory that is neither mirrored, nor movable. We'd allocate that memory to user proceses. Uncorrected errors in that memory would result in the death of the process (except in the case where the page is a clean copy mapped from a disk file ... e.g. .text mapping instructions from an executable). Linux would offline the affected 4K page so as not to hit the problem again.

-Tony

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#44 lore raw

RFC PATCH 11/12 mm: add the PCP interface

In reply to Xishi Qiu

Add the PCP interface for address range mirroring feature.

---
 mm/page_alloc.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)
mm/page_alloc.c +13 -3
index 0fb55288..cf3b7cb 100644
@@ -1401,11 +1401,16 @@ 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, mt;
 
 	spin_lock(&zone->lock);
 	for (i = 0; i < count; ++i) {
-		struct page *page = __rmqueue(zone, order, migratetype);
+		struct page *page;
+
+		if (is_migrate_mirror(migratetype))
+			page = __rmqueue_smallest(zone, order, migratetype);
+		else
+			page = __rmqueue(zone, order, migratetype);
 		if (unlikely(page == NULL))
 			break;
 
@@ -1423,9 +1428,14 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
 		else
 			list_add_tail(&page->lru, list);
 		list = &page->lru;
-		if (is_migrate_cma(get_freepage_migratetype(page)))
+
+		mt = get_freepage_migratetype(page);
+		if (is_migrate_cma(mt))
 			__mod_zone_page_state(zone, NR_FREE_CMA_PAGES,
 					      -(1 << order));
+		if (is_migrate_mirror(mt))
+			__mod_zone_page_state(zone, NR_FREE_MIRROR_PAGES,
+					      -(1 << order));
 	}
 	__mod_zone_page_state(zone, NR_FREE_PAGES, -(i << order));
 	spin_unlock(&zone->lock);
Signature · 1 line
2.0.0
#45 lore raw

Re: [RFC PATCH 11/12] mm: add the PCP interface

mm/page_alloc.c static int rmqueue_bulk(struct zone *zone, unsigned int order, · line 1415

Quoted 11 lines · Xishi Qiu
mm/page_alloc.c +6 -1
 	spin_lock(&zone->lock);
 	for (i = 0; i < count; ++i) {
-		struct page *page = __rmqueue(zone, order, migratetype);
+		struct page *page;
+
+		if (is_migrate_mirror(migratetype))
+			page = __rmqueue_smallest(zone, order, migratetype);
+		else
+			page = __rmqueue(zone, order, migratetype);
 		if (unlikely(page == NULL))
 			break;

Why is this necessary/helpful? The changelog doesn't tell me either. :(

Why was this code modified in stead of putting the changes in __rmqueue() itself (like CMA did)?

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#46 lore raw

RFC PATCH 12/12 mm: let slab/slub/slob use mirrored memory

In reply to Xishi Qiu

Add __GFP_MIRROR flag when allocate a new slab.

---
 mm/slab.c | 3 ++-
 mm/slob.c | 2 +-
 mm/slub.c | 2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)
mm/slab.c +2 -1
index 7eb38dd..3b3ef22 100644
@@ -1594,7 +1594,8 @@ static struct page *kmem_getpages(struct kmem_cache *cachep, gfp_t flags,
 	if (memcg_charge_slab(cachep, flags, cachep->gfporder))
 		return NULL;
 
-	page = alloc_pages_exact_node(nodeid, flags | __GFP_NOTRACK, cachep->gfporder);
+	page = alloc_pages_exact_node(nodeid, flags | __GFP_NOTRACK | __GFP_MIRROR,
+					cachep->gfporder);
 	if (!page) {
 		memcg_uncharge_slab(cachep, cachep->gfporder);
 		slab_out_of_memory(cachep, flags, nodeid);
mm/slob.c +1 -1
index 4765f65..4ff9bde 100644
@@ -452,7 +452,7 @@ __do_kmalloc_node(size_t size, gfp_t gfp, int node, unsigned long caller)
 
 		if (likely(order))
 			gfp |= __GFP_COMP;
-		ret = slob_new_pages(gfp, order, node);
+		ret = slob_new_pages(gfp | __GFP_MIRROR, order, node);
 
 		trace_kmalloc_node(caller, ret,
 				   size, PAGE_SIZE << order, gfp, node);
mm/slub.c +1 -1
index 54c0876..1219e33 100644
@@ -1315,7 +1315,7 @@ static inline struct page *alloc_slab_page(struct kmem_cache *s,
 	struct page *page;
 	int order = oo_order(oo);
 
-	flags |= __GFP_NOTRACK;
+	flags |= __GFP_NOTRACK | __GFP_MIRROR;
 
 	if (memcg_charge_slab(s, flags, order))
 		return NULL;
Signature · 1 line
2.0.0
#47 lore raw

RE: [RFC PATCH 12/12] mm: let slab/slub/slob use mirrored memory

- page = alloc_pages_exact_node(nodeid, flags | __GFP_NOTRACK, cachep->gfporder);
+ page = alloc_pages_exact_node(nodeid, flags | __GFP_NOTRACK | __GFP_MIRROR,
+ cachep->gfporder);

Set some global "got_mirror"[*] if we have any mirrored memory to __GFP_MIRROR, else to 0.

then

	page = alloc_pages_exact_node(nodeid, flags | __GFP_NOTRACK | got_mirror,
					cachep->gfporder);

-Tony

[*] Someone will suggest a better name. I'm bad at picking names.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#48 lore raw
In reply to Xishi Qiu
Quoted 16 lines · Xishi Qiu

Intel Xeon processor E7 v3 product family-based platforms introduces support for partial memory mirroring called as 'Address Range Mirroring'. This feature allows BIOS to specify a subset of total available memory to be mirrored (and optionally also specify whether to mirror the range 0-4 GB). This capability allows user to make an appropriate tradeoff between non-mirrored memory range and mirrored memory range thus optimizing total available memory and still achieving highly reliable memory range for mission critical workloads and/or kernel space.

Tony has already send a patchset to supprot this feature at boot time.
https://lkml.org/lkml/2015/5/8/521

This patchset can support the feature after boot time. It introduces mirror_info to save the mirrored memory range. Then use __GFP_MIRROR to allocate mirrored pages.

Quoted 7 lines

I think add a new migratetype is btter and easier than a new zone, so I use MIGRATE_MIRROR to manage the mirrored pages. However it changed some code in the core file, please review and comment, thanks.

TBD:
1) call add_mirror_info() to fill mirrored memory info.
2) add compatibility with memory online/offline.

Maybe simply disabling memory offlining of memory block including MIGRATE_MIRROR?

Quoted 1 line

3) add more interface? others?

4?) I don't have the whole picture of how address ranging mirroring works, but I'm curious about what happens when an uncorrected memory error happens on the a mirror page. If HW/FW do some useful work invisible from kernel, please document it somewhere. And my questions are:
- can the kernel with this patchset really continue its operation without breaking consistency? More specifically, the corrupted page is replaced with its mirror page, but can any other pages which have references (like struct page or pfn) for the corrupted page properly switch these references to the mirror page? Or no worry about that? (This is difficult for kernel pages like slab, and that's why currently hwpoison doesn't handle any kernel pages.)
- How can we test/confirm that the whole scheme works fine? Is current memory error injection framework enough?

It's really nice if any roadmap including testing is shared.

# And please CC me as [email protected] (my primary email address :)

Thanks,
Naoya Horiguchi

Quoted 14 lines

Xishi Qiu (12):
mm: add a new config to manage the code
mm: introduce mirror_info
mm: introduce MIGRATE_MIRROR to manage the mirrored pages
mm: add mirrored pages to buddy system
mm: introduce a new zone_stat_item NR_FREE_MIRROR_PAGES
mm: add free mirrored pages info
mm: introduce __GFP_MIRROR to allocate mirrored pages
mm: use mirrorable to switch allocate mirrored memory
mm: enable allocate mirrored memory at boot time
mm: add the buddy system interface
mm: add the PCP interface
mm: let slab/slub/slob use mirrored memory

Quoted 24 lines
 arch/x86/mm/numa.c     |   3 ++
 drivers/base/node.c    |  17 ++++---
 fs/proc/meminfo.c      |   6 +++
 include/linux/gfp.h    |   5 +-
 include/linux/mmzone.h |  23 +++++++++
 include/linux/vmstat.h |   2 +
 kernel/sysctl.c        |   9 ++++
 mm/Kconfig             |   8 +++
 mm/page_alloc.c        | 134 ++++++++++++++++++++++++++++++++++++++++++++++---
 mm/slab.c              |   3 +-
 mm/slob.c              |   2 +-
 mm/slub.c              |   2 +-
 mm/vmstat.c            |   4 ++
 13 files changed, 202 insertions(+), 16 deletions(-)
Signature · 8 lines
2.0.0


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#49 lore raw
Quoted 25 lines · Naoya Horiguchi
Quoted 16 lines · Xishi Qiu

Intel Xeon processor E7 v3 product family-based platforms introduces support for partial memory mirroring called as 'Address Range Mirroring'. This feature allows BIOS to specify a subset of total available memory to be mirrored (and optionally also specify whether to mirror the range 0-4 GB). This capability allows user to make an appropriate tradeoff between non-mirrored memory range and mirrored memory range thus optimizing total available memory and still achieving highly reliable memory range for mission critical workloads and/or kernel space.

Tony has already send a patchset to supprot this feature at boot time.
https://lkml.org/lkml/2015/5/8/521

This patchset can support the feature after boot time. It introduces mirror_info to save the mirrored memory range. Then use __GFP_MIRROR to allocate mirrored pages.

Quoted 7 lines

I think add a new migratetype is btter and easier than a new zone, so I use MIGRATE_MIRROR to manage the mirrored pages. However it changed some code in the core file, please review and comment, thanks.

TBD:
1) call add_mirror_info() to fill mirrored memory info.
2) add compatibility with memory online/offline.

Quoted 8 lines

Maybe simply disabling memory offlining of memory block including MIGRATE_MIRROR?

Quoted 1 line

3) add more interface? others?

4?) I don't have the whole picture of how address ranging mirroring works, but I'm curious about what happens when an uncorrected memory error happens on the a mirror page. If HW/FW do some useful work invisible from kernel, please document it somewhere. And my questions are:

Hi Naoya,

I think the hardware and BIOS will do the work when page corrupted, and it is invisible to kernel. The kernel just use the mirrored memory (alloc pages in special physical address).

Thanks,
Xishi Qiu

Quoted 56 lines

- can the kernel with this patchset really continue its operation without breaking consistency? More specifically, the corrupted page is replaced with its mirror page, but can any other pages which have references (like struct page or pfn) for the corrupted page properly switch these references to the mirror page? Or no worry about that? (This is difficult for kernel pages like slab, and that's why currently hwpoison doesn't handle any kernel pages.)
- How can we test/confirm that the whole scheme works fine? Is current memory error injection framework enough?

It's really nice if any roadmap including testing is shared.

# And please CC me as [email protected] (my primary email address :)

Thanks,
Naoya Horiguchi

Quoted 14 lines

Xishi Qiu (12):
mm: add a new config to manage the code
mm: introduce mirror_info
mm: introduce MIGRATE_MIRROR to manage the mirrored pages
mm: add mirrored pages to buddy system
mm: introduce a new zone_stat_item NR_FREE_MIRROR_PAGES
mm: add free mirrored pages info
mm: introduce __GFP_MIRROR to allocate mirrored pages
mm: use mirrorable to switch allocate mirrored memory
mm: enable allocate mirrored memory at boot time
mm: add the buddy system interface
mm: add the PCP interface
mm: let slab/slub/slob use mirrored memory

Quoted 24 lines
 arch/x86/mm/numa.c     |   3 ++
 drivers/base/node.c    |  17 ++++---
 fs/proc/meminfo.c      |   6 +++
 include/linux/gfp.h    |   5 +-
 include/linux/mmzone.h |  23 +++++++++
 include/linux/vmstat.h |   2 +
 kernel/sysctl.c        |   9 ++++
 mm/Kconfig             |   8 +++
 mm/page_alloc.c        | 134 ++++++++++++++++++++++++++++++++++++++++++++++---
 mm/slab.c              |   3 +-
 mm/slob.c              |   2 +-
 mm/slub.c              |   2 +-
 mm/vmstat.c            |   4 ++
 13 files changed, 202 insertions(+), 16 deletions(-)
Signature · 8 lines
2.0.0


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

.

#50 lore raw
In reply to Naoya Horiguchi
Quoted 10 lines · Naoya Horiguchi

4?) I don't have the whole picture of how address ranging mirroring works, but I'm curious about what happens when an uncorrected memory error happens on the a mirror page. If HW/FW do some useful work invisible from kernel, please document it somewhere. And my questions are:
- can the kernel with this patchset really continue its operation without breaking consistency? More specifically, the corrupted page is replaced with its mirror page, but can any other pages which have references (like struct page or pfn) for the corrupted page properly switch these references to the mirror page? Or no worry about that? (This is difficult for kernel pages like slab, and that's why currently hwpoison doesn't handle any kernel pages.)

The mirror is operated by h/w (perhaps with some platform firmware intervention when things start breaking badly).

In normal operation there are two DIMM addresses backing each system physical address in the mirrored range (thus total system memory capacity is reduced when mirror is enabled). Memory writes are directed to both locations. Memory reads are interleaved to maintain bandwidth, so could come from either address.

When a read returns with an ECC failure the h/w automatically:
1) Re-issues the read to the other DIMM address. If that also fails - then we do the normal machine check processing for an uncorrected error
2) But if the other side of the mirror is good, we can send the good data to the reader (cpu, or dma) and, in parallel try to fix the bad side by writing the good data to it.
3) A corrected error will be logged, it may indicate whether the attempt to fix succeeded or not.
4) If platform firmware wants, it can be notified of the correction and it may keep statistics on the rate of errors, correction status, etc. If things get very bad it may "break" the mirror and direct all future reads to the remaining "good" side. If does this it will likely tell the OS via some ACPI method.

All of this is done at much less than page granularity. Cache coherence is maintained ... apart from some small performance glitches and the corrected error logs, the OS is unware of all of this.

Note that in current implementations the mirror copies are both behind the same memory controller ... so this isn't intended to cope with high level failure of a memory controller ... just to deal with randomly distributed ECC errors.

Quoted 2 lines

- How can we test/confirm that the whole scheme works fine? Is current memory error injection framework enough?

Still working on that piece. To validate you need to be able to inject errors to just one side of the mirror, and I'm not really sure that the ACPI/EINJ interface is up to the task.

-Tony

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#51 lore raw
Quoted 12 lines · Tony
Quoted 10 lines · Naoya Horiguchi

4?) I don't have the whole picture of how address ranging mirroring works, but I'm curious about what happens when an uncorrected memory error happens on the a mirror page. If HW/FW do some useful work invisible from kernel, please document it somewhere. And my questions are:
- can the kernel with this patchset really continue its operation without breaking consistency? More specifically, the corrupted page is replaced with its mirror page, but can any other pages which have references (like struct page or pfn) for the corrupted page properly switch these references to the mirror page? Or no worry about that? (This is difficult for kernel pages like slab, and that's why currently hwpoison doesn't handle any kernel pages.)

Quoted 8 lines

The mirror is operated by h/w (perhaps with some platform firmware intervention when things start breaking badly).

In normal operation there are two DIMM addresses backing each system physical address in the mirrored range (thus total system memory capacity is reduced when mirror is enabled). Memory writes are directed to both locations. Memory reads are interleaved to maintain bandwidth, so could come from either address.

I misunderstood that both of mirrored page and mirroring page are visible to OS, which is incorrect.

Quoted 5 lines

When a read returns with an ECC failure the h/w automatically:
1) Re-issues the read to the other DIMM address. If that also fails - then we do the normal machine check processing for an uncorrected error
2) But if the other side of the mirror is good, we can send the good data to the reader (cpu, or dma) and, in parallel try to fix the

Quoted 8 lines

bad side by writing the good data to it.
3) A corrected error will be logged, it may indicate whether the attempt to fix succeeded or not.
4) If platform firmware wants, it can be notified of the correction and it may keep statistics on the rate of errors, correction status, etc. If things get very bad it may "break" the mirror and direct all future reads to the remaining "good" side. If does this it will likely tell the OS via some ACPI method.

Thanks, this fully answered my question.

Quoted 8 lines

All of this is done at much less than page granularity. Cache coherence is maintained ... apart from some small performance glitches and the corrected error logs, the OS is unware of all of this.

Note that in current implementations the mirror copies are both behind the same memory controller ... so this isn't intended to cope with high level failure of a memory controller ... just to deal with randomly distributed ECC errors.

OK, I looked at "Memory Address Range Mirroring Validation Guide" and Fig 2-2 clearly shows that.

Quoted 6 lines
Quoted 2 lines

- How can we test/confirm that the whole scheme works fine? Is current memory error injection framework enough?

Still working on that piece. To validate you need to be able to inject errors to just one side of the mirror, and I'm not really sure that the ACPI/EINJ interface is up to the task.

OK.

Thanks,
Naoya Horiguchi
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#52 lore raw
In reply to Xishi Qiu
Quoted 9 lines · Xishi Qiu

Intel Xeon processor E7 v3 product family-based platforms introduces support for partial memory mirroring called as 'Address Range Mirroring'. This feature allows BIOS to specify a subset of total available memory to be mirrored (and optionally also specify whether to mirror the range 0-4 GB). This capability allows user to make an appropriate tradeoff between non-mirrored memory range and mirrored memory range thus optimizing total available memory and still achieving highly reliable memory range for mission critical workloads and/or kernel space.

Quoted 8 lines

Tony has already send a patchset to supprot this feature at boot time.
https://lkml.org/lkml/2015/5/8/521

This patchset can support the feature after boot time. It introduces mirror_info to save the mirrored memory range. Then use __GFP_MIRROR to allocate mirrored pages.

I think add a new migratetype is btter and easier than a new zone, so I use

If the mirrored memory is in a single reasonably compact (no large holes) range (per NUMA node) and won't dynamically change its size, then zone might be a better option. For one thing, it will still allow distinguishing movable and unmovable allocations within the mirrored memory.

We had enough fun with MIGRATE_CMA and all kinds of checks it added to allocator hot paths, and even CMA is now considering moving to a separate zone.

Quoted 22 lines

MIGRATE_MIRROR to manage the mirrored pages. However it changed some code in the core file, please review and comment, thanks.

TBD:
1) call add_mirror_info() to fill mirrored memory info.
2) add compatibility with memory online/offline.
3) add more interface? others?

Xishi Qiu (12):
mm: add a new config to manage the code
mm: introduce mirror_info
mm: introduce MIGRATE_MIRROR to manage the mirrored pages
mm: add mirrored pages to buddy system
mm: introduce a new zone_stat_item NR_FREE_MIRROR_PAGES
mm: add free mirrored pages info
mm: introduce __GFP_MIRROR to allocate mirrored pages
mm: use mirrorable to switch allocate mirrored memory
mm: enable allocate mirrored memory at boot time
mm: add the buddy system interface
mm: add the PCP interface
mm: let slab/slub/slob use mirrored memory

Quoted 15 lines
 arch/x86/mm/numa.c     |   3 ++
 drivers/base/node.c    |  17 ++++---
 fs/proc/meminfo.c      |   6 +++
 include/linux/gfp.h    |   5 +-
 include/linux/mmzone.h |  23 +++++++++
 include/linux/vmstat.h |   2 +
 kernel/sysctl.c        |   9 ++++
 mm/Kconfig             |   8 +++
 mm/page_alloc.c        | 134 ++++++++++++++++++++++++++++++++++++++++++++++---
 mm/slab.c              |   3 +-
 mm/slob.c              |   2 +-
 mm/slub.c              |   2 +-
 mm/vmstat.c            |   4 ++
 13 files changed, 202 insertions(+), 16 deletions(-)

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#53 lore raw
Quoted 19 lines · Vlastimil Babka
Quoted 9 lines · Xishi Qiu

Intel Xeon processor E7 v3 product family-based platforms introduces support for partial memory mirroring called as 'Address Range Mirroring'. This feature allows BIOS to specify a subset of total available memory to be mirrored (and optionally also specify whether to mirror the range 0-4 GB). This capability allows user to make an appropriate tradeoff between non-mirrored memory range and mirrored memory range thus optimizing total available memory and still achieving highly reliable memory range for mission critical workloads and/or kernel space.

Quoted 8 lines

Tony has already send a patchset to supprot this feature at boot time.
https://lkml.org/lkml/2015/5/8/521

This patchset can support the feature after boot time. It introduces mirror_info to save the mirrored memory range. Then use __GFP_MIRROR to allocate mirrored pages.

I think add a new migratetype is btter and easier than a new zone, so I use

Quoted 8 lines

If the mirrored memory is in a single reasonably compact (no large holes) range (per NUMA node) and won't dynamically change its size, then zone might be a better option. For one thing, it will still allow distinguishing movable and unmovable allocations within the mirrored memory.

We had enough fun with MIGRATE_CMA and all kinds of checks it added to allocator hot paths, and even CMA is now considering moving to a separate zone.

Hi, how about the problem of this case:
e.g. node 0: 0-4G(dma and dma32)

     node 1: 4G-8G(normal), 8-12G(mirror), 12-16G(normal),

so more than one normal zone in a node? or normal zone just span the mirror zone?

Thanks,
Xishi Qiu

#54 lore raw
Quoted 11 lines · Xishi Qiu
Quoted 9 lines · Vlastimil Babka
Quoted 2 lines · Xishi Qiu

I think add a new migratetype is btter and easier than a new zone, so I use

If the mirrored memory is in a single reasonably compact (no large holes) range (per NUMA node) and won't dynamically change its size, then zone might be a better option. For one thing, it will still allow distinguishing movable and unmovable allocations within the mirrored memory.

Quoted 8 lines
Quoted 3 lines

We had enough fun with MIGRATE_CMA and all kinds of checks it added to allocator hot paths, and even CMA is now considering moving to a separate zone.

Hi, how about the problem of this case:
e.g. node 0: 0-4G(dma and dma32)

     node 1: 4G-8G(normal), 8-12G(mirror), 12-16G(normal),

so more than one normal zone in a node? or normal zone just span the mirror zone?

Normal zone can span the mirror zone just fine. However, it will result in zone scanners such as compaction to skip over the mirror zone inefficiently. Hmm...

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#55 lore raw
Quoted 16 lines · Vlastimil Babka
Quoted 15 lines · Xishi Qiu
Quoted 12 lines · Vlastimil Babka
Quoted 2 lines · Xishi Qiu

I think add a new migratetype is btter and easier than a new zone, so I use

If the mirrored memory is in a single reasonably compact (no large holes) range (per NUMA node) and won't dynamically change its size, then zone might be a better option. For one thing, it will still allow distinguishing movable and unmovable allocations within the mirrored memory.

We had enough fun with MIGRATE_CMA and all kinds of checks it added to allocator hot paths, and even CMA is now considering moving to a separate zone.

Quoted 8 lines
Quoted 4 lines

Hi, how about the problem of this case:
e.g. node 0: 0-4G(dma and dma32)

     node 1: 4G-8G(normal), 8-12G(mirror), 12-16G(normal),

so more than one normal zone in a node? or normal zone just span the mirror zone?

Normal zone can span the mirror zone just fine. However, it will result in zone scanners such as compaction to skip over the mirror zone inefficiently. Hmm...

Hi Vlastimil,

If there are many mirror regions in one node, then it will be many holes in the normal zone, is this fine?

Thanks,
Xishi Qiu

Quoted 3 lines

.

#56 lore raw
Quoted 18 lines · Xishi Qiu
Quoted 16 lines · Vlastimil Babka
Quoted 15 lines · Xishi Qiu
Quoted 12 lines · Vlastimil Babka
Quoted 2 lines · Xishi Qiu

I think add a new migratetype is btter and easier than a new zone, so I use

If the mirrored memory is in a single reasonably compact (no large holes) range (per NUMA node) and won't dynamically change its size, then zone might be a better option. For one thing, it will still allow distinguishing movable and unmovable allocations within the mirrored memory.

We had enough fun with MIGRATE_CMA and all kinds of checks it added to allocator hot paths, and even CMA is now considering moving to a separate zone.

Quoted 7 lines
Quoted 7 lines
Quoted 4 lines

Hi, how about the problem of this case:
e.g. node 0: 0-4G(dma and dma32)

     node 1: 4G-8G(normal), 8-12G(mirror), 12-16G(normal),

so more than one normal zone in a node? or normal zone just span the mirror zone?

Normal zone can span the mirror zone just fine. However, it will result in zone scanners such as compaction to skip over the mirror zone inefficiently. Hmm...

On the other hand, it would skip just as inefficiently over MIGRATE_MIRROR pageblocks within a Normal zone. Since migrating pages between MIGRATE_MIRROR and other types pageblocks would violate what the allocations requested.

Having separate zone instead would allow compaction to run specifically on the zone and defragment movable allocations there (i.e. userspace pages if/when userspace requesting mirrored memory is supported).

Quoted 6 lines
Quoted 1 line

Hi Vlastimil,

If there are many mirror regions in one node, then it will be many holes in the normal zone, is this fine?

Yeah, it doesn't matter how many holes there are.

Quoted 9 lines

Thanks,
Xishi Qiu

Quoted 3 lines

.

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#57 lore raw
Quoted 37 lines · Vlastimil Babka
Quoted 18 lines · Xishi Qiu
Quoted 16 lines · Vlastimil Babka
Quoted 15 lines · Xishi Qiu
Quoted 12 lines · Vlastimil Babka
Quoted 2 lines · Xishi Qiu

I think add a new migratetype is btter and easier than a new zone, so I use

If the mirrored memory is in a single reasonably compact (no large holes) range (per NUMA node) and won't dynamically change its size, then zone might be a better option. For one thing, it will still allow distinguishing movable and unmovable allocations within the mirrored memory.

We had enough fun with MIGRATE_CMA and all kinds of checks it added to allocator hot paths, and even CMA is now considering moving to a separate zone.

Quoted 7 lines
Quoted 7 lines
Quoted 4 lines

Hi, how about the problem of this case:
e.g. node 0: 0-4G(dma and dma32)

     node 1: 4G-8G(normal), 8-12G(mirror), 12-16G(normal),

so more than one normal zone in a node? or normal zone just span the mirror zone?

Normal zone can span the mirror zone just fine. However, it will result in zone scanners such as compaction to skip over the mirror zone inefficiently. Hmm...

On the other hand, it would skip just as inefficiently over MIGRATE_MIRROR pageblocks within a Normal zone. Since migrating pages between MIGRATE_MIRROR and other types pageblocks would violate what the allocations requested.

Having separate zone instead would allow compaction to run specifically on the zone and defragment movable allocations there (i.e. userspace pages if/when userspace requesting mirrored memory is supported).

Quoted 2 lines
Quoted 1 line
Quoted 6 lines
Quoted 4 lines

Hi Vlastimil,

If there are many mirror regions in one node, then it will be many holes in the normal zone, is this fine?

Yeah, it doesn't matter how many holes there are.

So mirror zone and normal zone will span each other, right?

e.g. node 1: 4G-8G(normal), 8-12G(mirror), 12-16G(normal), 16-24G(mirror), 24-28G(normal) ...
normal: start=4G, size=28-4=24G,
mirror: start=8G, size=24-8=16G,

I think zone is defined according to the special address range, like 16M(DMA), 4G(DMA32), and is it appropriate to add a new mirror zone with a volatile physical address?

Thanks,
Xishi Qiu

#58 lore raw
Quoted 21 lines · Xishi Qiu
Quoted 19 lines · Vlastimil Babka
Quoted 2 lines · Xishi Qiu

On 2015/6/16 17:46, Vlastimil Babka wrote:

On the other hand, it would skip just as inefficiently over MIGRATE_MIRROR pageblocks within a Normal zone. Since migrating pages between MIGRATE_MIRROR and other types pageblocks would violate what the allocations requested.

Having separate zone instead would allow compaction to run specifically on the zone and defragment movable allocations there (i.e. userspace pages if/when userspace requesting mirrored memory is supported).

Quoted 6 lines
Quoted 1 line

Hi Vlastimil,

If there are many mirror regions in one node, then it will be many holes in the normal zone, is this fine?

Quoted 7 lines
Quoted 1 line

Yeah, it doesn't matter how many holes there are.

So mirror zone and normal zone will span each other, right?

e.g. node 1: 4G-8G(normal), 8-12G(mirror), 12-16G(normal), 16-24G(mirror), 24-28G(normal) ...
normal: start=4G, size=28-4=24G,
mirror: start=8G, size=24-8=16G,

Yes, that works. It's somewhat unfortunate wrt performance that the hardware does it like this though.

Quoted 1 line

I think zone is defined according to the special address range, like 16M(DMA), 4G(DMA32),

Traditionally yes. But then there is ZONE_MOVABLE, this year's LSF/MM we discussed (and didn't outright deny) ZONE_CMA... I'm not saying others will favour the new zone approach though, it's just my opinion that it might be a better option than a new migratetype.

Quoted 1 line

and is it appropriate to add a new mirror zone with a volatile physical address?

By "volatile" you mean what, that the example above would change dynamically? That would be rather challenging...

Quoted 3 lines

Thanks,
Xishi Qiu

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

#59 lore raw
Quoted 5 lines · Vlastimil Babka
Quoted 5 lines
Quoted 4 lines
Quoted 2 lines

If there are many mirror regions in one node, then it will be many holes in the normal zone, is this fine?

Yeah, it doesn't matter how many holes there are.

Quoted 8 lines
Quoted 5 lines

So mirror zone and normal zone will span each other, right?

e.g. node 1: 4G-8G(normal), 8-12G(mirror), 12-16G(normal), 16-24G(mirror), 24-28G(normal) ...
normal: start=4G, size=28-4=24G,
mirror: start=8G, size=24-8=16G,

Yes, that works. It's somewhat unfortunate wrt performance that the hardware does it like this though.

With current Xeon h/w you can have one mirrored range per memory controller ... and there are two memory controllers on a cpu socket, so two mirrored ranges per node. So a map might look like:

SKT0: MC0: 0-2G Mirrored (but we may want to ignore mirror here to keep it for ZONE_DMA)
SKT0: MC0: 2G-4G No memory ... I/O mapping area
SKT0: MC0: 4G-34G Not mirrored
SKT0: MC1: 34G-40G Mirrored
SKT0: MC1: 40G-66G Not mirrored

SKT1: MC0: 66G-70G Mirror
SKT1: MC0: 70G-98G Not Mirrored
SKT1: MC1: 98G-102G Mirror
SKT1: MC1: 102G-130G Not Mirrored

... and so on.

Quoted 6 lines
Quoted 1 line

I think zone is defined according to the special address range, like 16M(DMA), 4G(DMA32),

Traditionally yes. But then there is ZONE_MOVABLE, this year's LSF/MM we discussed (and didn't outright deny) ZONE_CMA...
I'm not saying others will favour the new zone approach though, it's just my opinion that it might be a better option than a new migratetype.

If we are going to have lots of zones ... then perhaps we will need a fast way to look at a "struct page" and decide which zone it belongs to. Complicated math on the address deosn't sound ideal. If the complex zone model is just for 64-bit, are there enough bits available in page->flags (3 bits for 8 options ... which we are close to filling now ... 4 bits for future breathing room).

Quoted 4 lines
Quoted 1 line

and is it appropriate to add a new mirror zone with a volatile physical address?

By "volatile" you mean what, that the example above would change dynamically? That would be rather challenging...

If we hot-add another cpu together with on die memory controllers connected to more memory ... then some of the new memory might be mirrored. Current h/w doesn't allow mirrored areas to grow/shrink (though if there are a lot of errors we may break a mirror so a whole range could lose the mirror attribute).

-Tony

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>

author
#60 lore raw
Quoted 51 lines · Tony
Quoted 5 lines · Vlastimil Babka
Quoted 5 lines
Quoted 4 lines
Quoted 2 lines

If there are many mirror regions in one node, then it will be many holes in the normal zone, is this fine?

Yeah, it doesn't matter how many holes there are.

Quoted 8 lines
Quoted 5 lines

So mirror zone and normal zone will span each other, right?

e.g. node 1: 4G-8G(normal), 8-12G(mirror), 12-16G(normal), 16-24G(mirror), 24-28G(normal) ...
normal: start=4G, size=28-4=24G,
mirror: start=8G, size=24-8=16G,

Yes, that works. It's somewhat unfortunate wrt performance that the hardware does it like this though.

With current Xeon h/w you can have one mirrored range per memory controller ... and there are two memory controllers on a cpu socket, so two mirrored ranges per node. So a map might look like:

SKT0: MC0: 0-2G Mirrored (but we may want to ignore mirror here to keep it for ZONE_DMA)
SKT0: MC0: 2G-4G No memory ... I/O mapping area
SKT0: MC0: 4G-34G Not mirrored
SKT0: MC1: 34G-40G Mirrored
SKT0: MC1: 40G-66G Not mirrored

SKT1: MC0: 66G-70G Mirror
SKT1: MC0: 70G-98G Not Mirrored
SKT1: MC1: 98G-102G Mirror
SKT1: MC1: 102G-130G Not Mirrored

... and so on.

Quoted 6 lines
Quoted 1 line

I think zone is defined according to the special address range, like 16M(DMA), 4G(DMA32),

Traditionally yes. But then there is ZONE_MOVABLE, this year's LSF/MM we discussed (and didn't outright deny) ZONE_CMA...
I'm not saying others will favour the new zone approach though, it's just my opinion that it might be a better option than a new migratetype.

If we are going to have lots of zones ... then perhaps we will need a fast way to look at a "struct page" and decide which zone it belongs to. Complicated math on the address deosn't sound ideal. If the complex zone model is just for 64-bit, are there enough bits available in page->flags (3 bits for 8 options ... which we are close to filling now ... 4 bits for future breathing room).

Quoted 4 lines
Quoted 1 line

and is it appropriate to add a new mirror zone with a volatile physical address?

By "volatile" you mean what, that the example above would change dynamically? That would be rather challenging...

Quoted 7 lines

If we hot-add another cpu together with on die memory controllers connected to more memory ... then some of the new memory might be mirrored. Current h/w doesn't allow mirrored areas to grow/shrink (though if there are a lot of errors we may break a mirror so a whole range could lose the mirror attribute).

-Tony

Hi Tony,

What's your suggestions? a new zone or a new migratetype? Maybe add a new zone will change more mm code.

Thanks,
Xishi Qiu

Quoted 2 lines

.

#61 lore raw
Quoted 2 lines

What's your suggestions? a new zone or a new migratetype? Maybe add a new zone will change more mm code.

I don't understand this code well enough (yet) to make a recommendation. I think our primary concern may not be "how much code we change", but more "how can we minimize the run-time impact on systems that don't have any mirrored memory.

Just putting all the heavy work behind a CONFIG option isn't sufficient ... we want enterprise distributions to ship with the option turned on ... even though most machines won't be using this feature.

-Tony

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>