LKML Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory
@ 2019-11-07  3:56 Dan Williams
  2019-11-07  3:56 ` [PATCH 01/16] libnvdimm: Move attribute groups to device type Dan Williams
                   ` (16 more replies)
  0 siblings, 17 replies; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:56 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, David Hildenbrand, Peter Zijlstra, Borislav Petkov,
	Michael Ellerman, Vishal Verma, H. Peter Anvin, x86,
	Thomas Gleixner, Dave Hansen, Andrew Morton, Ingo Molnar,
	Michal Hocko, Aneesh Kumar K.V, Rafael J. Wysocki,
	Andy Lutomirski, Oliver O'Halloran, linux-kernel, linux-mm

Yes, this patch series looks like a pile of boring libnvdimm cleanups,
but buried at the end are some small gems that testing with libnvdimm
uncovered. These gems will prove more valuable over time for Memory
Hierarchy management as more platforms, via the ACPI HMAT and EFI
Specific Purpose Memory, publish reserved or "soft-reserved" ranges to
Linux. Linux system administrators will expect to be able to interact
with those ranges with a unique numa node number when/if that memory is
onlined via the dax_kmem driver [1].

One configuration that currently fails to properly convey the target
node for the resulting memory hotplug operation is persistent memory
defined by the memmap=nn!ss parameter. For example, today if node1 is a
memory only node, and all the memory from node1 is specified to
memmap=nn!ss and subsequently onlined, it will end up being onlined as
node0 memory. As it stands, memory_add_physaddr_to_nid() can only
identify online nodes and since node1 in this example has no online cpus
/ memory the target node is initialized node0.

The fix is to preserve rather than discard the numa_meminfo entries that
are relevant for reserved memory ranges, and to uplevel the node
distance helper for determining the "local" (closest) node relative to
an initiator node.

The first 12 patches are cleanups to make sure that all nvdimm devices
and their children properly export a numa_node attribute. The switch to
a device-type is less code and less error prone as a result.

Patch 13 and 14 are the core changes (gems) to allow numa node
information for offline memory to be tracked.

Patches 15 and 16 use this new capability to fix the conveyance of numa
node information for memmap=nn!ss assignments. See patch 16 for more
details.

[1]: https://pmem.io/ndctl/daxctl-reconfigure-device.html

---

Dan Williams (16):
      libnvdimm: Move attribute groups to device type
      libnvdimm: Move region attribute group definition
      libnvdimm: Move nd_device_attribute_group to device_type
      libnvdimm: Move nd_numa_attribute_group to device_type
      libnvdimm: Move nd_region_attribute_group to device_type
      libnvdimm: Move nd_mapping_attribute_group to device_type
      libnvdimm: Move nvdimm_attribute_group to device_type
      libnvdimm: Move nvdimm_bus_attribute_group to device_type
      dax: Create a dax device_type
      dax: Simplify root read-only definition for the 'resource' attribute
      libnvdimm: Simplify root read-only definition for the 'resource' attribute
      dax: Add numa_node to the default device-dax attributes
      acpi/mm: Up-level "map to online node" functionality
      x86/numa: Provide a range-to-target_node lookup facility
      libnvdimm/e820: Drop the wrapper around memory_add_physaddr_to_nid
      libnvdimm/e820: Retrieve and populate correct 'target_node' info


 arch/powerpc/platforms/pseries/papr_scm.c |   25 ---
 arch/x86/mm/numa.c                        |   72 ++++++++-
 drivers/acpi/nfit/core.c                  |    7 -
 drivers/acpi/numa.c                       |   41 -----
 drivers/dax/bus.c                         |   22 ++-
 drivers/nvdimm/btt_devs.c                 |   24 +--
 drivers/nvdimm/bus.c                      |   15 +-
 drivers/nvdimm/core.c                     |    8 +
 drivers/nvdimm/dax_devs.c                 |   27 +--
 drivers/nvdimm/dimm_devs.c                |   30 ++--
 drivers/nvdimm/e820.c                     |   30 ----
 drivers/nvdimm/namespace_devs.c           |   77 +++++-----
 drivers/nvdimm/nd.h                       |    5 -
 drivers/nvdimm/of_pmem.c                  |   13 --
 drivers/nvdimm/pfn_devs.c                 |   38 ++---
 drivers/nvdimm/region_devs.c              |  235 +++++++++++++++--------------
 include/linux/acpi.h                      |   23 +++
 include/linux/libnvdimm.h                 |    7 -
 include/linux/memory_hotplug.h            |    6 +
 include/linux/numa.h                      |    2 
 mm/mempolicy.c                            |   30 ++++
 21 files changed, 382 insertions(+), 355 deletions(-)

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

* [PATCH 01/16] libnvdimm: Move attribute groups to device type
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
@ 2019-11-07  3:56 ` Dan Williams
  2019-11-12 11:28   ` Aneesh Kumar K.V
  2019-11-07  3:56 ` [PATCH 02/16] libnvdimm: Move region attribute group definition Dan Williams
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:56 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, Vishal Verma, peterz, dave.hansen, linux-kernel, linux-mm

Statically initialize the attribute groups for each libnvdimm
device_type. This is a preparation step for removing unnecessary exports
of attributes that can be included in the device_type by default.

Also take the opportunity to mark 'struct device_type' instances const.

Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/nvdimm/btt_devs.c       |   24 +++++++-------
 drivers/nvdimm/dax_devs.c       |   27 ++++++---------
 drivers/nvdimm/namespace_devs.c |   68 +++++++++++++++++++++------------------
 drivers/nvdimm/nd.h             |    2 +
 drivers/nvdimm/pfn_devs.c       |   28 ++++++++--------
 5 files changed, 73 insertions(+), 76 deletions(-)

diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c
index 3508a79110c7..05feb97e11ce 100644
--- a/drivers/nvdimm/btt_devs.c
+++ b/drivers/nvdimm/btt_devs.c
@@ -25,17 +25,6 @@ static void nd_btt_release(struct device *dev)
 	kfree(nd_btt);
 }
 
-static struct device_type nd_btt_device_type = {
-	.name = "nd_btt",
-	.release = nd_btt_release,
-};
-
-bool is_nd_btt(struct device *dev)
-{
-	return dev->type == &nd_btt_device_type;
-}
-EXPORT_SYMBOL(is_nd_btt);
-
 struct nd_btt *to_nd_btt(struct device *dev)
 {
 	struct nd_btt *nd_btt = container_of(dev, struct nd_btt, dev);
@@ -178,6 +167,18 @@ static const struct attribute_group *nd_btt_attribute_groups[] = {
 	NULL,
 };
 
+static const struct device_type nd_btt_device_type = {
+	.name = "nd_btt",
+	.release = nd_btt_release,
+	.groups = nd_btt_attribute_groups,
+};
+
+bool is_nd_btt(struct device *dev)
+{
+	return dev->type == &nd_btt_device_type;
+}
+EXPORT_SYMBOL(is_nd_btt);
+
 static struct device *__nd_btt_create(struct nd_region *nd_region,
 		unsigned long lbasize, u8 *uuid,
 		struct nd_namespace_common *ndns)
@@ -204,7 +205,6 @@ static struct device *__nd_btt_create(struct nd_region *nd_region,
 	dev_set_name(dev, "btt%d.%d", nd_region->id, nd_btt->id);
 	dev->parent = &nd_region->dev;
 	dev->type = &nd_btt_device_type;
-	dev->groups = nd_btt_attribute_groups;
 	device_initialize(&nd_btt->dev);
 	if (ndns && !__nd_attach_ndns(&nd_btt->dev, ndns, &nd_btt->ndns)) {
 		dev_dbg(&ndns->dev, "failed, already claimed by %s\n",
diff --git a/drivers/nvdimm/dax_devs.c b/drivers/nvdimm/dax_devs.c
index 6d22b0f83b3b..99965077bac4 100644
--- a/drivers/nvdimm/dax_devs.c
+++ b/drivers/nvdimm/dax_devs.c
@@ -23,17 +23,6 @@ static void nd_dax_release(struct device *dev)
 	kfree(nd_dax);
 }
 
-static struct device_type nd_dax_device_type = {
-	.name = "nd_dax",
-	.release = nd_dax_release,
-};
-
-bool is_nd_dax(struct device *dev)
-{
-	return dev ? dev->type == &nd_dax_device_type : false;
-}
-EXPORT_SYMBOL(is_nd_dax);
-
 struct nd_dax *to_nd_dax(struct device *dev)
 {
 	struct nd_dax *nd_dax = container_of(dev, struct nd_dax, nd_pfn.dev);
@@ -43,13 +32,18 @@ struct nd_dax *to_nd_dax(struct device *dev)
 }
 EXPORT_SYMBOL(to_nd_dax);
 
-static const struct attribute_group *nd_dax_attribute_groups[] = {
-	&nd_pfn_attribute_group,
-	&nd_device_attribute_group,
-	&nd_numa_attribute_group,
-	NULL,
+static const struct device_type nd_dax_device_type = {
+	.name = "nd_dax",
+	.release = nd_dax_release,
+	.groups = nd_pfn_attribute_groups,
 };
 
+bool is_nd_dax(struct device *dev)
+{
+	return dev ? dev->type == &nd_dax_device_type : false;
+}
+EXPORT_SYMBOL(is_nd_dax);
+
 static struct nd_dax *nd_dax_alloc(struct nd_region *nd_region)
 {
 	struct nd_pfn *nd_pfn;
@@ -69,7 +63,6 @@ static struct nd_dax *nd_dax_alloc(struct nd_region *nd_region)
 
 	dev = &nd_pfn->dev;
 	dev_set_name(dev, "dax%d.%d", nd_region->id, nd_pfn->id);
-	dev->groups = nd_dax_attribute_groups;
 	dev->type = &nd_dax_device_type;
 	dev->parent = &nd_region->dev;
 
diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index cca0a3ba1d2c..37471a272c1a 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -44,35 +44,9 @@ static void namespace_blk_release(struct device *dev)
 	kfree(nsblk);
 }
 
-static const struct device_type namespace_io_device_type = {
-	.name = "nd_namespace_io",
-	.release = namespace_io_release,
-};
-
-static const struct device_type namespace_pmem_device_type = {
-	.name = "nd_namespace_pmem",
-	.release = namespace_pmem_release,
-};
-
-static const struct device_type namespace_blk_device_type = {
-	.name = "nd_namespace_blk",
-	.release = namespace_blk_release,
-};
-
-static bool is_namespace_pmem(const struct device *dev)
-{
-	return dev ? dev->type == &namespace_pmem_device_type : false;
-}
-
-static bool is_namespace_blk(const struct device *dev)
-{
-	return dev ? dev->type == &namespace_blk_device_type : false;
-}
-
-static bool is_namespace_io(const struct device *dev)
-{
-	return dev ? dev->type == &namespace_io_device_type : false;
-}
+static bool is_namespace_pmem(const struct device *dev);
+static bool is_namespace_blk(const struct device *dev);
+static bool is_namespace_io(const struct device *dev);
 
 static int is_uuid_busy(struct device *dev, void *data)
 {
@@ -1680,6 +1654,39 @@ static const struct attribute_group *nd_namespace_attribute_groups[] = {
 	NULL,
 };
 
+static const struct device_type namespace_io_device_type = {
+	.name = "nd_namespace_io",
+	.release = namespace_io_release,
+	.groups = nd_namespace_attribute_groups,
+};
+
+static const struct device_type namespace_pmem_device_type = {
+	.name = "nd_namespace_pmem",
+	.release = namespace_pmem_release,
+	.groups = nd_namespace_attribute_groups,
+};
+
+static const struct device_type namespace_blk_device_type = {
+	.name = "nd_namespace_blk",
+	.release = namespace_blk_release,
+	.groups = nd_namespace_attribute_groups,
+};
+
+static bool is_namespace_pmem(const struct device *dev)
+{
+	return dev ? dev->type == &namespace_pmem_device_type : false;
+}
+
+static bool is_namespace_blk(const struct device *dev)
+{
+	return dev ? dev->type == &namespace_blk_device_type : false;
+}
+
+static bool is_namespace_io(const struct device *dev)
+{
+	return dev ? dev->type == &namespace_io_device_type : false;
+}
+
 struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev)
 {
 	struct nd_btt *nd_btt = is_nd_btt(dev) ? to_nd_btt(dev) : NULL;
@@ -2078,7 +2085,6 @@ static struct device *nd_namespace_blk_create(struct nd_region *nd_region)
 	}
 	dev_set_name(dev, "namespace%d.%d", nd_region->id, nsblk->id);
 	dev->parent = &nd_region->dev;
-	dev->groups = nd_namespace_attribute_groups;
 
 	return &nsblk->common.dev;
 }
@@ -2109,7 +2115,6 @@ static struct device *nd_namespace_pmem_create(struct nd_region *nd_region)
 		return NULL;
 	}
 	dev_set_name(dev, "namespace%d.%d", nd_region->id, nspm->id);
-	dev->groups = nd_namespace_attribute_groups;
 	nd_namespace_pmem_set_resource(nd_region, nspm, 0);
 
 	return dev;
@@ -2608,7 +2613,6 @@ int nd_region_register_namespaces(struct nd_region *nd_region, int *err)
 		if (id < 0)
 			break;
 		dev_set_name(dev, "namespace%d.%d", nd_region->id, id);
-		dev->groups = nd_namespace_attribute_groups;
 		nd_device_register(dev);
 	}
 	if (i)
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index ee5c04070ef9..5c8b077b3237 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -297,7 +297,7 @@ struct device *nd_pfn_create(struct nd_region *nd_region);
 struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn,
 		struct nd_namespace_common *ndns);
 int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig);
-extern struct attribute_group nd_pfn_attribute_group;
+extern const struct attribute_group *nd_pfn_attribute_groups[];
 #else
 static inline int nd_pfn_probe(struct device *dev,
 		struct nd_namespace_common *ndns)
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index 60d81fae06ee..e809961e2b6f 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -26,17 +26,6 @@ static void nd_pfn_release(struct device *dev)
 	kfree(nd_pfn);
 }
 
-static struct device_type nd_pfn_device_type = {
-	.name = "nd_pfn",
-	.release = nd_pfn_release,
-};
-
-bool is_nd_pfn(struct device *dev)
-{
-	return dev ? dev->type == &nd_pfn_device_type : false;
-}
-EXPORT_SYMBOL(is_nd_pfn);
-
 struct nd_pfn *to_nd_pfn(struct device *dev)
 {
 	struct nd_pfn *nd_pfn = container_of(dev, struct nd_pfn, dev);
@@ -287,18 +276,30 @@ static umode_t pfn_visible(struct kobject *kobj, struct attribute *a, int n)
 	return a->mode;
 }
 
-struct attribute_group nd_pfn_attribute_group = {
+static struct attribute_group nd_pfn_attribute_group = {
 	.attrs = nd_pfn_attributes,
 	.is_visible = pfn_visible,
 };
 
-static const struct attribute_group *nd_pfn_attribute_groups[] = {
+const struct attribute_group *nd_pfn_attribute_groups[] = {
 	&nd_pfn_attribute_group,
 	&nd_device_attribute_group,
 	&nd_numa_attribute_group,
 	NULL,
 };
 
+static const struct device_type nd_pfn_device_type = {
+	.name = "nd_pfn",
+	.release = nd_pfn_release,
+	.groups = nd_pfn_attribute_groups,
+};
+
+bool is_nd_pfn(struct device *dev)
+{
+	return dev ? dev->type == &nd_pfn_device_type : false;
+}
+EXPORT_SYMBOL(is_nd_pfn);
+
 struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn,
 		struct nd_namespace_common *ndns)
 {
@@ -337,7 +338,6 @@ static struct nd_pfn *nd_pfn_alloc(struct nd_region *nd_region)
 
 	dev = &nd_pfn->dev;
 	dev_set_name(dev, "pfn%d.%d", nd_region->id, nd_pfn->id);
-	dev->groups = nd_pfn_attribute_groups;
 	dev->type = &nd_pfn_device_type;
 	dev->parent = &nd_region->dev;
 


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

* [PATCH 02/16] libnvdimm: Move region attribute group definition
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
  2019-11-07  3:56 ` [PATCH 01/16] libnvdimm: Move attribute groups to device type Dan Williams
@ 2019-11-07  3:56 ` Dan Williams
  2019-11-12 11:29   ` Aneesh Kumar K.V
  2019-11-07  3:56 ` [PATCH 03/16] libnvdimm: Move nd_device_attribute_group to device_type Dan Williams
                   ` (14 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:56 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, Vishal Verma, peterz, dave.hansen, linux-kernel, linux-mm

In preparation for moving region attributes from device attribute groups
to the region device-type, reorder the declaration so that it can be
referenced by the device-type definition without forward declarations.
No functional changes are intended to result from this change.

Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/nvdimm/region_devs.c |  208 +++++++++++++++++++++---------------------
 1 file changed, 104 insertions(+), 104 deletions(-)

diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index ef423ba1a711..e89f2eb3678c 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -140,36 +140,6 @@ static void nd_region_release(struct device *dev)
 		kfree(nd_region);
 }
 
-static struct device_type nd_blk_device_type = {
-	.name = "nd_blk",
-	.release = nd_region_release,
-};
-
-static struct device_type nd_pmem_device_type = {
-	.name = "nd_pmem",
-	.release = nd_region_release,
-};
-
-static struct device_type nd_volatile_device_type = {
-	.name = "nd_volatile",
-	.release = nd_region_release,
-};
-
-bool is_nd_pmem(struct device *dev)
-{
-	return dev ? dev->type == &nd_pmem_device_type : false;
-}
-
-bool is_nd_blk(struct device *dev)
-{
-	return dev ? dev->type == &nd_blk_device_type : false;
-}
-
-bool is_nd_volatile(struct device *dev)
-{
-	return dev ? dev->type == &nd_volatile_device_type : false;
-}
-
 struct nd_region *to_nd_region(struct device *dev)
 {
 	struct nd_region *nd_region = container_of(dev, struct nd_region, dev);
@@ -674,80 +644,6 @@ static umode_t region_visible(struct kobject *kobj, struct attribute *a, int n)
 	return 0;
 }
 
-struct attribute_group nd_region_attribute_group = {
-	.attrs = nd_region_attributes,
-	.is_visible = region_visible,
-};
-EXPORT_SYMBOL_GPL(nd_region_attribute_group);
-
-u64 nd_region_interleave_set_cookie(struct nd_region *nd_region,
-		struct nd_namespace_index *nsindex)
-{
-	struct nd_interleave_set *nd_set = nd_region->nd_set;
-
-	if (!nd_set)
-		return 0;
-
-	if (nsindex && __le16_to_cpu(nsindex->major) == 1
-			&& __le16_to_cpu(nsindex->minor) == 1)
-		return nd_set->cookie1;
-	return nd_set->cookie2;
-}
-
-u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region)
-{
-	struct nd_interleave_set *nd_set = nd_region->nd_set;
-
-	if (nd_set)
-		return nd_set->altcookie;
-	return 0;
-}
-
-void nd_mapping_free_labels(struct nd_mapping *nd_mapping)
-{
-	struct nd_label_ent *label_ent, *e;
-
-	lockdep_assert_held(&nd_mapping->lock);
-	list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) {
-		list_del(&label_ent->list);
-		kfree(label_ent);
-	}
-}
-
-/*
- * When a namespace is activated create new seeds for the next
- * namespace, or namespace-personality to be configured.
- */
-void nd_region_advance_seeds(struct nd_region *nd_region, struct device *dev)
-{
-	nvdimm_bus_lock(dev);
-	if (nd_region->ns_seed == dev) {
-		nd_region_create_ns_seed(nd_region);
-	} else if (is_nd_btt(dev)) {
-		struct nd_btt *nd_btt = to_nd_btt(dev);
-
-		if (nd_region->btt_seed == dev)
-			nd_region_create_btt_seed(nd_region);
-		if (nd_region->ns_seed == &nd_btt->ndns->dev)
-			nd_region_create_ns_seed(nd_region);
-	} else if (is_nd_pfn(dev)) {
-		struct nd_pfn *nd_pfn = to_nd_pfn(dev);
-
-		if (nd_region->pfn_seed == dev)
-			nd_region_create_pfn_seed(nd_region);
-		if (nd_region->ns_seed == &nd_pfn->ndns->dev)
-			nd_region_create_ns_seed(nd_region);
-	} else if (is_nd_dax(dev)) {
-		struct nd_dax *nd_dax = to_nd_dax(dev);
-
-		if (nd_region->dax_seed == dev)
-			nd_region_create_dax_seed(nd_region);
-		if (nd_region->ns_seed == &nd_dax->nd_pfn.ndns->dev)
-			nd_region_create_ns_seed(nd_region);
-	}
-	nvdimm_bus_unlock(dev);
-}
-
 static ssize_t mappingN(struct device *dev, char *buf, int n)
 {
 	struct nd_region *nd_region = to_nd_region(dev);
@@ -861,6 +757,110 @@ struct attribute_group nd_mapping_attribute_group = {
 };
 EXPORT_SYMBOL_GPL(nd_mapping_attribute_group);
 
+struct attribute_group nd_region_attribute_group = {
+	.attrs = nd_region_attributes,
+	.is_visible = region_visible,
+};
+EXPORT_SYMBOL_GPL(nd_region_attribute_group);
+
+static struct device_type nd_blk_device_type = {
+	.name = "nd_blk",
+	.release = nd_region_release,
+};
+
+static struct device_type nd_pmem_device_type = {
+	.name = "nd_pmem",
+	.release = nd_region_release,
+};
+
+static struct device_type nd_volatile_device_type = {
+	.name = "nd_volatile",
+	.release = nd_region_release,
+};
+
+bool is_nd_pmem(struct device *dev)
+{
+	return dev ? dev->type == &nd_pmem_device_type : false;
+}
+
+bool is_nd_blk(struct device *dev)
+{
+	return dev ? dev->type == &nd_blk_device_type : false;
+}
+
+bool is_nd_volatile(struct device *dev)
+{
+	return dev ? dev->type == &nd_volatile_device_type : false;
+}
+
+u64 nd_region_interleave_set_cookie(struct nd_region *nd_region,
+		struct nd_namespace_index *nsindex)
+{
+	struct nd_interleave_set *nd_set = nd_region->nd_set;
+
+	if (!nd_set)
+		return 0;
+
+	if (nsindex && __le16_to_cpu(nsindex->major) == 1
+			&& __le16_to_cpu(nsindex->minor) == 1)
+		return nd_set->cookie1;
+	return nd_set->cookie2;
+}
+
+u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region)
+{
+	struct nd_interleave_set *nd_set = nd_region->nd_set;
+
+	if (nd_set)
+		return nd_set->altcookie;
+	return 0;
+}
+
+void nd_mapping_free_labels(struct nd_mapping *nd_mapping)
+{
+	struct nd_label_ent *label_ent, *e;
+
+	lockdep_assert_held(&nd_mapping->lock);
+	list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) {
+		list_del(&label_ent->list);
+		kfree(label_ent);
+	}
+}
+
+/*
+ * When a namespace is activated create new seeds for the next
+ * namespace, or namespace-personality to be configured.
+ */
+void nd_region_advance_seeds(struct nd_region *nd_region, struct device *dev)
+{
+	nvdimm_bus_lock(dev);
+	if (nd_region->ns_seed == dev) {
+		nd_region_create_ns_seed(nd_region);
+	} else if (is_nd_btt(dev)) {
+		struct nd_btt *nd_btt = to_nd_btt(dev);
+
+		if (nd_region->btt_seed == dev)
+			nd_region_create_btt_seed(nd_region);
+		if (nd_region->ns_seed == &nd_btt->ndns->dev)
+			nd_region_create_ns_seed(nd_region);
+	} else if (is_nd_pfn(dev)) {
+		struct nd_pfn *nd_pfn = to_nd_pfn(dev);
+
+		if (nd_region->pfn_seed == dev)
+			nd_region_create_pfn_seed(nd_region);
+		if (nd_region->ns_seed == &nd_pfn->ndns->dev)
+			nd_region_create_ns_seed(nd_region);
+	} else if (is_nd_dax(dev)) {
+		struct nd_dax *nd_dax = to_nd_dax(dev);
+
+		if (nd_region->dax_seed == dev)
+			nd_region_create_dax_seed(nd_region);
+		if (nd_region->ns_seed == &nd_dax->nd_pfn.ndns->dev)
+			nd_region_create_ns_seed(nd_region);
+	}
+	nvdimm_bus_unlock(dev);
+}
+
 int nd_blk_region_init(struct nd_region *nd_region)
 {
 	struct device *dev = &nd_region->dev;


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

* [PATCH 03/16] libnvdimm: Move nd_device_attribute_group to device_type
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
  2019-11-07  3:56 ` [PATCH 01/16] libnvdimm: Move attribute groups to device type Dan Williams
  2019-11-07  3:56 ` [PATCH 02/16] libnvdimm: Move region attribute group definition Dan Williams
@ 2019-11-07  3:56 ` Dan Williams
  2019-11-12 11:30   ` Aneesh Kumar K.V
  2019-11-07  3:56 ` [PATCH 04/16] libnvdimm: Move nd_numa_attribute_group " Dan Williams
                   ` (13 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:56 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, Michael Ellerman, Oliver O'Halloran, Vishal Verma,
	Aneesh Kumar K.V, peterz, dave.hansen, linux-kernel, linux-mm

A 'struct device_type' instance can carry default attributes for the
device. Use this facility to remove the export of
nd_device_attribute_group and put the responsibility on the core rather
than leaf implementations to define this attribute.

For regions this creates a new nd_region_attribute_groups[] added to the
per-region device-type instances.

Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: "Oliver O'Halloran" <oohall@gmail.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/powerpc/platforms/pseries/papr_scm.c |    2 --
 drivers/acpi/nfit/core.c                  |    2 --
 drivers/nvdimm/bus.c                      |    3 +--
 drivers/nvdimm/dimm_devs.c                |    8 +++++++-
 drivers/nvdimm/e820.c                     |    1 -
 drivers/nvdimm/nd.h                       |    1 +
 drivers/nvdimm/of_pmem.c                  |    1 -
 drivers/nvdimm/region_devs.c              |   18 +++++++++++++-----
 include/linux/libnvdimm.h                 |    1 -
 9 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 61883291defc..04726f8fd189 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -286,7 +286,6 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 
 static const struct attribute_group *region_attr_groups[] = {
 	&nd_region_attribute_group,
-	&nd_device_attribute_group,
 	&nd_mapping_attribute_group,
 	&nd_numa_attribute_group,
 	NULL,
@@ -299,7 +298,6 @@ static const struct attribute_group *bus_attr_groups[] = {
 
 static const struct attribute_group *papr_scm_dimm_groups[] = {
 	&nvdimm_attribute_group,
-	&nd_device_attribute_group,
 	NULL,
 };
 
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 14e68f202f81..dec7c2b08672 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -1699,7 +1699,6 @@ static const struct attribute_group acpi_nfit_dimm_attribute_group = {
 
 static const struct attribute_group *acpi_nfit_dimm_attribute_groups[] = {
 	&nvdimm_attribute_group,
-	&nd_device_attribute_group,
 	&acpi_nfit_dimm_attribute_group,
 	NULL,
 };
@@ -2199,7 +2198,6 @@ static const struct attribute_group acpi_nfit_region_attribute_group = {
 static const struct attribute_group *acpi_nfit_region_attribute_groups[] = {
 	&nd_region_attribute_group,
 	&nd_mapping_attribute_group,
-	&nd_device_attribute_group,
 	&nd_numa_attribute_group,
 	&acpi_nfit_region_attribute_group,
 	NULL,
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index d47412dcdf38..eb422527dd57 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -669,10 +669,9 @@ static struct attribute *nd_device_attributes[] = {
 /*
  * nd_device_attribute_group - generic attributes for all devices on an nd bus
  */
-struct attribute_group nd_device_attribute_group = {
+const struct attribute_group nd_device_attribute_group = {
 	.attrs = nd_device_attributes,
 };
-EXPORT_SYMBOL_GPL(nd_device_attribute_group);
 
 static ssize_t numa_node_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 196aa44c4936..278867c68682 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -202,9 +202,15 @@ static void nvdimm_release(struct device *dev)
 	kfree(nvdimm);
 }
 
-static struct device_type nvdimm_device_type = {
+static const struct attribute_group *nvdimm_attribute_groups[] = {
+	&nd_device_attribute_group,
+	NULL,
+};
+
+static const struct device_type nvdimm_device_type = {
 	.name = "nvdimm",
 	.release = nvdimm_release,
+	.groups = nvdimm_attribute_groups,
 };
 
 bool is_nvdimm(struct device *dev)
diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c
index 87f72f725e4f..adde2864c6a4 100644
--- a/drivers/nvdimm/e820.c
+++ b/drivers/nvdimm/e820.c
@@ -15,7 +15,6 @@ static const struct attribute_group *e820_pmem_attribute_groups[] = {
 
 static const struct attribute_group *e820_pmem_region_attribute_groups[] = {
 	&nd_region_attribute_group,
-	&nd_device_attribute_group,
 	NULL,
 };
 
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 5c8b077b3237..3f509bb6b5c0 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -298,6 +298,7 @@ struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn,
 		struct nd_namespace_common *ndns);
 int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig);
 extern const struct attribute_group *nd_pfn_attribute_groups[];
+extern const struct attribute_group nd_device_attribute_group;
 #else
 static inline int nd_pfn_probe(struct device *dev,
 		struct nd_namespace_common *ndns)
diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
index 97187d6c0bdb..41348fa6b74c 100644
--- a/drivers/nvdimm/of_pmem.c
+++ b/drivers/nvdimm/of_pmem.c
@@ -11,7 +11,6 @@
 
 static const struct attribute_group *region_attr_groups[] = {
 	&nd_region_attribute_group,
-	&nd_device_attribute_group,
 	NULL,
 };
 
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index e89f2eb3678c..710b5111eaa8 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -763,19 +763,27 @@ struct attribute_group nd_region_attribute_group = {
 };
 EXPORT_SYMBOL_GPL(nd_region_attribute_group);
 
-static struct device_type nd_blk_device_type = {
+static const struct attribute_group *nd_region_attribute_groups[] = {
+	&nd_device_attribute_group,
+	NULL,
+};
+
+static const struct device_type nd_blk_device_type = {
 	.name = "nd_blk",
 	.release = nd_region_release,
+	.groups = nd_region_attribute_groups,
 };
 
-static struct device_type nd_pmem_device_type = {
+static const struct device_type nd_pmem_device_type = {
 	.name = "nd_pmem",
 	.release = nd_region_release,
+	.groups = nd_region_attribute_groups,
 };
 
-static struct device_type nd_volatile_device_type = {
+static const struct device_type nd_volatile_device_type = {
 	.name = "nd_volatile",
 	.release = nd_region_release,
+	.groups = nd_region_attribute_groups,
 };
 
 bool is_nd_pmem(struct device *dev)
@@ -931,8 +939,8 @@ void nd_region_release_lane(struct nd_region *nd_region, unsigned int lane)
 EXPORT_SYMBOL(nd_region_release_lane);
 
 static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
-		struct nd_region_desc *ndr_desc, struct device_type *dev_type,
-		const char *caller)
+		struct nd_region_desc *ndr_desc,
+		const struct device_type *dev_type, const char *caller)
 {
 	struct nd_region *nd_region;
 	struct device *dev;
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index b6eddf912568..d7dbf42498af 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -67,7 +67,6 @@ enum {
 
 extern struct attribute_group nvdimm_bus_attribute_group;
 extern struct attribute_group nvdimm_attribute_group;
-extern struct attribute_group nd_device_attribute_group;
 extern struct attribute_group nd_numa_attribute_group;
 extern struct attribute_group nd_region_attribute_group;
 extern struct attribute_group nd_mapping_attribute_group;


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

* [PATCH 04/16] libnvdimm: Move nd_numa_attribute_group to device_type
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (2 preceding siblings ...)
  2019-11-07  3:56 ` [PATCH 03/16] libnvdimm: Move nd_device_attribute_group to device_type Dan Williams
@ 2019-11-07  3:56 ` " Dan Williams
  2019-11-12  9:22   ` Aneesh Kumar K.V
  2019-11-07  3:57 ` [PATCH 05/16] libnvdimm: Move nd_region_attribute_group " Dan Williams
                   ` (12 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:56 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, Michael Ellerman, Oliver O'Halloran, Vishal Verma,
	Aneesh Kumar K.V, peterz, dave.hansen, linux-kernel, linux-mm

A 'struct device_type' instance can carry default attributes for the
device. Use this facility to remove the export of
nd_numa_attribute_group and put the responsibility on the core rather
than leaf implementations to define this attribute.

Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: "Oliver O'Halloran" <oohall@gmail.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/powerpc/platforms/pseries/papr_scm.c |    1 -
 drivers/acpi/nfit/core.c                  |    1 -
 drivers/nvdimm/bus.c                      |    3 +--
 drivers/nvdimm/nd.h                       |    1 +
 drivers/nvdimm/region_devs.c              |    1 +
 include/linux/libnvdimm.h                 |    1 -
 6 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 04726f8fd189..6ffda03a6349 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -287,7 +287,6 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 static const struct attribute_group *region_attr_groups[] = {
 	&nd_region_attribute_group,
 	&nd_mapping_attribute_group,
-	&nd_numa_attribute_group,
 	NULL,
 };
 
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index dec7c2b08672..b3213faf37b5 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -2198,7 +2198,6 @@ static const struct attribute_group acpi_nfit_region_attribute_group = {
 static const struct attribute_group *acpi_nfit_region_attribute_groups[] = {
 	&nd_region_attribute_group,
 	&nd_mapping_attribute_group,
-	&nd_numa_attribute_group,
 	&acpi_nfit_region_attribute_group,
 	NULL,
 };
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index eb422527dd57..28e1b265aa63 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -697,11 +697,10 @@ static umode_t nd_numa_attr_visible(struct kobject *kobj, struct attribute *a,
 /*
  * nd_numa_attribute_group - NUMA attributes for all devices on an nd bus
  */
-struct attribute_group nd_numa_attribute_group = {
+const struct attribute_group nd_numa_attribute_group = {
 	.attrs = nd_numa_attributes,
 	.is_visible = nd_numa_attr_visible,
 };
-EXPORT_SYMBOL_GPL(nd_numa_attribute_group);
 
 int nvdimm_bus_create_ndctl(struct nvdimm_bus *nvdimm_bus)
 {
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index 3f509bb6b5c0..e7f3a2fee2ab 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -299,6 +299,7 @@ struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn,
 int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig);
 extern const struct attribute_group *nd_pfn_attribute_groups[];
 extern const struct attribute_group nd_device_attribute_group;
+extern const struct attribute_group nd_numa_attribute_group;
 #else
 static inline int nd_pfn_probe(struct device *dev,
 		struct nd_namespace_common *ndns)
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 710b5111eaa8..e4281f806adc 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -765,6 +765,7 @@ EXPORT_SYMBOL_GPL(nd_region_attribute_group);
 
 static const struct attribute_group *nd_region_attribute_groups[] = {
 	&nd_device_attribute_group,
+	&nd_numa_attribute_group,
 	NULL,
 };
 
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index d7dbf42498af..e9a4e25fc708 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -67,7 +67,6 @@ enum {
 
 extern struct attribute_group nvdimm_bus_attribute_group;
 extern struct attribute_group nvdimm_attribute_group;
-extern struct attribute_group nd_numa_attribute_group;
 extern struct attribute_group nd_region_attribute_group;
 extern struct attribute_group nd_mapping_attribute_group;
 


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

* [PATCH 05/16] libnvdimm: Move nd_region_attribute_group to device_type
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (3 preceding siblings ...)
  2019-11-07  3:56 ` [PATCH 04/16] libnvdimm: Move nd_numa_attribute_group " Dan Williams
@ 2019-11-07  3:57 ` " Dan Williams
  2019-11-12 11:45   ` Aneesh Kumar K.V
  2019-11-07  3:57 ` [PATCH 06/16] libnvdimm: Move nd_mapping_attribute_group " Dan Williams
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:57 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, Michael Ellerman, Oliver O'Halloran, Vishal Verma,
	Aneesh Kumar K.V, peterz, dave.hansen, linux-kernel, linux-mm

A 'struct device_type' instance can carry default attributes for the
device. Use this facility to remove the export of
nd_region_attribute_group and put the responsibility on the core rather
than leaf implementations to define this attribute.

Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: "Oliver O'Halloran" <oohall@gmail.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/powerpc/platforms/pseries/papr_scm.c |    1 -
 drivers/acpi/nfit/core.c                  |    1 -
 drivers/nvdimm/e820.c                     |    6 ------
 drivers/nvdimm/of_pmem.c                  |    6 ------
 drivers/nvdimm/region_devs.c              |    4 ++--
 include/linux/libnvdimm.h                 |    1 -
 6 files changed, 2 insertions(+), 17 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 6ffda03a6349..6428834d7cd5 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -285,7 +285,6 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 }
 
 static const struct attribute_group *region_attr_groups[] = {
-	&nd_region_attribute_group,
 	&nd_mapping_attribute_group,
 	NULL,
 };
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index b3213faf37b5..99e20b8b6ea0 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -2196,7 +2196,6 @@ static const struct attribute_group acpi_nfit_region_attribute_group = {
 };
 
 static const struct attribute_group *acpi_nfit_region_attribute_groups[] = {
-	&nd_region_attribute_group,
 	&nd_mapping_attribute_group,
 	&acpi_nfit_region_attribute_group,
 	NULL,
diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c
index adde2864c6a4..9a971a59dec7 100644
--- a/drivers/nvdimm/e820.c
+++ b/drivers/nvdimm/e820.c
@@ -13,11 +13,6 @@ static const struct attribute_group *e820_pmem_attribute_groups[] = {
 	NULL,
 };
 
-static const struct attribute_group *e820_pmem_region_attribute_groups[] = {
-	&nd_region_attribute_group,
-	NULL,
-};
-
 static int e820_pmem_remove(struct platform_device *pdev)
 {
 	struct nvdimm_bus *nvdimm_bus = platform_get_drvdata(pdev);
@@ -45,7 +40,6 @@ static int e820_register_one(struct resource *res, void *data)
 
 	memset(&ndr_desc, 0, sizeof(ndr_desc));
 	ndr_desc.res = res;
-	ndr_desc.attr_groups = e820_pmem_region_attribute_groups;
 	ndr_desc.numa_node = e820_range_to_nid(res->start);
 	ndr_desc.target_node = ndr_desc.numa_node;
 	set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
index 41348fa6b74c..c0b5ac36df9d 100644
--- a/drivers/nvdimm/of_pmem.c
+++ b/drivers/nvdimm/of_pmem.c
@@ -9,11 +9,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 
-static const struct attribute_group *region_attr_groups[] = {
-	&nd_region_attribute_group,
-	NULL,
-};
-
 static const struct attribute_group *bus_attr_groups[] = {
 	&nvdimm_bus_attribute_group,
 	NULL,
@@ -65,7 +60,6 @@ static int of_pmem_region_probe(struct platform_device *pdev)
 		 * structures so passing a stack pointer is fine.
 		 */
 		memset(&ndr_desc, 0, sizeof(ndr_desc));
-		ndr_desc.attr_groups = region_attr_groups;
 		ndr_desc.numa_node = dev_to_node(&pdev->dev);
 		ndr_desc.target_node = ndr_desc.numa_node;
 		ndr_desc.res = &pdev->resource[i];
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index e4281f806adc..f97166583294 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -757,14 +757,14 @@ struct attribute_group nd_mapping_attribute_group = {
 };
 EXPORT_SYMBOL_GPL(nd_mapping_attribute_group);
 
-struct attribute_group nd_region_attribute_group = {
+static const struct attribute_group nd_region_attribute_group = {
 	.attrs = nd_region_attributes,
 	.is_visible = region_visible,
 };
-EXPORT_SYMBOL_GPL(nd_region_attribute_group);
 
 static const struct attribute_group *nd_region_attribute_groups[] = {
 	&nd_device_attribute_group,
+	&nd_region_attribute_group,
 	&nd_numa_attribute_group,
 	NULL,
 };
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index e9a4e25fc708..312248d334c7 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -67,7 +67,6 @@ enum {
 
 extern struct attribute_group nvdimm_bus_attribute_group;
 extern struct attribute_group nvdimm_attribute_group;
-extern struct attribute_group nd_region_attribute_group;
 extern struct attribute_group nd_mapping_attribute_group;
 
 struct nvdimm;


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

* [PATCH 06/16] libnvdimm: Move nd_mapping_attribute_group to device_type
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (4 preceding siblings ...)
  2019-11-07  3:57 ` [PATCH 05/16] libnvdimm: Move nd_region_attribute_group " Dan Williams
@ 2019-11-07  3:57 ` " Dan Williams
  2019-11-12 11:45   ` Aneesh Kumar K.V
  2019-11-07  3:57 ` [PATCH 07/16] libnvdimm: Move nvdimm_attribute_group " Dan Williams
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:57 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, Michael Ellerman, Oliver O'Halloran, Vishal Verma,
	Aneesh Kumar K.V, peterz, dave.hansen, linux-kernel, linux-mm

A 'struct device_type' instance can carry default attributes for the
device. Use this facility to remove the export of
nd_mapping_attribute_group and put the responsibility on the core rather
than leaf implementations to define this attribute.

Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: "Oliver O'Halloran" <oohall@gmail.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/powerpc/platforms/pseries/papr_scm.c |    6 ------
 drivers/acpi/nfit/core.c                  |    1 -
 drivers/nvdimm/region_devs.c              |    4 ++--
 include/linux/libnvdimm.h                 |    1 -
 4 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 6428834d7cd5..0405fb769336 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -284,11 +284,6 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 	return 0;
 }
 
-static const struct attribute_group *region_attr_groups[] = {
-	&nd_mapping_attribute_group,
-	NULL,
-};
-
 static const struct attribute_group *bus_attr_groups[] = {
 	&nvdimm_bus_attribute_group,
 	NULL,
@@ -362,7 +357,6 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
 	mapping.size = p->blocks * p->block_size; // XXX: potential overflow?
 
 	memset(&ndr_desc, 0, sizeof(ndr_desc));
-	ndr_desc.attr_groups = region_attr_groups;
 	target_nid = dev_to_node(&p->pdev->dev);
 	online_nid = papr_scm_node(target_nid);
 	ndr_desc.numa_node = online_nid;
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 99e20b8b6ea0..69c406ecc3a6 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -2196,7 +2196,6 @@ static const struct attribute_group acpi_nfit_region_attribute_group = {
 };
 
 static const struct attribute_group *acpi_nfit_region_attribute_groups[] = {
-	&nd_mapping_attribute_group,
 	&acpi_nfit_region_attribute_group,
 	NULL,
 };
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index f97166583294..0afc1973e938 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -751,11 +751,10 @@ static struct attribute *mapping_attributes[] = {
 	NULL,
 };
 
-struct attribute_group nd_mapping_attribute_group = {
+static const struct attribute_group nd_mapping_attribute_group = {
 	.is_visible = mapping_visible,
 	.attrs = mapping_attributes,
 };
-EXPORT_SYMBOL_GPL(nd_mapping_attribute_group);
 
 static const struct attribute_group nd_region_attribute_group = {
 	.attrs = nd_region_attributes,
@@ -766,6 +765,7 @@ static const struct attribute_group *nd_region_attribute_groups[] = {
 	&nd_device_attribute_group,
 	&nd_region_attribute_group,
 	&nd_numa_attribute_group,
+	&nd_mapping_attribute_group,
 	NULL,
 };
 
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index 312248d334c7..eb597d1cb891 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -67,7 +67,6 @@ enum {
 
 extern struct attribute_group nvdimm_bus_attribute_group;
 extern struct attribute_group nvdimm_attribute_group;
-extern struct attribute_group nd_mapping_attribute_group;
 
 struct nvdimm;
 struct nvdimm_bus_descriptor;


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

* [PATCH 07/16] libnvdimm: Move nvdimm_attribute_group to device_type
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (5 preceding siblings ...)
  2019-11-07  3:57 ` [PATCH 06/16] libnvdimm: Move nd_mapping_attribute_group " Dan Williams
@ 2019-11-07  3:57 ` " Dan Williams
  2019-11-12 11:48   ` Aneesh Kumar K.V
  2019-11-07  3:57 ` [PATCH 08/16] libnvdimm: Move nvdimm_bus_attribute_group " Dan Williams
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:57 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, Michael Ellerman, Oliver O'Halloran, Vishal Verma,
	Aneesh Kumar K.V, peterz, dave.hansen, linux-kernel, linux-mm

A 'struct device_type' instance can carry default attributes for the
device. Use this facility to remove the export of
nvdimm_attribute_group and put the responsibility on the core rather
than leaf implementations to define this attribute.

Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: "Oliver O'Halloran" <oohall@gmail.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/powerpc/platforms/pseries/papr_scm.c |    9 ++-----
 drivers/acpi/nfit/core.c                  |    1 -
 drivers/nvdimm/dimm_devs.c                |   36 +++++++++++++++--------------
 include/linux/libnvdimm.h                 |    1 -
 4 files changed, 20 insertions(+), 27 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 0405fb769336..8354737ac340 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -289,11 +289,6 @@ static const struct attribute_group *bus_attr_groups[] = {
 	NULL,
 };
 
-static const struct attribute_group *papr_scm_dimm_groups[] = {
-	&nvdimm_attribute_group,
-	NULL,
-};
-
 static inline int papr_scm_node(int node)
 {
 	int min_dist = INT_MAX, dist;
@@ -339,8 +334,8 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
 	dimm_flags = 0;
 	set_bit(NDD_ALIASING, &dimm_flags);
 
-	p->nvdimm = nvdimm_create(p->bus, p, papr_scm_dimm_groups,
-				dimm_flags, PAPR_SCM_DIMM_CMD_MASK, 0, NULL);
+	p->nvdimm = nvdimm_create(p->bus, p, NULL, dimm_flags,
+				  PAPR_SCM_DIMM_CMD_MASK, 0, NULL);
 	if (!p->nvdimm) {
 		dev_err(dev, "Error creating DIMM object for %pOF\n", p->dn);
 		goto err;
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 69c406ecc3a6..84fc1f865802 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -1698,7 +1698,6 @@ static const struct attribute_group acpi_nfit_dimm_attribute_group = {
 };
 
 static const struct attribute_group *acpi_nfit_dimm_attribute_groups[] = {
-	&nvdimm_attribute_group,
 	&acpi_nfit_dimm_attribute_group,
 	NULL,
 };
diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
index 278867c68682..94ea6dba6b4f 100644
--- a/drivers/nvdimm/dimm_devs.c
+++ b/drivers/nvdimm/dimm_devs.c
@@ -202,22 +202,6 @@ static void nvdimm_release(struct device *dev)
 	kfree(nvdimm);
 }
 
-static const struct attribute_group *nvdimm_attribute_groups[] = {
-	&nd_device_attribute_group,
-	NULL,
-};
-
-static const struct device_type nvdimm_device_type = {
-	.name = "nvdimm",
-	.release = nvdimm_release,
-	.groups = nvdimm_attribute_groups,
-};
-
-bool is_nvdimm(struct device *dev)
-{
-	return dev->type == &nvdimm_device_type;
-}
-
 struct nvdimm *to_nvdimm(struct device *dev)
 {
 	struct nvdimm *nvdimm = container_of(dev, struct nvdimm, dev);
@@ -456,11 +440,27 @@ static umode_t nvdimm_visible(struct kobject *kobj, struct attribute *a, int n)
 	return 0;
 }
 
-struct attribute_group nvdimm_attribute_group = {
+static const struct attribute_group nvdimm_attribute_group = {
 	.attrs = nvdimm_attributes,
 	.is_visible = nvdimm_visible,
 };
-EXPORT_SYMBOL_GPL(nvdimm_attribute_group);
+
+static const struct attribute_group *nvdimm_attribute_groups[] = {
+	&nd_device_attribute_group,
+	&nvdimm_attribute_group,
+	NULL,
+};
+
+static const struct device_type nvdimm_device_type = {
+	.name = "nvdimm",
+	.release = nvdimm_release,
+	.groups = nvdimm_attribute_groups,
+};
+
+bool is_nvdimm(struct device *dev)
+{
+	return dev->type == &nvdimm_device_type;
+}
 
 struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus,
 		void *provider_data, const struct attribute_group **groups,
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index eb597d1cb891..3644af97bcb4 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -66,7 +66,6 @@ enum {
 };
 
 extern struct attribute_group nvdimm_bus_attribute_group;
-extern struct attribute_group nvdimm_attribute_group;
 
 struct nvdimm;
 struct nvdimm_bus_descriptor;


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

* [PATCH 08/16] libnvdimm: Move nvdimm_bus_attribute_group to device_type
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (6 preceding siblings ...)
  2019-11-07  3:57 ` [PATCH 07/16] libnvdimm: Move nvdimm_attribute_group " Dan Williams
@ 2019-11-07  3:57 ` " Dan Williams
  2019-11-12 11:48   ` Aneesh Kumar K.V
  2019-11-07  3:57 ` [PATCH 09/16] dax: Create a dax device_type Dan Williams
                   ` (8 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:57 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, Michael Ellerman, Oliver O'Halloran, Vishal Verma,
	Aneesh Kumar K.V, peterz, dave.hansen, linux-kernel, linux-mm

A 'struct device_type' instance can carry default attributes for the
device. Use this facility to remove the export of
nvdimm_bus_attribute_group and put the responsibility on the core rather
than leaf implementations to define this attribute.

Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: "Oliver O'Halloran" <oohall@gmail.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/powerpc/platforms/pseries/papr_scm.c |    6 ------
 drivers/acpi/nfit/core.c                  |    1 -
 drivers/nvdimm/bus.c                      |    9 +++++++--
 drivers/nvdimm/core.c                     |    8 ++++++--
 drivers/nvdimm/e820.c                     |    6 ------
 drivers/nvdimm/nd.h                       |    1 +
 drivers/nvdimm/of_pmem.c                  |    6 ------
 include/linux/libnvdimm.h                 |    2 --
 8 files changed, 14 insertions(+), 25 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
index 8354737ac340..33aa59e666e5 100644
--- a/arch/powerpc/platforms/pseries/papr_scm.c
+++ b/arch/powerpc/platforms/pseries/papr_scm.c
@@ -284,11 +284,6 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
 	return 0;
 }
 
-static const struct attribute_group *bus_attr_groups[] = {
-	&nvdimm_bus_attribute_group,
-	NULL,
-};
-
 static inline int papr_scm_node(int node)
 {
 	int min_dist = INT_MAX, dist;
@@ -319,7 +314,6 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
 	p->bus_desc.ndctl = papr_scm_ndctl;
 	p->bus_desc.module = THIS_MODULE;
 	p->bus_desc.of_node = p->pdev->dev.of_node;
-	p->bus_desc.attr_groups = bus_attr_groups;
 	p->bus_desc.provider_name = kstrdup(p->pdev->name, GFP_KERNEL);
 
 	if (!p->bus_desc.provider_name)
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 84fc1f865802..a3320f93616d 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -1404,7 +1404,6 @@ static const struct attribute_group acpi_nfit_attribute_group = {
 };
 
 static const struct attribute_group *acpi_nfit_attribute_groups[] = {
-	&nvdimm_bus_attribute_group,
 	&acpi_nfit_attribute_group,
 	NULL,
 };
diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
index 28e1b265aa63..1d330d46d036 100644
--- a/drivers/nvdimm/bus.c
+++ b/drivers/nvdimm/bus.c
@@ -300,9 +300,14 @@ static void nvdimm_bus_release(struct device *dev)
 	kfree(nvdimm_bus);
 }
 
+static const struct device_type nvdimm_bus_dev_type = {
+	.release = nvdimm_bus_release,
+	.groups = nvdimm_bus_attribute_groups,
+};
+
 bool is_nvdimm_bus(struct device *dev)
 {
-	return dev->release == nvdimm_bus_release;
+	return dev->type == &nvdimm_bus_dev_type;
 }
 
 struct nvdimm_bus *walk_to_nvdimm_bus(struct device *nd_dev)
@@ -355,7 +360,7 @@ struct nvdimm_bus *nvdimm_bus_register(struct device *parent,
 	badrange_init(&nvdimm_bus->badrange);
 	nvdimm_bus->nd_desc = nd_desc;
 	nvdimm_bus->dev.parent = parent;
-	nvdimm_bus->dev.release = nvdimm_bus_release;
+	nvdimm_bus->dev.type = &nvdimm_bus_dev_type;
 	nvdimm_bus->dev.groups = nd_desc->attr_groups;
 	nvdimm_bus->dev.bus = &nvdimm_bus_type;
 	nvdimm_bus->dev.of_node = nd_desc->of_node;
diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c
index 9204f1e9fd14..81231ca23db0 100644
--- a/drivers/nvdimm/core.c
+++ b/drivers/nvdimm/core.c
@@ -385,10 +385,14 @@ static struct attribute *nvdimm_bus_attributes[] = {
 	NULL,
 };
 
-struct attribute_group nvdimm_bus_attribute_group = {
+static const struct attribute_group nvdimm_bus_attribute_group = {
 	.attrs = nvdimm_bus_attributes,
 };
-EXPORT_SYMBOL_GPL(nvdimm_bus_attribute_group);
+
+const struct attribute_group *nvdimm_bus_attribute_groups[] = {
+	&nvdimm_bus_attribute_group,
+	NULL,
+};
 
 int nvdimm_bus_add_badrange(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length)
 {
diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c
index 9a971a59dec7..e02f60ad6c99 100644
--- a/drivers/nvdimm/e820.c
+++ b/drivers/nvdimm/e820.c
@@ -8,11 +8,6 @@
 #include <linux/libnvdimm.h>
 #include <linux/module.h>
 
-static const struct attribute_group *e820_pmem_attribute_groups[] = {
-	&nvdimm_bus_attribute_group,
-	NULL,
-};
-
 static int e820_pmem_remove(struct platform_device *pdev)
 {
 	struct nvdimm_bus *nvdimm_bus = platform_get_drvdata(pdev);
@@ -55,7 +50,6 @@ static int e820_pmem_probe(struct platform_device *pdev)
 	struct nvdimm_bus *nvdimm_bus;
 	int rc = -ENXIO;
 
-	nd_desc.attr_groups = e820_pmem_attribute_groups;
 	nd_desc.provider_name = "e820";
 	nd_desc.module = THIS_MODULE;
 	nvdimm_bus = nvdimm_bus_register(dev, &nd_desc);
diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
index e7f3a2fee2ab..577800242110 100644
--- a/drivers/nvdimm/nd.h
+++ b/drivers/nvdimm/nd.h
@@ -300,6 +300,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig);
 extern const struct attribute_group *nd_pfn_attribute_groups[];
 extern const struct attribute_group nd_device_attribute_group;
 extern const struct attribute_group nd_numa_attribute_group;
+extern const struct attribute_group *nvdimm_bus_attribute_groups[];
 #else
 static inline int nd_pfn_probe(struct device *dev,
 		struct nd_namespace_common *ndns)
diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
index c0b5ac36df9d..8224d1431ea9 100644
--- a/drivers/nvdimm/of_pmem.c
+++ b/drivers/nvdimm/of_pmem.c
@@ -9,11 +9,6 @@
 #include <linux/ioport.h>
 #include <linux/slab.h>
 
-static const struct attribute_group *bus_attr_groups[] = {
-	&nvdimm_bus_attribute_group,
-	NULL,
-};
-
 struct of_pmem_private {
 	struct nvdimm_bus_descriptor bus_desc;
 	struct nvdimm_bus *bus;
@@ -35,7 +30,6 @@ static int of_pmem_region_probe(struct platform_device *pdev)
 	if (!priv)
 		return -ENOMEM;
 
-	priv->bus_desc.attr_groups = bus_attr_groups;
 	priv->bus_desc.provider_name = kstrdup(pdev->name, GFP_KERNEL);
 	priv->bus_desc.module = THIS_MODULE;
 	priv->bus_desc.of_node = np;
diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
index 3644af97bcb4..9df091bd30ba 100644
--- a/include/linux/libnvdimm.h
+++ b/include/linux/libnvdimm.h
@@ -65,8 +65,6 @@ enum {
 	DPA_RESOURCE_ADJUSTED = 1 << 0,
 };
 
-extern struct attribute_group nvdimm_bus_attribute_group;
-
 struct nvdimm;
 struct nvdimm_bus_descriptor;
 typedef int (*ndctl_fn)(struct nvdimm_bus_descriptor *nd_desc,


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

* [PATCH 09/16] dax: Create a dax device_type
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (7 preceding siblings ...)
  2019-11-07  3:57 ` [PATCH 08/16] libnvdimm: Move nvdimm_bus_attribute_group " Dan Williams
@ 2019-11-07  3:57 ` Dan Williams
  2019-11-12 11:49   ` Aneesh Kumar K.V
  2019-11-07  3:57 ` [PATCH 10/16] dax: Simplify root read-only definition for the 'resource' attribute Dan Williams
                   ` (7 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:57 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, Vishal Verma, peterz, dave.hansen, linux-kernel, linux-mm

Move the open coded release method and attribute groups to a 'struct
device_type' instance.

Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/dax/bus.c |    8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
index 8fafbeab510a..f3e6e00ece40 100644
--- a/drivers/dax/bus.c
+++ b/drivers/dax/bus.c
@@ -373,6 +373,11 @@ static void dev_dax_release(struct device *dev)
 	kfree(dev_dax);
 }
 
+static const struct device_type dev_dax_type = {
+	.release = dev_dax_release,
+	.groups = dax_attribute_groups,
+};
+
 static void unregister_dev_dax(void *dev)
 {
 	struct dev_dax *dev_dax = to_dev_dax(dev);
@@ -430,8 +435,7 @@ struct dev_dax *__devm_create_dev_dax(struct dax_region *dax_region, int id,
 	else
 		dev->class = dax_class;
 	dev->parent = parent;
-	dev->groups = dax_attribute_groups;
-	dev->release = dev_dax_release;
+	dev->type = &dev_dax_type;
 	dev_set_name(dev, "dax%d.%d", dax_region->id, id);
 
 	rc = device_add(dev);


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

* [PATCH 10/16] dax: Simplify root read-only definition for the 'resource' attribute
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (8 preceding siblings ...)
  2019-11-07  3:57 ` [PATCH 09/16] dax: Create a dax device_type Dan Williams
@ 2019-11-07  3:57 ` Dan Williams
  2019-11-12 11:49   ` Aneesh Kumar K.V
  2019-11-07  3:57 ` [PATCH 11/16] libnvdimm: " Dan Williams
                   ` (6 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:57 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, Vishal Verma, peterz, dave.hansen, linux-kernel, linux-mm

Rather than update the permission in ->is_visible() set the permission
directly at declaration time.

Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/dax/bus.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
index f3e6e00ece40..ce6d648d7670 100644
--- a/drivers/dax/bus.c
+++ b/drivers/dax/bus.c
@@ -309,7 +309,7 @@ static ssize_t resource_show(struct device *dev,
 
 	return sprintf(buf, "%#llx\n", dev_dax_resource(dev_dax));
 }
-static DEVICE_ATTR_RO(resource);
+static DEVICE_ATTR(resource, 0400, resource_show, NULL);
 
 static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
 		char *buf)
@@ -329,8 +329,6 @@ static umode_t dev_dax_visible(struct kobject *kobj, struct attribute *a, int n)
 
 	if (a == &dev_attr_target_node.attr && dev_dax_target_node(dev_dax) < 0)
 		return 0;
-	if (a == &dev_attr_resource.attr)
-		return 0400;
 	return a->mode;
 }
 


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

* [PATCH 11/16] libnvdimm: Simplify root read-only definition for the 'resource' attribute
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (9 preceding siblings ...)
  2019-11-07  3:57 ` [PATCH 10/16] dax: Simplify root read-only definition for the 'resource' attribute Dan Williams
@ 2019-11-07  3:57 ` " Dan Williams
  2019-11-12 11:50   ` Aneesh Kumar K.V
  2019-11-07  3:57 ` [PATCH 12/16] dax: Add numa_node to the default device-dax attributes Dan Williams
                   ` (5 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:57 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, Vishal Verma, peterz, dave.hansen, linux-kernel, linux-mm

Rather than update the permission in ->is_visible() set the permission
directly at declaration time.

Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/nvdimm/namespace_devs.c |    9 +++------
 drivers/nvdimm/pfn_devs.c       |   10 +---------
 drivers/nvdimm/region_devs.c    |   10 +++-------
 3 files changed, 7 insertions(+), 22 deletions(-)

diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
index 37471a272c1a..85b553094d19 100644
--- a/drivers/nvdimm/namespace_devs.c
+++ b/drivers/nvdimm/namespace_devs.c
@@ -1303,7 +1303,7 @@ static ssize_t resource_show(struct device *dev,
 		return -ENXIO;
 	return sprintf(buf, "%#llx\n", (unsigned long long) res->start);
 }
-static DEVICE_ATTR_RO(resource);
+static DEVICE_ATTR(resource, 0400, resource_show, NULL);
 
 static const unsigned long blk_lbasize_supported[] = { 512, 520, 528,
 	4096, 4104, 4160, 4224, 0 };
@@ -1619,11 +1619,8 @@ static umode_t namespace_visible(struct kobject *kobj,
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
 
-	if (a == &dev_attr_resource.attr) {
-		if (is_namespace_blk(dev))
-			return 0;
-		return 0400;
-	}
+	if (a == &dev_attr_resource.attr && is_namespace_blk(dev))
+		return 0;
 
 	if (is_namespace_pmem(dev) || is_namespace_blk(dev)) {
 		if (a == &dev_attr_size.attr)
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index e809961e2b6f..9f9cb51301e7 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -218,7 +218,7 @@ static ssize_t resource_show(struct device *dev,
 
 	return rc;
 }
-static DEVICE_ATTR_RO(resource);
+static DEVICE_ATTR(resource, 0400, resource_show, NULL);
 
 static ssize_t size_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -269,16 +269,8 @@ static struct attribute *nd_pfn_attributes[] = {
 	NULL,
 };
 
-static umode_t pfn_visible(struct kobject *kobj, struct attribute *a, int n)
-{
-	if (a == &dev_attr_resource.attr)
-		return 0400;
-	return a->mode;
-}
-
 static struct attribute_group nd_pfn_attribute_group = {
 	.attrs = nd_pfn_attributes,
-	.is_visible = pfn_visible,
 };
 
 const struct attribute_group *nd_pfn_attribute_groups[] = {
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 0afc1973e938..be3e429e86af 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -553,7 +553,7 @@ static ssize_t resource_show(struct device *dev,
 
 	return sprintf(buf, "%#llx\n", nd_region->ndr_start);
 }
-static DEVICE_ATTR_RO(resource);
+static DEVICE_ATTR(resource, 0400, resource_show, NULL);
 
 static ssize_t persistence_domain_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
@@ -605,12 +605,8 @@ static umode_t region_visible(struct kobject *kobj, struct attribute *a, int n)
 	if (!is_memory(dev) && a == &dev_attr_badblocks.attr)
 		return 0;
 
-	if (a == &dev_attr_resource.attr) {
-		if (is_memory(dev))
-			return 0400;
-		else
-			return 0;
-	}
+	if (a == &dev_attr_resource.attr && !is_memory(dev))
+		return 0;
 
 	if (a == &dev_attr_deep_flush.attr) {
 		int has_flush = nvdimm_has_flush(nd_region);


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

* [PATCH 12/16] dax: Add numa_node to the default device-dax attributes
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (10 preceding siblings ...)
  2019-11-07  3:57 ` [PATCH 11/16] libnvdimm: " Dan Williams
@ 2019-11-07  3:57 ` Dan Williams
  2019-11-12 11:50   ` Aneesh Kumar K.V
  2019-11-07  3:57 ` [PATCH 13/16] acpi/mm: Up-level "map to online node" functionality Dan Williams
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:57 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, Vishal Verma, peterz, dave.hansen, linux-kernel, linux-mm

It is confusing that device-dax instances publish a 'target_node'
attribute, but not a 'numa_node'. The 'numa_node' information is
available elsewhere in the sysfs device hierarchy, but it is not obvious
and not reliable from one device-dax instance-type (e.g. child devices
of nvdimm namespaces) to the next (e.g. 'hmem' devices defined by EFI
Specific Purpose Memory and the ACPI HMAT).

Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/dax/bus.c |   10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
index ce6d648d7670..0879b9663eb7 100644
--- a/drivers/dax/bus.c
+++ b/drivers/dax/bus.c
@@ -322,6 +322,13 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR_RO(modalias);
 
+static ssize_t numa_node_show(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "%d\n", dev_to_node(dev));
+}
+static DEVICE_ATTR_RO(numa_node);
+
 static umode_t dev_dax_visible(struct kobject *kobj, struct attribute *a, int n)
 {
 	struct device *dev = container_of(kobj, struct device, kobj);
@@ -329,6 +336,8 @@ static umode_t dev_dax_visible(struct kobject *kobj, struct attribute *a, int n)
 
 	if (a == &dev_attr_target_node.attr && dev_dax_target_node(dev_dax) < 0)
 		return 0;
+	if (a == &dev_attr_numa_node.attr && !IS_ENABLED(CONFIG_NUMA))
+		return 0;
 	return a->mode;
 }
 
@@ -337,6 +346,7 @@ static struct attribute *dev_dax_attributes[] = {
 	&dev_attr_size.attr,
 	&dev_attr_target_node.attr,
 	&dev_attr_resource.attr,
+	&dev_attr_numa_node.attr,
 	NULL,
 };
 


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

* [PATCH 13/16] acpi/mm: Up-level "map to online node" functionality
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (11 preceding siblings ...)
  2019-11-07  3:57 ` [PATCH 12/16] dax: Add numa_node to the default device-dax attributes Dan Williams
@ 2019-11-07  3:57 ` Dan Williams
  2019-11-11 11:30   ` Aneesh Kumar K.V
  2019-11-07  3:57 ` [PATCH 14/16] x86/numa: Provide a range-to-target_node lookup facility Dan Williams
                   ` (3 subsequent siblings)
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:57 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Michal Hocko, Rafael J. Wysocki, peterz, vishal.l.verma,
	dave.hansen, linux-kernel, linux-mm

The acpi_map_pxm_to_online_node() helper is used to find the closest
online node to a given proximity domain. This is used to map devices in
a proximity domain with no online memory or cpus to the closest online
node and populate a device's 'numa_node' property. The numa_node
property allows applications to be migrated "close" to a resource.

In preparation for providing a generic facility to optionally map an
address range to its closest online node, or the node the range would
represent were it to be onlined (target_node), up-level the core of
acpi_map_pxm_to_online_node() to a generic mm/numa helper.

Cc: Michal Hocko <mhocko@suse.com>
Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/acpi/numa.c  |   41 -----------------------------------------
 include/linux/acpi.h |   23 ++++++++++++++++++++++-
 include/linux/numa.h |    2 ++
 mm/mempolicy.c       |   30 ++++++++++++++++++++++++++++++
 4 files changed, 54 insertions(+), 42 deletions(-)

diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
index eadbf90e65d1..47b4969d9b93 100644
--- a/drivers/acpi/numa.c
+++ b/drivers/acpi/numa.c
@@ -72,47 +72,6 @@ int acpi_map_pxm_to_node(int pxm)
 }
 EXPORT_SYMBOL(acpi_map_pxm_to_node);
 
-/**
- * acpi_map_pxm_to_online_node - Map proximity ID to online node
- * @pxm: ACPI proximity ID
- *
- * This is similar to acpi_map_pxm_to_node(), but always returns an online
- * node.  When the mapped node from a given proximity ID is offline, it
- * looks up the node distance table and returns the nearest online node.
- *
- * ACPI device drivers, which are called after the NUMA initialization has
- * completed in the kernel, can call this interface to obtain their device
- * NUMA topology from ACPI tables.  Such drivers do not have to deal with
- * offline nodes.  A node may be offline when a device proximity ID is
- * unique, SRAT memory entry does not exist, or NUMA is disabled, ex.
- * "numa=off" on x86.
- */
-int acpi_map_pxm_to_online_node(int pxm)
-{
-	int node, min_node;
-
-	node = acpi_map_pxm_to_node(pxm);
-
-	if (node == NUMA_NO_NODE)
-		node = 0;
-
-	min_node = node;
-	if (!node_online(node)) {
-		int min_dist = INT_MAX, dist, n;
-
-		for_each_online_node(n) {
-			dist = node_distance(node, n);
-			if (dist < min_dist) {
-				min_dist = dist;
-				min_node = n;
-			}
-		}
-	}
-
-	return min_node;
-}
-EXPORT_SYMBOL(acpi_map_pxm_to_online_node);
-
 static void __init
 acpi_table_print_srat_entry(struct acpi_subtable_header *header)
 {
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 8b4e516bac00..aeedd09f2f71 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -401,9 +401,30 @@ extern void acpi_osi_setup(char *str);
 extern bool acpi_osi_is_win8(void);
 
 #ifdef CONFIG_ACPI_NUMA
-int acpi_map_pxm_to_online_node(int pxm);
 int acpi_map_pxm_to_node(int pxm);
 int acpi_get_node(acpi_handle handle);
+
+/**
+ * acpi_map_pxm_to_online_node - Map proximity ID to online node
+ * @pxm: ACPI proximity ID
+ *
+ * This is similar to acpi_map_pxm_to_node(), but always returns an online
+ * node.  When the mapped node from a given proximity ID is offline, it
+ * looks up the node distance table and returns the nearest online node.
+ *
+ * ACPI device drivers, which are called after the NUMA initialization has
+ * completed in the kernel, can call this interface to obtain their device
+ * NUMA topology from ACPI tables.  Such drivers do not have to deal with
+ * offline nodes.  A node may be offline when a device proximity ID is
+ * unique, SRAT memory entry does not exist, or NUMA is disabled, ex.
+ * "numa=off" on x86.
+ */
+static inline int acpi_map_pxm_to_online_node(int pxm)
+{
+	int node = acpi_map_pxm_to_node(pxm);
+
+	return numa_map_to_online_node(node);
+}
 #else
 static inline int acpi_map_pxm_to_online_node(int pxm)
 {
diff --git a/include/linux/numa.h b/include/linux/numa.h
index 110b0e5d0fb0..4fd80f42be43 100644
--- a/include/linux/numa.h
+++ b/include/linux/numa.h
@@ -13,4 +13,6 @@
 
 #define	NUMA_NO_NODE	(-1)
 
+int numa_map_to_online_node(int node);
+
 #endif /* _LINUX_NUMA_H */
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 4ae967bcf954..e2d8dd21ce9d 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -127,6 +127,36 @@ static struct mempolicy default_policy = {
 
 static struct mempolicy preferred_node_policy[MAX_NUMNODES];
 
+/**
+ * numa_map_to_online_node - Find closest online node
+ * @nid: Node id to start the search
+ *
+ * Lookup the next closest node by distance if @nid is not online.
+ */
+int numa_map_to_online_node(int node)
+{
+	int min_node;
+
+	if (node == NUMA_NO_NODE)
+		node = 0;
+
+	min_node = node;
+	if (!node_online(node)) {
+		int min_dist = INT_MAX, dist, n;
+
+		for_each_online_node(n) {
+			dist = node_distance(node, n);
+			if (dist < min_dist) {
+				min_dist = dist;
+				min_node = n;
+			}
+		}
+	}
+
+	return min_node;
+}
+EXPORT_SYMBOL_GPL(numa_map_to_online_node);
+
 struct mempolicy *get_task_policy(struct task_struct *p)
 {
 	struct mempolicy *pol = p->mempolicy;


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

* [PATCH 14/16] x86/numa: Provide a range-to-target_node lookup facility
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (12 preceding siblings ...)
  2019-11-07  3:57 ` [PATCH 13/16] acpi/mm: Up-level "map to online node" functionality Dan Williams
@ 2019-11-07  3:57 ` Dan Williams
  2019-11-07  3:57 ` [PATCH 15/16] libnvdimm/e820: Drop the wrapper around memory_add_physaddr_to_nid Dan Williams
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:57 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Dave Hansen, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin, x86, Andrew Morton,
	David Hildenbrand, Michal Hocko, vishal.l.verma, linux-kernel,
	linux-mm

The DEV_DAX_KMEM facility is a generic mechanism to allow device-dax
instances, fronting performance-differentiated-memory like pmem, to be
added to the System RAM pool. The numa node for that hot-added memory is
derived from the device-dax instance's 'target_node' attribute.

Recall that the 'target_node' is the ACPI-PXM-to-node translation for
memory when it comes online whereas the 'numa_node' attribute of the
device represents the closest online cpu node.

Presently useful target_node information from the ACPI SRAT is discarded
with the expectation that "Reserved" memory will never be onlined. Now,
DEV_DAX_KMEM violates that assumption, there is a need to retain the
translation. Move, rather than discard, numa_memblk data to a secondary
array that memory_add_physaddr_to_target_node() may consider at a later
point in time.

Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: <x86@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: David Hildenbrand <david@redhat.com>
Cc: Michal Hocko <mhocko@suse.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 arch/x86/mm/numa.c             |   72 +++++++++++++++++++++++++++++++++++++---
 include/linux/memory_hotplug.h |    6 +++
 2 files changed, 73 insertions(+), 5 deletions(-)

diff --git a/arch/x86/mm/numa.c b/arch/x86/mm/numa.c
index 4123100e0eaf..3bbae90b3197 100644
--- a/arch/x86/mm/numa.c
+++ b/arch/x86/mm/numa.c
@@ -31,6 +31,20 @@ __initdata
 #endif
 ;
 
+#if IS_ENABLED(CONFIG_DEV_DAX_KMEM)
+static struct numa_meminfo __numa_reserved_meminfo;
+
+static struct numa_meminfo *numa_reserved_meminfo(void)
+{
+	return &__numa_reserved_meminfo;
+}
+#else
+static struct numa_meminfo *numa_reserved_meminfo(void)
+{
+	return NULL;
+}
+#endif
+
 static int numa_distance_cnt;
 static u8 *numa_distance;
 
@@ -168,6 +182,26 @@ void __init numa_remove_memblk_from(int idx, struct numa_meminfo *mi)
 		(mi->nr_blks - idx) * sizeof(mi->blk[0]));
 }
 
+/**
+ * numa_move_memblk - Move one numa_memblk from one numa_meminfo to another
+ * @dst: numa_meminfo to move block to
+ * @idx: Index of memblk to remove
+ * @src: numa_meminfo to remove memblk from
+ *
+ * If @dst is non-NULL add it at the @dst->nr_blks index and increment
+ * @dst->nr_blks, then remove it from @src.
+ */
+void __init numa_move_memblk(struct numa_meminfo *dst, int idx,
+		struct numa_meminfo *src)
+{
+	if (dst) {
+		memcpy(&dst->blk[dst->nr_blks], &src->blk[idx],
+				sizeof(struct numa_memblk));
+		dst->nr_blks++;
+	}
+	numa_remove_memblk_from(idx, src);
+}
+
 /**
  * numa_add_memblk - Add one numa_memblk to numa_meminfo
  * @nid: NUMA node ID of the new memblk
@@ -245,7 +279,7 @@ int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
 		if (bi->start >= bi->end ||
 		    !memblock_overlaps_region(&memblock.memory,
 			bi->start, bi->end - bi->start))
-			numa_remove_memblk_from(i--, mi);
+			numa_move_memblk(numa_reserved_meminfo(), i--, mi);
 	}
 
 	/* merge neighboring / overlapping entries */
@@ -882,15 +916,43 @@ EXPORT_SYMBOL(cpumask_of_node);
 #endif	/* !CONFIG_DEBUG_PER_CPU_MAPS */
 
 #ifdef CONFIG_MEMORY_HOTPLUG
+static int meminfo_to_nid(struct numa_meminfo *mi, u64 start, int *nid)
+{
+	int i;
+
+	for (i = 0; mi && i < mi->nr_blks; i++)
+		if (mi->blk[i].start <= start && mi->blk[i].end > start) {
+			*nid = mi->blk[i].nid;
+			break;
+		}
+	return i;
+}
+
+int memory_add_physaddr_to_target_node(u64 start)
+{
+	struct numa_meminfo *mi = &numa_meminfo;
+	int nid = mi->blk[0].nid;
+	int i = meminfo_to_nid(mi, start, &nid);
+
+	/*
+	 * Prefer online nodes, but if reserved memory might be
+	 * hot-added continue the search with reserved ranges.
+	 */
+	if (i < mi->nr_blks)
+		return nid;
+
+	mi = numa_reserved_meminfo();
+	meminfo_to_nid(mi, start, &nid);
+	return nid;
+}
+EXPORT_SYMBOL_GPL(memory_add_physaddr_to_target_node);
+
 int memory_add_physaddr_to_nid(u64 start)
 {
 	struct numa_meminfo *mi = &numa_meminfo;
 	int nid = mi->blk[0].nid;
-	int i;
 
-	for (i = 0; i < mi->nr_blks; i++)
-		if (mi->blk[i].start <= start && mi->blk[i].end > start)
-			nid = mi->blk[i].nid;
+	meminfo_to_nid(mi, start, &nid);
 	return nid;
 }
 EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid);
diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
index f46ea71b4ffd..84efb0f20f7e 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
@@ -145,11 +145,17 @@ int add_pages(int nid, unsigned long start_pfn, unsigned long nr_pages,
 
 #ifdef CONFIG_NUMA
 extern int memory_add_physaddr_to_nid(u64 start);
+extern int memory_add_physaddr_to_target_node(u64 start);
 #else
 static inline int memory_add_physaddr_to_nid(u64 start)
 {
 	return 0;
 }
+
+static inline int memory_add_physaddr_to_target_node(u64 start)
+{
+	return 0;
+}
 #endif
 
 #ifdef CONFIG_HAVE_ARCH_NODEDATA_EXTENSION


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

* [PATCH 15/16] libnvdimm/e820: Drop the wrapper around memory_add_physaddr_to_nid
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (13 preceding siblings ...)
  2019-11-07  3:57 ` [PATCH 14/16] x86/numa: Provide a range-to-target_node lookup facility Dan Williams
@ 2019-11-07  3:57 ` Dan Williams
  2019-11-07  3:58 ` [PATCH 16/16] libnvdimm/e820: Retrieve and populate correct 'target_node' info Dan Williams
  2019-11-12 11:42 ` [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Aneesh Kumar K.V
  16 siblings, 0 replies; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:57 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Ira Weiny, Vishal Verma, peterz, dave.hansen, linux-kernel, linux-mm

The definition of memory_add_physaddr_to_nid() already has a dummy
fallback, no need to duplicate this in the e820 driver.

Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/nvdimm/e820.c |   14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c
index e02f60ad6c99..b802291bcde1 100644
--- a/drivers/nvdimm/e820.c
+++ b/drivers/nvdimm/e820.c
@@ -16,18 +16,6 @@ static int e820_pmem_remove(struct platform_device *pdev)
 	return 0;
 }
 
-#ifdef CONFIG_MEMORY_HOTPLUG
-static int e820_range_to_nid(resource_size_t addr)
-{
-	return memory_add_physaddr_to_nid(addr);
-}
-#else
-static int e820_range_to_nid(resource_size_t addr)
-{
-	return NUMA_NO_NODE;
-}
-#endif
-
 static int e820_register_one(struct resource *res, void *data)
 {
 	struct nd_region_desc ndr_desc;
@@ -35,7 +23,7 @@ static int e820_register_one(struct resource *res, void *data)
 
 	memset(&ndr_desc, 0, sizeof(ndr_desc));
 	ndr_desc.res = res;
-	ndr_desc.numa_node = e820_range_to_nid(res->start);
+	ndr_desc.numa_node = memory_add_physaddr_to_nid(res->start);
 	ndr_desc.target_node = ndr_desc.numa_node;
 	set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
 	if (!nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc))


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

* [PATCH 16/16] libnvdimm/e820: Retrieve and populate correct 'target_node' info
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (14 preceding siblings ...)
  2019-11-07  3:57 ` [PATCH 15/16] libnvdimm/e820: Drop the wrapper around memory_add_physaddr_to_nid Dan Williams
@ 2019-11-07  3:58 ` Dan Williams
  2019-11-09  5:02   ` kbuild test robot
  2019-11-12 11:42 ` [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Aneesh Kumar K.V
  16 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-07  3:58 UTC (permalink / raw)
  To: linux-nvdimm
  Cc: Dave Hansen, Andy Lutomirski, Peter Zijlstra, Thomas Gleixner,
	Ingo Molnar, Andrew Morton, David Hildenbrand, Michal Hocko,
	Ira Weiny, Vishal Verma, linux-kernel, linux-mm

Use the new memory_add_physaddr_to_target_node() and
numa_map_to_online_node() helpers to retrieve the correct id for
the 'numa_node' (online initiator) and 'target_node' (offline target
memory node) sysfs attributes.

Below is an example from a 4 numa node system where all the memory on
node2 is pmem / reserved. It should be noted that with the arrival of
the ACPI HMAT table and EFI Specific Purpose Memory the kernel will
start to see more platforms with reserved / performance differentiated
memory in its own numa node. Hence all the stakeholders on the Cc for
what is ostensibly a libnvdimm local patch.

=== Before ===

/* Notice no online memory on node2 at start */

# numactl --hardware
available: 3 nodes (0-1,3)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
node 0 size: 3958 MB
node 0 free: 3708 MB
node 1 cpus: 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
node 1 size: 4027 MB
node 1 free: 3871 MB
node 3 cpus:
node 3 size: 3994 MB
node 3 free: 3971 MB
node distances:
node   0   1   3
  0:  10  21  21
  1:  21  10  21
  3:  21  21  10

/*
 * Put the pmem namespace into devdax mode so it can be assigned to the
 * kmem driver
 */

# ndctl create-namespace -e namespace0.0 -m devdax -f
{
  "dev":"namespace0.0",
  "mode":"devdax",
  "map":"dev",
  "size":"3.94 GiB (4.23 GB)",
  "uuid":"1650af9b-9ba3-4704-acd6-10178399d9a3",
  [..]
}

/* Online Persistent Memory as System RAM */

# daxctl reconfigure-device --mode=system-ram dax0.0
libdaxctl: memblock_in_dev: dax0.0: memory0: Unable to determine phys_index: Success
libdaxctl: memblock_in_dev: dax0.0: memory0: Unable to determine phys_index: Success
libdaxctl: memblock_in_dev: dax0.0: memory0: Unable to determine phys_index: Success
libdaxctl: memblock_in_dev: dax0.0: memory0: Unable to determine phys_index: Success
[
  {
    "chardev":"dax0.0",
    "size":4225761280,
    "target_node":0,
    "mode":"system-ram"
  }
]
reconfigured 1 device

/* Note that the memory is onlined by default to the wrong node, node0 */

# numactl --hardware
available: 3 nodes (0-1,3)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
node 0 size: 7926 MB
node 0 free: 7655 MB
node 1 cpus: 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
node 1 size: 4027 MB
node 1 free: 3871 MB
node 3 cpus:
node 3 size: 3994 MB
node 3 free: 3971 MB
node distances:
node   0   1   3
  0:  10  21  21
  1:  21  10  21
  3:  21  21  10


=== After ===

/* Notice that the "phys_index" error messages are gone */

# daxctl reconfigure-device --mode=system-ram dax0.0
[
  {
    "chardev":"dax0.0",
    "size":4225761280,
    "target_node":2,
    "mode":"system-ram"
  }
]
reconfigured 1 device

/* Notice that node2 is now correctly populated */

# numactl --hardware
available: 4 nodes (0-3)
node 0 cpus: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
node 0 size: 3958 MB
node 0 free: 3793 MB
node 1 cpus: 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
node 1 size: 4027 MB
node 1 free: 3851 MB
node 2 cpus:
node 2 size: 3968 MB
node 2 free: 3968 MB
node 3 cpus:
node 3 size: 3994 MB
node 3 free: 3908 MB
node distances:
node   0   1   2   3
  0:  10  21  21  21
  1:  21  10  21  21
  2:  21  21  10  21
  3:  21  21  21  10

Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: David Hildenbrand <david@redhat.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Vishal Verma <vishal.l.verma@intel.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 drivers/nvdimm/e820.c |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c
index b802291bcde1..23121dd6e494 100644
--- a/drivers/nvdimm/e820.c
+++ b/drivers/nvdimm/e820.c
@@ -20,11 +20,12 @@ static int e820_register_one(struct resource *res, void *data)
 {
 	struct nd_region_desc ndr_desc;
 	struct nvdimm_bus *nvdimm_bus = data;
+	int nid = memory_add_physaddr_to_target_node(res->start);
 
 	memset(&ndr_desc, 0, sizeof(ndr_desc));
 	ndr_desc.res = res;
-	ndr_desc.numa_node = memory_add_physaddr_to_nid(res->start);
-	ndr_desc.target_node = ndr_desc.numa_node;
+	ndr_desc.numa_node = numa_map_to_online_node(nid);
+	ndr_desc.target_node = nid;
 	set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
 	if (!nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc))
 		return -ENXIO;


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

* Re: [PATCH 16/16] libnvdimm/e820: Retrieve and populate correct 'target_node' info
  2019-11-07  3:58 ` [PATCH 16/16] libnvdimm/e820: Retrieve and populate correct 'target_node' info Dan Williams
@ 2019-11-09  5:02   ` kbuild test robot
  0 siblings, 0 replies; 37+ messages in thread
From: kbuild test robot @ 2019-11-09  5:02 UTC (permalink / raw)
  To: Dan Williams
  Cc: kbuild-all, linux-nvdimm, Dave Hansen, Andy Lutomirski,
	Peter Zijlstra, Thomas Gleixner, Ingo Molnar, Andrew Morton,
	David Hildenbrand, Michal Hocko, Ira Weiny, Vishal Verma,
	linux-kernel, linux-mm

[-- Attachment #1: Type: text/plain, Size: 1853 bytes --]

Hi Dan,

I love your patch! Yet something to improve:

[auto build test ERROR on powerpc/next]
[cannot apply to v5.4-rc6 next-20191108]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Dan-Williams/Memory-Hierarchy-Enable-target-node-lookups-for-reserved-memory/20191109-080607
base:   https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: x86_64-randconfig-d002-201944 (attached as .config)
compiler: gcc-7 (Debian 7.4.0-14) 7.4.0
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   ld: drivers/nvdimm/e820.o: in function `e820_register_one':
>> drivers/nvdimm/e820.c:27: undefined reference to `numa_map_to_online_node'

vim +27 drivers/nvdimm/e820.c

    18	
    19	static int e820_register_one(struct resource *res, void *data)
    20	{
    21		struct nd_region_desc ndr_desc;
    22		struct nvdimm_bus *nvdimm_bus = data;
    23		int nid = memory_add_physaddr_to_target_node(res->start);
    24	
    25		memset(&ndr_desc, 0, sizeof(ndr_desc));
    26		ndr_desc.res = res;
  > 27		ndr_desc.numa_node = numa_map_to_online_node(nid);
    28		ndr_desc.target_node = nid;
    29		set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
    30		if (!nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc))
    31			return -ENXIO;
    32		return 0;
    33	}
    34	

---
0-DAY kernel test infrastructure                 Open Source Technology Center
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 35944 bytes --]

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

* Re: [PATCH 13/16] acpi/mm: Up-level "map to online node" functionality
  2019-11-07  3:57 ` [PATCH 13/16] acpi/mm: Up-level "map to online node" functionality Dan Williams
@ 2019-11-11 11:30   ` Aneesh Kumar K.V
  2019-11-11 23:38     ` Dan Williams
  0 siblings, 1 reply; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-11 11:30 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm
  Cc: Michal Hocko, Rafael J. Wysocki, peterz, dave.hansen,
	linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> The acpi_map_pxm_to_online_node() helper is used to find the closest
> online node to a given proximity domain. This is used to map devices in
> a proximity domain with no online memory or cpus to the closest online
> node and populate a device's 'numa_node' property. The numa_node
> property allows applications to be migrated "close" to a resource.
>
> In preparation for providing a generic facility to optionally map an
> address range to its closest online node, or the node the range would
> represent were it to be onlined (target_node), up-level the core of
> acpi_map_pxm_to_online_node() to a generic mm/numa helper.
>
> Cc: Michal Hocko <mhocko@suse.com>
> Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  drivers/acpi/numa.c  |   41 -----------------------------------------
>  include/linux/acpi.h |   23 ++++++++++++++++++++++-
>  include/linux/numa.h |    2 ++
>  mm/mempolicy.c       |   30 ++++++++++++++++++++++++++++++
>  4 files changed, 54 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
> index eadbf90e65d1..47b4969d9b93 100644
> --- a/drivers/acpi/numa.c
> +++ b/drivers/acpi/numa.c
> @@ -72,47 +72,6 @@ int acpi_map_pxm_to_node(int pxm)
>  }
>  EXPORT_SYMBOL(acpi_map_pxm_to_node);
>  
> -/**
> - * acpi_map_pxm_to_online_node - Map proximity ID to online node
> - * @pxm: ACPI proximity ID
> - *
> - * This is similar to acpi_map_pxm_to_node(), but always returns an online
> - * node.  When the mapped node from a given proximity ID is offline, it
> - * looks up the node distance table and returns the nearest online node.
> - *
> - * ACPI device drivers, which are called after the NUMA initialization has
> - * completed in the kernel, can call this interface to obtain their device
> - * NUMA topology from ACPI tables.  Such drivers do not have to deal with
> - * offline nodes.  A node may be offline when a device proximity ID is
> - * unique, SRAT memory entry does not exist, or NUMA is disabled, ex.
> - * "numa=off" on x86.
> - */
> -int acpi_map_pxm_to_online_node(int pxm)
> -{
> -	int node, min_node;
> -
> -	node = acpi_map_pxm_to_node(pxm);
> -
> -	if (node == NUMA_NO_NODE)
> -		node = 0;
> -
> -	min_node = node;
> -	if (!node_online(node)) {
> -		int min_dist = INT_MAX, dist, n;
> -
> -		for_each_online_node(n) {
> -			dist = node_distance(node, n);
> -			if (dist < min_dist) {
> -				min_dist = dist;
> -				min_node = n;
> -			}
> -		}
> -	}
> -
> -	return min_node;
> -}
> -EXPORT_SYMBOL(acpi_map_pxm_to_online_node);
> -
>  static void __init
>  acpi_table_print_srat_entry(struct acpi_subtable_header *header)
>  {
> diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> index 8b4e516bac00..aeedd09f2f71 100644
> --- a/include/linux/acpi.h
> +++ b/include/linux/acpi.h
> @@ -401,9 +401,30 @@ extern void acpi_osi_setup(char *str);
>  extern bool acpi_osi_is_win8(void);
>  
>  #ifdef CONFIG_ACPI_NUMA
> -int acpi_map_pxm_to_online_node(int pxm);
>  int acpi_map_pxm_to_node(int pxm);
>  int acpi_get_node(acpi_handle handle);
> +
> +/**
> + * acpi_map_pxm_to_online_node - Map proximity ID to online node
> + * @pxm: ACPI proximity ID
> + *
> + * This is similar to acpi_map_pxm_to_node(), but always returns an online
> + * node.  When the mapped node from a given proximity ID is offline, it
> + * looks up the node distance table and returns the nearest online node.
> + *
> + * ACPI device drivers, which are called after the NUMA initialization has
> + * completed in the kernel, can call this interface to obtain their device
> + * NUMA topology from ACPI tables.  Such drivers do not have to deal with
> + * offline nodes.  A node may be offline when a device proximity ID is
> + * unique, SRAT memory entry does not exist, or NUMA is disabled, ex.
> + * "numa=off" on x86.
> + */
> +static inline int acpi_map_pxm_to_online_node(int pxm)
> +{
> +	int node = acpi_map_pxm_to_node(pxm);
> +
> +	return numa_map_to_online_node(node);
> +}
>  #else
>  static inline int acpi_map_pxm_to_online_node(int pxm)
>  {
> diff --git a/include/linux/numa.h b/include/linux/numa.h
> index 110b0e5d0fb0..4fd80f42be43 100644
> --- a/include/linux/numa.h
> +++ b/include/linux/numa.h
> @@ -13,4 +13,6 @@
>  
>  #define	NUMA_NO_NODE	(-1)
>  
> +int numa_map_to_online_node(int node);
> +
>  #endif /* _LINUX_NUMA_H */
> diff --git a/mm/mempolicy.c b/mm/mempolicy.c
> index 4ae967bcf954..e2d8dd21ce9d 100644
> --- a/mm/mempolicy.c
> +++ b/mm/mempolicy.c
> @@ -127,6 +127,36 @@ static struct mempolicy default_policy = {
>  
>  static struct mempolicy preferred_node_policy[MAX_NUMNODES];
>  
> +/**
> + * numa_map_to_online_node - Find closest online node
> + * @nid: Node id to start the search
> + *
> + * Lookup the next closest node by distance if @nid is not online.
> + */
> +int numa_map_to_online_node(int node)
> +{
> +	int min_node;
> +
> +	if (node == NUMA_NO_NODE)
> +		node = 0;

The ppc64 variant papr_scm_node return the NUMA_NO_NODE in this case.
Most of the mm helpers can handle with that value . So instead of
forcing node = 0, let the subsystem decide what to do with the
NUMA_NO_NODE value.?

> +
> +	min_node = node;
> +	if (!node_online(node)) {
> +		int min_dist = INT_MAX, dist, n;
> +
> +		for_each_online_node(n) {
> +			dist = node_distance(node, n);
> +			if (dist < min_dist) {
> +				min_dist = dist;
> +				min_node = n;
> +			}
> +		}
> +	}
> +
> +	return min_node;
> +}
> +EXPORT_SYMBOL_GPL(numa_map_to_online_node);
> +
>  struct mempolicy *get_task_policy(struct task_struct *p)
>  {
>  	struct mempolicy *pol = p->mempolicy;


Can we also switch papr_scm_node to numa_map_to_online_node()?

-aneesh

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

* Re: [PATCH 13/16] acpi/mm: Up-level "map to online node" functionality
  2019-11-11 11:30   ` Aneesh Kumar K.V
@ 2019-11-11 23:38     ` Dan Williams
  0 siblings, 0 replies; 37+ messages in thread
From: Dan Williams @ 2019-11-11 23:38 UTC (permalink / raw)
  To: Aneesh Kumar K.V
  Cc: linux-nvdimm, Michal Hocko, Rafael J. Wysocki, Peter Zijlstra,
	Dave Hansen, Linux Kernel Mailing List, Linux MM

On Mon, Nov 11, 2019 at 3:39 AM Aneesh Kumar K.V
<aneesh.kumar@linux.ibm.com> wrote:
>
> Dan Williams <dan.j.williams@intel.com> writes:
>
> > The acpi_map_pxm_to_online_node() helper is used to find the closest
> > online node to a given proximity domain. This is used to map devices in
> > a proximity domain with no online memory or cpus to the closest online
> > node and populate a device's 'numa_node' property. The numa_node
> > property allows applications to be migrated "close" to a resource.
> >
> > In preparation for providing a generic facility to optionally map an
> > address range to its closest online node, or the node the range would
> > represent were it to be onlined (target_node), up-level the core of
> > acpi_map_pxm_to_online_node() to a generic mm/numa helper.
> >
> > Cc: Michal Hocko <mhocko@suse.com>
> > Cc: "Rafael J. Wysocki" <rjw@rjwysocki.net>
> > Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> > ---
> >  drivers/acpi/numa.c  |   41 -----------------------------------------
> >  include/linux/acpi.h |   23 ++++++++++++++++++++++-
> >  include/linux/numa.h |    2 ++
> >  mm/mempolicy.c       |   30 ++++++++++++++++++++++++++++++
> >  4 files changed, 54 insertions(+), 42 deletions(-)
> >
> > diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
> > index eadbf90e65d1..47b4969d9b93 100644
> > --- a/drivers/acpi/numa.c
> > +++ b/drivers/acpi/numa.c
> > @@ -72,47 +72,6 @@ int acpi_map_pxm_to_node(int pxm)
> >  }
> >  EXPORT_SYMBOL(acpi_map_pxm_to_node);
> >
> > -/**
> > - * acpi_map_pxm_to_online_node - Map proximity ID to online node
> > - * @pxm: ACPI proximity ID
> > - *
> > - * This is similar to acpi_map_pxm_to_node(), but always returns an online
> > - * node.  When the mapped node from a given proximity ID is offline, it
> > - * looks up the node distance table and returns the nearest online node.
> > - *
> > - * ACPI device drivers, which are called after the NUMA initialization has
> > - * completed in the kernel, can call this interface to obtain their device
> > - * NUMA topology from ACPI tables.  Such drivers do not have to deal with
> > - * offline nodes.  A node may be offline when a device proximity ID is
> > - * unique, SRAT memory entry does not exist, or NUMA is disabled, ex.
> > - * "numa=off" on x86.
> > - */
> > -int acpi_map_pxm_to_online_node(int pxm)
> > -{
> > -     int node, min_node;
> > -
> > -     node = acpi_map_pxm_to_node(pxm);
> > -
> > -     if (node == NUMA_NO_NODE)
> > -             node = 0;
> > -
> > -     min_node = node;
> > -     if (!node_online(node)) {
> > -             int min_dist = INT_MAX, dist, n;
> > -
> > -             for_each_online_node(n) {
> > -                     dist = node_distance(node, n);
> > -                     if (dist < min_dist) {
> > -                             min_dist = dist;
> > -                             min_node = n;
> > -                     }
> > -             }
> > -     }
> > -
> > -     return min_node;
> > -}
> > -EXPORT_SYMBOL(acpi_map_pxm_to_online_node);
> > -
> >  static void __init
> >  acpi_table_print_srat_entry(struct acpi_subtable_header *header)
> >  {
> > diff --git a/include/linux/acpi.h b/include/linux/acpi.h
> > index 8b4e516bac00..aeedd09f2f71 100644
> > --- a/include/linux/acpi.h
> > +++ b/include/linux/acpi.h
> > @@ -401,9 +401,30 @@ extern void acpi_osi_setup(char *str);
> >  extern bool acpi_osi_is_win8(void);
> >
> >  #ifdef CONFIG_ACPI_NUMA
> > -int acpi_map_pxm_to_online_node(int pxm);
> >  int acpi_map_pxm_to_node(int pxm);
> >  int acpi_get_node(acpi_handle handle);
> > +
> > +/**
> > + * acpi_map_pxm_to_online_node - Map proximity ID to online node
> > + * @pxm: ACPI proximity ID
> > + *
> > + * This is similar to acpi_map_pxm_to_node(), but always returns an online
> > + * node.  When the mapped node from a given proximity ID is offline, it
> > + * looks up the node distance table and returns the nearest online node.
> > + *
> > + * ACPI device drivers, which are called after the NUMA initialization has
> > + * completed in the kernel, can call this interface to obtain their device
> > + * NUMA topology from ACPI tables.  Such drivers do not have to deal with
> > + * offline nodes.  A node may be offline when a device proximity ID is
> > + * unique, SRAT memory entry does not exist, or NUMA is disabled, ex.
> > + * "numa=off" on x86.
> > + */
> > +static inline int acpi_map_pxm_to_online_node(int pxm)
> > +{
> > +     int node = acpi_map_pxm_to_node(pxm);
> > +
> > +     return numa_map_to_online_node(node);
> > +}
> >  #else
> >  static inline int acpi_map_pxm_to_online_node(int pxm)
> >  {
> > diff --git a/include/linux/numa.h b/include/linux/numa.h
> > index 110b0e5d0fb0..4fd80f42be43 100644
> > --- a/include/linux/numa.h
> > +++ b/include/linux/numa.h
> > @@ -13,4 +13,6 @@
> >
> >  #define      NUMA_NO_NODE    (-1)
> >
> > +int numa_map_to_online_node(int node);
> > +
> >  #endif /* _LINUX_NUMA_H */
> > diff --git a/mm/mempolicy.c b/mm/mempolicy.c
> > index 4ae967bcf954..e2d8dd21ce9d 100644
> > --- a/mm/mempolicy.c
> > +++ b/mm/mempolicy.c
> > @@ -127,6 +127,36 @@ static struct mempolicy default_policy = {
> >
> >  static struct mempolicy preferred_node_policy[MAX_NUMNODES];
> >
> > +/**
> > + * numa_map_to_online_node - Find closest online node
> > + * @nid: Node id to start the search
> > + *
> > + * Lookup the next closest node by distance if @nid is not online.
> > + */
> > +int numa_map_to_online_node(int node)
> > +{
> > +     int min_node;
> > +
> > +     if (node == NUMA_NO_NODE)
> > +             node = 0;
>
> The ppc64 variant papr_scm_node return the NUMA_NO_NODE in this case.
> Most of the mm helpers can handle with that value . So instead of
> forcing node = 0, let the subsystem decide what to do with the
> NUMA_NO_NODE value.?
>
> > +
> > +     min_node = node;
> > +     if (!node_online(node)) {
> > +             int min_dist = INT_MAX, dist, n;
> > +
> > +             for_each_online_node(n) {
> > +                     dist = node_distance(node, n);
> > +                     if (dist < min_dist) {
> > +                             min_dist = dist;
> > +                             min_node = n;
> > +                     }
> > +             }
> > +     }
> > +
> > +     return min_node;
> > +}
> > +EXPORT_SYMBOL_GPL(numa_map_to_online_node);
> > +
> >  struct mempolicy *get_task_policy(struct task_struct *p)
> >  {
> >       struct mempolicy *pol = p->mempolicy;
>
>
> Can we also switch papr_scm_node to numa_map_to_online_node()?

Sure, I'll take a look.

May I ask for a review of patches 1-12? Should be quick as they're
mostly following the same theme.

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

* Re: [PATCH 04/16] libnvdimm: Move nd_numa_attribute_group to device_type
  2019-11-07  3:56 ` [PATCH 04/16] libnvdimm: Move nd_numa_attribute_group " Dan Williams
@ 2019-11-12  9:22   ` Aneesh Kumar K.V
  2019-11-13  1:26     ` Dan Williams
  0 siblings, 1 reply; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-12  9:22 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm
  Cc: Ira Weiny, Michael Ellerman, Oliver O'Halloran, Vishal Verma,
	peterz, dave.hansen, linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> A 'struct device_type' instance can carry default attributes for the
> device. Use this facility to remove the export of
> nd_numa_attribute_group and put the responsibility on the core rather
> than leaf implementations to define this attribute.
>
> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: "Oliver O'Halloran" <oohall@gmail.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>


can we also expose target_node in a similar way? This allows application
to better understand the node locality of the SCM device.

-aneesh

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

* Re: [PATCH 01/16] libnvdimm: Move attribute groups to device type
  2019-11-07  3:56 ` [PATCH 01/16] libnvdimm: Move attribute groups to device type Dan Williams
@ 2019-11-12 11:28   ` Aneesh Kumar K.V
  0 siblings, 0 replies; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-12 11:28 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm; +Cc: peterz, dave.hansen, linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> Statically initialize the attribute groups for each libnvdimm
> device_type. This is a preparation step for removing unnecessary exports
> of attributes that can be included in the device_type by default.
>
> Also take the opportunity to mark 'struct device_type' instances const.

Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
>
> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  drivers/nvdimm/btt_devs.c       |   24 +++++++-------
>  drivers/nvdimm/dax_devs.c       |   27 ++++++---------
>  drivers/nvdimm/namespace_devs.c |   68 +++++++++++++++++++++------------------
>  drivers/nvdimm/nd.h             |    2 +
>  drivers/nvdimm/pfn_devs.c       |   28 ++++++++--------
>  5 files changed, 73 insertions(+), 76 deletions(-)
>
> diff --git a/drivers/nvdimm/btt_devs.c b/drivers/nvdimm/btt_devs.c
> index 3508a79110c7..05feb97e11ce 100644
> --- a/drivers/nvdimm/btt_devs.c
> +++ b/drivers/nvdimm/btt_devs.c
> @@ -25,17 +25,6 @@ static void nd_btt_release(struct device *dev)
>  	kfree(nd_btt);
>  }
>  
> -static struct device_type nd_btt_device_type = {
> -	.name = "nd_btt",
> -	.release = nd_btt_release,
> -};
> -
> -bool is_nd_btt(struct device *dev)
> -{
> -	return dev->type == &nd_btt_device_type;
> -}
> -EXPORT_SYMBOL(is_nd_btt);
> -
>  struct nd_btt *to_nd_btt(struct device *dev)
>  {
>  	struct nd_btt *nd_btt = container_of(dev, struct nd_btt, dev);
> @@ -178,6 +167,18 @@ static const struct attribute_group *nd_btt_attribute_groups[] = {
>  	NULL,
>  };
>  
> +static const struct device_type nd_btt_device_type = {
> +	.name = "nd_btt",
> +	.release = nd_btt_release,
> +	.groups = nd_btt_attribute_groups,
> +};
> +
> +bool is_nd_btt(struct device *dev)
> +{
> +	return dev->type == &nd_btt_device_type;
> +}
> +EXPORT_SYMBOL(is_nd_btt);
> +
>  static struct device *__nd_btt_create(struct nd_region *nd_region,
>  		unsigned long lbasize, u8 *uuid,
>  		struct nd_namespace_common *ndns)
> @@ -204,7 +205,6 @@ static struct device *__nd_btt_create(struct nd_region *nd_region,
>  	dev_set_name(dev, "btt%d.%d", nd_region->id, nd_btt->id);
>  	dev->parent = &nd_region->dev;
>  	dev->type = &nd_btt_device_type;
> -	dev->groups = nd_btt_attribute_groups;
>  	device_initialize(&nd_btt->dev);
>  	if (ndns && !__nd_attach_ndns(&nd_btt->dev, ndns, &nd_btt->ndns)) {
>  		dev_dbg(&ndns->dev, "failed, already claimed by %s\n",
> diff --git a/drivers/nvdimm/dax_devs.c b/drivers/nvdimm/dax_devs.c
> index 6d22b0f83b3b..99965077bac4 100644
> --- a/drivers/nvdimm/dax_devs.c
> +++ b/drivers/nvdimm/dax_devs.c
> @@ -23,17 +23,6 @@ static void nd_dax_release(struct device *dev)
>  	kfree(nd_dax);
>  }
>  
> -static struct device_type nd_dax_device_type = {
> -	.name = "nd_dax",
> -	.release = nd_dax_release,
> -};
> -
> -bool is_nd_dax(struct device *dev)
> -{
> -	return dev ? dev->type == &nd_dax_device_type : false;
> -}
> -EXPORT_SYMBOL(is_nd_dax);
> -
>  struct nd_dax *to_nd_dax(struct device *dev)
>  {
>  	struct nd_dax *nd_dax = container_of(dev, struct nd_dax, nd_pfn.dev);
> @@ -43,13 +32,18 @@ struct nd_dax *to_nd_dax(struct device *dev)
>  }
>  EXPORT_SYMBOL(to_nd_dax);
>  
> -static const struct attribute_group *nd_dax_attribute_groups[] = {
> -	&nd_pfn_attribute_group,
> -	&nd_device_attribute_group,
> -	&nd_numa_attribute_group,
> -	NULL,
> +static const struct device_type nd_dax_device_type = {
> +	.name = "nd_dax",
> +	.release = nd_dax_release,
> +	.groups = nd_pfn_attribute_groups,
>  };
>  
> +bool is_nd_dax(struct device *dev)
> +{
> +	return dev ? dev->type == &nd_dax_device_type : false;
> +}
> +EXPORT_SYMBOL(is_nd_dax);
> +
>  static struct nd_dax *nd_dax_alloc(struct nd_region *nd_region)
>  {
>  	struct nd_pfn *nd_pfn;
> @@ -69,7 +63,6 @@ static struct nd_dax *nd_dax_alloc(struct nd_region *nd_region)
>  
>  	dev = &nd_pfn->dev;
>  	dev_set_name(dev, "dax%d.%d", nd_region->id, nd_pfn->id);
> -	dev->groups = nd_dax_attribute_groups;
>  	dev->type = &nd_dax_device_type;
>  	dev->parent = &nd_region->dev;
>  
> diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
> index cca0a3ba1d2c..37471a272c1a 100644
> --- a/drivers/nvdimm/namespace_devs.c
> +++ b/drivers/nvdimm/namespace_devs.c
> @@ -44,35 +44,9 @@ static void namespace_blk_release(struct device *dev)
>  	kfree(nsblk);
>  }
>  
> -static const struct device_type namespace_io_device_type = {
> -	.name = "nd_namespace_io",
> -	.release = namespace_io_release,
> -};
> -
> -static const struct device_type namespace_pmem_device_type = {
> -	.name = "nd_namespace_pmem",
> -	.release = namespace_pmem_release,
> -};
> -
> -static const struct device_type namespace_blk_device_type = {
> -	.name = "nd_namespace_blk",
> -	.release = namespace_blk_release,
> -};
> -
> -static bool is_namespace_pmem(const struct device *dev)
> -{
> -	return dev ? dev->type == &namespace_pmem_device_type : false;
> -}
> -
> -static bool is_namespace_blk(const struct device *dev)
> -{
> -	return dev ? dev->type == &namespace_blk_device_type : false;
> -}
> -
> -static bool is_namespace_io(const struct device *dev)
> -{
> -	return dev ? dev->type == &namespace_io_device_type : false;
> -}
> +static bool is_namespace_pmem(const struct device *dev);
> +static bool is_namespace_blk(const struct device *dev);
> +static bool is_namespace_io(const struct device *dev);
>  
>  static int is_uuid_busy(struct device *dev, void *data)
>  {
> @@ -1680,6 +1654,39 @@ static const struct attribute_group *nd_namespace_attribute_groups[] = {
>  	NULL,
>  };
>  
> +static const struct device_type namespace_io_device_type = {
> +	.name = "nd_namespace_io",
> +	.release = namespace_io_release,
> +	.groups = nd_namespace_attribute_groups,
> +};
> +
> +static const struct device_type namespace_pmem_device_type = {
> +	.name = "nd_namespace_pmem",
> +	.release = namespace_pmem_release,
> +	.groups = nd_namespace_attribute_groups,
> +};
> +
> +static const struct device_type namespace_blk_device_type = {
> +	.name = "nd_namespace_blk",
> +	.release = namespace_blk_release,
> +	.groups = nd_namespace_attribute_groups,
> +};
> +
> +static bool is_namespace_pmem(const struct device *dev)
> +{
> +	return dev ? dev->type == &namespace_pmem_device_type : false;
> +}
> +
> +static bool is_namespace_blk(const struct device *dev)
> +{
> +	return dev ? dev->type == &namespace_blk_device_type : false;
> +}
> +
> +static bool is_namespace_io(const struct device *dev)
> +{
> +	return dev ? dev->type == &namespace_io_device_type : false;
> +}
> +
>  struct nd_namespace_common *nvdimm_namespace_common_probe(struct device *dev)
>  {
>  	struct nd_btt *nd_btt = is_nd_btt(dev) ? to_nd_btt(dev) : NULL;
> @@ -2078,7 +2085,6 @@ static struct device *nd_namespace_blk_create(struct nd_region *nd_region)
>  	}
>  	dev_set_name(dev, "namespace%d.%d", nd_region->id, nsblk->id);
>  	dev->parent = &nd_region->dev;
> -	dev->groups = nd_namespace_attribute_groups;
>  
>  	return &nsblk->common.dev;
>  }
> @@ -2109,7 +2115,6 @@ static struct device *nd_namespace_pmem_create(struct nd_region *nd_region)
>  		return NULL;
>  	}
>  	dev_set_name(dev, "namespace%d.%d", nd_region->id, nspm->id);
> -	dev->groups = nd_namespace_attribute_groups;
>  	nd_namespace_pmem_set_resource(nd_region, nspm, 0);
>  
>  	return dev;
> @@ -2608,7 +2613,6 @@ int nd_region_register_namespaces(struct nd_region *nd_region, int *err)
>  		if (id < 0)
>  			break;
>  		dev_set_name(dev, "namespace%d.%d", nd_region->id, id);
> -		dev->groups = nd_namespace_attribute_groups;
>  		nd_device_register(dev);
>  	}
>  	if (i)
> diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
> index ee5c04070ef9..5c8b077b3237 100644
> --- a/drivers/nvdimm/nd.h
> +++ b/drivers/nvdimm/nd.h
> @@ -297,7 +297,7 @@ struct device *nd_pfn_create(struct nd_region *nd_region);
>  struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn,
>  		struct nd_namespace_common *ndns);
>  int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig);
> -extern struct attribute_group nd_pfn_attribute_group;
> +extern const struct attribute_group *nd_pfn_attribute_groups[];
>  #else
>  static inline int nd_pfn_probe(struct device *dev,
>  		struct nd_namespace_common *ndns)
> diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
> index 60d81fae06ee..e809961e2b6f 100644
> --- a/drivers/nvdimm/pfn_devs.c
> +++ b/drivers/nvdimm/pfn_devs.c
> @@ -26,17 +26,6 @@ static void nd_pfn_release(struct device *dev)
>  	kfree(nd_pfn);
>  }
>  
> -static struct device_type nd_pfn_device_type = {
> -	.name = "nd_pfn",
> -	.release = nd_pfn_release,
> -};
> -
> -bool is_nd_pfn(struct device *dev)
> -{
> -	return dev ? dev->type == &nd_pfn_device_type : false;
> -}
> -EXPORT_SYMBOL(is_nd_pfn);
> -
>  struct nd_pfn *to_nd_pfn(struct device *dev)
>  {
>  	struct nd_pfn *nd_pfn = container_of(dev, struct nd_pfn, dev);
> @@ -287,18 +276,30 @@ static umode_t pfn_visible(struct kobject *kobj, struct attribute *a, int n)
>  	return a->mode;
>  }
>  
> -struct attribute_group nd_pfn_attribute_group = {
> +static struct attribute_group nd_pfn_attribute_group = {
>  	.attrs = nd_pfn_attributes,
>  	.is_visible = pfn_visible,
>  };
>  
> -static const struct attribute_group *nd_pfn_attribute_groups[] = {
> +const struct attribute_group *nd_pfn_attribute_groups[] = {
>  	&nd_pfn_attribute_group,
>  	&nd_device_attribute_group,
>  	&nd_numa_attribute_group,
>  	NULL,
>  };
>  
> +static const struct device_type nd_pfn_device_type = {
> +	.name = "nd_pfn",
> +	.release = nd_pfn_release,
> +	.groups = nd_pfn_attribute_groups,
> +};
> +
> +bool is_nd_pfn(struct device *dev)
> +{
> +	return dev ? dev->type == &nd_pfn_device_type : false;
> +}
> +EXPORT_SYMBOL(is_nd_pfn);
> +
>  struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn,
>  		struct nd_namespace_common *ndns)
>  {
> @@ -337,7 +338,6 @@ static struct nd_pfn *nd_pfn_alloc(struct nd_region *nd_region)
>  
>  	dev = &nd_pfn->dev;
>  	dev_set_name(dev, "pfn%d.%d", nd_region->id, nd_pfn->id);
> -	dev->groups = nd_pfn_attribute_groups;
>  	dev->type = &nd_pfn_device_type;
>  	dev->parent = &nd_region->dev;
>  
> _______________________________________________
> Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
> To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

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

* Re: [PATCH 02/16] libnvdimm: Move region attribute group definition
  2019-11-07  3:56 ` [PATCH 02/16] libnvdimm: Move region attribute group definition Dan Williams
@ 2019-11-12 11:29   ` Aneesh Kumar K.V
  0 siblings, 0 replies; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-12 11:29 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm; +Cc: peterz, dave.hansen, linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> In preparation for moving region attributes from device attribute groups
> to the region device-type, reorder the declaration so that it can be
> referenced by the device-type definition without forward declarations.
> No functional changes are intended to result from this change.
>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>

> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  drivers/nvdimm/region_devs.c |  208 +++++++++++++++++++++---------------------
>  1 file changed, 104 insertions(+), 104 deletions(-)
>
> diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
> index ef423ba1a711..e89f2eb3678c 100644
> --- a/drivers/nvdimm/region_devs.c
> +++ b/drivers/nvdimm/region_devs.c
> @@ -140,36 +140,6 @@ static void nd_region_release(struct device *dev)
>  		kfree(nd_region);
>  }
>  
> -static struct device_type nd_blk_device_type = {
> -	.name = "nd_blk",
> -	.release = nd_region_release,
> -};
> -
> -static struct device_type nd_pmem_device_type = {
> -	.name = "nd_pmem",
> -	.release = nd_region_release,
> -};
> -
> -static struct device_type nd_volatile_device_type = {
> -	.name = "nd_volatile",
> -	.release = nd_region_release,
> -};
> -
> -bool is_nd_pmem(struct device *dev)
> -{
> -	return dev ? dev->type == &nd_pmem_device_type : false;
> -}
> -
> -bool is_nd_blk(struct device *dev)
> -{
> -	return dev ? dev->type == &nd_blk_device_type : false;
> -}
> -
> -bool is_nd_volatile(struct device *dev)
> -{
> -	return dev ? dev->type == &nd_volatile_device_type : false;
> -}
> -
>  struct nd_region *to_nd_region(struct device *dev)
>  {
>  	struct nd_region *nd_region = container_of(dev, struct nd_region, dev);
> @@ -674,80 +644,6 @@ static umode_t region_visible(struct kobject *kobj, struct attribute *a, int n)
>  	return 0;
>  }
>  
> -struct attribute_group nd_region_attribute_group = {
> -	.attrs = nd_region_attributes,
> -	.is_visible = region_visible,
> -};
> -EXPORT_SYMBOL_GPL(nd_region_attribute_group);
> -
> -u64 nd_region_interleave_set_cookie(struct nd_region *nd_region,
> -		struct nd_namespace_index *nsindex)
> -{
> -	struct nd_interleave_set *nd_set = nd_region->nd_set;
> -
> -	if (!nd_set)
> -		return 0;
> -
> -	if (nsindex && __le16_to_cpu(nsindex->major) == 1
> -			&& __le16_to_cpu(nsindex->minor) == 1)
> -		return nd_set->cookie1;
> -	return nd_set->cookie2;
> -}
> -
> -u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region)
> -{
> -	struct nd_interleave_set *nd_set = nd_region->nd_set;
> -
> -	if (nd_set)
> -		return nd_set->altcookie;
> -	return 0;
> -}
> -
> -void nd_mapping_free_labels(struct nd_mapping *nd_mapping)
> -{
> -	struct nd_label_ent *label_ent, *e;
> -
> -	lockdep_assert_held(&nd_mapping->lock);
> -	list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) {
> -		list_del(&label_ent->list);
> -		kfree(label_ent);
> -	}
> -}
> -
> -/*
> - * When a namespace is activated create new seeds for the next
> - * namespace, or namespace-personality to be configured.
> - */
> -void nd_region_advance_seeds(struct nd_region *nd_region, struct device *dev)
> -{
> -	nvdimm_bus_lock(dev);
> -	if (nd_region->ns_seed == dev) {
> -		nd_region_create_ns_seed(nd_region);
> -	} else if (is_nd_btt(dev)) {
> -		struct nd_btt *nd_btt = to_nd_btt(dev);
> -
> -		if (nd_region->btt_seed == dev)
> -			nd_region_create_btt_seed(nd_region);
> -		if (nd_region->ns_seed == &nd_btt->ndns->dev)
> -			nd_region_create_ns_seed(nd_region);
> -	} else if (is_nd_pfn(dev)) {
> -		struct nd_pfn *nd_pfn = to_nd_pfn(dev);
> -
> -		if (nd_region->pfn_seed == dev)
> -			nd_region_create_pfn_seed(nd_region);
> -		if (nd_region->ns_seed == &nd_pfn->ndns->dev)
> -			nd_region_create_ns_seed(nd_region);
> -	} else if (is_nd_dax(dev)) {
> -		struct nd_dax *nd_dax = to_nd_dax(dev);
> -
> -		if (nd_region->dax_seed == dev)
> -			nd_region_create_dax_seed(nd_region);
> -		if (nd_region->ns_seed == &nd_dax->nd_pfn.ndns->dev)
> -			nd_region_create_ns_seed(nd_region);
> -	}
> -	nvdimm_bus_unlock(dev);
> -}
> -
>  static ssize_t mappingN(struct device *dev, char *buf, int n)
>  {
>  	struct nd_region *nd_region = to_nd_region(dev);
> @@ -861,6 +757,110 @@ struct attribute_group nd_mapping_attribute_group = {
>  };
>  EXPORT_SYMBOL_GPL(nd_mapping_attribute_group);
>  
> +struct attribute_group nd_region_attribute_group = {
> +	.attrs = nd_region_attributes,
> +	.is_visible = region_visible,
> +};
> +EXPORT_SYMBOL_GPL(nd_region_attribute_group);
> +
> +static struct device_type nd_blk_device_type = {
> +	.name = "nd_blk",
> +	.release = nd_region_release,
> +};
> +
> +static struct device_type nd_pmem_device_type = {
> +	.name = "nd_pmem",
> +	.release = nd_region_release,
> +};
> +
> +static struct device_type nd_volatile_device_type = {
> +	.name = "nd_volatile",
> +	.release = nd_region_release,
> +};
> +
> +bool is_nd_pmem(struct device *dev)
> +{
> +	return dev ? dev->type == &nd_pmem_device_type : false;
> +}
> +
> +bool is_nd_blk(struct device *dev)
> +{
> +	return dev ? dev->type == &nd_blk_device_type : false;
> +}
> +
> +bool is_nd_volatile(struct device *dev)
> +{
> +	return dev ? dev->type == &nd_volatile_device_type : false;
> +}
> +
> +u64 nd_region_interleave_set_cookie(struct nd_region *nd_region,
> +		struct nd_namespace_index *nsindex)
> +{
> +	struct nd_interleave_set *nd_set = nd_region->nd_set;
> +
> +	if (!nd_set)
> +		return 0;
> +
> +	if (nsindex && __le16_to_cpu(nsindex->major) == 1
> +			&& __le16_to_cpu(nsindex->minor) == 1)
> +		return nd_set->cookie1;
> +	return nd_set->cookie2;
> +}
> +
> +u64 nd_region_interleave_set_altcookie(struct nd_region *nd_region)
> +{
> +	struct nd_interleave_set *nd_set = nd_region->nd_set;
> +
> +	if (nd_set)
> +		return nd_set->altcookie;
> +	return 0;
> +}
> +
> +void nd_mapping_free_labels(struct nd_mapping *nd_mapping)
> +{
> +	struct nd_label_ent *label_ent, *e;
> +
> +	lockdep_assert_held(&nd_mapping->lock);
> +	list_for_each_entry_safe(label_ent, e, &nd_mapping->labels, list) {
> +		list_del(&label_ent->list);
> +		kfree(label_ent);
> +	}
> +}
> +
> +/*
> + * When a namespace is activated create new seeds for the next
> + * namespace, or namespace-personality to be configured.
> + */
> +void nd_region_advance_seeds(struct nd_region *nd_region, struct device *dev)
> +{
> +	nvdimm_bus_lock(dev);
> +	if (nd_region->ns_seed == dev) {
> +		nd_region_create_ns_seed(nd_region);
> +	} else if (is_nd_btt(dev)) {
> +		struct nd_btt *nd_btt = to_nd_btt(dev);
> +
> +		if (nd_region->btt_seed == dev)
> +			nd_region_create_btt_seed(nd_region);
> +		if (nd_region->ns_seed == &nd_btt->ndns->dev)
> +			nd_region_create_ns_seed(nd_region);
> +	} else if (is_nd_pfn(dev)) {
> +		struct nd_pfn *nd_pfn = to_nd_pfn(dev);
> +
> +		if (nd_region->pfn_seed == dev)
> +			nd_region_create_pfn_seed(nd_region);
> +		if (nd_region->ns_seed == &nd_pfn->ndns->dev)
> +			nd_region_create_ns_seed(nd_region);
> +	} else if (is_nd_dax(dev)) {
> +		struct nd_dax *nd_dax = to_nd_dax(dev);
> +
> +		if (nd_region->dax_seed == dev)
> +			nd_region_create_dax_seed(nd_region);
> +		if (nd_region->ns_seed == &nd_dax->nd_pfn.ndns->dev)
> +			nd_region_create_ns_seed(nd_region);
> +	}
> +	nvdimm_bus_unlock(dev);
> +}
> +
>  int nd_blk_region_init(struct nd_region *nd_region)
>  {
>  	struct device *dev = &nd_region->dev;
> _______________________________________________
> Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
> To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

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

* Re: [PATCH 03/16] libnvdimm: Move nd_device_attribute_group to device_type
  2019-11-07  3:56 ` [PATCH 03/16] libnvdimm: Move nd_device_attribute_group to device_type Dan Williams
@ 2019-11-12 11:30   ` Aneesh Kumar K.V
  0 siblings, 0 replies; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-12 11:30 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm
  Cc: Michael Ellerman, peterz, dave.hansen, linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> A 'struct device_type' instance can carry default attributes for the
> device. Use this facility to remove the export of
> nd_device_attribute_group and put the responsibility on the core rather
> than leaf implementations to define this attribute.
>
> For regions this creates a new nd_region_attribute_groups[] added to the
> per-region device-type instances.
>

Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>

> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: "Oliver O'Halloran" <oohall@gmail.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  arch/powerpc/platforms/pseries/papr_scm.c |    2 --
>  drivers/acpi/nfit/core.c                  |    2 --
>  drivers/nvdimm/bus.c                      |    3 +--
>  drivers/nvdimm/dimm_devs.c                |    8 +++++++-
>  drivers/nvdimm/e820.c                     |    1 -
>  drivers/nvdimm/nd.h                       |    1 +
>  drivers/nvdimm/of_pmem.c                  |    1 -
>  drivers/nvdimm/region_devs.c              |   18 +++++++++++++-----
>  include/linux/libnvdimm.h                 |    1 -
>  9 files changed, 22 insertions(+), 15 deletions(-)
>
> diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
> index 61883291defc..04726f8fd189 100644
> --- a/arch/powerpc/platforms/pseries/papr_scm.c
> +++ b/arch/powerpc/platforms/pseries/papr_scm.c
> @@ -286,7 +286,6 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
>  
>  static const struct attribute_group *region_attr_groups[] = {
>  	&nd_region_attribute_group,
> -	&nd_device_attribute_group,
>  	&nd_mapping_attribute_group,
>  	&nd_numa_attribute_group,
>  	NULL,
> @@ -299,7 +298,6 @@ static const struct attribute_group *bus_attr_groups[] = {
>  
>  static const struct attribute_group *papr_scm_dimm_groups[] = {
>  	&nvdimm_attribute_group,
> -	&nd_device_attribute_group,
>  	NULL,
>  };
>  
> diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
> index 14e68f202f81..dec7c2b08672 100644
> --- a/drivers/acpi/nfit/core.c
> +++ b/drivers/acpi/nfit/core.c
> @@ -1699,7 +1699,6 @@ static const struct attribute_group acpi_nfit_dimm_attribute_group = {
>  
>  static const struct attribute_group *acpi_nfit_dimm_attribute_groups[] = {
>  	&nvdimm_attribute_group,
> -	&nd_device_attribute_group,
>  	&acpi_nfit_dimm_attribute_group,
>  	NULL,
>  };
> @@ -2199,7 +2198,6 @@ static const struct attribute_group acpi_nfit_region_attribute_group = {
>  static const struct attribute_group *acpi_nfit_region_attribute_groups[] = {
>  	&nd_region_attribute_group,
>  	&nd_mapping_attribute_group,
> -	&nd_device_attribute_group,
>  	&nd_numa_attribute_group,
>  	&acpi_nfit_region_attribute_group,
>  	NULL,
> diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
> index d47412dcdf38..eb422527dd57 100644
> --- a/drivers/nvdimm/bus.c
> +++ b/drivers/nvdimm/bus.c
> @@ -669,10 +669,9 @@ static struct attribute *nd_device_attributes[] = {
>  /*
>   * nd_device_attribute_group - generic attributes for all devices on an nd bus
>   */
> -struct attribute_group nd_device_attribute_group = {
> +const struct attribute_group nd_device_attribute_group = {
>  	.attrs = nd_device_attributes,
>  };
> -EXPORT_SYMBOL_GPL(nd_device_attribute_group);
>  
>  static ssize_t numa_node_show(struct device *dev,
>  		struct device_attribute *attr, char *buf)
> diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
> index 196aa44c4936..278867c68682 100644
> --- a/drivers/nvdimm/dimm_devs.c
> +++ b/drivers/nvdimm/dimm_devs.c
> @@ -202,9 +202,15 @@ static void nvdimm_release(struct device *dev)
>  	kfree(nvdimm);
>  }
>  
> -static struct device_type nvdimm_device_type = {
> +static const struct attribute_group *nvdimm_attribute_groups[] = {
> +	&nd_device_attribute_group,
> +	NULL,
> +};
> +
> +static const struct device_type nvdimm_device_type = {
>  	.name = "nvdimm",
>  	.release = nvdimm_release,
> +	.groups = nvdimm_attribute_groups,
>  };
>  
>  bool is_nvdimm(struct device *dev)
> diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c
> index 87f72f725e4f..adde2864c6a4 100644
> --- a/drivers/nvdimm/e820.c
> +++ b/drivers/nvdimm/e820.c
> @@ -15,7 +15,6 @@ static const struct attribute_group *e820_pmem_attribute_groups[] = {
>  
>  static const struct attribute_group *e820_pmem_region_attribute_groups[] = {
>  	&nd_region_attribute_group,
> -	&nd_device_attribute_group,
>  	NULL,
>  };
>  
> diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
> index 5c8b077b3237..3f509bb6b5c0 100644
> --- a/drivers/nvdimm/nd.h
> +++ b/drivers/nvdimm/nd.h
> @@ -298,6 +298,7 @@ struct device *nd_pfn_devinit(struct nd_pfn *nd_pfn,
>  		struct nd_namespace_common *ndns);
>  int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig);
>  extern const struct attribute_group *nd_pfn_attribute_groups[];
> +extern const struct attribute_group nd_device_attribute_group;
>  #else
>  static inline int nd_pfn_probe(struct device *dev,
>  		struct nd_namespace_common *ndns)
> diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
> index 97187d6c0bdb..41348fa6b74c 100644
> --- a/drivers/nvdimm/of_pmem.c
> +++ b/drivers/nvdimm/of_pmem.c
> @@ -11,7 +11,6 @@
>  
>  static const struct attribute_group *region_attr_groups[] = {
>  	&nd_region_attribute_group,
> -	&nd_device_attribute_group,
>  	NULL,
>  };
>  
> diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
> index e89f2eb3678c..710b5111eaa8 100644
> --- a/drivers/nvdimm/region_devs.c
> +++ b/drivers/nvdimm/region_devs.c
> @@ -763,19 +763,27 @@ struct attribute_group nd_region_attribute_group = {
>  };
>  EXPORT_SYMBOL_GPL(nd_region_attribute_group);
>  
> -static struct device_type nd_blk_device_type = {
> +static const struct attribute_group *nd_region_attribute_groups[] = {
> +	&nd_device_attribute_group,
> +	NULL,
> +};
> +
> +static const struct device_type nd_blk_device_type = {
>  	.name = "nd_blk",
>  	.release = nd_region_release,
> +	.groups = nd_region_attribute_groups,
>  };
>  
> -static struct device_type nd_pmem_device_type = {
> +static const struct device_type nd_pmem_device_type = {
>  	.name = "nd_pmem",
>  	.release = nd_region_release,
> +	.groups = nd_region_attribute_groups,
>  };
>  
> -static struct device_type nd_volatile_device_type = {
> +static const struct device_type nd_volatile_device_type = {
>  	.name = "nd_volatile",
>  	.release = nd_region_release,
> +	.groups = nd_region_attribute_groups,
>  };
>  
>  bool is_nd_pmem(struct device *dev)
> @@ -931,8 +939,8 @@ void nd_region_release_lane(struct nd_region *nd_region, unsigned int lane)
>  EXPORT_SYMBOL(nd_region_release_lane);
>  
>  static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
> -		struct nd_region_desc *ndr_desc, struct device_type *dev_type,
> -		const char *caller)
> +		struct nd_region_desc *ndr_desc,
> +		const struct device_type *dev_type, const char *caller)
>  {
>  	struct nd_region *nd_region;
>  	struct device *dev;
> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
> index b6eddf912568..d7dbf42498af 100644
> --- a/include/linux/libnvdimm.h
> +++ b/include/linux/libnvdimm.h
> @@ -67,7 +67,6 @@ enum {
>  
>  extern struct attribute_group nvdimm_bus_attribute_group;
>  extern struct attribute_group nvdimm_attribute_group;
> -extern struct attribute_group nd_device_attribute_group;
>  extern struct attribute_group nd_numa_attribute_group;
>  extern struct attribute_group nd_region_attribute_group;
>  extern struct attribute_group nd_mapping_attribute_group;
> _______________________________________________
> Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
> To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

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

* Re: [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory
  2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
                   ` (15 preceding siblings ...)
  2019-11-07  3:58 ` [PATCH 16/16] libnvdimm/e820: Retrieve and populate correct 'target_node' info Dan Williams
@ 2019-11-12 11:42 ` Aneesh Kumar K.V
  2019-11-12 19:37   ` Dan Williams
  16 siblings, 1 reply; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-12 11:42 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm
  Cc: David Hildenbrand, Peter Zijlstra, Borislav Petkov,
	Michael Ellerman, H. Peter Anvin, x86, Thomas Gleixner,
	Dave Hansen, Andrew Morton, Ingo Molnar, Michal Hocko,
	Rafael J. Wysocki, Andy Lutomirski, linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> Yes, this patch series looks like a pile of boring libnvdimm cleanups,
> but buried at the end are some small gems that testing with libnvdimm
> uncovered. These gems will prove more valuable over time for Memory
> Hierarchy management as more platforms, via the ACPI HMAT and EFI
> Specific Purpose Memory, publish reserved or "soft-reserved" ranges to
> Linux. Linux system administrators will expect to be able to interact
> with those ranges with a unique numa node number when/if that memory is
> onlined via the dax_kmem driver [1].
>
> One configuration that currently fails to properly convey the target
> node for the resulting memory hotplug operation is persistent memory
> defined by the memmap=nn!ss parameter. For example, today if node1 is a
> memory only node, and all the memory from node1 is specified to
> memmap=nn!ss and subsequently onlined, it will end up being onlined as
> node0 memory. As it stands, memory_add_physaddr_to_nid() can only
> identify online nodes and since node1 in this example has no online cpus
> / memory the target node is initialized node0.
>
> The fix is to preserve rather than discard the numa_meminfo entries that
> are relevant for reserved memory ranges, and to uplevel the node
> distance helper for determining the "local" (closest) node relative to
> an initiator node.
>
> The first 12 patches are cleanups to make sure that all nvdimm devices
> and their children properly export a numa_node attribute. The switch to
> a device-type is less code and less error prone as a result.


Will this still allow leaf driver to have platform specific attribute
exposed via sysfs? Or do we want to still keep them in nvdimm core and
control the visibility via is_visible() callback?

-aneesh

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

* Re: [PATCH 05/16] libnvdimm: Move nd_region_attribute_group to device_type
  2019-11-07  3:57 ` [PATCH 05/16] libnvdimm: Move nd_region_attribute_group " Dan Williams
@ 2019-11-12 11:45   ` Aneesh Kumar K.V
  0 siblings, 0 replies; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-12 11:45 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm
  Cc: Ira Weiny, Michael Ellerman, Oliver O'Halloran, Vishal Verma,
	peterz, dave.hansen, linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> A 'struct device_type' instance can carry default attributes for the
> device. Use this facility to remove the export of
> nd_region_attribute_group and put the responsibility on the core rather
> than leaf implementations to define this attribute.
>

Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>

> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: "Oliver O'Halloran" <oohall@gmail.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  arch/powerpc/platforms/pseries/papr_scm.c |    1 -
>  drivers/acpi/nfit/core.c                  |    1 -
>  drivers/nvdimm/e820.c                     |    6 ------
>  drivers/nvdimm/of_pmem.c                  |    6 ------
>  drivers/nvdimm/region_devs.c              |    4 ++--
>  include/linux/libnvdimm.h                 |    1 -
>  6 files changed, 2 insertions(+), 17 deletions(-)
>
> diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
> index 6ffda03a6349..6428834d7cd5 100644
> --- a/arch/powerpc/platforms/pseries/papr_scm.c
> +++ b/arch/powerpc/platforms/pseries/papr_scm.c
> @@ -285,7 +285,6 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
>  }
>  
>  static const struct attribute_group *region_attr_groups[] = {
> -	&nd_region_attribute_group,
>  	&nd_mapping_attribute_group,
>  	NULL,
>  };
> diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
> index b3213faf37b5..99e20b8b6ea0 100644
> --- a/drivers/acpi/nfit/core.c
> +++ b/drivers/acpi/nfit/core.c
> @@ -2196,7 +2196,6 @@ static const struct attribute_group acpi_nfit_region_attribute_group = {
>  };
>  
>  static const struct attribute_group *acpi_nfit_region_attribute_groups[] = {
> -	&nd_region_attribute_group,
>  	&nd_mapping_attribute_group,
>  	&acpi_nfit_region_attribute_group,
>  	NULL,
> diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c
> index adde2864c6a4..9a971a59dec7 100644
> --- a/drivers/nvdimm/e820.c
> +++ b/drivers/nvdimm/e820.c
> @@ -13,11 +13,6 @@ static const struct attribute_group *e820_pmem_attribute_groups[] = {
>  	NULL,
>  };
>  
> -static const struct attribute_group *e820_pmem_region_attribute_groups[] = {
> -	&nd_region_attribute_group,
> -	NULL,
> -};
> -
>  static int e820_pmem_remove(struct platform_device *pdev)
>  {
>  	struct nvdimm_bus *nvdimm_bus = platform_get_drvdata(pdev);
> @@ -45,7 +40,6 @@ static int e820_register_one(struct resource *res, void *data)
>  
>  	memset(&ndr_desc, 0, sizeof(ndr_desc));
>  	ndr_desc.res = res;
> -	ndr_desc.attr_groups = e820_pmem_region_attribute_groups;
>  	ndr_desc.numa_node = e820_range_to_nid(res->start);
>  	ndr_desc.target_node = ndr_desc.numa_node;
>  	set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
> diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
> index 41348fa6b74c..c0b5ac36df9d 100644
> --- a/drivers/nvdimm/of_pmem.c
> +++ b/drivers/nvdimm/of_pmem.c
> @@ -9,11 +9,6 @@
>  #include <linux/ioport.h>
>  #include <linux/slab.h>
>  
> -static const struct attribute_group *region_attr_groups[] = {
> -	&nd_region_attribute_group,
> -	NULL,
> -};
> -
>  static const struct attribute_group *bus_attr_groups[] = {
>  	&nvdimm_bus_attribute_group,
>  	NULL,
> @@ -65,7 +60,6 @@ static int of_pmem_region_probe(struct platform_device *pdev)
>  		 * structures so passing a stack pointer is fine.
>  		 */
>  		memset(&ndr_desc, 0, sizeof(ndr_desc));
> -		ndr_desc.attr_groups = region_attr_groups;
>  		ndr_desc.numa_node = dev_to_node(&pdev->dev);
>  		ndr_desc.target_node = ndr_desc.numa_node;
>  		ndr_desc.res = &pdev->resource[i];
> diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
> index e4281f806adc..f97166583294 100644
> --- a/drivers/nvdimm/region_devs.c
> +++ b/drivers/nvdimm/region_devs.c
> @@ -757,14 +757,14 @@ struct attribute_group nd_mapping_attribute_group = {
>  };
>  EXPORT_SYMBOL_GPL(nd_mapping_attribute_group);
>  
> -struct attribute_group nd_region_attribute_group = {
> +static const struct attribute_group nd_region_attribute_group = {
>  	.attrs = nd_region_attributes,
>  	.is_visible = region_visible,
>  };
> -EXPORT_SYMBOL_GPL(nd_region_attribute_group);
>  
>  static const struct attribute_group *nd_region_attribute_groups[] = {
>  	&nd_device_attribute_group,
> +	&nd_region_attribute_group,
>  	&nd_numa_attribute_group,
>  	NULL,
>  };
> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
> index e9a4e25fc708..312248d334c7 100644
> --- a/include/linux/libnvdimm.h
> +++ b/include/linux/libnvdimm.h
> @@ -67,7 +67,6 @@ enum {
>  
>  extern struct attribute_group nvdimm_bus_attribute_group;
>  extern struct attribute_group nvdimm_attribute_group;
> -extern struct attribute_group nd_region_attribute_group;
>  extern struct attribute_group nd_mapping_attribute_group;
>  
>  struct nvdimm;

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

* Re: [PATCH 06/16] libnvdimm: Move nd_mapping_attribute_group to device_type
  2019-11-07  3:57 ` [PATCH 06/16] libnvdimm: Move nd_mapping_attribute_group " Dan Williams
@ 2019-11-12 11:45   ` Aneesh Kumar K.V
  0 siblings, 0 replies; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-12 11:45 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm
  Cc: Michael Ellerman, peterz, dave.hansen, linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> A 'struct device_type' instance can carry default attributes for the
> device. Use this facility to remove the export of
> nd_mapping_attribute_group and put the responsibility on the core rather
> than leaf implementations to define this attribute.
>

Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>

> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: "Oliver O'Halloran" <oohall@gmail.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  arch/powerpc/platforms/pseries/papr_scm.c |    6 ------
>  drivers/acpi/nfit/core.c                  |    1 -
>  drivers/nvdimm/region_devs.c              |    4 ++--
>  include/linux/libnvdimm.h                 |    1 -
>  4 files changed, 2 insertions(+), 10 deletions(-)
>
> diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
> index 6428834d7cd5..0405fb769336 100644
> --- a/arch/powerpc/platforms/pseries/papr_scm.c
> +++ b/arch/powerpc/platforms/pseries/papr_scm.c
> @@ -284,11 +284,6 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
>  	return 0;
>  }
>  
> -static const struct attribute_group *region_attr_groups[] = {
> -	&nd_mapping_attribute_group,
> -	NULL,
> -};
> -
>  static const struct attribute_group *bus_attr_groups[] = {
>  	&nvdimm_bus_attribute_group,
>  	NULL,
> @@ -362,7 +357,6 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
>  	mapping.size = p->blocks * p->block_size; // XXX: potential overflow?
>  
>  	memset(&ndr_desc, 0, sizeof(ndr_desc));
> -	ndr_desc.attr_groups = region_attr_groups;
>  	target_nid = dev_to_node(&p->pdev->dev);
>  	online_nid = papr_scm_node(target_nid);
>  	ndr_desc.numa_node = online_nid;
> diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
> index 99e20b8b6ea0..69c406ecc3a6 100644
> --- a/drivers/acpi/nfit/core.c
> +++ b/drivers/acpi/nfit/core.c
> @@ -2196,7 +2196,6 @@ static const struct attribute_group acpi_nfit_region_attribute_group = {
>  };
>  
>  static const struct attribute_group *acpi_nfit_region_attribute_groups[] = {
> -	&nd_mapping_attribute_group,
>  	&acpi_nfit_region_attribute_group,
>  	NULL,
>  };
> diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
> index f97166583294..0afc1973e938 100644
> --- a/drivers/nvdimm/region_devs.c
> +++ b/drivers/nvdimm/region_devs.c
> @@ -751,11 +751,10 @@ static struct attribute *mapping_attributes[] = {
>  	NULL,
>  };
>  
> -struct attribute_group nd_mapping_attribute_group = {
> +static const struct attribute_group nd_mapping_attribute_group = {
>  	.is_visible = mapping_visible,
>  	.attrs = mapping_attributes,
>  };
> -EXPORT_SYMBOL_GPL(nd_mapping_attribute_group);
>  
>  static const struct attribute_group nd_region_attribute_group = {
>  	.attrs = nd_region_attributes,
> @@ -766,6 +765,7 @@ static const struct attribute_group *nd_region_attribute_groups[] = {
>  	&nd_device_attribute_group,
>  	&nd_region_attribute_group,
>  	&nd_numa_attribute_group,
> +	&nd_mapping_attribute_group,
>  	NULL,
>  };
>  
> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
> index 312248d334c7..eb597d1cb891 100644
> --- a/include/linux/libnvdimm.h
> +++ b/include/linux/libnvdimm.h
> @@ -67,7 +67,6 @@ enum {
>  
>  extern struct attribute_group nvdimm_bus_attribute_group;
>  extern struct attribute_group nvdimm_attribute_group;
> -extern struct attribute_group nd_mapping_attribute_group;
>  
>  struct nvdimm;
>  struct nvdimm_bus_descriptor;
> _______________________________________________
> Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
> To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

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

* Re: [PATCH 07/16] libnvdimm: Move nvdimm_attribute_group to device_type
  2019-11-07  3:57 ` [PATCH 07/16] libnvdimm: Move nvdimm_attribute_group " Dan Williams
@ 2019-11-12 11:48   ` Aneesh Kumar K.V
  0 siblings, 0 replies; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-12 11:48 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm
  Cc: Michael Ellerman, peterz, dave.hansen, linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> A 'struct device_type' instance can carry default attributes for the
> device. Use this facility to remove the export of
> nvdimm_attribute_group and put the responsibility on the core rather
> than leaf implementations to define this attribute.
>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: "Oliver O'Halloran" <oohall@gmail.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  arch/powerpc/platforms/pseries/papr_scm.c |    9 ++-----
>  drivers/acpi/nfit/core.c                  |    1 -
>  drivers/nvdimm/dimm_devs.c                |   36 +++++++++++++++--------------
>  include/linux/libnvdimm.h                 |    1 -
>  4 files changed, 20 insertions(+), 27 deletions(-)
>
> diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
> index 0405fb769336..8354737ac340 100644
> --- a/arch/powerpc/platforms/pseries/papr_scm.c
> +++ b/arch/powerpc/platforms/pseries/papr_scm.c
> @@ -289,11 +289,6 @@ static const struct attribute_group *bus_attr_groups[] = {
>  	NULL,
>  };
>  
> -static const struct attribute_group *papr_scm_dimm_groups[] = {
> -	&nvdimm_attribute_group,
> -	NULL,
> -};
> -
>  static inline int papr_scm_node(int node)
>  {
>  	int min_dist = INT_MAX, dist;
> @@ -339,8 +334,8 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
>  	dimm_flags = 0;
>  	set_bit(NDD_ALIASING, &dimm_flags);
>  
> -	p->nvdimm = nvdimm_create(p->bus, p, papr_scm_dimm_groups,
> -				dimm_flags, PAPR_SCM_DIMM_CMD_MASK, 0, NULL);
> +	p->nvdimm = nvdimm_create(p->bus, p, NULL, dimm_flags,
> +				  PAPR_SCM_DIMM_CMD_MASK, 0, NULL);
>  	if (!p->nvdimm) {
>  		dev_err(dev, "Error creating DIMM object for %pOF\n", p->dn);
>  		goto err;
> diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
> index 69c406ecc3a6..84fc1f865802 100644
> --- a/drivers/acpi/nfit/core.c
> +++ b/drivers/acpi/nfit/core.c
> @@ -1698,7 +1698,6 @@ static const struct attribute_group acpi_nfit_dimm_attribute_group = {
>  };
>  
>  static const struct attribute_group *acpi_nfit_dimm_attribute_groups[] = {
> -	&nvdimm_attribute_group,
>  	&acpi_nfit_dimm_attribute_group,
>  	NULL,
>  };
> diff --git a/drivers/nvdimm/dimm_devs.c b/drivers/nvdimm/dimm_devs.c
> index 278867c68682..94ea6dba6b4f 100644
> --- a/drivers/nvdimm/dimm_devs.c
> +++ b/drivers/nvdimm/dimm_devs.c
> @@ -202,22 +202,6 @@ static void nvdimm_release(struct device *dev)
>  	kfree(nvdimm);
>  }
>  
> -static const struct attribute_group *nvdimm_attribute_groups[] = {
> -	&nd_device_attribute_group,
> -	NULL,
> -};
> -
> -static const struct device_type nvdimm_device_type = {
> -	.name = "nvdimm",
> -	.release = nvdimm_release,
> -	.groups = nvdimm_attribute_groups,
> -};
> -
> -bool is_nvdimm(struct device *dev)
> -{
> -	return dev->type == &nvdimm_device_type;
> -}
> -
>  struct nvdimm *to_nvdimm(struct device *dev)
>  {
>  	struct nvdimm *nvdimm = container_of(dev, struct nvdimm, dev);
> @@ -456,11 +440,27 @@ static umode_t nvdimm_visible(struct kobject *kobj, struct attribute *a, int n)
>  	return 0;
>  }
>  
> -struct attribute_group nvdimm_attribute_group = {
> +static const struct attribute_group nvdimm_attribute_group = {
>  	.attrs = nvdimm_attributes,
>  	.is_visible = nvdimm_visible,
>  };
> -EXPORT_SYMBOL_GPL(nvdimm_attribute_group);
> +
> +static const struct attribute_group *nvdimm_attribute_groups[] = {
> +	&nd_device_attribute_group,
> +	&nvdimm_attribute_group,
> +	NULL,
> +};
> +
> +static const struct device_type nvdimm_device_type = {
> +	.name = "nvdimm",
> +	.release = nvdimm_release,
> +	.groups = nvdimm_attribute_groups,
> +};
> +
> +bool is_nvdimm(struct device *dev)
> +{
> +	return dev->type == &nvdimm_device_type;
> +}
>  
>  struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus,
>  		void *provider_data, const struct attribute_group **groups,
> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
> index eb597d1cb891..3644af97bcb4 100644
> --- a/include/linux/libnvdimm.h
> +++ b/include/linux/libnvdimm.h
> @@ -66,7 +66,6 @@ enum {
>  };
>  
>  extern struct attribute_group nvdimm_bus_attribute_group;
> -extern struct attribute_group nvdimm_attribute_group;
>  
>  struct nvdimm;
>  struct nvdimm_bus_descriptor;
> _______________________________________________
> Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
> To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

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

* Re: [PATCH 08/16] libnvdimm: Move nvdimm_bus_attribute_group to device_type
  2019-11-07  3:57 ` [PATCH 08/16] libnvdimm: Move nvdimm_bus_attribute_group " Dan Williams
@ 2019-11-12 11:48   ` Aneesh Kumar K.V
  0 siblings, 0 replies; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-12 11:48 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm
  Cc: Ira Weiny, Michael Ellerman, Oliver O'Halloran, Vishal Verma,
	peterz, dave.hansen, linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> A 'struct device_type' instance can carry default attributes for the
> device. Use this facility to remove the export of
> nvdimm_bus_attribute_group and put the responsibility on the core rather
> than leaf implementations to define this attribute.
>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>

> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: "Oliver O'Halloran" <oohall@gmail.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  arch/powerpc/platforms/pseries/papr_scm.c |    6 ------
>  drivers/acpi/nfit/core.c                  |    1 -
>  drivers/nvdimm/bus.c                      |    9 +++++++--
>  drivers/nvdimm/core.c                     |    8 ++++++--
>  drivers/nvdimm/e820.c                     |    6 ------
>  drivers/nvdimm/nd.h                       |    1 +
>  drivers/nvdimm/of_pmem.c                  |    6 ------
>  include/linux/libnvdimm.h                 |    2 --
>  8 files changed, 14 insertions(+), 25 deletions(-)
>
> diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
> index 8354737ac340..33aa59e666e5 100644
> --- a/arch/powerpc/platforms/pseries/papr_scm.c
> +++ b/arch/powerpc/platforms/pseries/papr_scm.c
> @@ -284,11 +284,6 @@ int papr_scm_ndctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
>  	return 0;
>  }
>  
> -static const struct attribute_group *bus_attr_groups[] = {
> -	&nvdimm_bus_attribute_group,
> -	NULL,
> -};
> -
>  static inline int papr_scm_node(int node)
>  {
>  	int min_dist = INT_MAX, dist;
> @@ -319,7 +314,6 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
>  	p->bus_desc.ndctl = papr_scm_ndctl;
>  	p->bus_desc.module = THIS_MODULE;
>  	p->bus_desc.of_node = p->pdev->dev.of_node;
> -	p->bus_desc.attr_groups = bus_attr_groups;
>  	p->bus_desc.provider_name = kstrdup(p->pdev->name, GFP_KERNEL);
>  
>  	if (!p->bus_desc.provider_name)
> diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
> index 84fc1f865802..a3320f93616d 100644
> --- a/drivers/acpi/nfit/core.c
> +++ b/drivers/acpi/nfit/core.c
> @@ -1404,7 +1404,6 @@ static const struct attribute_group acpi_nfit_attribute_group = {
>  };
>  
>  static const struct attribute_group *acpi_nfit_attribute_groups[] = {
> -	&nvdimm_bus_attribute_group,
>  	&acpi_nfit_attribute_group,
>  	NULL,
>  };
> diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c
> index 28e1b265aa63..1d330d46d036 100644
> --- a/drivers/nvdimm/bus.c
> +++ b/drivers/nvdimm/bus.c
> @@ -300,9 +300,14 @@ static void nvdimm_bus_release(struct device *dev)
>  	kfree(nvdimm_bus);
>  }
>  
> +static const struct device_type nvdimm_bus_dev_type = {
> +	.release = nvdimm_bus_release,
> +	.groups = nvdimm_bus_attribute_groups,
> +};
> +
>  bool is_nvdimm_bus(struct device *dev)
>  {
> -	return dev->release == nvdimm_bus_release;
> +	return dev->type == &nvdimm_bus_dev_type;
>  }
>  
>  struct nvdimm_bus *walk_to_nvdimm_bus(struct device *nd_dev)
> @@ -355,7 +360,7 @@ struct nvdimm_bus *nvdimm_bus_register(struct device *parent,
>  	badrange_init(&nvdimm_bus->badrange);
>  	nvdimm_bus->nd_desc = nd_desc;
>  	nvdimm_bus->dev.parent = parent;
> -	nvdimm_bus->dev.release = nvdimm_bus_release;
> +	nvdimm_bus->dev.type = &nvdimm_bus_dev_type;
>  	nvdimm_bus->dev.groups = nd_desc->attr_groups;
>  	nvdimm_bus->dev.bus = &nvdimm_bus_type;
>  	nvdimm_bus->dev.of_node = nd_desc->of_node;
> diff --git a/drivers/nvdimm/core.c b/drivers/nvdimm/core.c
> index 9204f1e9fd14..81231ca23db0 100644
> --- a/drivers/nvdimm/core.c
> +++ b/drivers/nvdimm/core.c
> @@ -385,10 +385,14 @@ static struct attribute *nvdimm_bus_attributes[] = {
>  	NULL,
>  };
>  
> -struct attribute_group nvdimm_bus_attribute_group = {
> +static const struct attribute_group nvdimm_bus_attribute_group = {
>  	.attrs = nvdimm_bus_attributes,
>  };
> -EXPORT_SYMBOL_GPL(nvdimm_bus_attribute_group);
> +
> +const struct attribute_group *nvdimm_bus_attribute_groups[] = {
> +	&nvdimm_bus_attribute_group,
> +	NULL,
> +};
>  
>  int nvdimm_bus_add_badrange(struct nvdimm_bus *nvdimm_bus, u64 addr, u64 length)
>  {
> diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c
> index 9a971a59dec7..e02f60ad6c99 100644
> --- a/drivers/nvdimm/e820.c
> +++ b/drivers/nvdimm/e820.c
> @@ -8,11 +8,6 @@
>  #include <linux/libnvdimm.h>
>  #include <linux/module.h>
>  
> -static const struct attribute_group *e820_pmem_attribute_groups[] = {
> -	&nvdimm_bus_attribute_group,
> -	NULL,
> -};
> -
>  static int e820_pmem_remove(struct platform_device *pdev)
>  {
>  	struct nvdimm_bus *nvdimm_bus = platform_get_drvdata(pdev);
> @@ -55,7 +50,6 @@ static int e820_pmem_probe(struct platform_device *pdev)
>  	struct nvdimm_bus *nvdimm_bus;
>  	int rc = -ENXIO;
>  
> -	nd_desc.attr_groups = e820_pmem_attribute_groups;
>  	nd_desc.provider_name = "e820";
>  	nd_desc.module = THIS_MODULE;
>  	nvdimm_bus = nvdimm_bus_register(dev, &nd_desc);
> diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
> index e7f3a2fee2ab..577800242110 100644
> --- a/drivers/nvdimm/nd.h
> +++ b/drivers/nvdimm/nd.h
> @@ -300,6 +300,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig);
>  extern const struct attribute_group *nd_pfn_attribute_groups[];
>  extern const struct attribute_group nd_device_attribute_group;
>  extern const struct attribute_group nd_numa_attribute_group;
> +extern const struct attribute_group *nvdimm_bus_attribute_groups[];
>  #else
>  static inline int nd_pfn_probe(struct device *dev,
>  		struct nd_namespace_common *ndns)
> diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
> index c0b5ac36df9d..8224d1431ea9 100644
> --- a/drivers/nvdimm/of_pmem.c
> +++ b/drivers/nvdimm/of_pmem.c
> @@ -9,11 +9,6 @@
>  #include <linux/ioport.h>
>  #include <linux/slab.h>
>  
> -static const struct attribute_group *bus_attr_groups[] = {
> -	&nvdimm_bus_attribute_group,
> -	NULL,
> -};
> -
>  struct of_pmem_private {
>  	struct nvdimm_bus_descriptor bus_desc;
>  	struct nvdimm_bus *bus;
> @@ -35,7 +30,6 @@ static int of_pmem_region_probe(struct platform_device *pdev)
>  	if (!priv)
>  		return -ENOMEM;
>  
> -	priv->bus_desc.attr_groups = bus_attr_groups;
>  	priv->bus_desc.provider_name = kstrdup(pdev->name, GFP_KERNEL);
>  	priv->bus_desc.module = THIS_MODULE;
>  	priv->bus_desc.of_node = np;
> diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
> index 3644af97bcb4..9df091bd30ba 100644
> --- a/include/linux/libnvdimm.h
> +++ b/include/linux/libnvdimm.h
> @@ -65,8 +65,6 @@ enum {
>  	DPA_RESOURCE_ADJUSTED = 1 << 0,
>  };
>  
> -extern struct attribute_group nvdimm_bus_attribute_group;
> -
>  struct nvdimm;
>  struct nvdimm_bus_descriptor;
>  typedef int (*ndctl_fn)(struct nvdimm_bus_descriptor *nd_desc,

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

* Re: [PATCH 09/16] dax: Create a dax device_type
  2019-11-07  3:57 ` [PATCH 09/16] dax: Create a dax device_type Dan Williams
@ 2019-11-12 11:49   ` Aneesh Kumar K.V
  0 siblings, 0 replies; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-12 11:49 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm
  Cc: Ira Weiny, Vishal Verma, peterz, dave.hansen, linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> Move the open coded release method and attribute groups to a 'struct
> device_type' instance.
>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>

> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  drivers/dax/bus.c |    8 ++++++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
> index 8fafbeab510a..f3e6e00ece40 100644
> --- a/drivers/dax/bus.c
> +++ b/drivers/dax/bus.c
> @@ -373,6 +373,11 @@ static void dev_dax_release(struct device *dev)
>  	kfree(dev_dax);
>  }
>  
> +static const struct device_type dev_dax_type = {
> +	.release = dev_dax_release,
> +	.groups = dax_attribute_groups,
> +};
> +
>  static void unregister_dev_dax(void *dev)
>  {
>  	struct dev_dax *dev_dax = to_dev_dax(dev);
> @@ -430,8 +435,7 @@ struct dev_dax *__devm_create_dev_dax(struct dax_region *dax_region, int id,
>  	else
>  		dev->class = dax_class;
>  	dev->parent = parent;
> -	dev->groups = dax_attribute_groups;
> -	dev->release = dev_dax_release;
> +	dev->type = &dev_dax_type;
>  	dev_set_name(dev, "dax%d.%d", dax_region->id, id);
>  
>  	rc = device_add(dev);

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

* Re: [PATCH 10/16] dax: Simplify root read-only definition for the 'resource' attribute
  2019-11-07  3:57 ` [PATCH 10/16] dax: Simplify root read-only definition for the 'resource' attribute Dan Williams
@ 2019-11-12 11:49   ` Aneesh Kumar K.V
  0 siblings, 0 replies; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-12 11:49 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm
  Cc: Ira Weiny, Vishal Verma, peterz, dave.hansen, linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> Rather than update the permission in ->is_visible() set the permission
> directly at declaration time.
>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>

> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  drivers/dax/bus.c |    4 +---
>  1 file changed, 1 insertion(+), 3 deletions(-)
>
> diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
> index f3e6e00ece40..ce6d648d7670 100644
> --- a/drivers/dax/bus.c
> +++ b/drivers/dax/bus.c
> @@ -309,7 +309,7 @@ static ssize_t resource_show(struct device *dev,
>  
>  	return sprintf(buf, "%#llx\n", dev_dax_resource(dev_dax));
>  }
> -static DEVICE_ATTR_RO(resource);
> +static DEVICE_ATTR(resource, 0400, resource_show, NULL);
>  
>  static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
>  		char *buf)
> @@ -329,8 +329,6 @@ static umode_t dev_dax_visible(struct kobject *kobj, struct attribute *a, int n)
>  
>  	if (a == &dev_attr_target_node.attr && dev_dax_target_node(dev_dax) < 0)
>  		return 0;
> -	if (a == &dev_attr_resource.attr)
> -		return 0400;
>  	return a->mode;
>  }
>  

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

* Re: [PATCH 12/16] dax: Add numa_node to the default device-dax attributes
  2019-11-07  3:57 ` [PATCH 12/16] dax: Add numa_node to the default device-dax attributes Dan Williams
@ 2019-11-12 11:50   ` Aneesh Kumar K.V
  0 siblings, 0 replies; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-12 11:50 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm; +Cc: peterz, dave.hansen, linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> It is confusing that device-dax instances publish a 'target_node'
> attribute, but not a 'numa_node'. The 'numa_node' information is
> available elsewhere in the sysfs device hierarchy, but it is not obvious
> and not reliable from one device-dax instance-type (e.g. child devices
> of nvdimm namespaces) to the next (e.g. 'hmem' devices defined by EFI
> Specific Purpose Memory and the ACPI HMAT).
>

Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>

> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  drivers/dax/bus.c |   10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
> index ce6d648d7670..0879b9663eb7 100644
> --- a/drivers/dax/bus.c
> +++ b/drivers/dax/bus.c
> @@ -322,6 +322,13 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
>  }
>  static DEVICE_ATTR_RO(modalias);
>  
> +static ssize_t numa_node_show(struct device *dev,
> +		struct device_attribute *attr, char *buf)
> +{
> +	return sprintf(buf, "%d\n", dev_to_node(dev));
> +}
> +static DEVICE_ATTR_RO(numa_node);
> +
>  static umode_t dev_dax_visible(struct kobject *kobj, struct attribute *a, int n)
>  {
>  	struct device *dev = container_of(kobj, struct device, kobj);
> @@ -329,6 +336,8 @@ static umode_t dev_dax_visible(struct kobject *kobj, struct attribute *a, int n)
>  
>  	if (a == &dev_attr_target_node.attr && dev_dax_target_node(dev_dax) < 0)
>  		return 0;
> +	if (a == &dev_attr_numa_node.attr && !IS_ENABLED(CONFIG_NUMA))
> +		return 0;
>  	return a->mode;
>  }
>  
> @@ -337,6 +346,7 @@ static struct attribute *dev_dax_attributes[] = {
>  	&dev_attr_size.attr,
>  	&dev_attr_target_node.attr,
>  	&dev_attr_resource.attr,
> +	&dev_attr_numa_node.attr,
>  	NULL,
>  };
>  
> _______________________________________________
> Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
> To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

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

* Re: [PATCH 11/16] libnvdimm: Simplify root read-only definition for the 'resource' attribute
  2019-11-07  3:57 ` [PATCH 11/16] libnvdimm: " Dan Williams
@ 2019-11-12 11:50   ` Aneesh Kumar K.V
  0 siblings, 0 replies; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-12 11:50 UTC (permalink / raw)
  To: Dan Williams, linux-nvdimm; +Cc: peterz, dave.hansen, linux-kernel, linux-mm

Dan Williams <dan.j.williams@intel.com> writes:

> Rather than update the permission in ->is_visible() set the permission
> directly at declaration time.
>
Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>

> Cc: Ira Weiny <ira.weiny@intel.com>
> Cc: Vishal Verma <vishal.l.verma@intel.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  drivers/nvdimm/namespace_devs.c |    9 +++------
>  drivers/nvdimm/pfn_devs.c       |   10 +---------
>  drivers/nvdimm/region_devs.c    |   10 +++-------
>  3 files changed, 7 insertions(+), 22 deletions(-)
>
> diff --git a/drivers/nvdimm/namespace_devs.c b/drivers/nvdimm/namespace_devs.c
> index 37471a272c1a..85b553094d19 100644
> --- a/drivers/nvdimm/namespace_devs.c
> +++ b/drivers/nvdimm/namespace_devs.c
> @@ -1303,7 +1303,7 @@ static ssize_t resource_show(struct device *dev,
>  		return -ENXIO;
>  	return sprintf(buf, "%#llx\n", (unsigned long long) res->start);
>  }
> -static DEVICE_ATTR_RO(resource);
> +static DEVICE_ATTR(resource, 0400, resource_show, NULL);
>  
>  static const unsigned long blk_lbasize_supported[] = { 512, 520, 528,
>  	4096, 4104, 4160, 4224, 0 };
> @@ -1619,11 +1619,8 @@ static umode_t namespace_visible(struct kobject *kobj,
>  {
>  	struct device *dev = container_of(kobj, struct device, kobj);
>  
> -	if (a == &dev_attr_resource.attr) {
> -		if (is_namespace_blk(dev))
> -			return 0;
> -		return 0400;
> -	}
> +	if (a == &dev_attr_resource.attr && is_namespace_blk(dev))
> +		return 0;
>  
>  	if (is_namespace_pmem(dev) || is_namespace_blk(dev)) {
>  		if (a == &dev_attr_size.attr)
> diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
> index e809961e2b6f..9f9cb51301e7 100644
> --- a/drivers/nvdimm/pfn_devs.c
> +++ b/drivers/nvdimm/pfn_devs.c
> @@ -218,7 +218,7 @@ static ssize_t resource_show(struct device *dev,
>  
>  	return rc;
>  }
> -static DEVICE_ATTR_RO(resource);
> +static DEVICE_ATTR(resource, 0400, resource_show, NULL);
>  
>  static ssize_t size_show(struct device *dev,
>  		struct device_attribute *attr, char *buf)
> @@ -269,16 +269,8 @@ static struct attribute *nd_pfn_attributes[] = {
>  	NULL,
>  };
>  
> -static umode_t pfn_visible(struct kobject *kobj, struct attribute *a, int n)
> -{
> -	if (a == &dev_attr_resource.attr)
> -		return 0400;
> -	return a->mode;
> -}
> -
>  static struct attribute_group nd_pfn_attribute_group = {
>  	.attrs = nd_pfn_attributes,
> -	.is_visible = pfn_visible,
>  };
>  
>  const struct attribute_group *nd_pfn_attribute_groups[] = {
> diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
> index 0afc1973e938..be3e429e86af 100644
> --- a/drivers/nvdimm/region_devs.c
> +++ b/drivers/nvdimm/region_devs.c
> @@ -553,7 +553,7 @@ static ssize_t resource_show(struct device *dev,
>  
>  	return sprintf(buf, "%#llx\n", nd_region->ndr_start);
>  }
> -static DEVICE_ATTR_RO(resource);
> +static DEVICE_ATTR(resource, 0400, resource_show, NULL);
>  
>  static ssize_t persistence_domain_show(struct device *dev,
>  		struct device_attribute *attr, char *buf)
> @@ -605,12 +605,8 @@ static umode_t region_visible(struct kobject *kobj, struct attribute *a, int n)
>  	if (!is_memory(dev) && a == &dev_attr_badblocks.attr)
>  		return 0;
>  
> -	if (a == &dev_attr_resource.attr) {
> -		if (is_memory(dev))
> -			return 0400;
> -		else
> -			return 0;
> -	}
> +	if (a == &dev_attr_resource.attr && !is_memory(dev))
> +		return 0;
>  
>  	if (a == &dev_attr_deep_flush.attr) {
>  		int has_flush = nvdimm_has_flush(nd_region);
> _______________________________________________
> Linux-nvdimm mailing list -- linux-nvdimm@lists.01.org
> To unsubscribe send an email to linux-nvdimm-leave@lists.01.org

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

* Re: [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory
  2019-11-12 11:42 ` [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Aneesh Kumar K.V
@ 2019-11-12 19:37   ` Dan Williams
  0 siblings, 0 replies; 37+ messages in thread
From: Dan Williams @ 2019-11-12 19:37 UTC (permalink / raw)
  To: Aneesh Kumar K.V
  Cc: linux-nvdimm, David Hildenbrand, Peter Zijlstra, Borislav Petkov,
	Michael Ellerman, H. Peter Anvin, X86 ML, Thomas Gleixner,
	Dave Hansen, Andrew Morton, Ingo Molnar, Michal Hocko,
	Rafael J. Wysocki, Andy Lutomirski, Linux Kernel Mailing List,
	Linux MM

On Tue, Nov 12, 2019 at 3:43 AM Aneesh Kumar K.V
<aneesh.kumar@linux.ibm.com> wrote:
>
> Dan Williams <dan.j.williams@intel.com> writes:
>
> > Yes, this patch series looks like a pile of boring libnvdimm cleanups,
> > but buried at the end are some small gems that testing with libnvdimm
> > uncovered. These gems will prove more valuable over time for Memory
> > Hierarchy management as more platforms, via the ACPI HMAT and EFI
> > Specific Purpose Memory, publish reserved or "soft-reserved" ranges to
> > Linux. Linux system administrators will expect to be able to interact
> > with those ranges with a unique numa node number when/if that memory is
> > onlined via the dax_kmem driver [1].
> >
> > One configuration that currently fails to properly convey the target
> > node for the resulting memory hotplug operation is persistent memory
> > defined by the memmap=nn!ss parameter. For example, today if node1 is a
> > memory only node, and all the memory from node1 is specified to
> > memmap=nn!ss and subsequently onlined, it will end up being onlined as
> > node0 memory. As it stands, memory_add_physaddr_to_nid() can only
> > identify online nodes and since node1 in this example has no online cpus
> > / memory the target node is initialized node0.
> >
> > The fix is to preserve rather than discard the numa_meminfo entries that
> > are relevant for reserved memory ranges, and to uplevel the node
> > distance helper for determining the "local" (closest) node relative to
> > an initiator node.
> >
> > The first 12 patches are cleanups to make sure that all nvdimm devices
> > and their children properly export a numa_node attribute. The switch to
> > a device-type is less code and less error prone as a result.
>
>
> Will this still allow leaf driver to have platform specific attribute
> exposed via sysfs? Or do we want to still keep them in nvdimm core and
> control the visibility via is_visible() callback?

The leaf driver can still have platform specific attributes, see:

    acpi_nfit_attribute_groups
    acpi_nfit_dimm_attribute_groups
    acpi_nfit_region_attribute_groups

...that still exist after this conversion. This conversion simply
arranges for those to passed in without making the leaf driver also be
responsible for specifying the core attributes.

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

* Re: [PATCH 04/16] libnvdimm: Move nd_numa_attribute_group to device_type
  2019-11-12  9:22   ` Aneesh Kumar K.V
@ 2019-11-13  1:26     ` Dan Williams
  2019-11-13  6:02       ` Aneesh Kumar K.V
  0 siblings, 1 reply; 37+ messages in thread
From: Dan Williams @ 2019-11-13  1:26 UTC (permalink / raw)
  To: Aneesh Kumar K.V
  Cc: linux-nvdimm, Ira Weiny, Michael Ellerman, Oliver O'Halloran,
	Vishal Verma, Peter Zijlstra, Dave Hansen,
	Linux Kernel Mailing List, Linux MM

On Tue, Nov 12, 2019 at 1:23 AM Aneesh Kumar K.V
<aneesh.kumar@linux.ibm.com> wrote:
>
> Dan Williams <dan.j.williams@intel.com> writes:
>
> > A 'struct device_type' instance can carry default attributes for the
> > device. Use this facility to remove the export of
> > nd_numa_attribute_group and put the responsibility on the core rather
> > than leaf implementations to define this attribute.
> >
> > Cc: Ira Weiny <ira.weiny@intel.com>
> > Cc: Michael Ellerman <mpe@ellerman.id.au>
> > Cc: "Oliver O'Halloran" <oohall@gmail.com>
> > Cc: Vishal Verma <vishal.l.verma@intel.com>
> > Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> > Signed-off-by: Dan Williams <dan.j.williams@intel.com>
>
>
> can we also expose target_node in a similar way? This allows application
> to better understand the node locality of the SCM device.

It is already exported for device-dax instances. See
DEVICE_ATTR_RO(target_node) in drivers/dax/bus.c. I did not see a use
case for it to be exported for other nvdimm device types.

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

* Re: [PATCH 04/16] libnvdimm: Move nd_numa_attribute_group to device_type
  2019-11-13  1:26     ` Dan Williams
@ 2019-11-13  6:02       ` Aneesh Kumar K.V
  2019-11-13  6:14         ` Dan Williams
  0 siblings, 1 reply; 37+ messages in thread
From: Aneesh Kumar K.V @ 2019-11-13  6:02 UTC (permalink / raw)
  To: Dan Williams
  Cc: linux-nvdimm, Ira Weiny, Michael Ellerman, Oliver O'Halloran,
	Vishal Verma, Peter Zijlstra, Dave Hansen,
	Linux Kernel Mailing List, Linux MM

On 11/13/19 6:56 AM, Dan Williams wrote:
> On Tue, Nov 12, 2019 at 1:23 AM Aneesh Kumar K.V
> <aneesh.kumar@linux.ibm.com> wrote:
>>
>> Dan Williams <dan.j.williams@intel.com> writes:
>>
>>> A 'struct device_type' instance can carry default attributes for the
>>> device. Use this facility to remove the export of
>>> nd_numa_attribute_group and put the responsibility on the core rather
>>> than leaf implementations to define this attribute.
>>>
>>> Cc: Ira Weiny <ira.weiny@intel.com>
>>> Cc: Michael Ellerman <mpe@ellerman.id.au>
>>> Cc: "Oliver O'Halloran" <oohall@gmail.com>
>>> Cc: Vishal Verma <vishal.l.verma@intel.com>
>>> Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
>>> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
>>
>>
>> can we also expose target_node in a similar way? This allows application
>> to better understand the node locality of the SCM device.
> 
> It is already exported for device-dax instances. See
> DEVICE_ATTR_RO(target_node) in drivers/dax/bus.c. I did not see a use
> case for it to be exported for other nvdimm device types.
> 

some applications do want to access the fsdax namspace as different 
mount points based on numa affinity. If can differentiate the two 
regions with different target_node and same numa_node, that will help 
them better isolate these mounts.

-aneesh

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

* Re: [PATCH 04/16] libnvdimm: Move nd_numa_attribute_group to device_type
  2019-11-13  6:02       ` Aneesh Kumar K.V
@ 2019-11-13  6:14         ` Dan Williams
  0 siblings, 0 replies; 37+ messages in thread
From: Dan Williams @ 2019-11-13  6:14 UTC (permalink / raw)
  To: Aneesh Kumar K.V
  Cc: linux-nvdimm, Ira Weiny, Michael Ellerman, Oliver O'Halloran,
	Vishal Verma, Peter Zijlstra, Dave Hansen,
	Linux Kernel Mailing List, Linux MM

On Tue, Nov 12, 2019 at 10:02 PM Aneesh Kumar K.V
<aneesh.kumar@linux.ibm.com> wrote:
>
> On 11/13/19 6:56 AM, Dan Williams wrote:
> > On Tue, Nov 12, 2019 at 1:23 AM Aneesh Kumar K.V
> > <aneesh.kumar@linux.ibm.com> wrote:
> >>
> >> Dan Williams <dan.j.williams@intel.com> writes:
> >>
> >>> A 'struct device_type' instance can carry default attributes for the
> >>> device. Use this facility to remove the export of
> >>> nd_numa_attribute_group and put the responsibility on the core rather
> >>> than leaf implementations to define this attribute.
> >>>
> >>> Cc: Ira Weiny <ira.weiny@intel.com>
> >>> Cc: Michael Ellerman <mpe@ellerman.id.au>
> >>> Cc: "Oliver O'Halloran" <oohall@gmail.com>
> >>> Cc: Vishal Verma <vishal.l.verma@intel.com>
> >>> Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
> >>> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> >>
> >>
> >> can we also expose target_node in a similar way? This allows application
> >> to better understand the node locality of the SCM device.
> >
> > It is already exported for device-dax instances. See
> > DEVICE_ATTR_RO(target_node) in drivers/dax/bus.c. I did not see a use
> > case for it to be exported for other nvdimm device types.
> >
>
> some applications do want to access the fsdax namspace as different
> mount points based on numa affinity. If can differentiate the two
> regions with different target_node and same numa_node, that will help
> them better isolate these mounts.

Can you be more explicit than "some", and what's the impact if the
kernel continues with the status quo and does not export this data?
I'm trying to come up with the justification to include into the
changelog that adds that information.

At least on the pmem platforms I am working with the pmem ranges with
different target nodes also appear on different numa nodes so there is
no incremental benefit for target node there.

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

end of thread, back to index

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-11-07  3:56 [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Dan Williams
2019-11-07  3:56 ` [PATCH 01/16] libnvdimm: Move attribute groups to device type Dan Williams
2019-11-12 11:28   ` Aneesh Kumar K.V
2019-11-07  3:56 ` [PATCH 02/16] libnvdimm: Move region attribute group definition Dan Williams
2019-11-12 11:29   ` Aneesh Kumar K.V
2019-11-07  3:56 ` [PATCH 03/16] libnvdimm: Move nd_device_attribute_group to device_type Dan Williams
2019-11-12 11:30   ` Aneesh Kumar K.V
2019-11-07  3:56 ` [PATCH 04/16] libnvdimm: Move nd_numa_attribute_group " Dan Williams
2019-11-12  9:22   ` Aneesh Kumar K.V
2019-11-13  1:26     ` Dan Williams
2019-11-13  6:02       ` Aneesh Kumar K.V
2019-11-13  6:14         ` Dan Williams
2019-11-07  3:57 ` [PATCH 05/16] libnvdimm: Move nd_region_attribute_group " Dan Williams
2019-11-12 11:45   ` Aneesh Kumar K.V
2019-11-07  3:57 ` [PATCH 06/16] libnvdimm: Move nd_mapping_attribute_group " Dan Williams
2019-11-12 11:45   ` Aneesh Kumar K.V
2019-11-07  3:57 ` [PATCH 07/16] libnvdimm: Move nvdimm_attribute_group " Dan Williams
2019-11-12 11:48   ` Aneesh Kumar K.V
2019-11-07  3:57 ` [PATCH 08/16] libnvdimm: Move nvdimm_bus_attribute_group " Dan Williams
2019-11-12 11:48   ` Aneesh Kumar K.V
2019-11-07  3:57 ` [PATCH 09/16] dax: Create a dax device_type Dan Williams
2019-11-12 11:49   ` Aneesh Kumar K.V
2019-11-07  3:57 ` [PATCH 10/16] dax: Simplify root read-only definition for the 'resource' attribute Dan Williams
2019-11-12 11:49   ` Aneesh Kumar K.V
2019-11-07  3:57 ` [PATCH 11/16] libnvdimm: " Dan Williams
2019-11-12 11:50   ` Aneesh Kumar K.V
2019-11-07  3:57 ` [PATCH 12/16] dax: Add numa_node to the default device-dax attributes Dan Williams
2019-11-12 11:50   ` Aneesh Kumar K.V
2019-11-07  3:57 ` [PATCH 13/16] acpi/mm: Up-level "map to online node" functionality Dan Williams
2019-11-11 11:30   ` Aneesh Kumar K.V
2019-11-11 23:38     ` Dan Williams
2019-11-07  3:57 ` [PATCH 14/16] x86/numa: Provide a range-to-target_node lookup facility Dan Williams
2019-11-07  3:57 ` [PATCH 15/16] libnvdimm/e820: Drop the wrapper around memory_add_physaddr_to_nid Dan Williams
2019-11-07  3:58 ` [PATCH 16/16] libnvdimm/e820: Retrieve and populate correct 'target_node' info Dan Williams
2019-11-09  5:02   ` kbuild test robot
2019-11-12 11:42 ` [PATCH 00/16] Memory Hierarchy: Enable target node lookups for reserved memory Aneesh Kumar K.V
2019-11-12 19:37   ` Dan Williams

LKML Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/lkml/0 lkml/git/0.git
	git clone --mirror https://lore.kernel.org/lkml/1 lkml/git/1.git
	git clone --mirror https://lore.kernel.org/lkml/2 lkml/git/2.git
	git clone --mirror https://lore.kernel.org/lkml/3 lkml/git/3.git
	git clone --mirror https://lore.kernel.org/lkml/4 lkml/git/4.git
	git clone --mirror https://lore.kernel.org/lkml/5 lkml/git/5.git
	git clone --mirror https://lore.kernel.org/lkml/6 lkml/git/6.git
	git clone --mirror https://lore.kernel.org/lkml/7 lkml/git/7.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 lkml lkml/ https://lore.kernel.org/lkml \
		linux-kernel@vger.kernel.org
	public-inbox-index lkml

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.linux-kernel


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git