From 3ac35c30bc05f1a0deeb7dbd6fca8a4edf5928a3 Mon Sep 17 00:00:00 2001
From: Weronika Lewandowska <weronika.lewandowska@intel.com>
Date: Mon, 15 Jun 2020 09:53:41 +0200
Subject: [PATCH] pmem2: ndctl get size

---
 src/libpmem2/pmem2_utils.h       |  2 +-
 src/libpmem2/pmem2_utils_linux.c | 68 --------------------------------
 src/libpmem2/pmem2_utils_ndctl.c | 40 +++++++++++++++++++
 src/libpmem2/pmem2_utils_none.c  | 12 ++++++
 src/libpmem2/pmem2_utils_other.c |  8 ++--
 src/libpmem2/source_posix.c      |  2 +-
 6 files changed, 58 insertions(+), 74 deletions(-)

diff --git a/src/libpmem2/pmem2_utils.h b/src/libpmem2/pmem2_utils.h
index 270d84c33..2a8f130f8 100644
--- a/src/libpmem2/pmem2_utils.h
+++ b/src/libpmem2/pmem2_utils.h
@@ -37,7 +37,7 @@ int pmem2_lasterror_to_err();
 #endif
 
 int pmem2_get_type_from_stat(const os_stat_t *st, enum pmem2_file_type *type);
-int pmem2_device_dax_size_from_dev(dev_t st_rdev, size_t *size);
+int pmem2_device_dax_size(const struct pmem2_source *src, size_t *size);
 int pmem2_device_dax_alignment(const struct pmem2_source *src,
 		size_t *alignment);
 
diff --git a/src/libpmem2/pmem2_utils_linux.c b/src/libpmem2/pmem2_utils_linux.c
index 7e7eaaf79..57cc432ff 100644
--- a/src/libpmem2/pmem2_utils_linux.c
+++ b/src/libpmem2/pmem2_utils_linux.c
@@ -15,8 +15,6 @@
 #include "region_namespace.h"
 #include "source.h"
 
-#define MAX_SIZE_LENGTH 64
-
 /*
  * pmem2_get_type_from_stat -- determine type of file based on output of stat
  * syscall
@@ -70,69 +68,3 @@ pmem2_get_type_from_stat(const os_stat_t *st, enum pmem2_file_type *type)
 
 	return 0;
 }
-
-/*
- * pmem2_device_dax_size_from_dev -- checks the size of a given
- * dax device from given stat structure
- */
-int
-pmem2_device_dax_size_from_dev(dev_t st_rdev, size_t *size)
-{
-	char spath[PATH_MAX];
-	int ret = util_snprintf(spath, PATH_MAX, "/sys/dev/char/%u:%u/size",
-		os_major(st_rdev), os_minor(st_rdev));
-
-	if (ret < 0) {
-		/* impossible */
-		ERR("!snprintf");
-		ASSERTinfo(0, "snprintf failed");
-		return PMEM2_E_ERRNO;
-	}
-
-	LOG(4, "device size path \"%s\"", spath);
-
-	int fd = os_open(spath, O_RDONLY);
-	if (fd < 0) {
-		ERR("!open \"%s\"", spath);
-		return PMEM2_E_ERRNO;
-	}
-
-	char sizebuf[MAX_SIZE_LENGTH + 1];
-
-	ssize_t nread = read(fd, sizebuf, MAX_SIZE_LENGTH);
-	if (nread < 0) {
-		ERR("!read");
-		int ret = PMEM2_E_ERRNO;
-		(void) os_close(fd);
-		return ret;
-	}
-	int olderrno = errno;
-	(void) os_close(fd);
-
-	sizebuf[nread] = 0; /* null termination */
-
-	char *endptr;
-
-	errno = 0;
-
-	unsigned long long tmpsize;
-	tmpsize = strtoull(sizebuf, &endptr, 0);
-	if (endptr == sizebuf || *endptr != '\n') {
-		ERR("invalid device size format '%s'", sizebuf);
-		errno = olderrno;
-		return PMEM2_E_INVALID_SIZE_FORMAT;
-	}
-
-	if (tmpsize == ULLONG_MAX && errno == ERANGE) {
-		ret = PMEM2_E_ERRNO;
-		ERR("invalid device size '%s'", sizebuf);
-		errno = olderrno;
-		return ret;
-	}
-
-	errno = olderrno;
-
-	*size = tmpsize;
-	LOG(4, "device size %zu", *size);
-	return 0;
-}
diff --git a/src/libpmem2/pmem2_utils_ndctl.c b/src/libpmem2/pmem2_utils_ndctl.c
index efeb1ee1c..fed823063 100644
--- a/src/libpmem2/pmem2_utils_ndctl.c
+++ b/src/libpmem2/pmem2_utils_ndctl.c
@@ -49,3 +49,43 @@ end:
 
 	return ret;
 }
+
+/*
+ * pmem2_device_dax_size -- checks the size of a given
+ * dax device from given source structure
+ */
+int
+pmem2_device_dax_size(const struct pmem2_source *src, size_t *size)
+{
+	int ret = 0;
+	struct ndctl_ctx *ctx;
+	struct ndctl_namespace *ndns;
+
+	errno = ndctl_new(&ctx) * (-1);
+	if (errno) {
+		ERR("!ndctl_new");
+		return PMEM2_E_ERRNO;
+	}
+
+	ret = pmem2_region_namespace(ctx, src, NULL, &ndns);
+	if (ret) {
+		LOG(1, "getting region and namespace failed");
+		goto end;
+	}
+
+	struct ndctl_dax *dax = ndctl_namespace_get_dax(ndns);
+
+	if (dax) {
+		*size = ndctl_dax_get_size(dax);
+	} else {
+		ret = PMEM2_E_DAX_REGION_NOT_FOUND;
+		ERR("Issue while reading Device Dax size - cannot "
+			"find dax region");
+	}
+
+end:
+	ndctl_unref(ctx);
+	LOG(4, "device size %zu", *size);
+
+	return ret;
+}
diff --git a/src/libpmem2/pmem2_utils_none.c b/src/libpmem2/pmem2_utils_none.c
index 2fdb81103..d24a9d45e 100644
--- a/src/libpmem2/pmem2_utils_none.c
+++ b/src/libpmem2/pmem2_utils_none.c
@@ -19,3 +19,15 @@ pmem2_device_dax_alignment(const struct pmem2_source *src, size_t *alignment)
 
 	return PMEM2_E_NOSUPP;
 }
+
+/*
+ * pmem2_device_dax_size -- checks the size of a given dax device from
+ * given source
+ */
+int
+pmem2_device_dax_size(const struct pmem2_source *src, size_t *size)
+{
+	ERR("Cannot read Device Dax size - ndctl is not available");
+
+	return PMEM2_E_NOSUPP;
+}
diff --git a/src/libpmem2/pmem2_utils_other.c b/src/libpmem2/pmem2_utils_other.c
index 0facab9f8..3df5e6f07 100644
--- a/src/libpmem2/pmem2_utils_other.c
+++ b/src/libpmem2/pmem2_utils_other.c
@@ -31,14 +31,14 @@ pmem2_get_type_from_stat(const os_stat_t *st, enum pmem2_file_type *type)
 }
 
 /*
- * pmem2_device_dax_size_from_dev -- (internal) checks the size of a given
- * dax device from given stat structure
+ * pmem2_device_dax_size -- checks the size of a given
+ * dax device from given source structure
  */
 int
-pmem2_device_dax_size_from_dev(dev_t st_rdev, size_t *size)
+pmem2_device_dax_size(const struct pmem2_source *src, size_t *size)
 {
 	const char *err =
-		"BUG: pmem2_device_dax_size_from_dev should never be called on this OS";
+		"BUG: pmem2_device_dax_size should never be called on this OS";
 	ERR("%s", err);
 	ASSERTinfo(0, err);
 	return PMEM2_E_NOSUPP;
diff --git a/src/libpmem2/source_posix.c b/src/libpmem2/source_posix.c
index 9c2b13767..3c079f925 100644
--- a/src/libpmem2/source_posix.c
+++ b/src/libpmem2/source_posix.c
@@ -106,7 +106,7 @@ pmem2_source_size(const struct pmem2_source *src, size_t *size)
 
 	switch (src->value.ftype) {
 	case PMEM2_FTYPE_DEVDAX: {
-		int ret = pmem2_device_dax_size_from_dev(st.st_rdev, size);
+		int ret = pmem2_device_dax_size(src, size);
 		if (ret)
 			return ret;
 		break;
-- 
GitLab