Newer kernels advertise the list of alignments that they support
through sysfs. This patch adds parsing inside of libndctl to
determine the alignments permitted.

Signed-off-by: Oliver O'Halloran <[email protected]>
---
 ndctl/lib/libndctl.c   | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++
 ndctl/lib/libndctl.sym |  4 ++++
 ndctl/libndctl.h.in    |  4 ++++
 3 files changed, 61 insertions(+)

diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 25a1e6d20d10..f9bc4ee72bb8 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -34,6 +34,7 @@
 #include <ndctl.h>
 #endif
 
+#include <util/size.h>
 #include <util/sysfs.h>
 #include <ndctl/libndctl.h>
 #include <daxctl/libdaxctl.h>
@@ -323,6 +324,8 @@ struct ndctl_pfn {
        int buf_len;
        uuid_t uuid;
        int id, generation;
+       struct ndctl_sizes alignments;
+       unsigned long default_align;
 };
 
 struct ndctl_dax {
@@ -4025,6 +4028,29 @@ static void *__add_pfn(struct ndctl_pfn *pfn, const char 
*pfn_base)
        else
                pfn->size = strtoull(buf, NULL, 0);
 
+       /*
+        * Newer kernels explicitly state what they support with the
+        * supported_alignments attribuate and older kernels only
+        * support 4K, 2M or 1G alignments.
+        */
+       sprintf(path, "%s/supported_alignments", pfn_base);
+       if (!sysfs_read_attr(ctx, path, buf)) {
+               if (parse_sizes(ctx, devpath_to_devname(pfn_base),
+                               buf, &pfn->alignments)) {
+                       goto err_read;
+               }
+
+               sprintf(path, "%s/default_alignment", pfn_base);
+               if (sysfs_read_attr(ctx, path, buf) < 0)
+                       goto err_read;
+
+               pfn->default_align = strtoull(buf, NULL, 0);
+       } else {
+               pfn->alignments.supported =
+                       (unsigned int []) {SZ_4K, SZ_2M, SZ_1G};
+               pfn->default_align = SZ_2M;
+       }
+
        free(path);
        return pfn;
 
@@ -4256,6 +4282,22 @@ NDCTL_EXPORT int ndctl_pfn_set_align(struct ndctl_pfn 
*pfn, unsigned long align)
        return 0;
 }
 
+NDCTL_EXPORT unsigned long ndctl_pfn_def_align(struct ndctl_pfn *pfn)
+{
+       return pfn->default_align;
+}
+
+NDCTL_EXPORT int ndctl_pfn_supports_align(struct ndctl_pfn *pfn,
+               unsigned long align)
+{
+       int i;
+
+       for (i = 0; i < pfn->alignments.num; i++)
+               if (pfn->alignments.supported[i] == align)
+                       return true;
+       return false;
+}
+
 NDCTL_EXPORT int ndctl_pfn_set_namespace(struct ndctl_pfn *pfn,
                struct ndctl_namespace *ndns)
 {
@@ -4482,6 +4524,17 @@ NDCTL_EXPORT int ndctl_dax_has_align(struct ndctl_dax 
*dax)
        return ndctl_pfn_has_align(&dax->pfn);
 }
 
+NDCTL_EXPORT unsigned long ndctl_dax_def_align(struct ndctl_dax *dax)
+{
+       return ndctl_pfn_def_align(&dax->pfn);
+}
+
+NDCTL_EXPORT int ndctl_dax_supports_align(struct ndctl_dax *dax,
+               unsigned long align)
+{
+       return ndctl_pfn_supports_align(&dax->pfn, align);
+}
+
 NDCTL_EXPORT int ndctl_dax_set_align(struct ndctl_dax *dax, unsigned long 
align)
 {
        return ndctl_pfn_set_align(&dax->pfn, align);
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index be2e3680d202..fa60dfb82a9e 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -231,6 +231,8 @@ global:
        ndctl_pfn_get_location;
        ndctl_pfn_set_location;
        ndctl_pfn_get_align;
+       ndctl_pfn_def_align;
+       ndctl_pfn_supports_align;
        ndctl_pfn_get_size;
        ndctl_pfn_get_resource;
        ndctl_pfn_has_align;
@@ -259,6 +261,8 @@ global:
        ndctl_dax_get_location;
        ndctl_dax_set_location;
        ndctl_dax_get_align;
+       ndctl_dax_def_align;
+       ndctl_dax_supports_align;
        ndctl_dax_has_align;
        ndctl_dax_set_align;
        ndctl_dax_set_namespace;
diff --git a/ndctl/libndctl.h.in b/ndctl/libndctl.h.in
index c27581d939c5..be0e20b706fa 100644
--- a/ndctl/libndctl.h.in
+++ b/ndctl/libndctl.h.in
@@ -572,6 +572,8 @@ void ndctl_pfn_get_uuid(struct ndctl_pfn *pfn, uuid_t uu);
 int ndctl_pfn_has_align(struct ndctl_pfn *pfn);
 int ndctl_pfn_set_align(struct ndctl_pfn *pfn, unsigned long align);
 unsigned long ndctl_pfn_get_align(struct ndctl_pfn *pfn);
+unsigned long ndctl_pfn_def_align(struct ndctl_pfn *pfn);
+int ndctl_pfn_supports_align(struct ndctl_pfn *pfn, unsigned long align);
 unsigned long long ndctl_pfn_get_resource(struct ndctl_pfn *pfn);
 unsigned long long ndctl_pfn_get_size(struct ndctl_pfn *pfn);
 int ndctl_pfn_set_namespace(struct ndctl_pfn *pfn, struct ndctl_namespace 
*ndns);
@@ -603,6 +605,8 @@ int ndctl_dax_set_uuid(struct ndctl_dax *dax, uuid_t uu);
 enum ndctl_pfn_loc ndctl_dax_get_location(struct ndctl_dax *dax);
 int ndctl_dax_set_location(struct ndctl_dax *dax, enum ndctl_pfn_loc loc);
 unsigned long ndctl_dax_get_align(struct ndctl_dax *dax);
+unsigned long ndctl_dax_def_align(struct ndctl_dax *dax);
+int ndctl_dax_supports_align(struct ndctl_dax *dax, unsigned long align);
 int ndctl_dax_has_align(struct ndctl_dax *dax);
 int ndctl_dax_set_align(struct ndctl_dax *dax, unsigned long align);
 int ndctl_dax_set_namespace(struct ndctl_dax *dax,
-- 
2.9.3

_______________________________________________
Linux-nvdimm mailing list
[email protected]
https://lists.01.org/mailman/listinfo/linux-nvdimm

Reply via email to