diff mbox series

[daxctl,v3,1/3] daxctl: Support the /sys/bus/dax ABI

Message ID 154777878668.2060068.4181003086210283179.stgit@dwillia2-desk3.amr.corp.intel.com (mailing list archive)
State Accepted
Commit 5754018dd7068967172940a7d243b58d8e3dfdb9
Headers show
Series daxctl: Opt-in to /sys/bus/dax ABI | expand

Commit Message

Dan Williams Jan. 18, 2019, 2:33 a.m. UTC
The kernel is implementing a '/sys/bus/dax' ABI to allow for alternate
device-DAX drivers to be bound to device instances.  In support of this
conversion, teach the libdaxctl subsystem-layout-specific code to parse
the new layout.

For backwards compatibility the implementation transparently and
optionally supports either '/sys/bus/dax' or '/sys/class/dax'.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 daxctl/lib/libdaxctl-private.h |   11 ++++++
 daxctl/lib/libdaxctl.c         |   70 +++++++++++++++++++++++++++++-----------
 util/sysfs.c                   |    2 +
 3 files changed, 62 insertions(+), 21 deletions(-)
diff mbox series

Patch

diff --git a/daxctl/lib/libdaxctl-private.h b/daxctl/lib/libdaxctl-private.h
index f7667324026f..4a462e7245d2 100644
--- a/daxctl/lib/libdaxctl-private.h
+++ b/daxctl/lib/libdaxctl-private.h
@@ -15,6 +15,17 @@ 
 
 #define DAXCTL_EXPORT __attribute__ ((visibility("default")))
 
+enum dax_subsystem {
+	DAX_UNKNOWN,
+	DAX_CLASS,
+	DAX_BUS,
+};
+
+static const char *dax_subsystems[] = {
+	[DAX_CLASS] = "/sys/class/dax",
+	[DAX_BUS] = "/sys/bus/dax/devices",
+};
+
 /**
  * struct daxctl_region - container for dax_devices
  */
diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
index 22f4210a7ea0..c2e3a52d6c7c 100644
--- a/daxctl/lib/libdaxctl.c
+++ b/daxctl/lib/libdaxctl.c
@@ -444,26 +444,38 @@  static void dax_devices_init(struct daxctl_region *region)
 {
 	struct daxctl_ctx *ctx = daxctl_region_get_ctx(region);
 	char daxdev_fmt[50];
-	char *region_path;
+	size_t i;
 
 	if (region->devices_init)
 		return;
 
 	region->devices_init = 1;
 	sprintf(daxdev_fmt, "dax%d.", region->id);
-	if (asprintf(&region_path, "%s/dax", region->region_path) < 0) {
-		dbg(ctx, "region path alloc fail\n");
-		return;
+	for (i = 0; i < ARRAY_SIZE(dax_subsystems); i++) {
+		char *region_path;
+
+		if (i == DAX_BUS)
+			region_path = region->region_path;
+		else if (i == DAX_CLASS) {
+			if (asprintf(&region_path, "%s/dax",
+						region->region_path) < 0) {
+				dbg(ctx, "region path alloc fail\n");
+				continue;
+			}
+		} else
+			continue;
+		sysfs_device_parse(ctx, region_path, daxdev_fmt, region,
+				add_dax_dev);
+		if (i == DAX_CLASS)
+			free(region_path);
 	}
-	sysfs_device_parse(ctx, region_path, daxdev_fmt, region, add_dax_dev);
-	free(region_path);
 }
 
-static char *dax_region_path(const char *base, const char *device)
+static char *dax_region_path(const char *device, enum dax_subsystem subsys)
 {
 	char *path, *region_path, *c;
 
-	if (asprintf(&path, "%s/%s", base, device) < 0)
+	if (asprintf(&path, "%s/%s", dax_subsystems[subsys], device) < 0)
 		return NULL;
 
 	/* dax_region must be the instance's direct parent */
@@ -472,7 +484,11 @@  static char *dax_region_path(const char *base, const char *device)
 	if (!region_path)
 		return NULL;
 
-	/* 'region_path' is now regionX/dax/daxX.Y', trim back to regionX */
+	/*
+	 * 'region_path' is now regionX/dax/daxX.Y' (DAX_CLASS), or
+	 * regionX/daxX.Y (DAX_BUS), trim it back to the regionX
+	 * component
+	 */
 	c = strrchr(region_path, '/');
 	if (!c) {
 		free(region_path);
@@ -480,6 +496,9 @@  static char *dax_region_path(const char *base, const char *device)
 	}
 	*c = '\0';
 
+	if (subsys == DAX_BUS)
+		return region_path;
+
 	c = strrchr(region_path, '/');
 	if (!c) {
 		free(region_path);
@@ -490,20 +509,15 @@  static char *dax_region_path(const char *base, const char *device)
 	return region_path;
 }
 
-static void dax_regions_init(struct daxctl_ctx *ctx)
+static void __dax_regions_init(struct daxctl_ctx *ctx, enum dax_subsystem subsys)
 {
-	const char *base = "/sys/class/dax";
 	struct dirent *de;
-	DIR *dir;
+	DIR *dir = NULL;
 
-	if (ctx->regions_init)
-		return;
-
-	ctx->regions_init = 1;
-
-	dir = opendir(base);
+	dir = opendir(dax_subsystems[subsys]);
 	if (!dir) {
-		dbg(ctx, "no dax regions found\n");
+		dbg(ctx, "no dax regions found via: %s\n",
+				dax_subsystems[subsys]);
 		return;
 	}
 
@@ -516,7 +530,7 @@  static void dax_regions_init(struct daxctl_ctx *ctx)
 			continue;
 		if (sscanf(de->d_name, "dax%d.%d", &region_id, &id) != 2)
 			continue;
-		dev_path = dax_region_path(base, de->d_name);
+		dev_path = dax_region_path(de->d_name, subsys);
 		if (!dev_path) {
 			err(ctx, "dax region path allocation failure\n");
 			continue;
@@ -529,6 +543,22 @@  static void dax_regions_init(struct daxctl_ctx *ctx)
 	closedir(dir);
 }
 
+static void dax_regions_init(struct daxctl_ctx *ctx)
+{
+	size_t i;
+
+	if (ctx->regions_init)
+		return;
+
+	ctx->regions_init = 1;
+
+	for (i = 0; i < ARRAY_SIZE(dax_subsystems); i++) {
+		if (i == DAX_UNKNOWN)
+			continue;
+		__dax_regions_init(ctx, i);
+	}
+}
+
 DAXCTL_EXPORT struct daxctl_dev *daxctl_dev_get_first(struct daxctl_region *region)
 {
 	dax_devices_init(region);
diff --git a/util/sysfs.c b/util/sysfs.c
index 0440fd0f49a3..9f7bc1f4930f 100644
--- a/util/sysfs.c
+++ b/util/sysfs.c
@@ -91,7 +91,7 @@  int __sysfs_device_parse(struct log_ctx *ctx, const char *base_path,
 	struct dirent *de;
 	DIR *dir;
 
-	log_dbg(ctx, "base: %s dev: %s\n", base_path, dev_name);
+	log_dbg(ctx, "base: '%s' dev: '%s'\n", base_path, dev_name);
 	dir = opendir(base_path);
 	if (!dir) {
 		log_dbg(ctx, "no \"%s\" devices found\n", dev_name);