Le 08/04/2019 à 21:55, Brice Goglin a écrit :
Le 08/04/2019 à 16:56, Dan Williams a écrit :
> Yes, I agree with all of the above, but I think we need a way to fix
> this independent of the HMAT data being present. The SLIT already
> tells the kernel enough to let tooling figure out equidistant "local"
> nodes. While the numa_node attribute will remain a singleton the
> tooling needs to handle this case and can't assume the HMAT data will
> be present.
So you want to export the part of SLIT that is currently hidden to
userspace because the corresponding nodes aren't registered?
With the patch below, I get 17 17 28 28 in dax0.0/node_distance which
means it's close to node0 and node1.
The code is pretty much a duplicate of read_node_distance() in
drivers/base/node.c. Not sure it's worth factorizing such small functions?
The name "node_distance" (instead of "distance" for NUMA nodes) is
also
subject to discussion.
Here's a better patch that exports the existing routine for showing
node distances, and reuses it in dax/bus.c and nvdimm/pfn_devs.c:
# cat /sys/class/block/pmem1/device/node_distance
28 28 17 17
# cat /sys/bus/dax/devices/dax0.0/node_distance
17 17 28 28
By the way, it also handles the case where the nd_region has no
valid target_node (idea stolen from kmem.c).
Are there other places where it'd be useful to export that attribute?
Ideally we could just export it in the region sysfs directory,
but I can't find backlinks going from daxX.Y or pmemZ to that
region directory :/
Signed-off-by: Brice Goglin <brice.goglin(a)inria.fr>
diff --git a/drivers/base/node.c b/drivers/base/node.c
index 8598fcb..5c6bce1 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -509,10 +509,9 @@ static ssize_t node_read_vmstat(struct device *dev,
}
static DEVICE_ATTR(vmstat, S_IRUGO, node_read_vmstat, NULL);
-static ssize_t node_read_distance(struct device *dev,
+ssize_t generic_node_distance_show(int nid,
struct device_attribute *attr, char *buf)
{
- int nid = dev->id;
int len = 0;
int i;
@@ -528,6 +527,13 @@ static ssize_t node_read_distance(struct device *dev,
len += sprintf(buf + len, "\n");
return len;
}
+EXPORT_SYMBOL_GPL(generic_node_distance_show);
+
+static ssize_t node_read_distance(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return generic_node_distance_show(dev->id, attr, buf);
+}
static DEVICE_ATTR(distance, S_IRUGO, node_read_distance, NULL);
static struct attribute *node_dev_attrs[] = {
diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
index 2109cfe..37d750e 100644
--- a/drivers/dax/bus.c
+++ b/drivers/dax/bus.c
@@ -6,6 +6,7 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/dax.h>
+#include <linux/node.h>
#include "dax-private.h"
#include "bus.h"
@@ -295,6 +296,18 @@ static ssize_t target_node_show(struct device *dev,
}
static DEVICE_ATTR_RO(target_node);
+static ssize_t node_distance_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct dev_dax *dev_dax = to_dev_dax(dev);
+ int nid = dev_dax_target_node(dev_dax);
+
+ if (nid < 0)
+ return 0;
+ return generic_node_distance_show(nid, attr, buf);
+}
+static DEVICE_ATTR(node_distance, S_IRUGO, node_distance_show, NULL);
+
static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
@@ -320,6 +333,7 @@ static umode_t dev_dax_visible(struct kobject *kobj, struct attribute
*a, int n)
&dev_attr_modalias.attr,
&dev_attr_size.attr,
&dev_attr_target_node.attr,
+ &dev_attr_node_distance.attr,
NULL,
};
diff --git a/drivers/nvdimm/pfn_devs.c b/drivers/nvdimm/pfn_devs.c
index d271bd73..5a0f55c 100644
--- a/drivers/nvdimm/pfn_devs.c
+++ b/drivers/nvdimm/pfn_devs.c
@@ -18,6 +18,7 @@
#include <linux/slab.h>
#include <linux/fs.h>
#include <linux/mm.h>
+#include <linux/node.h>
#include "nd-core.h"
#include "pfn.h"
#include "nd.h"
@@ -271,6 +272,18 @@ static ssize_t supported_alignments_show(struct device *dev,
}
static DEVICE_ATTR_RO(supported_alignments);
+static ssize_t node_distance_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct nd_region *nd_region = to_nd_region(dev->parent);
+ int nid = nd_region->target_node;
+
+ if (nid < 0)
+ return 0;
+ return generic_node_distance_show(nid, attr, buf);
+}
+static DEVICE_ATTR(node_distance, S_IRUGO, node_distance_show, NULL);
+
static struct attribute *nd_pfn_attributes[] = {
&dev_attr_mode.attr,
&dev_attr_namespace.attr,
@@ -279,6 +292,7 @@ static ssize_t supported_alignments_show(struct device *dev,
&dev_attr_resource.attr,
&dev_attr_size.attr,
&dev_attr_supported_alignments.attr,
+ &dev_attr_node_distance.attr,
NULL,
};
diff --git a/include/linux/node.h b/include/linux/node.h
index 1a557c5..949e7ed 100644
--- a/include/linux/node.h
+++ b/include/linux/node.h
@@ -150,6 +150,11 @@ extern int register_memory_node_under_compute_node(unsigned int
mem_nid,
extern void register_hugetlbfs_with_node(node_registration_func_t doregister,
node_registration_func_t unregister);
#endif
+
+extern ssize_t generic_node_distance_show(int nid,
+ struct device_attribute *attr,
+ char *buf);
+
#else
static inline int __register_one_node(int nid)
{
@@ -186,6 +191,13 @@ static inline void
register_hugetlbfs_with_node(node_registration_func_t reg,
node_registration_func_t unreg)
{
}
+
+static inline ssize_t generic_node_distance_show(int nid,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return 0;
+}
#endif
#define to_node(device) container_of(device, struct node, dev)