Hello community, here is the log from the commit of package ndctl for openSUSE:Factory checked in at 2020-08-23 09:19:02 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/ndctl (Old) and /work/SRC/openSUSE:Factory/.ndctl.new.3399 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ndctl" Sun Aug 23 09:19:02 2020 rev:29 rq:827551 version:69 Changes: -------- --- /work/SRC/openSUSE:Factory/ndctl/ndctl.changes 2020-05-20 18:36:16.772081981 +0200 +++ /work/SRC/openSUSE:Factory/.ndctl.new.3399/ndctl.changes 2020-08-23 09:19:05.510615719 +0200 @@ -1,0 +2,18 @@ +Mon Aug 10 09:25:52 UTC 2020 - Michal Suchanek <[email protected]> + +- Update to v69 (jsc#SLE-13824, jsc#SLE-12770, jsc#SLE-15065): + * infoblock: Set the default alignment to the platform alignment + * libndctl/papr_scm: Add support for reporting "life_used_percentage" metric + * Skip region filtering if numa_node attribute is not present + * libndctl,papr_scm: Implement support for PAPR_PDSM_HEALTH + * miscellaneous bugfixes + +- Removed ndctl-Documentation-use-includes-in-more-ndctl-command-pag.patch + +------------------------------------------------------------------- +Tue Jul 14 08:24:42 UTC 2020 - Michal Suchanek <[email protected]> + +- Clarify documentation about filtering options (bsc#1173861) + + ndctl-Documentation-use-includes-in-more-ndctl-command-pag.patch + +------------------------------------------------------------------- Old: ---- ndctl-68.tar.gz New: ---- ndctl-69.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ ndctl.spec ++++++ --- /var/tmp/diff_new_pack.1F24kP/_old 2020-08-23 09:19:06.170616085 +0200 +++ /var/tmp/diff_new_pack.1F24kP/_new 2020-08-23 09:19:06.174616086 +0200 @@ -20,14 +20,13 @@ %define lname libndctl6 %define dname libndctl-devel Name: ndctl -Version: 68 +Version: 69 Release: 0 Summary: Manage "libnvdimm" subsystem devices (Non-volatile Memory) License: GPL-2.0-only Group: Hardware/Other URL: https://github.com/pmem/ndctl -# Snapshot tarball can be created using: ./make-git-shapshot.sh [gitcommit] -Source0: %{name}-%{version}.tar.gz +Source0: https://github.com/pmem/ndctl/archive/v%{version}.tar.gz#/%{name}-%{version}.tar.gz Patch9: %{name}-namespace-skip-zero-namespaces-when-processing.patch BuildRequires: autoconf BuildRequires: automake ++++++ ndctl-68.tar.gz -> ndctl-69.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/.gitignore new/ndctl-69/.gitignore --- old/ndctl-68/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/ndctl-69/.gitignore 2020-07-23 07:15:11.000000000 +0200 @@ -0,0 +1,61 @@ +*.o +*.xml +.deps/ +.libs/ +Makefile +!contrib/Makefile +Makefile.in +/aclocal.m4 +/autom4te.cache +/build-aux +/config.* +/configure +/libtool +/stamp-h1 +*.1 +Documentation/daxctl/asciidoc.conf +Documentation/ndctl/asciidoc.conf +Documentation/daxctl/asciidoctor-extensions.rb +Documentation/ndctl/asciidoctor-extensions.rb +.dirstamp +daxctl/config.h +daxctl/daxctl +daxctl/lib/libdaxctl.la +daxctl/lib/libdaxctl.lo +daxctl/lib/libdaxctl.pc +*.a +ndctl/config.h +ndctl/lib/libndctl.pc +ndctl/ndctl +rhel/ +sles/ndctl.spec +util/log.lo +util/sysfs.lo +version.m4 +*.swp +cscope.files +cscope*.out +tags +test/*.log +test/*.trs +test/blk-ns +test/dax-dev +test/dax-errors +test/dax-pmd +test/daxdev-errors +test/device-dax +test/dpa-alloc +test/dsm-fail +test/hugetlb +test/image +test/libndctl +test/mmap +test/multi-pmem +test/parent-uuid +test/pmem-ns +test/smart-listen +test/smart-notify +test/fio.job +test/local-write-0-verify.state +test/ack-shutdown-count-set +test/list-smart-dimm diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/Documentation/daxctl/movable-options.txt new/ndctl-69/Documentation/daxctl/movable-options.txt --- old/ndctl-68/Documentation/daxctl/movable-options.txt 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/Documentation/daxctl/movable-options.txt 2020-07-23 07:15:11.000000000 +0200 @@ -2,7 +2,7 @@ --no-movable:: '--movable' is the default. This can be overridden to online new - memory such that is is not 'movable'. This allows any allocation + memory such that it is not 'movable'. This allows any allocation to potentially be served from this memory. This may preclude subsequent removal. With the '--movable' behavior (which is default), kernel allocations will not consider this memory, and it will be reserved diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/Documentation/ndctl/labels-options.txt new/ndctl-69/Documentation/ndctl/labels-options.txt --- old/ndctl-68/Documentation/ndctl/labels-options.txt 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/Documentation/ndctl/labels-options.txt 2020-07-23 07:15:11.000000000 +0200 @@ -1,9 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 <memory device(s)>:: - One or more 'nmemX' device names. The keyword 'all' can be specified to - operate on every dimm in the system, optionally filtered by bus id (see - --bus= option). +include::xable-dimm-options.txt[] -s:: --size=:: @@ -16,8 +14,7 @@ -b:: --bus=:: - Limit operation to memory devices (dimms) that are on the given bus. - Where 'bus' can be a provider name or a bus id number. +include::xable-bus-options.txt[] -v:: Turn on verbose debug messages in the library (if ndctl was built with diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/Documentation/ndctl/ndctl-inject-smart.txt new/ndctl-69/Documentation/ndctl/ndctl-inject-smart.txt --- old/ndctl-68/Documentation/ndctl/ndctl-inject-smart.txt 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/Documentation/ndctl/ndctl-inject-smart.txt 2020-07-23 07:15:11.000000000 +0200 @@ -38,9 +38,7 @@ ------- -b:: --bus=:: - Enforce that the operation only be carried on devices that are - attached to the given bus. Where 'bus' can be a provider name or a bus - id number. +include::xable-bus-options.txt[] -m:: --media-temperature=:: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/Documentation/ndctl/ndctl-monitor.txt new/ndctl-69/Documentation/ndctl/ndctl-monitor.txt --- old/ndctl-68/Documentation/ndctl/ndctl-monitor.txt 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/Documentation/ndctl/ndctl-monitor.txt 2020-07-23 07:15:11.000000000 +0200 @@ -49,20 +49,15 @@ ------- -b:: --bus=:: - Enforce that the operation only be carried on devices that are - attached to the given bus. Where 'bus' can be a provider name - or a bus id number. +include::xable-bus-options.txt[] -d:: --dimm=:: - A 'nmemX' device name, or dimm id number. Select the devices to - monitor reference the given dimm. +include::xable-dimm-options.txt[] -r:: --region=:: - A 'regionX' device name, or a region id number. The keyword 'all' - can be specified to carry out the operation on every region in - the system, optionally filtered by bus id (see --bus= option). +include::xable-region-options.txt[] -n:: --namespace=:: @@ -108,6 +103,10 @@ The monitor will attempt to enable the alarm control bits for all specified events. +-p:: +--poll=:: + Poll and report status/event every <n> seconds. + -u:: --human:: Output monitor notification as human friendly json format instead diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/Makefile.am.in new/ndctl-69/Makefile.am.in --- old/ndctl-68/Makefile.am.in 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/Makefile.am.in 2020-07-23 07:15:11.000000000 +0200 @@ -35,9 +35,9 @@ -e 's,@includedir\@,$(includedir),g' \ < $< > $@ || rm $@ -LIBNDCTL_CURRENT=23 +LIBNDCTL_CURRENT=24 LIBNDCTL_REVISION=0 -LIBNDCTL_AGE=17 +LIBNDCTL_AGE=18 LIBDAXCTL_CURRENT=5 LIBDAXCTL_REVISION=0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/README.md new/ndctl-69/README.md --- old/ndctl-68/README.md 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/README.md 2020-07-23 07:15:11.000000000 +0200 @@ -65,6 +65,7 @@ CONFIG_NVDIMM_PFN=y CONFIG_NVDIMM_DAX=y CONFIG_DEV_DAX_PMEM=m + CONFIG_ENCRYPTED_KEYS=y ``` 1. Build and install the unit test enabled libnvdimm modules in the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/git-version new/ndctl-69/git-version --- old/ndctl-68/git-version 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/git-version 2020-07-23 07:15:11.000000000 +0200 @@ -19,7 +19,7 @@ fi } -DEF_VER=68 +DEF_VER=69 LF=' ' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/m4/.gitignore new/ndctl-69/m4/.gitignore --- old/ndctl-68/m4/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/ndctl-69/m4/.gitignore 2020-07-23 07:15:11.000000000 +0200 @@ -0,0 +1,6 @@ +libtool.m4 +ltoptions.m4 +ltsugar.m4 +ltversion.m4 +lt~obsolete.m4 + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/lib/.gitignore new/ndctl-69/ndctl/lib/.gitignore --- old/ndctl-68/ndctl/lib/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/ndctl-69/ndctl/lib/.gitignore 2020-07-23 07:15:11.000000000 +0200 @@ -0,0 +1,7 @@ +.dirstamp +.deps/ +.libs/ +*.la +*.lo +libabc.pc +test-libabc diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/lib/Makefile.am new/ndctl-69/ndctl/lib/Makefile.am --- old/ndctl-68/ndctl/lib/Makefile.am 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/ndctl/lib/Makefile.am 2020-07-23 07:15:11.000000000 +0200 @@ -23,6 +23,7 @@ hpe1.c \ msft.c \ hyperv.c \ + papr.c \ ars.c \ firmware.c \ libndctl.c \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/lib/hpe1.h new/ndctl-69/ndctl/lib/hpe1.h --- old/ndctl-68/ndctl/lib/hpe1.h 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/ndctl/lib/hpe1.h 2020-07-23 07:15:11.000000000 +0200 @@ -111,7 +111,7 @@ __u32 status; union { __u8 buf[124]; - struct ndn_hpe1_smart_data data[0]; + struct ndn_hpe1_smart_data data[1]; }; } __attribute__((packed)); @@ -136,7 +136,7 @@ __u32 status; union { __u8 buf[32]; - struct ndn_hpe1_smart_threshold_data data[0]; + struct ndn_hpe1_smart_threshold_data data[1]; }; } __attribute__((packed)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/lib/libndctl.c new/ndctl-69/ndctl/lib/libndctl.c --- old/ndctl-68/ndctl/lib/libndctl.c 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/ndctl/lib/libndctl.c 2020-07-23 07:15:11.000000000 +0200 @@ -799,6 +799,28 @@ ndctl_dimm_get_devname(dimm), flags); } +static void parse_papr_flags(struct ndctl_dimm *dimm, char *flags) +{ + struct ndctl_ctx *ctx = ndctl_dimm_get_ctx(dimm); + char *start, *end; + + start = flags; + while ((end = strchr(start, ' '))) { + *end = '\0'; + if (strcmp(start, "not_armed") == 0) + dimm->flags.f_arm = 1; + else if (strcmp(start, "flush_fail") == 0) + dimm->flags.f_flush = 1; + else if (strcmp(start, "restore_fail") == 0) + dimm->flags.f_restore = 1; + else if (strcmp(start, "smart_notify") == 0) + dimm->flags.f_smart = 1; + start = end + 1; + } + if (end != start) + dbg(ctx, "%s: Flags:%s\n", ndctl_dimm_get_devname(dimm), flags); +} + static void parse_dimm_flags(struct ndctl_dimm *dimm, char *flags) { char *start, *end; @@ -856,6 +878,12 @@ bus->revision = strtoul(buf, NULL, 0); } + sprintf(path, "%s/device/of_node/compatible", ctl_base); + if (sysfs_read_attr(ctx, path, buf) < 0) + bus->has_of_node = 0; + else + bus->has_of_node = 1; + sprintf(path, "%s/device/nfit/dsm_mask", ctl_base); if (sysfs_read_attr(ctx, path, buf) < 0) bus->nfit_dsm_mask = 0; @@ -964,6 +992,23 @@ return bus->has_nfit; } +NDCTL_EXPORT int ndctl_bus_has_of_node(struct ndctl_bus *bus) +{ + return bus->has_of_node; +} + +NDCTL_EXPORT int ndctl_bus_is_papr_scm(struct ndctl_bus *bus) +{ + char buf[SYSFS_ATTR_SIZE]; + + snprintf(bus->bus_buf, bus->buf_len, + "%s/of_node/compatible", bus->bus_path); + if (sysfs_read_attr(bus->ctx, bus->bus_buf, buf) < 0) + return 0; + + return (strcmp(buf, "ibm,pmemory") == 0); +} + /** * ndctl_bus_get_major - nd bus character device major number * @bus: ndctl_bus instance returned from ndctl_bus_get_{first|next} @@ -1441,82 +1486,49 @@ static int ndctl_unbind(struct ndctl_ctx *ctx, const char *devpath); static struct kmod_module *to_module(struct ndctl_ctx *ctx, const char *alias); -static void *add_dimm(void *parent, int id, const char *dimm_base) +static int add_papr_dimm(struct ndctl_dimm *dimm, const char *dimm_base) { - int formats, i; - struct ndctl_dimm *dimm; + int rc = -ENODEV; char buf[SYSFS_ATTR_SIZE]; - struct ndctl_bus *bus = parent; - struct ndctl_ctx *ctx = bus->ctx; + struct ndctl_ctx *ctx = dimm->bus->ctx; char *path = calloc(1, strlen(dimm_base) + 100); + const char * const devname = ndctl_dimm_get_devname(dimm); - if (!path) - return NULL; + dbg(ctx, "%s: Probing of_pmem dimm at %s\n", devname, dimm_base); - sprintf(path, "%s/nfit/formats", dimm_base); - if (sysfs_read_attr(ctx, path, buf) < 0) - formats = 1; - else - formats = clamp(strtoul(buf, NULL, 0), 1UL, 2UL); - - dimm = calloc(1, sizeof(*dimm) + sizeof(int) * formats); - if (!dimm) - goto err_dimm; - dimm->bus = bus; - dimm->id = id; + if (!path) + return -ENOMEM; - sprintf(path, "%s/dev", dimm_base); - if (sysfs_read_attr(ctx, path, buf) < 0) - goto err_read; - if (sscanf(buf, "%d:%d", &dimm->major, &dimm->minor) != 2) - goto err_read; + /* construct path to the papr compatible dimm flags file */ + sprintf(path, "%s/papr/flags", dimm_base); - sprintf(path, "%s/commands", dimm_base); - if (sysfs_read_attr(ctx, path, buf) < 0) - goto err_read; - dimm->cmd_mask = parse_commands(buf, 1); + if (ndctl_bus_is_papr_scm(dimm->bus) && + sysfs_read_attr(ctx, path, buf) == 0) { - dimm->dimm_buf = calloc(1, strlen(dimm_base) + 50); - if (!dimm->dimm_buf) - goto err_read; - dimm->buf_len = strlen(dimm_base) + 50; + dbg(ctx, "%s: Adding papr-scm dimm flags:\"%s\"\n", devname, buf); + dimm->cmd_family = NVDIMM_FAMILY_PAPR; - dimm->dimm_path = strdup(dimm_base); - if (!dimm->dimm_path) - goto err_read; + /* Parse dimm flags */ + parse_papr_flags(dimm, buf); - sprintf(path, "%s/modalias", dimm_base); - if (sysfs_read_attr(ctx, path, buf) < 0) - goto err_read; - dimm->module = to_module(ctx, buf); + /* Allocate monitor mode fd */ + dimm->health_eventfd = open(path, O_RDONLY|O_CLOEXEC); + rc = 0; + } - dimm->handle = -1; - dimm->phys_id = -1; - dimm->serial = -1; - dimm->vendor_id = -1; - dimm->device_id = -1; - dimm->revision_id = -1; - dimm->health_eventfd = -1; - dimm->dirty_shutdown = -ENOENT; - dimm->subsystem_vendor_id = -1; - dimm->subsystem_device_id = -1; - dimm->subsystem_revision_id = -1; - dimm->manufacturing_date = -1; - dimm->manufacturing_location = -1; - dimm->cmd_family = -1; - dimm->nfit_dsm_mask = ULONG_MAX; - for (i = 0; i < formats; i++) - dimm->format[i] = -1; + free(path); + return rc; +} - sprintf(path, "%s/flags", dimm_base); - if (sysfs_read_attr(ctx, path, buf) < 0) { - dimm->locked = -1; - dimm->aliased = -1; - } else - parse_dimm_flags(dimm, buf); +static int add_nfit_dimm(struct ndctl_dimm *dimm, const char *dimm_base) +{ + int i, rc = -1; + char buf[SYSFS_ATTR_SIZE]; + struct ndctl_ctx *ctx = dimm->bus->ctx; + char *path = calloc(1, strlen(dimm_base) + 100); - if (!ndctl_bus_has_nfit(bus)) - goto out; + if (!path) + return -ENOMEM; /* * 'unique_id' may not be available on older kernels, so don't @@ -1582,24 +1594,15 @@ sprintf(path, "%s/nfit/family", dimm_base); if (sysfs_read_attr(ctx, path, buf) == 0) dimm->cmd_family = strtoul(buf, NULL, 0); - if (dimm->cmd_family == NVDIMM_FAMILY_INTEL) - dimm->ops = intel_dimm_ops; - if (dimm->cmd_family == NVDIMM_FAMILY_HPE1) - dimm->ops = hpe1_dimm_ops; - if (dimm->cmd_family == NVDIMM_FAMILY_MSFT) - dimm->ops = msft_dimm_ops; - if (dimm->cmd_family == NVDIMM_FAMILY_HYPERV) - dimm->ops = hyperv_dimm_ops; sprintf(path, "%s/nfit/dsm_mask", dimm_base); if (sysfs_read_attr(ctx, path, buf) == 0) dimm->nfit_dsm_mask = strtoul(buf, NULL, 0); - dimm->formats = formats; sprintf(path, "%s/nfit/format", dimm_base); if (sysfs_read_attr(ctx, path, buf) == 0) dimm->format[0] = strtoul(buf, NULL, 0); - for (i = 1; i < formats; i++) { + for (i = 1; i < dimm->formats; i++) { sprintf(path, "%s/nfit/format%d", dimm_base, i); if (sysfs_read_attr(ctx, path, buf) == 0) dimm->format[i] = strtoul(buf, NULL, 0); @@ -1610,7 +1613,120 @@ parse_nfit_mem_flags(dimm, buf); dimm->health_eventfd = open(path, O_RDONLY|O_CLOEXEC); + rc = 0; + err_read: + + free(path); + return rc; +} + +static void *add_dimm(void *parent, int id, const char *dimm_base) +{ + int formats, i, rc = -ENODEV; + struct ndctl_dimm *dimm = NULL; + char buf[SYSFS_ATTR_SIZE]; + struct ndctl_bus *bus = parent; + struct ndctl_ctx *ctx = bus->ctx; + char *path = calloc(1, strlen(dimm_base) + 100); + + if (!path) + return NULL; + + sprintf(path, "%s/nfit/formats", dimm_base); + if (sysfs_read_attr(ctx, path, buf) < 0) + formats = 1; + else + formats = clamp(strtoul(buf, NULL, 0), 1UL, 2UL); + + dimm = calloc(1, sizeof(*dimm) + sizeof(int) * formats); + if (!dimm) + goto err_dimm; + dimm->bus = bus; + dimm->id = id; + + sprintf(path, "%s/dev", dimm_base); + if (sysfs_read_attr(ctx, path, buf) < 0) + goto err_read; + if (sscanf(buf, "%d:%d", &dimm->major, &dimm->minor) != 2) + goto err_read; + + sprintf(path, "%s/commands", dimm_base); + if (sysfs_read_attr(ctx, path, buf) < 0) + goto err_read; + dimm->cmd_mask = parse_commands(buf, 1); + + dimm->dimm_buf = calloc(1, strlen(dimm_base) + 50); + if (!dimm->dimm_buf) + goto err_read; + dimm->buf_len = strlen(dimm_base) + 50; + + dimm->dimm_path = strdup(dimm_base); + if (!dimm->dimm_path) + goto err_read; + + sprintf(path, "%s/modalias", dimm_base); + if (sysfs_read_attr(ctx, path, buf) < 0) + goto err_read; + dimm->module = to_module(ctx, buf); + + dimm->handle = -1; + dimm->phys_id = -1; + dimm->serial = -1; + dimm->vendor_id = -1; + dimm->device_id = -1; + dimm->revision_id = -1; + dimm->health_eventfd = -1; + dimm->dirty_shutdown = -ENOENT; + dimm->subsystem_vendor_id = -1; + dimm->subsystem_device_id = -1; + dimm->subsystem_revision_id = -1; + dimm->manufacturing_date = -1; + dimm->manufacturing_location = -1; + dimm->cmd_family = -1; + dimm->nfit_dsm_mask = ULONG_MAX; + for (i = 0; i < formats; i++) + dimm->format[i] = -1; + + sprintf(path, "%s/flags", dimm_base); + if (sysfs_read_attr(ctx, path, buf) < 0) { + dimm->locked = -1; + dimm->aliased = -1; + } else + parse_dimm_flags(dimm, buf); + + /* Check if the given dimm supports nfit */ + if (ndctl_bus_has_nfit(bus)) { + dimm->formats = formats; + rc = add_nfit_dimm(dimm, dimm_base); + } else if (ndctl_bus_has_of_node(bus)) { + rc = add_papr_dimm(dimm, dimm_base); + } + + if (rc == -ENODEV) { + /* Unprobed dimm with no family */ + rc = 0; + goto out; + } + + /* Assign dimm-ops based on command family */ + if (dimm->cmd_family == NVDIMM_FAMILY_INTEL) + dimm->ops = intel_dimm_ops; + if (dimm->cmd_family == NVDIMM_FAMILY_HPE1) + dimm->ops = hpe1_dimm_ops; + if (dimm->cmd_family == NVDIMM_FAMILY_MSFT) + dimm->ops = msft_dimm_ops; + if (dimm->cmd_family == NVDIMM_FAMILY_HYPERV) + dimm->ops = hyperv_dimm_ops; + if (dimm->cmd_family == NVDIMM_FAMILY_PAPR) + dimm->ops = papr_dimm_ops; + out: + if (rc) { + err(ctx, "%s: probe failed: %s\n", ndctl_dimm_get_devname(dimm), + strerror(-rc)); + goto err_read; + } + list_add(&bus->dimms, &dimm->list); free(path); @@ -2136,7 +2252,7 @@ struct ndctl_bus *bus = parent; struct ndctl_ctx *ctx = bus->ctx; char *path = calloc(1, strlen(region_base) + 100); - int perm; + int perm, rc; if (!path) return NULL; @@ -2186,10 +2302,12 @@ region->module = to_module(ctx, buf); sprintf(path, "%s/numa_node", region_base); - if (sysfs_read_attr(ctx, path, buf) == 0) + if ((rc = sysfs_read_attr(ctx, path, buf)) == 0) region->numa_node = strtol(buf, NULL, 0); + else if (rc == -ENOENT) + region->numa_node = NUMA_NO_ATTR; else - region->numa_node = -1; + region->numa_node = NUMA_NO_NODE; sprintf(path, "%s/target_node", region_base); if (sysfs_read_attr(ctx, path, buf) == 0) @@ -2471,6 +2589,11 @@ return NULL; } +NDCTL_EXPORT int ndctl_region_has_numa(struct ndctl_region *region) +{ + return (region->numa_node != NUMA_NO_ATTR); +} + NDCTL_EXPORT int ndctl_region_get_numa_node(struct ndctl_region *region) { return region->numa_node; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/lib/libndctl.sym new/ndctl-69/ndctl/lib/libndctl.sym --- old/ndctl-68/ndctl/lib/libndctl.sym 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/ndctl/lib/libndctl.sym 2020-07-23 07:15:11.000000000 +0200 @@ -431,3 +431,9 @@ ndctl_region_get_align; ndctl_region_set_align; } LIBNDCTL_22; + +LIBNDCTL_24 { + ndctl_bus_has_of_node; + ndctl_bus_is_papr_scm; + ndctl_region_has_numa; +} LIBNDCTL_23; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/lib/msft.h new/ndctl-69/ndctl/lib/msft.h --- old/ndctl-68/ndctl/lib/msft.h 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/ndctl/lib/msft.h 2020-07-23 07:15:11.000000000 +0200 @@ -46,7 +46,7 @@ __u32 status; union { __u8 buf[9]; - struct ndn_msft_smart_data data[0]; + struct ndn_msft_smart_data data[1]; }; } __attribute__((packed)); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/lib/papr.c new/ndctl-69/ndctl/lib/papr.c --- old/ndctl-68/ndctl/lib/papr.c 1970-01-01 01:00:00.000000000 +0100 +++ new/ndctl-69/ndctl/lib/papr.c 2020-07-23 07:15:11.000000000 +0200 @@ -0,0 +1,248 @@ +// SPDX-License-Identifier: LGPL-2.1 +/* + * libndctl support for PAPR-SCM based NVDIMMs + * + * (C) Copyright IBM 2020 + * + */ + +#include <stdint.h> +#include <stdlib.h> +#include <limits.h> +#include <util/log.h> +#include <ndctl.h> +#include <ndctl/libndctl.h> +#include <lib/private.h> +#include "papr.h" + +/* Utility logging maros for simplify logging */ +#define papr_dbg(_dimm, _format_str, ...) dbg(_dimm->bus->ctx, \ + "%s:" _format_str, \ + ndctl_dimm_get_devname(_dimm), \ + ##__VA_ARGS__) + +#define papr_err(_dimm, _format_str, ...) err(_dimm->bus->ctx, \ + "%s:" _format_str, \ + ndctl_dimm_get_devname(_dimm), \ + ##__VA_ARGS__) + +/* Convert a ndctl_cmd to pdsm package */ +#define to_pdsm(C) (&(C)->papr[0].pdsm) + +/* Convert a ndctl_cmd to nd_cmd_pkg */ +#define to_ndcmd(C) (&(C)->papr[0].gen) + +/* Return payload from a ndctl_cmd */ +#define to_payload(C) (&(C)->papr[0].pdsm.payload) + +/* return the pdsm command */ +#define to_pdsm_cmd(C) ((enum papr_pdsm)to_ndcmd(C)->nd_command) + +static bool papr_cmd_is_supported(struct ndctl_dimm *dimm, int cmd) +{ + /* Handle this separately to support monitor mode */ + if (cmd == ND_CMD_SMART) + return true; + + return !!(dimm->cmd_mask & (1ULL << cmd)); +} + +static u32 papr_get_firmware_status(struct ndctl_cmd *cmd) +{ + const struct nd_pkg_pdsm *pcmd = to_pdsm(cmd); + + return (u32) pcmd->cmd_status; +} + +static int papr_xlat_firmware_status(struct ndctl_cmd *cmd) +{ + return (cmd->type == ND_CMD_CALL) ? to_pdsm(cmd)->cmd_status : 0; +} + +/* Verify if the given command is supported and valid */ +static bool cmd_is_valid(struct ndctl_cmd *cmd) +{ + const struct nd_cmd_pkg *ncmd = NULL; + + if (cmd == NULL) + return false; + + ncmd = to_ndcmd(cmd); + + /* Verify the command family */ + if (ncmd->nd_family != NVDIMM_FAMILY_PAPR) { + papr_err(cmd->dimm, "Invalid command family:0x%016llx\n", + ncmd->nd_family); + return false; + } + + /* Verify the PDSM */ + if (ncmd->nd_command <= PAPR_PDSM_MIN || + ncmd->nd_command >= PAPR_PDSM_MAX) { + papr_err(cmd->dimm, "Invalid command :0x%016llx\n", + ncmd->nd_command); + return false; + } + + return true; +} + +/* Allocate a struct ndctl_cmd for given pdsm request with payload size */ +static struct ndctl_cmd *allocate_cmd(struct ndctl_dimm *dimm, + enum papr_pdsm pdsm_cmd, + size_t payload_size) +{ + struct ndctl_cmd *cmd; + + /* Verify that payload size is within acceptable range */ + if (payload_size > ND_PDSM_PAYLOAD_MAX_SIZE) { + papr_err(dimm, "Requested payload size too large %lu bytes\n", + payload_size); + return NULL; + } + + cmd = calloc(1, sizeof(struct ndctl_cmd) + sizeof(struct nd_pkg_papr)); + if (!cmd) + return NULL; + + ndctl_cmd_ref(cmd); + cmd->dimm = dimm; + cmd->type = ND_CMD_CALL; + cmd->status = 0; + cmd->get_firmware_status = &papr_get_firmware_status; + + /* Populate the nd_cmd_pkg contained in nd_pkg_pdsm */ + *to_ndcmd(cmd) = (struct nd_cmd_pkg) { + .nd_family = NVDIMM_FAMILY_PAPR, + .nd_command = pdsm_cmd, + .nd_size_in = 0, + .nd_size_out = ND_PDSM_HDR_SIZE + payload_size, + .nd_fw_size = 0, + }; + return cmd; +} + +/* Parse the nd_papr_pdsm_health and update dimm flags */ +static int update_dimm_flags(struct ndctl_dimm *dimm, struct nd_papr_pdsm_health *health) +{ + /* Update the dimm flags */ + dimm->flags.f_arm = health->dimm_unarmed; + dimm->flags.f_flush = health->dimm_bad_shutdown; + dimm->flags.f_restore = health->dimm_bad_restore; + dimm->flags.f_smart = (health->dimm_health != 0); + + return 0; +} + +/* Validate the ndctl_cmd and return applicable flags */ +static unsigned int papr_smart_get_flags(struct ndctl_cmd *cmd) +{ + struct nd_pkg_pdsm *pcmd; + struct nd_papr_pdsm_health health; + unsigned int flags; + + if (!cmd_is_valid(cmd)) + return 0; + + pcmd = to_pdsm(cmd); + /* If error reported then return empty flags */ + if (pcmd->cmd_status) { + papr_err(cmd->dimm, "PDSM(0x%x) reported error:%d\n", + to_pdsm_cmd(cmd), pcmd->cmd_status); + return 0; + } + + /* + * In case of nvdimm health PDSM, update dimm flags + * and return possible flags. + */ + if (to_pdsm_cmd(cmd) == PAPR_PDSM_HEALTH) { + health = pcmd->payload.health; + update_dimm_flags(cmd->dimm, &health); + flags = ND_SMART_HEALTH_VALID | ND_SMART_SHUTDOWN_VALID; + + /* check for extension flags */ + if (health.extension_flags & PDSM_DIMM_HEALTH_RUN_GAUGE_VALID) + flags |= ND_SMART_USED_VALID; + + return flags; + } + + /* Else return empty flags */ + return 0; +} + +static struct ndctl_cmd *papr_new_smart_health(struct ndctl_dimm *dimm) +{ + struct ndctl_cmd *cmd; + + cmd = allocate_cmd(dimm, PAPR_PDSM_HEALTH, + sizeof(struct nd_papr_pdsm_health)); + if (!cmd) + papr_err(dimm, "Unable to allocate smart_health command\n"); + + return cmd; +} + +static unsigned int papr_smart_get_health(struct ndctl_cmd *cmd) +{ + struct nd_papr_pdsm_health health; + + /* Ignore in case of error or invalid pdsm */ + if (!cmd_is_valid(cmd) || + to_pdsm(cmd)->cmd_status != 0 || + to_pdsm_cmd(cmd) != PAPR_PDSM_HEALTH) + return 0; + + /* get the payload from command */ + health = to_payload(cmd)->health; + + /* Use some math to return one of defined ND_SMART_*_HEALTH values */ + return !health.dimm_health ? 0 : 1 << (health.dimm_health - 1); +} + +static unsigned int papr_smart_get_shutdown_state(struct ndctl_cmd *cmd) +{ + struct nd_papr_pdsm_health health; + + /* Ignore in case of error or invalid pdsm */ + if (!cmd_is_valid(cmd) || + to_pdsm(cmd)->cmd_status != 0 || + to_pdsm_cmd(cmd) != PAPR_PDSM_HEALTH) + return 0; + + /* get the payload from command */ + health = to_payload(cmd)->health; + + /* return the bad shutdown flag returned from papr_scm */ + return health.dimm_bad_shutdown; +} + +static unsigned int papr_smart_get_life_used(struct ndctl_cmd *cmd) +{ + struct nd_papr_pdsm_health health; + + /* Ignore in case of error or invalid pdsm */ + if (!cmd_is_valid(cmd) || + to_pdsm(cmd)->cmd_status != 0 || + to_pdsm_cmd(cmd) != PAPR_PDSM_HEALTH) + return 0; + + /* get the payload from command */ + health = to_payload(cmd)->health; + + /* return dimm life remaining from the health payload */ + return (health.extension_flags & PDSM_DIMM_HEALTH_RUN_GAUGE_VALID) ? + (100 - health.dimm_fuel_gauge) : 0; +} + +struct ndctl_dimm_ops * const papr_dimm_ops = &(struct ndctl_dimm_ops) { + .cmd_is_supported = papr_cmd_is_supported, + .smart_get_flags = papr_smart_get_flags, + .get_firmware_status = papr_get_firmware_status, + .xlat_firmware_status = papr_xlat_firmware_status, + .new_smart = papr_new_smart_health, + .smart_get_health = papr_smart_get_health, + .smart_get_shutdown_state = papr_smart_get_shutdown_state, + .smart_get_life_used = papr_smart_get_life_used, +}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/lib/papr.h new/ndctl-69/ndctl/lib/papr.h --- old/ndctl-68/ndctl/lib/papr.h 1970-01-01 01:00:00.000000000 +0100 +++ new/ndctl-69/ndctl/lib/papr.h 2020-07-23 07:15:11.000000000 +0200 @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: LGPL-2.1 */ +/* (C) Copyright IBM 2020 */ + +#ifndef __PAPR_H__ +#define __PAPR_H__ + +#include <papr_pdsm.h> + +/* Wraps a nd_cmd generic header with pdsm header */ +struct nd_pkg_papr { + struct nd_cmd_pkg gen; + struct nd_pkg_pdsm pdsm; +}; + +#endif /* __PAPR_H__ */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/lib/papr_pdsm.h new/ndctl-69/ndctl/lib/papr_pdsm.h --- old/ndctl-68/ndctl/lib/papr_pdsm.h 1970-01-01 01:00:00.000000000 +0100 +++ new/ndctl-69/ndctl/lib/papr_pdsm.h 2020-07-23 07:15:11.000000000 +0200 @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * PAPR nvDimm Specific Methods (PDSM) and structs for libndctl + * + * (C) Copyright IBM 2020 + * + * Author: Vaibhav Jain <vaibhav at linux.ibm.com> + */ + +#ifndef _UAPI_ASM_POWERPC_PAPR_PDSM_H_ +#define _UAPI_ASM_POWERPC_PAPR_PDSM_H_ + +#include <linux/types.h> +#include <linux/ndctl.h> + +/* + * PDSM Envelope: + * + * The ioctl ND_CMD_CALL exchange data between user-space and kernel via + * envelope which consists of 2 headers sections and payload sections as + * illustrated below: + * +-----------------+---------------+---------------------------+ + * | 64-Bytes | 8-Bytes | Max 184-Bytes | + * +-----------------+---------------+---------------------------+ + * | ND-HEADER | PDSM-HEADER | PDSM-PAYLOAD | + * +-----------------+---------------+---------------------------+ + * | nd_family | | | + * | nd_size_out | cmd_status | | + * | nd_size_in | reserved | nd_pdsm_payload | + * | nd_command | payload --> | | + * | nd_fw_size | | | + * | nd_payload ---> | | | + * +---------------+-----------------+---------------------------+ + * + * ND Header: + * This is the generic libnvdimm header described as 'struct nd_cmd_pkg' + * which is interpreted by libnvdimm before passed on to papr_scm. Important + * member fields used are: + * 'nd_family' : (In) NVDIMM_FAMILY_PAPR_SCM + * 'nd_size_in' : (In) PDSM-HEADER + PDSM-IN-PAYLOAD (usually 0) + * 'nd_size_out' : (In) PDSM-HEADER + PDSM-RETURN-PAYLOAD + * 'nd_command' : (In) One of PAPR_PDSM_XXX + * 'nd_fw_size' : (Out) PDSM-HEADER + size of actual payload returned + * + * PDSM Header: + * This is papr-scm specific header that precedes the payload. This is defined + * as nd_cmd_pdsm_pkg. Following fields aare available in this header: + * + * 'cmd_status' : (Out) Errors if any encountered while servicing PDSM. + * 'reserved' : Not used, reserved for future and should be set to 0. + * 'payload' : A union of all the possible payload structs + * + * PDSM Payload: + * + * The layout of the PDSM Payload is defined by various structs shared between + * papr_scm and libndctl so that contents of payload can be interpreted. As such + * its defined as a union of all possible payload structs as + * 'union nd_pdsm_payload'. Based on the value of 'nd_cmd_pkg.nd_command' + * appropriate member of the union is accessed. + */ + +/* Max payload size that we can handle */ +#define ND_PDSM_PAYLOAD_MAX_SIZE 184 + +/* Max payload size that we can handle */ +#define ND_PDSM_HDR_SIZE \ + (sizeof(struct nd_pkg_pdsm) - ND_PDSM_PAYLOAD_MAX_SIZE) + +/* Various nvdimm health indicators */ +#define PAPR_PDSM_DIMM_HEALTHY 0 +#define PAPR_PDSM_DIMM_UNHEALTHY 1 +#define PAPR_PDSM_DIMM_CRITICAL 2 +#define PAPR_PDSM_DIMM_FATAL 3 + +/* Indicate that the 'dimm_fuel_gauge' field is valid */ +#define PDSM_DIMM_HEALTH_RUN_GAUGE_VALID 1 + +/* + * Struct exchanged between kernel & ndctl in for PAPR_PDSM_HEALTH + * Various flags indicate the health status of the dimm. + * + * extension_flags : Any extension fields present in the struct. + * dimm_unarmed : Dimm not armed. So contents wont persist. + * dimm_bad_shutdown : Previous shutdown did not persist contents. + * dimm_bad_restore : Contents from previous shutdown werent restored. + * dimm_scrubbed : Contents of the dimm have been scrubbed. + * dimm_locked : Contents of the dimm cant be modified until CEC reboot + * dimm_encrypted : Contents of dimm are encrypted. + * dimm_health : Dimm health indicator. One of PAPR_PDSM_DIMM_XXXX + * dimm_fuel_gauge : Life remaining of DIMM as a percentage from 0-100 + */ +struct nd_papr_pdsm_health { + union { + struct { + __u32 extension_flags; + __u8 dimm_unarmed; + __u8 dimm_bad_shutdown; + __u8 dimm_bad_restore; + __u8 dimm_scrubbed; + __u8 dimm_locked; + __u8 dimm_encrypted; + __u16 dimm_health; + + /* Extension flag PDSM_DIMM_HEALTH_RUN_GAUGE_VALID */ + __u16 dimm_fuel_gauge; + }; + __u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE]; + }; +}; + +/* + * Methods to be embedded in ND_CMD_CALL request. These are sent to the kernel + * via 'nd_cmd_pkg.nd_command' member of the ioctl struct + */ +enum papr_pdsm { + PAPR_PDSM_MIN = 0x0, + PAPR_PDSM_HEALTH, + PAPR_PDSM_MAX, +}; + +/* Maximal union that can hold all possible payload types */ +union nd_pdsm_payload { + struct nd_papr_pdsm_health health; + __u8 buf[ND_PDSM_PAYLOAD_MAX_SIZE]; +} __attribute__((packed)); + +/* + * PDSM-header + payload expected with ND_CMD_CALL ioctl from libnvdimm + * Valid member of union 'payload' is identified via 'nd_cmd_pkg.nd_command' + * that should always precede this struct when sent to papr_scm via CMD_CALL + * interface. + */ +struct nd_pkg_pdsm { + __s32 cmd_status; /* Out: Sub-cmd status returned back */ + __u16 reserved[2]; /* Ignored and to be set as '0' */ + union nd_pdsm_payload payload; +} __attribute__((packed)); + +#endif /* _UAPI_ASM_POWERPC_PAPR_PDSM_H_ */ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/lib/private.h new/ndctl-69/ndctl/lib/private.h --- old/ndctl-68/ndctl/lib/private.h 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/ndctl/lib/private.h 2020-07-23 07:15:11.000000000 +0200 @@ -32,6 +32,7 @@ #include "hpe1.h" #include "msft.h" #include "hyperv.h" +#include "papr.h" #include "libndctl-nfit.h" struct nvdimm_data { @@ -167,6 +168,7 @@ int dimms_init; int regions_init; int has_nfit; + int has_of_node; char *bus_path; char *bus_buf; size_t buf_len; @@ -276,6 +278,7 @@ struct ndn_pkg_msft msft[0]; struct nd_pkg_hyperv hyperv[0]; struct nd_pkg_intel intel[0]; + struct nd_pkg_papr papr[0]; struct nd_cmd_get_config_size get_size[0]; struct nd_cmd_get_config_data_hdr get_data[0]; struct nd_cmd_set_config_hdr set_data[0]; @@ -352,6 +355,7 @@ extern struct ndctl_dimm_ops * const hpe1_dimm_ops; extern struct ndctl_dimm_ops * const msft_dimm_ops; extern struct ndctl_dimm_ops * const hyperv_dimm_ops; +extern struct ndctl_dimm_ops * const papr_dimm_ops; static inline struct ndctl_bus *cmd_to_bus(struct ndctl_cmd *cmd) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/libndctl.h new/ndctl-69/ndctl/libndctl.h --- old/ndctl-68/ndctl/libndctl.h 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/ndctl/libndctl.h 2020-07-23 07:15:11.000000000 +0200 @@ -119,6 +119,8 @@ bus = ndctl_bus_get_next(bus)) struct ndctl_ctx *ndctl_bus_get_ctx(struct ndctl_bus *bus); int ndctl_bus_has_nfit(struct ndctl_bus *bus); +int ndctl_bus_has_of_node(struct ndctl_bus *bus); +int ndctl_bus_is_papr_scm(struct ndctl_bus *bus); unsigned int ndctl_bus_get_major(struct ndctl_bus *bus); unsigned int ndctl_bus_get_minor(struct ndctl_bus *bus); const char *ndctl_bus_get_devname(struct ndctl_bus *bus); @@ -385,6 +387,7 @@ struct ndctl_dimm *ndctl_region_get_next_dimm(struct ndctl_region *region, struct ndctl_dimm *dimm); int ndctl_region_get_numa_node(struct ndctl_region *region); +int ndctl_region_has_numa(struct ndctl_region *region); int ndctl_region_get_target_node(struct ndctl_region *region); struct ndctl_region *ndctl_bus_get_region_by_physical_address(struct ndctl_bus *bus, unsigned long long address); @@ -734,6 +737,9 @@ #define ND_KEY_DESC_SIZE 128 #define ND_KEY_CMD_SIZE 128 +#define NUMA_NO_NODE (-1) +#define NUMA_NO_ATTR (-2) + #ifdef __cplusplus } /* extern "C" */ #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/monitor.c new/ndctl-69/ndctl/monitor.c --- old/ndctl-68/ndctl/monitor.c 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/ndctl/monitor.c 2020-07-23 07:15:11.000000000 +0200 @@ -4,6 +4,7 @@ #include <stdio.h> #include <json-c/json.h> #include <libgen.h> +#include <time.h> #include <dirent.h> #include <util/json.h> #include <util/filter.h> @@ -33,6 +34,7 @@ bool daemon; bool human; bool verbose; + unsigned int poll_timeout; unsigned int event_flags; struct log_ctx ctx; } monitor; @@ -322,9 +324,14 @@ struct monitor_filter_arg *mfa) { struct epoll_event ev, *events; - int nfds, epollfd, i, rc = 0; + int nfds, epollfd, i, rc = 0, polltimeout = -1; struct monitor_dimm *mdimm; char buf; + /* last time a full poll happened */ + struct timespec fullpoll_ts, ts; + + if (monitor.poll_timeout) + polltimeout = monitor.poll_timeout * 1000; events = calloc(mfa->num_dimm, sizeof(struct epoll_event)); if (!events) { @@ -354,14 +361,30 @@ } } + clock_gettime(CLOCK_BOOTTIME, &fullpoll_ts); while (1) { did_fail = 0; - nfds = epoll_wait(epollfd, events, mfa->num_dimm, -1); - if (nfds <= 0 && errno != EINTR) { + nfds = epoll_wait(epollfd, events, mfa->num_dimm, polltimeout); + if (nfds < 0 && errno != EINTR) { err(&monitor, "epoll_wait error: (%s)\n", strerror(errno)); rc = -errno; goto out; } + + /* If needed force a full poll of dimm health */ + clock_gettime(CLOCK_BOOTTIME, &ts); + if ((fullpoll_ts.tv_sec - ts.tv_sec) > monitor.poll_timeout) { + nfds = 0; + dbg(&monitor, "forcing a full poll\n"); + } + + /* If we timed out then fill events array with all dimms */ + if (nfds == 0) { + list_for_each(&mfa->dimms, mdimm, list) + events[nfds++].data.ptr = mdimm; + fullpoll_ts = ts; + } + for (i = 0; i < nfds; i++) { mdimm = events[i].data.ptr; if (util_dimm_event_filter(mdimm, monitor.event_flags)) { @@ -570,6 +593,8 @@ "use human friendly output formats"), OPT_BOOLEAN('v', "verbose", &monitor.verbose, "emit extra debug messages to log"), + OPT_UINTEGER('p', "poll", &monitor.poll_timeout, + "poll and report events/status every <n> seconds"), OPT_END(), }; const char * const u[] = { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/namespace.c new/ndctl-69/ndctl/namespace.c --- old/ndctl-68/ndctl/namespace.c 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/ndctl/namespace.c 2020-07-23 07:15:11.000000000 +0200 @@ -175,7 +175,7 @@ OPT_STRING('s', "size", ¶m.size, "size", \ "override the image size to instantiate the infoblock"), \ OPT_STRING('a', "align", ¶m.align, "align", \ - "specify the expected physical alignment (default: 2M)"), \ + "specify the expected physical alignment"), \ OPT_STRING('u', "uuid", ¶m.uuid, "uuid", \ "specify the uuid for the infoblock (default: autogenerate)"), \ OPT_STRING('M', "map", ¶m.map, "memmap-location", \ @@ -325,23 +325,15 @@ sysconf(_SC_PAGE_SIZE)); rc = -EINVAL; } - } else if (action == ACTION_WRITE_INFOBLOCK) - param.align = "2M"; + } if (param.size) { unsigned long long size = parse_size64(param.size); - unsigned long long align = parse_size64(param.align); if (size == ULLONG_MAX) { error("failed to parse namespace size '%s'\n", param.size); rc = -EINVAL; - } else if (action == ACTION_WRITE_INFOBLOCK - && align < ULLONG_MAX - && !IS_ALIGNED(size, align)) { - error("--size=%s not aligned to %s\n", param.size, - param.align); - rc = -EINVAL; } } @@ -1977,11 +1969,28 @@ free(buf); out: - if (fd > 0 && fd != STDOUT_FILENO) + if (fd >= 0 && fd != STDOUT_FILENO) close(fd); return rc; } +static unsigned long ndctl_get_default_alignment(struct ndctl_namespace *ndns) +{ + unsigned long long align = 0; + struct ndctl_dax *dax = ndctl_namespace_get_dax(ndns); + struct ndctl_pfn *pfn = ndctl_namespace_get_pfn(ndns); + + if (ndctl_namespace_get_mode(ndns) == NDCTL_NS_MODE_FSDAX && pfn) + align = ndctl_pfn_get_supported_alignment(pfn, 1); + else if (ndctl_namespace_get_mode(ndns) == NDCTL_NS_MODE_DEVDAX && dax) + align = ndctl_dax_get_supported_alignment(dax, 1); + + if (!align) + align = sysconf(_SC_PAGE_SIZE); + + return align; +} + static int namespace_rw_infoblock(struct ndctl_namespace *ndns, struct read_infoblock_ctx *ri_ctx, int write) { @@ -2013,9 +2022,40 @@ } sprintf(path, "/dev/%s", ndctl_namespace_get_block_device(ndns)); - if (write) - rc = file_write_infoblock(path); - else + if (write) { + unsigned long long align; + bool align_provided = true; + + if (!param.align) { + align = ndctl_get_default_alignment(ndns); + + if (asprintf((char **)¶m.align, "%llu", align) < 0) { + rc = -EINVAL; + goto out; + } + align_provided = false; + } + + if (param.size) { + unsigned long long size = parse_size64(param.size); + align = parse_size64(param.align); + + if (align < ULLONG_MAX && !IS_ALIGNED(size, align)) { + error("--size=%s not aligned to %s\n", param.size, + param.align); + + rc = -EINVAL; + } + } + + if (!rc) + rc = file_write_infoblock(path); + + if (!align_provided) { + free((char *)param.align); + param.align = NULL; + } + } else rc = file_read_infoblock(path, ndns, ri_ctx); param.parent_uuid = save; out: @@ -2060,6 +2100,9 @@ } if (action == ACTION_WRITE_INFOBLOCK && !namespace) { + if (!param.align) + param.align = "2M"; + rc = file_write_infoblock(param.outfile); if (rc >= 0) (*processed)++; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/ndctl/ndctl.h new/ndctl-69/ndctl/ndctl.h --- old/ndctl-68/ndctl/ndctl.h 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/ndctl/ndctl.h 2020-07-23 07:15:11.000000000 +0200 @@ -91,7 +91,7 @@ __u32 reserved; __u64 err_address; __u64 length; - } __attribute__((packed)) records[0]; + } __attribute__((packed)) records[]; } __attribute__((packed)); struct nd_cmd_clear_error { @@ -263,6 +263,7 @@ #define NVDIMM_FAMILY_HPE2 2 #define NVDIMM_FAMILY_MSFT 3 #define NVDIMM_FAMILY_HYPERV 4 +#define NVDIMM_FAMILY_PAPR 5 #define ND_IOCTL_CALL _IOWR(ND_IOCTL, ND_CMD_CALL,\ struct nd_cmd_pkg) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/test/align.sh new/ndctl-69/test/align.sh --- old/ndctl-68/test/align.sh 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/test/align.sh 2020-07-23 07:15:11.000000000 +0200 @@ -34,8 +34,19 @@ set -e trap 'err $LINENO cleanup' ERR -region=$($NDCTL list -R -b ACPI.NFIT | jq -r '.[] | [select(.available_size == .size)] | .[0].dev') +find_region() +{ + $NDCTL list -R -b ACPI.NFIT | jq -r '[.[] | select(.available_size == .size)][0] | .dev' +} +region=$(find_region) +if [ "x$region" = "xnull" ]; then + # this is destructive + $NDCTL disable-region -b ACPI.NFIT all + $NDCTL init-labels -f -b ACPI.NFIT all + $NDCTL enable-region -b ACPI.NFIT all +fi +region=$(find_region) if [ "x$region" = "xnull" ]; then unset $region echo "unable to find empty region" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ndctl-68/util/filter.c new/ndctl-69/util/filter.c --- old/ndctl-68/util/filter.c 2020-03-24 05:54:05.000000000 +0100 +++ new/ndctl-69/util/filter.c 2020-07-23 07:15:11.000000000 +0200 @@ -23,8 +23,6 @@ #include <ndctl/libndctl.h> #include <daxctl/libdaxctl.h> -#define NUMA_NO_NODE (-1) - struct ndctl_bus *util_bus_filter(struct ndctl_bus *bus, const char *__ident) { char *end = NULL, *ident, *save; @@ -467,7 +465,22 @@ param->namespace)) continue; + /* + * if numa_node attribute is not available for regions + * (which is true for pre 5.4 kernels), don't skip the + * region if namespace is also requested, let the + * namespace filter handle the NUMA node filtering. + */ if (numa_node != NUMA_NO_NODE && + !ndctl_region_has_numa(region) && + !fctx->filter_namespace) { + fprintf(stderr, + "This kernel does not provide NUMA node information per-region\n"); + continue; + } + + if (ndctl_region_has_numa(region) && + numa_node != NUMA_NO_NODE && ndctl_region_get_numa_node(region) != numa_node) continue; @@ -489,6 +502,10 @@ if (param->mode && util_nsmode(param->mode) != mode) continue; + if (numa_node != NUMA_NO_NODE && + ndctl_namespace_get_numa_node(ndns) != numa_node) + continue; + fctx->filter_namespace(ndns, fctx); } }
