All of lore.kernel.org
 help / color / mirror / Atom feed
* [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command
@ 2019-05-03 21:32 Vishal Verma
  2019-05-03 21:32 ` [ndctl PATCH 1/8] libdaxctl: add interfaces in support of device modes Vishal Verma
                   ` (8 more replies)
  0 siblings, 9 replies; 12+ messages in thread
From: Vishal Verma @ 2019-05-03 21:32 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: Dave Hansen, Pavel Tatashin

Add a new daxctl-reconfigure-device command that lets us reconfigure DAX
devices back and forth between 'system-ram' and 'device-dax' modes. It
also includes facilities to online any newly hot-plugged memory
(default), and attempt to offline memory before converting away from the
system-ram mode (not default, requires a --attempt-offline option).

Currently missing from this series is a way to persistently store which
devices have been 'marked' for use as system-ram. This depends on a
config system overhaul in ndctl, and patches for those will follow
separately and are independent of this work.

Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Pavel Tatashin <pasha.tatashin@soleen.com>


Vishal Verma (8):
  libdaxctl: add interfaces in support of device modes
  libdaxctl: cache 'subsystem' in daxctl_ctx
  daxctl: add libdaxctl interfaces to enable/disable devices
  ndctl: add helpers to get/set the online state for a node
  daxctl: add a new reconfigure-device command
  Documentation/daxctl: add a man page for daxctl-reconfigure-device
  contrib/ndctl: fix region-id completions for daxctl
  contrib/ndctl: add bash-completion for daxctl-reconfigure-device

 Documentation/daxctl/Makefile.am              |   3 +-
 .../daxctl/daxctl-reconfigure-device.txt      |  74 +++
 contrib/ndctl                                 |  34 +-
 daxctl/Makefile.am                            |   2 +
 daxctl/builtin.h                              |   1 +
 daxctl/daxctl.c                               |   1 +
 daxctl/device.c                               | 217 ++++++++
 daxctl/lib/Makefile.am                        |   3 +-
 daxctl/lib/libdaxctl-private.h                |  21 +
 daxctl/lib/libdaxctl.c                        | 511 +++++++++++++++++-
 daxctl/lib/libdaxctl.sym                      |  13 +
 daxctl/libdaxctl.h                            |  15 +
 12 files changed, 884 insertions(+), 11 deletions(-)
 create mode 100644 Documentation/daxctl/daxctl-reconfigure-device.txt
 create mode 100644 daxctl/device.c

-- 
2.20.1

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* [ndctl PATCH 1/8] libdaxctl: add interfaces in support of device modes
  2019-05-03 21:32 [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Vishal Verma
@ 2019-05-03 21:32 ` Vishal Verma
  2019-05-03 21:32 ` [ndctl PATCH 2/8] libdaxctl: cache 'subsystem' in daxctl_ctx Vishal Verma
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Vishal Verma @ 2019-05-03 21:32 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: Dave Hansen, Pavel Tatashin

In preparation for libdaxctl and daxctl to grow operational modes for
DAX devices, add the following supporting APIs:

  daxctl_dev_get_ctx
  daxctl_dev_is_enabled

Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 daxctl/lib/libdaxctl.c   | 30 ++++++++++++++++++++++++++++++
 daxctl/lib/libdaxctl.sym |  6 ++++++
 daxctl/libdaxctl.h       |  2 ++
 3 files changed, 38 insertions(+)

diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
index c2e3a52..70f896b 100644
--- a/daxctl/lib/libdaxctl.c
+++ b/daxctl/lib/libdaxctl.c
@@ -559,6 +559,36 @@ static void dax_regions_init(struct daxctl_ctx *ctx)
 	}
 }
 
+static int is_enabled(const char *drvpath)
+{
+	struct stat st;
+
+	if (lstat(drvpath, &st) < 0 || !S_ISLNK(st.st_mode))
+		return 0;
+	else
+		return 1;
+}
+
+DAXCTL_EXPORT int daxctl_dev_is_enabled(struct daxctl_dev *dev)
+{
+	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
+	char *path = dev->dev_buf;
+	int len = dev->buf_len;
+
+	if (snprintf(path, len, "%s/driver", dev->dev_path) >= len) {
+		err(ctx, "%s: buffer too small!\n",
+				daxctl_dev_get_devname(dev));
+		return 0;
+	}
+
+	return is_enabled(path);
+}
+
+DAXCTL_EXPORT struct daxctl_ctx *daxctl_dev_get_ctx(struct daxctl_dev *dev)
+{
+	return dev->region->ctx;
+}
+
 DAXCTL_EXPORT struct daxctl_dev *daxctl_dev_get_first(struct daxctl_region *region)
 {
 	dax_devices_init(region);
diff --git a/daxctl/lib/libdaxctl.sym b/daxctl/lib/libdaxctl.sym
index 84d3a69..c4af9a7 100644
--- a/daxctl/lib/libdaxctl.sym
+++ b/daxctl/lib/libdaxctl.sym
@@ -50,3 +50,9 @@ LIBDAXCTL_5 {
 global:
 	daxctl_region_get_path;
 } LIBDAXCTL_4;
+
+LIBDAXCTL_6 {
+global:
+	daxctl_dev_get_ctx;
+	daxctl_dev_is_enabled;
+} LIBDAXCTL_5;
diff --git a/daxctl/libdaxctl.h b/daxctl/libdaxctl.h
index 1d13ea2..e20ccb4 100644
--- a/daxctl/libdaxctl.h
+++ b/daxctl/libdaxctl.h
@@ -67,6 +67,8 @@ const char *daxctl_dev_get_devname(struct daxctl_dev *dev);
 int daxctl_dev_get_major(struct daxctl_dev *dev);
 int daxctl_dev_get_minor(struct daxctl_dev *dev);
 unsigned long long daxctl_dev_get_size(struct daxctl_dev *dev);
+struct daxctl_ctx *daxctl_dev_get_ctx(struct daxctl_dev *dev);
+int daxctl_dev_is_enabled(struct daxctl_dev *dev);
 
 #define daxctl_dev_foreach(region, dev) \
         for (dev = daxctl_dev_get_first(region); \
-- 
2.20.1

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* [ndctl PATCH 2/8] libdaxctl: cache 'subsystem' in daxctl_ctx
  2019-05-03 21:32 [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Vishal Verma
  2019-05-03 21:32 ` [ndctl PATCH 1/8] libdaxctl: add interfaces in support of device modes Vishal Verma
@ 2019-05-03 21:32 ` Vishal Verma
  2019-05-03 21:32 ` [ndctl PATCH 3/8] daxctl: add libdaxctl interfaces to enable/disable devices Vishal Verma
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Vishal Verma @ 2019-05-03 21:32 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: Dave Hansen, Pavel Tatashin

The 'DAX subsystem' in effect is determined at region or device init
time, and dictates the sysfs base paths for all device/region
operations. In preparation for adding bind/unbind functionality, cache
the subsystem as determined at init time in the library context.

Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 daxctl/lib/libdaxctl.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
index 70f896b..f8f5b8c 100644
--- a/daxctl/lib/libdaxctl.c
+++ b/daxctl/lib/libdaxctl.c
@@ -46,6 +46,7 @@ struct daxctl_ctx {
 	void *userdata;
 	int regions_init;
 	struct list_head regions;
+	enum dax_subsystem subsys;
 };
 
 /**
@@ -96,6 +97,7 @@ DAXCTL_EXPORT int daxctl_new(struct daxctl_ctx **ctx)
 	dbg(c, "log_priority=%d\n", c->ctx.log_priority);
 	*ctx = c;
 	list_head_init(&c->regions);
+	c->subsys = DAX_UNKNOWN;
 
 	return 0;
 }
@@ -454,14 +456,18 @@ static void dax_devices_init(struct daxctl_region *region)
 	for (i = 0; i < ARRAY_SIZE(dax_subsystems); i++) {
 		char *region_path;
 
-		if (i == DAX_BUS)
+		if (i == DAX_BUS) {
 			region_path = region->region_path;
-		else if (i == DAX_CLASS) {
+			if (ctx->subsys == DAX_UNKNOWN)
+				ctx->subsys = DAX_BUS;
+		} else if (i == DAX_CLASS) {
 			if (asprintf(&region_path, "%s/dax",
 						region->region_path) < 0) {
 				dbg(ctx, "region path alloc fail\n");
 				continue;
 			}
+			if (ctx->subsys == DAX_UNKNOWN)
+				ctx->subsys = DAX_CLASS;
 		} else
 			continue;
 		sysfs_device_parse(ctx, region_path, daxdev_fmt, region,
@@ -539,6 +545,8 @@ static void __dax_regions_init(struct daxctl_ctx *ctx, enum dax_subsystem subsys
 		free(dev_path);
 		if (!region)
 			err(ctx, "add_dax_region() for %s failed\n", de->d_name);
+		if (ctx->subsys == DAX_UNKNOWN)
+			ctx->subsys = subsys;
 	}
 	closedir(dir);
 }
-- 
2.20.1

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* [ndctl PATCH 3/8] daxctl: add libdaxctl interfaces to enable/disable devices
  2019-05-03 21:32 [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Vishal Verma
  2019-05-03 21:32 ` [ndctl PATCH 1/8] libdaxctl: add interfaces in support of device modes Vishal Verma
  2019-05-03 21:32 ` [ndctl PATCH 2/8] libdaxctl: cache 'subsystem' in daxctl_ctx Vishal Verma
@ 2019-05-03 21:32 ` Vishal Verma
  2019-05-03 21:32 ` [ndctl PATCH 4/8] ndctl: add helpers to get/set the online state for a node Vishal Verma
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Vishal Verma @ 2019-05-03 21:32 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: Dave Hansen, Pavel Tatashin

Add new libdaxctl interfaces to disable a device_dax based devices, and
to enable it into a given mode. The modes available are 'device_dax',
and 'system-ram', where device_dax is the normal device DAX mode used
via a character device, and 'system-ram' uses the kernel's 'kmem'
facility to hotplug the device into the system's memory space, and can
be used as normal system memory.

This adds the following new interfaces:

  daxctl_dev_disable;
  daxctl_dev_enable_devdax;
  daxctl_dev_enable_ram;

Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 daxctl/lib/Makefile.am         |   3 +-
 daxctl/lib/libdaxctl-private.h |  15 ++
 daxctl/lib/libdaxctl.c         | 241 +++++++++++++++++++++++++++++++++
 daxctl/lib/libdaxctl.sym       |   3 +
 daxctl/libdaxctl.h             |   9 ++
 5 files changed, 270 insertions(+), 1 deletion(-)

diff --git a/daxctl/lib/Makefile.am b/daxctl/lib/Makefile.am
index d3d4852..9f0e444 100644
--- a/daxctl/lib/Makefile.am
+++ b/daxctl/lib/Makefile.am
@@ -16,7 +16,8 @@ libdaxctl_la_SOURCES =\
 	libdaxctl.c
 
 libdaxctl_la_LIBADD =\
-	$(UUID_LIBS)
+	$(UUID_LIBS) \
+	$(KMOD_LIBS)
 
 daxctl_modprobe_data_DATA = daxctl.conf
 
diff --git a/daxctl/lib/libdaxctl-private.h b/daxctl/lib/libdaxctl-private.h
index 4a462e7..e64d0a7 100644
--- a/daxctl/lib/libdaxctl-private.h
+++ b/daxctl/lib/libdaxctl-private.h
@@ -13,6 +13,8 @@
 #ifndef _LIBDAXCTL_PRIVATE_H_
 #define _LIBDAXCTL_PRIVATE_H_
 
+#include <libkmod.h>
+
 #define DAXCTL_EXPORT __attribute__ ((visibility("default")))
 
 enum dax_subsystem {
@@ -26,6 +28,11 @@ static const char *dax_subsystems[] = {
 	[DAX_BUS] = "/sys/bus/dax/devices",
 };
 
+static const char *dax_modules[] = {
+	[DAXCTL_DEV_MODE_DEVDAX] = "device_dax",
+	[DAXCTL_DEV_MODE_RAM] = "kmem",
+};
+
 /**
  * struct daxctl_region - container for dax_devices
  */
@@ -53,6 +60,14 @@ struct daxctl_dev {
 	char *dev_path;
 	struct list_node list;
 	unsigned long long size;
+	struct kmod_module *module;
+	struct kmod_list *kmod_list;
 	struct daxctl_region *region;
 };
+
+static inline int check_kmod(struct kmod_ctx *kmod_ctx)
+{
+	return kmod_ctx ? 0 : -ENXIO;
+}
+
 #endif /* _LIBDAXCTL_PRIVATE_H_ */
diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
index f8f5b8c..d50b321 100644
--- a/daxctl/lib/libdaxctl.c
+++ b/daxctl/lib/libdaxctl.c
@@ -47,6 +47,7 @@ struct daxctl_ctx {
 	int regions_init;
 	struct list_head regions;
 	enum dax_subsystem subsys;
+	struct kmod_ctx *kmod_ctx;
 };
 
 /**
@@ -85,12 +86,20 @@ DAXCTL_EXPORT void daxctl_set_userdata(struct daxctl_ctx *ctx, void *userdata)
  */
 DAXCTL_EXPORT int daxctl_new(struct daxctl_ctx **ctx)
 {
+	struct kmod_ctx *kmod_ctx;
 	struct daxctl_ctx *c;
+	int rc = 0;
 
 	c = calloc(1, sizeof(struct daxctl_ctx));
 	if (!c)
 		return -ENOMEM;
 
+	kmod_ctx = kmod_new(NULL, NULL);
+	if (check_kmod(kmod_ctx) != 0) {
+		rc = -ENXIO;
+		goto out;
+	}
+
 	c->refcount = 1;
 	log_init(&c->ctx, "libdaxctl", "DAXCTL_LOG");
 	info(c, "ctx %p created\n", c);
@@ -98,8 +107,12 @@ DAXCTL_EXPORT int daxctl_new(struct daxctl_ctx **ctx)
 	*ctx = c;
 	list_head_init(&c->regions);
 	c->subsys = DAX_UNKNOWN;
+	c->kmod_ctx = kmod_ctx;
 
 	return 0;
+out:
+	free(c);
+	return rc;
 }
 
 /**
@@ -134,6 +147,7 @@ DAXCTL_EXPORT void daxctl_unref(struct daxctl_ctx *ctx)
 	list_for_each_safe(&ctx->regions, region, _r, list)
 		free_region(region, &ctx->regions);
 
+	kmod_unref(ctx->kmod_ctx);
 	info(ctx, "context %p released\n", ctx);
 	free(ctx);
 }
@@ -191,6 +205,7 @@ static void free_dev(struct daxctl_dev *dev, struct list_head *head)
 {
 	if (head)
 		list_del_from(head, &dev->list);
+	kmod_module_unref_list(dev->kmod_list);
 	free(dev->dev_buf);
 	free(dev->dev_path);
 	free(dev);
@@ -308,6 +323,27 @@ DAXCTL_EXPORT struct daxctl_region *daxctl_new_region(struct daxctl_ctx *ctx,
 	return region;
 }
 
+static struct kmod_list *to_module_list(struct daxctl_ctx *ctx,
+		const char *alias)
+{
+	struct kmod_list *list = NULL;
+	int rc;
+
+	if (!ctx->kmod_ctx || !alias)
+		return NULL;
+	if (alias[0] == 0)
+		return NULL;
+
+	rc = kmod_module_new_from_lookup(ctx->kmod_ctx, alias, &list);
+	if (rc < 0 || !list) {
+		dbg(ctx, "failed to find modules for alias: %s %d list: %s\n",
+				alias, rc, list ? "populated" : "empty");
+		return NULL;
+	}
+
+	return list;
+}
+
 static void *add_dax_dev(void *parent, int id, const char *daxdev_base)
 {
 	const char *devname = devpath_to_devname(daxdev_base);
@@ -317,6 +353,7 @@ static void *add_dax_dev(void *parent, int id, const char *daxdev_base)
 	struct daxctl_dev *dev, *dev_dup;
 	char buf[SYSFS_ATTR_SIZE];
 	struct stat st;
+	int rc;
 
 	if (!path)
 		return NULL;
@@ -348,6 +385,18 @@ static void *add_dax_dev(void *parent, int id, const char *daxdev_base)
 		goto err_read;
 	dev->buf_len = strlen(daxdev_base) + 50;
 
+	sprintf(path, "%s/modalias", daxdev_base);
+	rc = sysfs_read_attr(ctx, path, buf);
+	/* older kernels may be lack the modalias attribute */
+	if (rc < 0 && rc != -ENOENT)
+		goto err_read;
+	if (rc == 0) {
+		dev->kmod_list = to_module_list(ctx, buf);
+		if (dev->kmod_list == NULL)
+			goto err_read;
+	} else
+		dbg(ctx, "%s: modalias attribute missing\n", devname);
+
 	daxctl_dev_foreach(region, dev_dup)
 		if (dev_dup->id == dev->id) {
 			free_dev(dev, NULL);
@@ -577,6 +626,83 @@ static int is_enabled(const char *drvpath)
 		return 1;
 }
 
+static int daxctl_bind(struct daxctl_ctx *ctx, const char *devname,
+		const char *mod_name)
+{
+	DIR *dir;
+	int rc = 0;
+	char path[200];
+	struct dirent *de;
+	const int len = sizeof(path);
+
+	if (!devname) {
+		err(ctx, "missing devname\n");
+		return -EINVAL;
+	}
+
+	/* this is only called by daxctl_dev_enable which gates on dax-bus */
+	if (snprintf(path, len, "/sys/bus/dax/drivers") >= len) {
+		err(ctx, "%s: buffer too small!\n", devname);
+		return -ENXIO;
+	}
+
+	dir = opendir(path);
+	if (!dir) {
+		err(ctx, "%s: opendir(\"%s\") failed\n", devname, path);
+		return -ENXIO;
+	}
+
+	while ((de = readdir(dir)) != NULL) {
+		char *drv_path;
+
+		if (de->d_ino == 0)
+			continue;
+		if (de->d_name[0] == '.')
+			continue;
+		if (strcmp(de->d_name, mod_name) != 0)
+			continue;
+
+		if (asprintf(&drv_path, "%s/%s/new_id", path, de->d_name) < 0) {
+			err(ctx, "%s: path allocation failure\n", devname);
+			rc = -ENOMEM;
+			break;
+		}
+		rc = sysfs_write_attr_quiet(ctx, drv_path, devname);
+		free(drv_path);
+
+		if (asprintf(&drv_path, "%s/%s/bind", path, de->d_name) < 0) {
+			err(ctx, "%s: path allocation failure\n", devname);
+			rc = -ENOMEM;
+			break;
+		}
+		rc = sysfs_write_attr_quiet(ctx, drv_path, devname);
+		free(drv_path);
+		break;
+	}
+	closedir(dir);
+
+	if (rc) {
+		dbg(ctx, "%s: bind failed\n", devname);
+		return rc;
+	}
+	return 0;
+}
+
+static int daxctl_unbind(struct daxctl_ctx *ctx, const char *devpath)
+{
+	const char *devname = devpath_to_devname(devpath);
+	char path[200];
+	const int len = sizeof(path);
+
+	/* this is only called by daxctl_dev_disable which gates on dax-bus */
+	if (snprintf(path, len, "%s/driver/unbind", devpath) >= len) {
+		err(ctx, "%s: buffer too small!\n", devname);
+		return -ENXIO;
+	}
+
+	return sysfs_write_attr(ctx, path, devname);
+}
+
 DAXCTL_EXPORT int daxctl_dev_is_enabled(struct daxctl_dev *dev)
 {
 	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
@@ -592,6 +718,121 @@ DAXCTL_EXPORT int daxctl_dev_is_enabled(struct daxctl_dev *dev)
 	return is_enabled(path);
 }
 
+static int daxctl_insert_kmod_for_mode(struct daxctl_dev *dev,
+		const char *mod_name)
+{
+	const char *devname = daxctl_dev_get_devname(dev);
+	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
+	struct kmod_list *iter;
+	int rc = -ENXIO;
+
+	if (dev->kmod_list == NULL) {
+		err(ctx, "%s: a modalias lookup list was not created\n",
+				devname);
+		return rc;
+	}
+
+	kmod_list_foreach(iter, dev->kmod_list) {
+		struct kmod_module *mod = kmod_module_get_module(iter);
+		const char *name = kmod_module_get_name(mod);
+
+		if (strcmp(name, mod_name) != 0) {
+			kmod_module_unref(mod);
+			continue;
+		}
+		dbg(ctx, "%s inserting module: %s\n", devname, name);
+		rc = kmod_module_probe_insert_module(mod,
+				KMOD_PROBE_APPLY_BLACKLIST, NULL, NULL, NULL,
+				NULL);
+		if (rc < 0) {
+			err(ctx, "%s: insert failure: %d\n", devname, rc);
+			return rc;
+		}
+		dev->module = mod;
+	}
+
+	if (rc == -ENXIO)
+		err(ctx, "%s: Unable to find module: %s in alias list\n",
+				devname, mod_name);
+	return rc;
+}
+
+static int daxctl_dev_enable(struct daxctl_dev *dev, enum daxctl_dev_mode mode)
+{
+	struct daxctl_region *region = daxctl_dev_get_region(dev);
+	const char *devname = daxctl_dev_get_devname(dev);
+	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
+	const char *mod_name = dax_modules[mode];
+	int rc;
+
+	if (daxctl_dev_is_enabled(dev))
+		return 0;
+
+	if (ctx->subsys != DAX_BUS) {
+		err(ctx, "%s: invalid operation for dax subsystem\n", devname);
+		err(ctx, "%s:  see daxctl-migrate-device-model(1)\n", devname);
+		return -ENXIO;
+	}
+
+	if (mode == DAXCTL_DEV_MODE_UNKNOWN || mod_name == NULL) {
+		err(ctx, "%s: Invalid mode: %d\n", devname, mode);
+		return -EINVAL;
+	}
+
+	rc = daxctl_insert_kmod_for_mode(dev, mod_name);
+	if (rc)
+		return rc;
+
+	rc = daxctl_bind(ctx, devname, mod_name);
+	if (!daxctl_dev_is_enabled(dev)) {
+		err(ctx, "%s: failed to enable\n", devname);
+		return rc ? rc : -ENXIO;
+	}
+
+	region->devices_init = 0;
+	dax_devices_init(region);
+	rc = 0;
+	dbg(ctx, "%s: enabled\n", devname);
+	return rc;
+}
+
+DAXCTL_EXPORT int daxctl_dev_enable_devdax(struct daxctl_dev *dev)
+{
+	return daxctl_dev_enable(dev, DAXCTL_DEV_MODE_DEVDAX);
+}
+
+DAXCTL_EXPORT int daxctl_dev_enable_ram(struct daxctl_dev *dev)
+{
+	return daxctl_dev_enable(dev, DAXCTL_DEV_MODE_RAM);
+}
+
+DAXCTL_EXPORT int daxctl_dev_disable(struct daxctl_dev *dev)
+{
+	const char *devname = daxctl_dev_get_devname(dev);
+	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
+
+	if (!daxctl_dev_is_enabled(dev))
+		return 0;
+
+	if (ctx->subsys != DAX_BUS) {
+		err(ctx, "%s: invalid operation for dax subsystem\n", devname);
+		err(ctx, "%s:  see daxctl-migrate-device-model(1)\n", devname);
+		return -ENXIO;
+	}
+
+	daxctl_unbind(ctx, dev->dev_path);
+
+	if (daxctl_dev_is_enabled(dev)) {
+		err(ctx, "%s: failed to disable\n", devname);
+		return -EBUSY;
+	}
+
+	kmod_module_unref(dev->module);
+	dbg(ctx, "%s: disabled\n", devname);
+
+	return 0;
+}
+
 DAXCTL_EXPORT struct daxctl_ctx *daxctl_dev_get_ctx(struct daxctl_dev *dev)
 {
 	return dev->region->ctx;
diff --git a/daxctl/lib/libdaxctl.sym b/daxctl/lib/libdaxctl.sym
index c4af9a7..19904a2 100644
--- a/daxctl/lib/libdaxctl.sym
+++ b/daxctl/lib/libdaxctl.sym
@@ -55,4 +55,7 @@ LIBDAXCTL_6 {
 global:
 	daxctl_dev_get_ctx;
 	daxctl_dev_is_enabled;
+	daxctl_dev_disable;
+	daxctl_dev_enable_devdax;
+	daxctl_dev_enable_ram;
 } LIBDAXCTL_5;
diff --git a/daxctl/libdaxctl.h b/daxctl/libdaxctl.h
index e20ccb4..b80488e 100644
--- a/daxctl/libdaxctl.h
+++ b/daxctl/libdaxctl.h
@@ -69,6 +69,9 @@ int daxctl_dev_get_minor(struct daxctl_dev *dev);
 unsigned long long daxctl_dev_get_size(struct daxctl_dev *dev);
 struct daxctl_ctx *daxctl_dev_get_ctx(struct daxctl_dev *dev);
 int daxctl_dev_is_enabled(struct daxctl_dev *dev);
+int daxctl_dev_disable(struct daxctl_dev *dev);
+int daxctl_dev_enable_devdax(struct daxctl_dev *dev);
+int daxctl_dev_enable_ram(struct daxctl_dev *dev);
 
 #define daxctl_dev_foreach(region, dev) \
         for (dev = daxctl_dev_get_first(region); \
@@ -81,6 +84,12 @@ int daxctl_dev_is_enabled(struct daxctl_dev *dev);
              region != NULL; \
              region = daxctl_region_get_next(region))
 
+enum daxctl_dev_mode {
+	DAXCTL_DEV_MODE_UNKNOWN,
+	DAXCTL_DEV_MODE_RAM,
+	DAXCTL_DEV_MODE_DEVDAX,
+};
+
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
-- 
2.20.1

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* [ndctl PATCH 4/8] ndctl: add helpers to get/set the online state for a node
  2019-05-03 21:32 [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Vishal Verma
                   ` (2 preceding siblings ...)
  2019-05-03 21:32 ` [ndctl PATCH 3/8] daxctl: add libdaxctl interfaces to enable/disable devices Vishal Verma
@ 2019-05-03 21:32 ` Vishal Verma
  2019-05-03 21:32 ` [ndctl PATCH 5/8] daxctl: add a new reconfigure-device command Vishal Verma
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Vishal Verma @ 2019-05-03 21:32 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: Dave Hansen, Pavel Tatashin

In preparation for converting DAX devices for use as system-ram via the
kernel's 'kmem' facility, add libndctl helpers to manipulate the sysfs
interfaces to get the target_node of a DAX device, and to online,
offline, and query the state of hotplugged memory sections associated
with a given node.

This adds the following new interfaces:

  daxctl_dev_get_target_node
  daxctl_dev_online_node
  daxctl_dev_offline_node
  daxctl_dev_node_is_online

Cc: Pavel Tatashin <pasha.tatashin@soleen.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 daxctl/lib/libdaxctl-private.h |   6 +
 daxctl/lib/libdaxctl.c         | 228 +++++++++++++++++++++++++++++++++
 daxctl/lib/libdaxctl.sym       |   4 +
 daxctl/libdaxctl.h             |   4 +
 4 files changed, 242 insertions(+)

diff --git a/daxctl/lib/libdaxctl-private.h b/daxctl/lib/libdaxctl-private.h
index e64d0a7..ef443aa 100644
--- a/daxctl/lib/libdaxctl-private.h
+++ b/daxctl/lib/libdaxctl-private.h
@@ -33,6 +33,11 @@ static const char *dax_modules[] = {
 	[DAXCTL_DEV_MODE_RAM] = "kmem",
 };
 
+enum node_state {
+	NODE_OFFLINE,
+	NODE_ONLINE,
+};
+
 /**
  * struct daxctl_region - container for dax_devices
  */
@@ -63,6 +68,7 @@ struct daxctl_dev {
 	struct kmod_module *module;
 	struct kmod_list *kmod_list;
 	struct daxctl_region *region;
+	int target_node;
 };
 
 static inline int check_kmod(struct kmod_ctx *kmod_ctx)
diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
index d50b321..aab2364 100644
--- a/daxctl/lib/libdaxctl.c
+++ b/daxctl/lib/libdaxctl.c
@@ -28,6 +28,7 @@
 #include "libdaxctl-private.h"
 
 static const char *attrs = "dax_region";
+static const char *node_base = "/sys/devices/system/node";
 
 static void free_region(struct daxctl_region *region, struct list_head *head);
 
@@ -397,6 +398,12 @@ static void *add_dax_dev(void *parent, int id, const char *daxdev_base)
 	} else
 		dbg(ctx, "%s: modalias attribute missing\n", devname);
 
+	sprintf(path, "%s/target_node", daxdev_base);
+	if (sysfs_read_attr(ctx, path, buf) == 0)
+		dev->target_node = strtol(buf, NULL, 0);
+	else
+		dev->target_node = -1;
+
 	daxctl_dev_foreach(region, dev_dup)
 		if (dev_dup->id == dev->id) {
 			free_dev(dev, NULL);
@@ -897,3 +904,224 @@ DAXCTL_EXPORT unsigned long long daxctl_dev_get_size(struct daxctl_dev *dev)
 {
 	return dev->size;
 }
+
+DAXCTL_EXPORT int daxctl_dev_get_target_node(struct daxctl_dev *dev)
+{
+	return dev->target_node;
+}
+
+static int online_one_memblock(struct daxctl_dev *dev, char *path)
+{
+	const char *devname = daxctl_dev_get_devname(dev);
+	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
+	const char *mode = "online_movable";
+	char buf[SYSFS_ATTR_SIZE];
+	int rc;
+
+	rc = sysfs_read_attr(ctx, path, buf);
+	if (rc) {
+		err(ctx, "%s: Failed to read %s: %s\n",
+			devname, path, strerror(-rc));
+		return rc;
+	}
+
+	/*
+	 * if already online, possibly due to kernel config or a udev rule,
+	 * there is nothing to do and we can skip over the memblock
+	 */
+	if (strncmp(buf, "online", 6) == 0)
+		return 0;
+
+	rc = sysfs_write_attr_quiet(ctx, path, mode);
+	if (rc)
+		err(ctx, "%s: Failed to online %s: %s\n",
+			devname, path, strerror(-rc));
+	return rc;
+}
+
+static int offline_one_memblock(struct daxctl_dev *dev, char *path)
+{
+	const char *devname = daxctl_dev_get_devname(dev);
+	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
+	const char *mode = "offline";
+	char buf[SYSFS_ATTR_SIZE];
+	int rc;
+
+	rc = sysfs_read_attr(ctx, path, buf);
+	if (rc) {
+		err(ctx, "%s: Failed to read %s: %s\n",
+			devname, path, strerror(-rc));
+		return rc;
+	}
+
+	/* if already offline, there is nothing to do */
+	if (strncmp(buf, "offline", 6) == 0)
+		return 0;
+
+	rc = sysfs_write_attr_quiet(ctx, path, mode);
+	if (rc)
+		err(ctx, "%s: Failed to offline %s: %s\n",
+			devname, path, strerror(-rc));
+	return rc;
+}
+
+static int daxctl_dev_node_set_state(struct daxctl_dev *dev,
+		enum node_state state)
+{
+	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
+	int target_node, rc, changed = 0;
+	struct dirent *de;
+	char *node_path;
+	DIR *node_dir;
+
+	target_node = daxctl_dev_get_target_node(dev);
+	if (target_node < 0) {
+		err(ctx, "%s: Unable to get target node\n",
+			daxctl_dev_get_devname(dev));
+		return -ENXIO;
+	}
+
+	rc = asprintf(&node_path, "%s/node%d", node_base, target_node);
+	if (rc < 0)
+		return -ENOMEM;
+
+	node_dir = opendir(node_path);
+	if (!node_dir) {
+		rc = -errno;
+		goto out_path;
+	}
+
+	errno = 0;
+	while ((de = readdir(node_dir)) != NULL) {
+		char *mem_path;
+
+		if (strcmp(de->d_name, ".") == 0 ||
+				strcmp(de->d_name, "..") == 0)
+			continue;
+		if (strncmp(de->d_name, "memory", 6) == 0) {
+			rc = asprintf(&mem_path, "%s/%s/state",
+				node_path, de->d_name);
+			if (rc < 0) {
+				rc = -ENOMEM;
+				goto out_dir;
+			}
+			if (state == NODE_ONLINE)
+				rc = online_one_memblock(dev, mem_path);
+			else if (state == NODE_OFFLINE)
+				rc = offline_one_memblock(dev, mem_path);
+			else
+				rc = -EINVAL;
+			free(mem_path);
+			if (rc)
+				goto out_dir;
+			changed++;
+		}
+		errno = 0;
+	}
+	if (errno) {
+		rc = -errno;
+		goto out_dir;
+	}
+	rc = changed;
+
+out_dir:
+	closedir(node_dir);
+out_path:
+	free(node_path);
+	return rc;
+}
+
+DAXCTL_EXPORT int daxctl_dev_online_node(struct daxctl_dev *dev)
+{
+	return daxctl_dev_node_set_state(dev, NODE_ONLINE);
+}
+
+DAXCTL_EXPORT int daxctl_dev_offline_node(struct daxctl_dev *dev)
+{
+	return daxctl_dev_node_set_state(dev, NODE_OFFLINE);
+}
+
+static int memblock_is_online(struct daxctl_dev *dev, char *path)
+{
+	const char *devname = daxctl_dev_get_devname(dev);
+	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
+	char buf[SYSFS_ATTR_SIZE];
+	int rc;
+
+	rc = sysfs_read_attr(ctx, path, buf);
+	if (rc) {
+		err(ctx, "%s: Failed to read %s: %s\n",
+			devname, path, strerror(-rc));
+		return rc;
+	}
+
+	if (strncmp(buf, "online", 6) == 0)
+		return 1;
+
+	return 0;
+}
+
+DAXCTL_EXPORT int daxctl_dev_node_is_online(struct daxctl_dev *dev)
+{
+	const char *devname = daxctl_dev_get_devname(dev);
+	struct daxctl_ctx *ctx = daxctl_dev_get_ctx(dev);
+	int target_node, rc, num_online = 0;
+	struct dirent *de;
+	char *node_path;
+	DIR *node_dir;
+
+	target_node = daxctl_dev_get_target_node(dev);
+	if (target_node < 0) {
+		err(ctx, "%s: Unable to get target node\n", devname);
+		return -ENXIO;
+	}
+
+	rc = asprintf(&node_path, "%s/node%d", node_base, target_node);
+	if (rc < 0)
+		return -ENOMEM;
+
+	node_dir = opendir(node_path);
+	if (!node_dir) {
+		rc = -errno;
+		goto out_path;
+	}
+
+	errno = 0;
+	while ((de = readdir(node_dir)) != NULL) {
+		char *mem_path;
+
+		if (strcmp(de->d_name, ".") == 0 ||
+				strcmp(de->d_name, "..") == 0)
+			continue;
+		if (strncmp(de->d_name, "memory", 6) == 0) {
+			rc = asprintf(&mem_path, "%s/%s/state",
+				node_path, de->d_name);
+			if (rc < 0) {
+				rc = -ENOMEM;
+				goto out_dir;
+			}
+			rc = memblock_is_online(dev, mem_path);
+			if (rc < 0) {
+				err(ctx, "%s: Unable to determine state: %s\n",
+					devname, mem_path);
+				goto out_dir;
+			}
+			if (rc > 0)
+				num_online++;
+			free(mem_path);
+		}
+		errno = 0;
+	}
+	if (errno) {
+		rc = -errno;
+		goto out_dir;
+	}
+	rc = num_online;
+
+out_dir:
+	closedir(node_dir);
+out_path:
+	free(node_path);
+	return rc;
+
+}
diff --git a/daxctl/lib/libdaxctl.sym b/daxctl/lib/libdaxctl.sym
index 19904a2..cc47ed6 100644
--- a/daxctl/lib/libdaxctl.sym
+++ b/daxctl/lib/libdaxctl.sym
@@ -54,8 +54,12 @@ global:
 LIBDAXCTL_6 {
 global:
 	daxctl_dev_get_ctx;
+	daxctl_dev_get_target_node;
 	daxctl_dev_is_enabled;
 	daxctl_dev_disable;
 	daxctl_dev_enable_devdax;
 	daxctl_dev_enable_ram;
+	daxctl_dev_online_node;
+	daxctl_dev_offline_node;
+	daxctl_dev_node_is_online;
 } LIBDAXCTL_5;
diff --git a/daxctl/libdaxctl.h b/daxctl/libdaxctl.h
index b80488e..db0d4ea 100644
--- a/daxctl/libdaxctl.h
+++ b/daxctl/libdaxctl.h
@@ -68,10 +68,14 @@ int daxctl_dev_get_major(struct daxctl_dev *dev);
 int daxctl_dev_get_minor(struct daxctl_dev *dev);
 unsigned long long daxctl_dev_get_size(struct daxctl_dev *dev);
 struct daxctl_ctx *daxctl_dev_get_ctx(struct daxctl_dev *dev);
+int daxctl_dev_get_target_node(struct daxctl_dev *dev);
 int daxctl_dev_is_enabled(struct daxctl_dev *dev);
 int daxctl_dev_disable(struct daxctl_dev *dev);
 int daxctl_dev_enable_devdax(struct daxctl_dev *dev);
 int daxctl_dev_enable_ram(struct daxctl_dev *dev);
+int daxctl_dev_online_node(struct daxctl_dev *dev);
+int daxctl_dev_offline_node(struct daxctl_dev *dev);
+int daxctl_dev_node_is_online(struct daxctl_dev *dev);
 
 #define daxctl_dev_foreach(region, dev) \
         for (dev = daxctl_dev_get_first(region); \
-- 
2.20.1

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* [ndctl PATCH 5/8] daxctl: add a new reconfigure-device command
  2019-05-03 21:32 [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Vishal Verma
                   ` (3 preceding siblings ...)
  2019-05-03 21:32 ` [ndctl PATCH 4/8] ndctl: add helpers to get/set the online state for a node Vishal Verma
@ 2019-05-03 21:32 ` Vishal Verma
  2019-05-03 21:32 ` [ndctl PATCH 6/8] Documentation/daxctl: add a man page for daxctl-reconfigure-device Vishal Verma
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Vishal Verma @ 2019-05-03 21:32 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: Dave Hansen, Pavel Tatashin

Add a new command 'daxctl-reconfigure-device'. This is used to switch
the mode of a dax device between regular 'device_dax' and
'system-memory'. The command also uses the memory hotplug sysfs
interfaces to online the newly available memory when converting to
'system-ram', and to attempt to offline the memory when converting back
to a DAX device.

Cc: Pavel Tatashin <pasha.tatashin@soleen.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 daxctl/Makefile.am |   2 +
 daxctl/builtin.h   |   1 +
 daxctl/daxctl.c    |   1 +
 daxctl/device.c    | 217 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 221 insertions(+)
 create mode 100644 daxctl/device.c

diff --git a/daxctl/Makefile.am b/daxctl/Makefile.am
index 94f73f9..66dcc7f 100644
--- a/daxctl/Makefile.am
+++ b/daxctl/Makefile.am
@@ -15,10 +15,12 @@ daxctl_SOURCES =\
 		daxctl.c \
 		list.c \
 		migrate.c \
+		device.c \
 		../util/json.c
 
 daxctl_LDADD =\
 	lib/libdaxctl.la \
 	../libutil.a \
 	$(UUID_LIBS) \
+	$(KMOD_LIBS) \
 	$(JSON_LIBS)
diff --git a/daxctl/builtin.h b/daxctl/builtin.h
index 00ef5e9..756ba2a 100644
--- a/daxctl/builtin.h
+++ b/daxctl/builtin.h
@@ -6,4 +6,5 @@
 struct daxctl_ctx;
 int cmd_list(int argc, const char **argv, struct daxctl_ctx *ctx);
 int cmd_migrate(int argc, const char **argv, struct daxctl_ctx *ctx);
+int cmd_reconfig_device(int argc, const char **argv, struct daxctl_ctx *ctx);
 #endif /* _DAXCTL_BUILTIN_H_ */
diff --git a/daxctl/daxctl.c b/daxctl/daxctl.c
index 2e41747..e1ba7b8 100644
--- a/daxctl/daxctl.c
+++ b/daxctl/daxctl.c
@@ -71,6 +71,7 @@ static struct cmd_struct commands[] = {
 	{ "list", .d_fn = cmd_list },
 	{ "help", .d_fn = cmd_help },
 	{ "migrate-device-model", .d_fn = cmd_migrate },
+	{ "reconfigure-device", .d_fn = cmd_reconfig_device },
 };
 
 int main(int argc, const char **argv)
diff --git a/daxctl/device.c b/daxctl/device.c
new file mode 100644
index 0000000..0a6102f
--- /dev/null
+++ b/daxctl/device.c
@@ -0,0 +1,217 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2019 Intel Corporation. All rights reserved. */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <limits.h>
+#include <util/json.h>
+#include <util/filter.h>
+#include <json-c/json.h>
+#include <daxctl/libdaxctl.h>
+#include <util/parse-options.h>
+#include <ccan/array_size/array_size.h>
+
+static struct {
+	const char *dev;
+	const char *mode;
+	int region_id;
+	bool no_online;
+	bool do_offline;
+	bool human;
+	bool verbose;
+} param = {
+	.region_id = -1,
+};
+
+static int dev_disable(struct daxctl_dev *dev)
+{
+	int rc;
+
+	if (!daxctl_dev_is_enabled(dev))
+		return 0;
+
+	rc = daxctl_dev_disable(dev);
+	if (rc)
+		fprintf(stderr, "%s: disable failed: %s\n",
+			daxctl_dev_get_devname(dev), strerror(-rc));
+
+	return rc;
+}
+
+static int reconfig_mode_ram(struct daxctl_dev *dev)
+{
+	const char *devname = daxctl_dev_get_devname(dev);
+	int rc;
+
+	rc = dev_disable(dev);
+	if (rc)
+		return rc;
+	rc = daxctl_dev_enable_ram(dev);
+	if (rc)
+		return rc;
+
+	if (param.no_online)
+		return 0;
+
+	rc = daxctl_dev_online_node(dev);
+	if (rc < 0) {
+		fprintf(stderr, "%s: unable to online memory: %s\n",
+			devname, strerror(-rc));
+		return rc;
+	}
+	if (param.verbose)
+		fprintf(stderr, "%s: onlined %d memory sections\n",
+			devname, rc);
+
+	return 0;
+}
+
+static int reconfig_mode_devdax(struct daxctl_dev *dev)
+{
+	const char *devname = daxctl_dev_get_devname(dev);
+	int rc;
+
+	if (param.do_offline) {
+		rc = daxctl_dev_offline_node(dev);
+		if (rc < 0) {
+			fprintf(stderr, "%s: unable to offline memory: %s\n",
+				devname, strerror(-rc));
+			return rc;
+		}
+		if (param.verbose)
+			fprintf(stderr, "%s: offlined %d memory sections\n",
+				devname, rc);
+	}
+
+	rc = daxctl_dev_node_is_online(dev);
+	if (rc < 0) {
+		fprintf(stderr, "%s: unable to determine node state: %s\n",
+			devname, strerror(-rc));
+		return rc;
+	}
+	if (rc > 0) {
+		if (param.verbose) {
+			fprintf(stderr, "%s: found %d memory sections online\n",
+				devname, rc);
+			fprintf(stderr, "%s: refusing to change modes\n",
+				devname);
+		}
+		return -EBUSY;
+	}
+
+	rc = dev_disable(dev);
+	if (rc)
+		return rc;
+
+	rc = daxctl_dev_enable_devdax(dev);
+	if (rc)
+		return rc;
+
+	return 0;
+}
+
+static int do_reconfig(struct daxctl_dev *dev, unsigned long flags,
+		enum daxctl_dev_mode mode)
+{
+	int rc = 0;
+
+	switch (mode) {
+	case DAXCTL_DEV_MODE_RAM:
+		rc = reconfig_mode_ram(dev);
+		break;
+	case DAXCTL_DEV_MODE_DEVDAX:
+		rc = reconfig_mode_devdax(dev);
+		break;
+	default:
+		fprintf(stderr, "%s: unknown mode: %d\n",
+			daxctl_dev_get_devname(dev), mode);
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+int cmd_reconfig_device(int argc, const char **argv, struct daxctl_ctx *ctx)
+{
+	const struct option options[] = {
+		OPT_INTEGER('r', "region", &param.region_id,
+				"restrict to the given region"),
+		OPT_STRING('m', "mode", &param.mode, "mode",
+				"mode to switch the device to"),
+		OPT_BOOLEAN('N', "no-online", &param.no_online,
+				"don't auto-online memory sections"),
+		OPT_BOOLEAN('\0', "attempt-offline", &param.do_offline,
+				"attempt to offline memory sections"),
+		OPT_BOOLEAN('u', "human", &param.human,
+				"use human friendly number formats"),
+		OPT_BOOLEAN('v', "verbose", &param.verbose,
+				"emit more debug messages"),
+		OPT_END(),
+	};
+	const char * const u[] = {
+		"daxctl reconfigure-device [<options>] <device> ...",
+		NULL
+	};
+	enum daxctl_dev_mode mode = DAXCTL_DEV_MODE_UNKNOWN;
+	struct daxctl_region *region;
+	int i, rc = 0, done = 0;
+	unsigned long flags = 0;
+	struct daxctl_dev *dev;
+
+        argc = parse_options(argc, argv, options, u, 0);
+	if (argc == 0)
+		usage_with_options(u, options);
+	for (i = 0; i < argc; i++) {
+		if (strcmp(argv[i], "all") == 0) {
+			argv[0] = "all";
+			argc = 1;
+			break;
+		}
+	}
+
+	if (param.human)
+		flags |= UTIL_JSON_HUMAN;
+
+	if (!param.mode) {
+		fprintf(stderr, "error: a 'mode' option is required\n");
+		usage_with_options(u, options);
+	}
+	if (strcmp(param.mode, "system-ram") == 0)
+		mode = DAXCTL_DEV_MODE_RAM;
+	else if (strcmp(param.mode, "devdax") == 0)
+		mode = DAXCTL_DEV_MODE_DEVDAX;
+
+	daxctl_region_foreach(ctx, region) {
+		if (param.region_id >= 0 && param.region_id
+				!= daxctl_region_get_id(region))
+			continue;
+
+		daxctl_dev_foreach(region, dev) {
+			bool dev_requested = false;
+
+			for (i = 0; i < argc; i++) {
+				if ((strcmp(daxctl_dev_get_devname(dev),
+						argv[i]) == 0) ||
+						(strcmp(argv[i], "all") == 0)) {
+					dev_requested = true;
+					break;
+				}
+			}
+			if (dev_requested) {
+				rc = do_reconfig(dev, flags, mode);
+				if (rc < 0)
+					goto out_err;
+				done++;
+			}
+		}
+	}
+	fprintf(stderr, "reconfigured %d device%s\n", done,
+		done == 1 ? "" : "s");
+	return 0;
+
+out_err:
+	fprintf(stderr, "error reconfiguring %s: %s\n",
+		daxctl_dev_get_devname(dev), strerror(-rc));
+	return rc;
+}
-- 
2.20.1

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* [ndctl PATCH 6/8] Documentation/daxctl: add a man page for daxctl-reconfigure-device
  2019-05-03 21:32 [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Vishal Verma
                   ` (4 preceding siblings ...)
  2019-05-03 21:32 ` [ndctl PATCH 5/8] daxctl: add a new reconfigure-device command Vishal Verma
@ 2019-05-03 21:32 ` Vishal Verma
  2019-05-03 21:32 ` [ndctl PATCH 7/8] contrib/ndctl: fix region-id completions for daxctl Vishal Verma
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 12+ messages in thread
From: Vishal Verma @ 2019-05-03 21:32 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: Dave Hansen, Pavel Tatashin

Add a man page describing the new daxctl-reconfigure-device command.

Cc: Pavel Tatashin <pasha.tatashin@soleen.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 Documentation/daxctl/Makefile.am              |  3 +-
 .../daxctl/daxctl-reconfigure-device.txt      | 74 +++++++++++++++++++
 2 files changed, 76 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/daxctl/daxctl-reconfigure-device.txt

diff --git a/Documentation/daxctl/Makefile.am b/Documentation/daxctl/Makefile.am
index 6aba035..715fbad 100644
--- a/Documentation/daxctl/Makefile.am
+++ b/Documentation/daxctl/Makefile.am
@@ -28,7 +28,8 @@ endif
 man1_MANS = \
 	daxctl.1 \
 	daxctl-list.1 \
-	daxctl-migrate-device-model.1
+	daxctl-migrate-device-model.1 \
+	daxctl-reconfigure-device.1
 
 CLEANFILES = $(man1_MANS)
 
diff --git a/Documentation/daxctl/daxctl-reconfigure-device.txt b/Documentation/daxctl/daxctl-reconfigure-device.txt
new file mode 100644
index 0000000..d79547c
--- /dev/null
+++ b/Documentation/daxctl/daxctl-reconfigure-device.txt
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0
+
+daxctl-reconfigure-device(1)
+============================
+
+NAME
+----
+daxctl-reconfigure-device - Reconfigure a dax device into a different mode
+
+SYNOPSIS
+--------
+[verse]
+'daxctl reconfigure-device' <dax0.0> [<dax1.0>...<daxY.Z>] [<options>]
+
+DESCRIPTION
+-----------
+
+Reconfigure the operational mode of a dax device. This can be used to convert
+a regular 'devdax' mode device to the 'system-ram' mode which allows for the dax
+range to be hot-plugged into the system as regular memory.
+
+NOTE: This is a destructive, one-way operation. Any data on the dax device
+*will* be lost, and once reconfigured, there is no equivalent operation to
+go back to the normal 'devdax' mode until a reboot.
+
+OPTIONS
+-------
+-r::
+--region=::
+	Restrict the reconfigure operation to devices belonging to the
+	specified region(s). A device-dax region is a contiguous range of
+	memory that hosts one or more /dev/daxX.Y devices, where X is the
+	region id and Y is the device instance id.
+
+-m::
+--mode=::
+	Specify the mode to which the dax device(s) should be reconfigured.
+	- "system-ram": hotplug the device into system memory. This is a
+	  one-way operation. Once a device is configured this way, the
+	  setting persists across reboots, until the command is called again
+	  to explicitly switch to the 'devdax' mode.
+
+	- "devdax": switch to the normal "device dax" mode. This only takes
+	  effect following a system reboot.
+
+-N::
+--no-online::
+	By default, memory sections provided by system-ram devices will be
+	brought online automatically and immediately. Use this option to
+	disable the automatic onlining behavior.
+
+--attempt-offline::
+	When converting from "system-ram" mode to "devdax", it is expected
+	that all the memory sections are first made offline. By default,
+	daxctl won't touch online memory. However with this option, attempt
+	to offline the memory on the NUMA node associated with the dax device
+	before converting it back to "devdax" mode.
+
+-u::
+--human::
+	By default the command will output machine-friendly raw-integer
+	data. Instead, with this flag, numbers representing storage size
+	will be formatted as human readable strings with units, other
+	fields are converted to hexadecimal strings.
+
+-v::
+--verbose::
+	Emit more debug messages for the reconfiguration process
+
+include::../copyright.txt[]
+
+SEE ALSO
+--------
+linkdaxctl:daxctl-list[1]
-- 
2.20.1

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* [ndctl PATCH 7/8] contrib/ndctl: fix region-id completions for daxctl
  2019-05-03 21:32 [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Vishal Verma
                   ` (5 preceding siblings ...)
  2019-05-03 21:32 ` [ndctl PATCH 6/8] Documentation/daxctl: add a man page for daxctl-reconfigure-device Vishal Verma
@ 2019-05-03 21:32 ` Vishal Verma
  2019-05-03 21:32 ` [ndctl PATCH 8/8] contrib/ndctl: add bash-completion for daxctl-reconfigure-device Vishal Verma
  2019-05-06 21:50 ` [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Dave Hansen
  8 siblings, 0 replies; 12+ messages in thread
From: Vishal Verma @ 2019-05-03 21:32 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: Dave Hansen, Pavel Tatashin

The completion helpers for daxctl assumed the region arguments for
specifying daxctl regions were the same as ndctl regions, i.e.
"regionX". This is not true - daxctl region arguments are a simple
numeric 'id'.

Add a new helper __daxctl_get_regions() to complete daxctl region IDs
properly.

While at it, fix a useless use of 'echo' in __daxctl_get_devs() and
quoting in __daxctl_comp_options()

Fixes: d6790a32f32c ("daxctl: Add bash-completion")
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 contrib/ndctl | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/contrib/ndctl b/contrib/ndctl
index e17fb0b..d1f8bd6 100755
--- a/contrib/ndctl
+++ b/contrib/ndctl
@@ -528,8 +528,14 @@ _ndctl()
 
 __daxctl_get_devs()
 {
-	local opts="--devices $*"
-	echo "$(daxctl list $opts | grep -E "^\s*\"chardev\":" | cut -d\" -f4)"
+	local opts=("--devices" "$*")
+	daxctl list "${opts[@]}" | grep -E "^\s*\"chardev\":" | cut -d'"' -f4
+}
+
+__daxctl_get_regions()
+{
+	local opts=("--regions" "$*")
+	daxctl list "${opts[@]}" | grep -E "^\s*\"id\":" | grep -Eo "[0-9]+"
 }
 
 __daxctlcomp()
@@ -558,10 +564,10 @@ __daxctl_comp_options()
 		local cur_arg=${cur##*=}
 		case $cur_subopt in
 		--region)
-			opts=$(__ndctl_get_regions -i)
+			opts="$(__daxctl_get_regions -i)"
 			;;
 		--dev)
-			opts=$(__daxctl_get_devs -i)
+			opts="$(__daxctl_get_devs -i)"
 			;;
 		*)
 			return
-- 
2.20.1

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* [ndctl PATCH 8/8] contrib/ndctl: add bash-completion for daxctl-reconfigure-device
  2019-05-03 21:32 [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Vishal Verma
                   ` (6 preceding siblings ...)
  2019-05-03 21:32 ` [ndctl PATCH 7/8] contrib/ndctl: fix region-id completions for daxctl Vishal Verma
@ 2019-05-03 21:32 ` Vishal Verma
  2019-05-06 21:50 ` [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Dave Hansen
  8 siblings, 0 replies; 12+ messages in thread
From: Vishal Verma @ 2019-05-03 21:32 UTC (permalink / raw)
  To: linux-nvdimm; +Cc: Dave Hansen, Pavel Tatashin

Add bash completion helpers for the new daxctl-reconfigure-device
command.

Cc: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 contrib/ndctl | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/contrib/ndctl b/contrib/ndctl
index d1f8bd6..32c4731 100755
--- a/contrib/ndctl
+++ b/contrib/ndctl
@@ -544,7 +544,7 @@ __daxctlcomp()
 
 	COMPREPLY=( $( compgen -W "$1" -- "$2" ) )
 	for cword in "${COMPREPLY[@]}"; do
-		if [[ "$cword" == @(--region|--dev) ]]; then
+		if [[ "$cword" == @(--region|--dev|--mode) ]]; then
 			COMPREPLY[$i]="${cword}="
 		else
 			COMPREPLY[$i]="${cword} "
@@ -569,6 +569,9 @@ __daxctl_comp_options()
 		--dev)
 			opts="$(__daxctl_get_devs -i)"
 			;;
+		--mode)
+			opts="system-ram devdax"
+			;;
 		*)
 			return
 			;;
@@ -579,8 +582,19 @@ __daxctl_comp_options()
 
 __daxctl_comp_non_option_args()
 {
-	# there aren't any commands that accept non option arguments yet
-	return
+	local subcmd=$1
+	local cur=$2
+	local opts
+
+	case $subcmd in
+	reconfigure-device)
+		opts="$(__daxctl_get_devs -i) all"
+		;;
+	*)
+		return
+		;;
+	esac
+	__daxctlcomp "$opts" "$cur"
 }
 
 __daxctl_main()
-- 
2.20.1

_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* Re: [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command
  2019-05-03 21:32 [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Vishal Verma
                   ` (7 preceding siblings ...)
  2019-05-03 21:32 ` [ndctl PATCH 8/8] contrib/ndctl: add bash-completion for daxctl-reconfigure-device Vishal Verma
@ 2019-05-06 21:50 ` Dave Hansen
  2019-05-06 22:14   ` Verma, Vishal L
  8 siblings, 1 reply; 12+ messages in thread
From: Dave Hansen @ 2019-05-06 21:50 UTC (permalink / raw)
  To: Vishal Verma, linux-nvdimm; +Cc: Dave Hansen, Pavel Tatashin

This all looks quite nice to me.  Thanks, Vishal!

One minor nit: for those of us new to daxctl and friends, they can be a
bit hard to get started with.  Could you maybe add a few example
invocations to the Documentation, or even this cover letter to help us
newbies get started?
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* Re: [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command
  2019-05-06 21:50 ` [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Dave Hansen
@ 2019-05-06 22:14   ` Verma, Vishal L
  2019-05-06 22:17     ` Verma, Vishal L
  0 siblings, 1 reply; 12+ messages in thread
From: Verma, Vishal L @ 2019-05-06 22:14 UTC (permalink / raw)
  To: linux-nvdimm, Hansen, Dave; +Cc: dave.hansen, pasha.tatashin

On Mon, 2019-05-06 at 14:50 -0700, Dave Hansen wrote:
> This all looks quite nice to me.  Thanks, Vishal!
> 
> One minor nit: for those of us new to daxctl and friends, they can be
> a
> bit hard to get started with.  Could you maybe add a few example
> invocations to the Documentation, or even this cover letter to help us
> newbies get started?

Yes, good idea, I'll add an examples section to the Documentation page
(other commands do this, and this should too), and add those to the
cover letter as well for v2.

Thanks!
-Vishal
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

* Re: [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command
  2019-05-06 22:14   ` Verma, Vishal L
@ 2019-05-06 22:17     ` Verma, Vishal L
  0 siblings, 0 replies; 12+ messages in thread
From: Verma, Vishal L @ 2019-05-06 22:17 UTC (permalink / raw)
  To: linux-nvdimm, Hansen, Dave; +Cc: dave.hansen, pasha.tatashin


On Mon, 2019-05-06 at 22:14 +0000, Verma, Vishal L wrote:
> On Mon, 2019-05-06 at 14:50 -0700, Dave Hansen wrote:
> > This all looks quite nice to me.  Thanks, Vishal!
> > 
> > One minor nit: for those of us new to daxctl and friends, they can
> > be
> > a
> > bit hard to get started with.  Could you maybe add a few example
> > invocations to the Documentation, or even this cover letter to help
> > us
> > newbies get started?
> 
> Yes, good idea, I'll add an examples section to the Documentation page
> (other commands do this, and this should too), and add those to the
> cover letter as well for v2.

I meant to add, for now, a few of the most useful invocations probably
look like:

1. # daxctl reconfigure-device --mode=system-ram dax0.0
(this will also online the memory sections)

2. # daxctl reconfigure-device --mode=system-ram --no-online dax0.0
(this will *not* online the memory sections)

3. # daxctl reconfigure-device --mode=devdax --attempt-offline dax0.0
(this requires Pavel's patches for kmem-unbind, and won't work with
vanilla v5.1)
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

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

end of thread, other threads:[~2019-05-06 22:17 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-05-03 21:32 [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Vishal Verma
2019-05-03 21:32 ` [ndctl PATCH 1/8] libdaxctl: add interfaces in support of device modes Vishal Verma
2019-05-03 21:32 ` [ndctl PATCH 2/8] libdaxctl: cache 'subsystem' in daxctl_ctx Vishal Verma
2019-05-03 21:32 ` [ndctl PATCH 3/8] daxctl: add libdaxctl interfaces to enable/disable devices Vishal Verma
2019-05-03 21:32 ` [ndctl PATCH 4/8] ndctl: add helpers to get/set the online state for a node Vishal Verma
2019-05-03 21:32 ` [ndctl PATCH 5/8] daxctl: add a new reconfigure-device command Vishal Verma
2019-05-03 21:32 ` [ndctl PATCH 6/8] Documentation/daxctl: add a man page for daxctl-reconfigure-device Vishal Verma
2019-05-03 21:32 ` [ndctl PATCH 7/8] contrib/ndctl: fix region-id completions for daxctl Vishal Verma
2019-05-03 21:32 ` [ndctl PATCH 8/8] contrib/ndctl: add bash-completion for daxctl-reconfigure-device Vishal Verma
2019-05-06 21:50 ` [ndctl PATCH 0/8] daxctl: add a new reconfigure-device command Dave Hansen
2019-05-06 22:14   ` Verma, Vishal L
2019-05-06 22:17     ` Verma, Vishal L

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.