@@ -34,6 +34,7 @@
#include <ndctl.h>
#endif
+#include <util/size.h>
#include <util/sysfs.h>
#include <ndctl/libndctl.h>
#include <daxctl/libdaxctl.h>
@@ -327,6 +328,7 @@ struct ndctl_pfn {
int buf_len;
uuid_t uuid;
int id, generation;
+ struct ndctl_sizes alignments;
};
struct ndctl_dax {
@@ -2858,6 +2860,18 @@ static char *get_block_device(struct ndctl_ctx *ctx, const char *block_path)
static int parse_sizes(struct ndctl_ctx *ctx, const char *devname,
const char *buf, struct ndctl_sizes *lba);
+static int sizes_contains(struct ndctl_sizes *sizes, unsigned long size)
+{
+ int i;
+
+ for (i = 0; i < sizes->num; i++)
+ if (sizes->supported[i] == size)
+ return 1;
+
+ return 0;
+}
+
+
static void *add_namespace(void *parent, int id, const char *ndns_base)
{
const char *devname = devpath_to_devname(ndns_base);
@@ -4148,6 +4162,7 @@ static void *__add_pfn(struct ndctl_pfn *pfn, const char *pfn_base)
char *path = calloc(1, strlen(pfn_base) + 100);
struct ndctl_region *region = pfn->region;
char buf[SYSFS_ATTR_SIZE];
+ char *end = NULL;
if (!path)
return NULL;
@@ -4190,7 +4205,19 @@ static void *__add_pfn(struct ndctl_pfn *pfn, const char *pfn_base)
if (sysfs_read_attr(ctx, path, buf) < 0)
pfn->align = 0;
else
- pfn->align = strtoul(buf, NULL, 0);
+ pfn->align = strtoul(buf, &end, 0);
+
+
+ sprintf(path, "%s/supported_alignments", pfn_base);
+ if (sysfs_read_attr(ctx, path, buf) >= 0)
+ parse_sizes(ctx, devpath_to_devname(pfn_base),
+ buf, &pfn->alignments);
+
+ if (!pfn->alignments.supported) {
+ pfn->alignments.supported =
+ (unsigned int []) {SZ_4K, SZ_2M, SZ_1G};
+ pfn->alignments.num = 3;
+ }
sprintf(path, "%s/resource", pfn_base);
if (sysfs_read_attr(ctx, path, buf) < 0)
@@ -4435,6 +4462,29 @@ NDCTL_EXPORT int ndctl_pfn_set_align(struct ndctl_pfn *pfn, unsigned long align)
return 0;
}
+NDCTL_EXPORT unsigned int ndctl_pfn_get_supported_align(
+ struct ndctl_pfn *pfn, int i)
+{
+ if (pfn->alignments.num == 0)
+ return 0;
+
+ if (i < 0 || i > pfn->alignments.num)
+ return UINT_MAX;
+ else
+ return pfn->alignments.supported[i];
+}
+
+NDCTL_EXPORT int ndctl_pfn_get_num_aligns(struct ndctl_pfn *pfn)
+{
+ return pfn->alignments.num;
+}
+
+NDCTL_EXPORT int ndctl_pfn_supports_align(struct ndctl_pfn *pfn,
+ unsigned long align)
+{
+ return sizes_contains(&pfn->alignments, align);
+}
+
NDCTL_EXPORT int ndctl_pfn_set_namespace(struct ndctl_pfn *pfn,
struct ndctl_namespace *ndns)
{
@@ -4661,6 +4711,23 @@ NDCTL_EXPORT int ndctl_dax_has_align(struct ndctl_dax *dax)
return ndctl_pfn_has_align(&dax->pfn);
}
+NDCTL_EXPORT unsigned int ndctl_dax_get_supported_align(
+ struct ndctl_dax *dax, int i)
+{
+ return ndctl_pfn_get_supported_align(&dax->pfn, i);
+}
+
+NDCTL_EXPORT int ndctl_dax_get_num_aligns(struct ndctl_dax *dax)
+{
+ return ndctl_pfn_get_num_aligns(&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);
@@ -238,6 +238,7 @@ global:
ndctl_pfn_get_location;
ndctl_pfn_set_location;
ndctl_pfn_get_align;
+ ndctl_pfn_supports_align;
ndctl_pfn_get_size;
ndctl_pfn_get_resource;
ndctl_pfn_has_align;
@@ -266,6 +267,7 @@ global:
ndctl_dax_get_location;
ndctl_dax_set_location;
ndctl_dax_get_align;
+ ndctl_dax_supports_align;
ndctl_dax_has_align;
ndctl_dax_set_align;
ndctl_dax_set_namespace;
@@ -587,7 +587,11 @@ int ndctl_pfn_set_uuid(struct ndctl_pfn *pfn, uuid_t uu);
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);
+int ndctl_pfn_get_num_aligns(struct ndctl_pfn *pfn);
+int ndctl_pfn_supports_align(struct ndctl_pfn *pfn, unsigned long size);
+unsigned int ndctl_pfn_get_supported_align(struct ndctl_pfn *pfn, int i);
unsigned long ndctl_pfn_get_align(struct ndctl_pfn *pfn);
+unsigned long ndctl_pfn_def_align(struct ndctl_pfn *pfn);
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);
@@ -619,8 +623,12 @@ 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_has_align(struct ndctl_dax *dax);
int ndctl_dax_set_align(struct ndctl_dax *dax, unsigned long align);
+int ndctl_dax_get_num_aligns(struct ndctl_dax *dax);
+unsigned int ndctl_dax_get_supported_align(struct ndctl_dax *dax, int i);
+int ndctl_dax_supports_align(struct ndctl_dax *dax, unsigned long size);
int ndctl_dax_set_namespace(struct ndctl_dax *dax,
struct ndctl_namespace *ndns);
struct ndctl_bus *ndctl_dax_get_bus(struct ndctl_dax *dax);
Newer kernels advertise the list of alignments that they support through sysfs. This patch adds parsing inside of libndctl to determine the alignments the kernel supports for PFN and DAX regions. Signed-off-by: Oliver O'Halloran <oohall@gmail.com> --- ndctl/lib/libndctl.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++- ndctl/lib/libndctl.sym | 2 ++ ndctl/libndctl.h.in | 8 ++++++ 3 files changed, 78 insertions(+), 1 deletion(-)