diff mbox

[ndctl,01/13] ndctl: add support for the namespace 'mode' attribute

Message ID 20160128225203.17855.30676.stgit@dwillia2-desk3.amr.corp.intel.com (mailing list archive)
State Accepted
Commit 46449562931d
Headers show

Commit Message

Dan Williams Jan. 28, 2016, 10:52 p.m. UTC
The three modes for a namespace are:

1/ 'memory': the kernel has the infrastructure to support the usage of
   DAX mappings of this namespace in any context.  In contrast to a
   'raw' pmem namespace that, for example, does not support direct I/O in
   current kernels.

2/ 'safe': the namespace is being fronted by a btt to provide atomic
   sector udpates.

3/ 'raw': Neither of the above two modes, this namespace may tear
   sectors on interrupted writes or fail direct I/O requests.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
---
 lib/libndctl.c      |   26 ++++++++++++++++++++++++++
 lib/libndctl.sym    |    1 +
 lib/test-dax-dev.c  |    5 +++++
 lib/test-libndctl.c |   13 +++++++++++++
 4 files changed, 45 insertions(+)
diff mbox

Patch

diff --git a/lib/libndctl.c b/lib/libndctl.c
index c0730690ed79..22bd2c123415 100644
--- a/lib/libndctl.c
+++ b/lib/libndctl.c
@@ -2868,6 +2868,32 @@  NDCTL_EXPORT const char *ndctl_namespace_get_block_device(struct ndctl_namespace
 	return ndns->bdev ? ndns->bdev : "";
 }
 
+NDCTL_EXPORT enum ndctl_namespace_mode ndctl_namespace_get_mode(
+		struct ndctl_namespace *ndns)
+{
+	struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns);
+	char *path = ndns->ndns_buf;
+	int len = ndns->buf_len;
+	char buf[SYSFS_ATTR_SIZE];
+
+	if (snprintf(path, len, "%s/mode", ndns->ndns_path) >= len) {
+		err(ctx, "%s: buffer too small!\n",
+				ndctl_namespace_get_devname(ndns));
+		return -ENOMEM;
+	}
+
+	if (sysfs_read_attr(ctx, path, buf) < 0)
+		return -ENXIO;
+
+	if (strcmp("memory", buf) == 0)
+		return NDCTL_NS_MODE_MEMORY;
+	if (strcmp("raw", buf) == 0)
+		return NDCTL_NS_MODE_RAW;
+	if (strcmp("safe", buf) == 0)
+		return NDCTL_NS_MODE_SAFE;
+	return -ENXIO;
+}
+
 NDCTL_EXPORT int ndctl_namespace_is_valid(struct ndctl_namespace *ndns)
 {
 	struct ndctl_region *region = ndctl_namespace_get_region(ndns);
diff --git a/lib/libndctl.sym b/lib/libndctl.sym
index 9cb2f0002c52..fe89fa26348e 100644
--- a/lib/libndctl.sym
+++ b/lib/libndctl.sym
@@ -132,6 +132,7 @@  global:
 	ndctl_namespace_get_id;
 	ndctl_namespace_get_devname;
 	ndctl_namespace_get_block_device;
+	ndctl_namespace_get_mode;
 	ndctl_region_get_nstype;
 	ndctl_namespace_get_type;
 	ndctl_namespace_get_type_name;
diff --git a/lib/test-dax-dev.c b/lib/test-dax-dev.c
index 3ca7cef0f71c..47d98ddd15a9 100755
--- a/lib/test-dax-dev.c
+++ b/lib/test-dax-dev.c
@@ -34,6 +34,7 @@  static int emit_e820_device(int loglevel, struct ndctl_test *test)
 	struct ndctl_bus *bus;
 	struct ndctl_region *region;
 	struct ndctl_namespace *ndns;
+	enum ndctl_namespace_mode mode;
 
 	if (!ndctl_test_attempt(test, KERNEL_VERSION(4, 3, 0)))
 		return 77;
@@ -56,6 +57,10 @@  static int emit_e820_device(int loglevel, struct ndctl_test *test)
 	if (!ndns)
 		goto out;
 
+	mode = ndctl_namespace_get_mode(ndns);
+	if (mode >= 0 && mode != NDCTL_NS_MODE_MEMORY)
+		goto out;
+
 	bdev = ndctl_namespace_get_block_device(ndns);
 	if (!bdev)
 		goto out;
diff --git a/lib/test-libndctl.c b/lib/test-libndctl.c
index 5acf971a1fb7..b6720ed59d95 100644
--- a/lib/test-libndctl.c
+++ b/lib/test-libndctl.c
@@ -575,6 +575,7 @@  static int __check_pfn_create(struct ndctl_region *region,
 		uuid_t uuid)
 {
 	struct ndctl_pfn *pfn_seed = ndctl_region_get_pfn_seed(region);
+	enum ndctl_namespace_mode mode;
 	struct ndctl_pfn *pfn;
 	const char *devname;
 	int fd, retry = 10;
@@ -600,6 +601,12 @@  static int __check_pfn_create(struct ndctl_region *region,
 		ndctl_pfn_delete(pfn);
 		return 0;
 	}
+
+	mode = ndctl_namespace_get_mode(ndns);
+	if (mode >= 0 && mode != NDCTL_NS_MODE_MEMORY)
+		fprintf(stderr, "%s: expected memory mode got: %d\n",
+				devname, mode);
+
 	if (namespace->ro == (rc == 0)) {
 		fprintf(stderr, "%s: expected pfn enable %s, %s read-%s\n",
 				devname,
@@ -718,6 +725,7 @@  static int check_btt_create(struct ndctl_region *region, struct ndctl_namespace
 	for (i = 0; i < btt_s->num_sector_sizes; i++) {
 		struct ndctl_namespace *ns_seed = ndctl_region_get_namespace_seed(region);
 		struct ndctl_btt *btt_seed = ndctl_region_get_btt_seed(region);
+		enum ndctl_namespace_mode mode;
 
 		btt = get_idle_btt(region);
 		if (!btt)
@@ -737,6 +745,11 @@  static int check_btt_create(struct ndctl_region *region, struct ndctl_namespace
 			goto err;
 		}
 
+		mode = ndctl_namespace_get_mode(ndns);
+		if (mode >= 0 && mode != NDCTL_NS_MODE_SAFE)
+			fprintf(stderr, "%s: expected safe mode got: %d\n",
+					devname, mode);
+
 		if (btt_seed == ndctl_region_get_btt_seed(region)
 				&& btt == btt_seed) {
 			fprintf(stderr, "%s: failed to advance btt seed\n",