[ndctl PATCH v2 1/4] ndctl, inject-error: error out for a non-existent namespace
by Vishal Verma
When an invalid namespace was specified, inject-error would simply walk
through a loop trying to matching namespace, and at the end, exit out
silently. This could make it look as though the operation had been
successful, when in reality, nothing had been done.
Fix to print a message, and exit with an ENXIO when this happens.
Signed-off-by: Vishal Verma <vishal.l.verma(a)intel.com>
---
ndctl/inject-error.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/ndctl/inject-error.c b/ndctl/inject-error.c
index 9b9d821..efa9f92 100644
--- a/ndctl/inject-error.c
+++ b/ndctl/inject-error.c
@@ -338,7 +338,8 @@ static int do_inject(const char *namespace, struct ndctl_ctx *ctx)
}
}
- return 0;
+ error("%s: no such namespace\n", namespace);
+ return rc;
}
int cmd_inject_error(int argc, const char **argv, void *ctx)
--
2.14.3
4 years, 4 months
[ndctl PATCH 1/4] ndctl, inject-error: error out for a non-existent namespace
by Vishal Verma
When an invalid namespace was specified, inject-error would simply walk
through a loop trying to matching namespace, and at the end, exit out
silently. This could make it look as though the operation had been
successful, when in reality, nothing had been done.
Fix to print a message, and exit with an ENXIO when this happens.
Signed-off-by: Vishal Verma <vishal.l.verma(a)intel.com>
---
ndctl/inject-error.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/ndctl/inject-error.c b/ndctl/inject-error.c
index 9b9d821..efa9f92 100644
--- a/ndctl/inject-error.c
+++ b/ndctl/inject-error.c
@@ -338,7 +338,8 @@ static int do_inject(const char *namespace, struct ndctl_ctx *ctx)
}
}
- return 0;
+ error("%s: no such namespace\n", namespace);
+ return rc;
}
int cmd_inject_error(int argc, const char **argv, void *ctx)
--
2.14.3
4 years, 4 months
[PATCH v6] ndctl: add firmware update command option for ndctl
by Dave Jiang
Adding option "update-firmware" to ndctl for update firmware support from
Intel DSM v1.6. ndctl update-firmware takes an option of -f for a firmware
binary and a -d for the DIMM name:
ndctl update-firmware -d nmem0 -f new_firmware.bin
Signed-off-by: Dave Jiang <dave.jiang(a)intel.com>
---
Fixed issue from coverity warning that points to using stat and then
opening the file based on the result of stat. We will now open the file,
flock the file exclusively, and then use fstat.
Documentation/ndctl/Makefile.am | 1
Documentation/ndctl/ndctl-update-firmware.txt | 18 +
builtin.h | 1
ndctl/Makefile.am | 3
ndctl/ndctl.c | 1
ndctl/update.c | 553 +++++++++++++++++++++++++
6 files changed, 576 insertions(+), 1 deletion(-)
create mode 100644 Documentation/ndctl/ndctl-update-firmware.txt
create mode 100644 ndctl/update.c
diff --git a/Documentation/ndctl/Makefile.am b/Documentation/ndctl/Makefile.am
index 615baf0..27b2076 100644
--- a/Documentation/ndctl/Makefile.am
+++ b/Documentation/ndctl/Makefile.am
@@ -31,6 +31,7 @@ man1_MANS = \
ndctl-destroy-namespace.1 \
ndctl-check-namespace.1 \
ndctl-inject-error.1 \
+ ndctl-update-firmware.1 \
ndctl-list.1
CLEANFILES = $(man1_MANS)
diff --git a/Documentation/ndctl/ndctl-update-firmware.txt b/Documentation/ndctl/ndctl-update-firmware.txt
new file mode 100644
index 0000000..d742302
--- /dev/null
+++ b/Documentation/ndctl/ndctl-update-firmware.txt
@@ -0,0 +1,18 @@
+ndctl-update-firmware(1)
+========================
+
+NAME
+----
+ndctl-update-firmware - provides updating of NVDIMM firmware
+
+SYNOPSIS
+--------
+[verse]
+'ndctl update-firmware' -f <firmware_file> -d <dimm name>
+
+COPYRIGHT
+---------
+Copyright (c) 2016 - 2017, Intel Corporation. License GPLv2: GNU GPL
+version 2 <http://gnu.org/licenses/gpl.html>. This is free software:
+you are free to change and redistribute it. There is NO WARRANTY, to
+the extent permitted by law.
diff --git a/builtin.h b/builtin.h
index 5e1b7ef..1f423dc 100644
--- a/builtin.h
+++ b/builtin.h
@@ -43,4 +43,5 @@ int cmd_test(int argc, const char **argv, void *ctx);
#ifdef ENABLE_DESTRUCTIVE
int cmd_bat(int argc, const char **argv, void *ctx);
#endif
+int cmd_update_firmware(int argc, const char **argv, void *ctx);
#endif /* _NDCTL_BUILTIN_H_ */
diff --git a/ndctl/Makefile.am b/ndctl/Makefile.am
index 6677607..5cd8678 100644
--- a/ndctl/Makefile.am
+++ b/ndctl/Makefile.am
@@ -13,7 +13,8 @@ ndctl_SOURCES = ndctl.c \
test.c \
../util/json.c \
util/json-smart.c \
- inject-error.c
+ inject-error.c \
+ update.c
if ENABLE_DESTRUCTIVE
ndctl_SOURCES += ../test/blk_namespaces.c \
diff --git a/ndctl/ndctl.c b/ndctl/ndctl.c
index 0f748e1..a0e5153 100644
--- a/ndctl/ndctl.c
+++ b/ndctl/ndctl.c
@@ -84,6 +84,7 @@ static struct cmd_struct commands[] = {
{ "init-labels", cmd_init_labels },
{ "check-labels", cmd_check_labels },
{ "inject-error", cmd_inject_error },
+ { "update-firmware", cmd_update_firmware },
{ "list", cmd_list },
{ "help", cmd_help },
#ifdef ENABLE_TEST
diff --git a/ndctl/update.c b/ndctl/update.c
new file mode 100644
index 0000000..877d37f
--- /dev/null
+++ b/ndctl/update.c
@@ -0,0 +1,553 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2018 Intel Corporation. All rights reserved. */
+
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <syslog.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/file.h>
+
+#include <util/log.h>
+#include <util/size.h>
+#include <util/util.h>
+#include <uuid/uuid.h>
+#include <util/json.h>
+#include <util/filter.h>
+#include <json-c/json.h>
+#include <util/fletcher.h>
+#include <ndctl/libndctl.h>
+#include <ndctl/namespace.h>
+#include <util/parse-options.h>
+#include <ccan/minmax/minmax.h>
+#include <ccan/array_size/array_size.h>
+#ifdef HAVE_NDCTL_H
+#include <linux/ndctl.h>
+#else
+#include <ndctl.h>
+#endif
+
+#include <libndctl-nfit.h>
+#include "private.h"
+#include <builtin.h>
+#include <test.h>
+
+#define ND_CMD_STATUS_SUCCESS 0
+#define ND_CMD_STATUS_NOTSUPP 1
+#define ND_CMD_STATUS_NOTEXIST 2
+#define ND_CMD_STATUS_INVALPARM 3
+#define ND_CMD_STATUS_HWERR 4
+#define ND_CMD_STATUS_RETRY 5
+#define ND_CMD_STATUS_UNKNOWN 6
+#define ND_CMD_STATUS_EXTEND 7
+#define ND_CMD_STATUS_NORES 8
+#define ND_CMD_STATUS_NOTREADY 9
+
+#define ND_CMD_STATUS_START_BUSY 0x10000
+#define ND_CMD_STATUS_SEND_CTXINVAL 0x10000
+#define ND_CMD_STATUS_FIN_CTXINVAL 0x10000
+#define ND_CMD_STATUS_FIN_DONE 0x20000
+#define ND_CMD_STATUS_FIN_BAD 0x30000
+#define ND_CMD_STATUS_FIN_ABORTED 0x40000
+#define ND_CMD_STATUS_FQ_CTXINVAL 0x10000
+#define ND_CMD_STATUS_FQ_BUSY 0x20000
+#define ND_CMD_STATUS_FQ_BAD 0x30000
+#define ND_CMD_STATUS_FQ_ORDER 0x40000
+
+struct fw_info {
+ uint32_t store_size;
+ uint32_t update_size;
+ uint32_t query_interval;
+ uint32_t max_query;
+ uint64_t run_version;
+ uint32_t context;
+};
+
+struct update_context {
+ int fw_fd;
+ size_t fw_size;
+ const char *fw_path;
+ const char *dimm_id;
+ struct ndctl_dimm *dimm;
+ struct fw_info dimm_fw;
+ struct ndctl_cmd *start;
+};
+
+/*
+ * updating firmware consists of performing the following steps:
+ * 1. Call GET_FIMRWARE_INFO DSM. The return results provide:
+ * A. Size of the firmware storage area
+ * B. Max size per send command
+ * C. Polling interval for check finish status
+ * D. Max time for finish update poll
+ * E. Update capabilities
+ * F. Running FIS version
+ * G. Running FW revision
+ * H. Updated FW revision. Only valid after firmware update done.
+ * 2. Call START_FW_UPDATE. The return results provide:
+ * A. Ready to start status
+ * B. Valid FW update context
+ * 3. Call SEND_FW_UPDATE_DATA with valid payload
+ * Repeat until done.
+ * 4. Call FINISH_FW_UPDATE
+ * 5. Poll with QUERY_FINISH_UPDATE success or failure
+ */
+
+static int verify_fw_size(struct update_context *uctx)
+{
+ struct fw_info *fw = &uctx->dimm_fw;
+
+ if (uctx->fw_size > fw->store_size) {
+ error("Firmware file size greater than DIMM store\n");
+ return -ENOSPC;
+ }
+
+ return 0;
+}
+
+static int submit_get_firmware_info(struct update_context *uctx)
+{
+ struct ndctl_cmd *cmd;
+ int rc;
+ enum ND_FW_STATUS status;
+ struct fw_info *fw = &uctx->dimm_fw;
+
+ cmd = ndctl_dimm_cmd_new_fw_get_info(uctx->dimm);
+ if (!cmd)
+ return -ENXIO;
+
+ rc = ndctl_cmd_submit(cmd);
+ if (rc < 0)
+ return rc;
+
+ status = ndctl_cmd_fw_xlat_firmware_status(cmd);
+ if (status != FW_SUCCESS) {
+ error("GET FIRMWARE INFO failed: %#x\n", status);
+ return -ENXIO;
+ }
+
+ fw->store_size = ndctl_cmd_fw_info_get_storage_size(cmd);
+ if (fw->store_size == UINT_MAX)
+ return -ENXIO;
+
+ fw->update_size = ndctl_cmd_fw_info_get_max_send_len(cmd);
+ if (fw->update_size == UINT_MAX)
+ return -ENXIO;
+
+ fw->query_interval = ndctl_cmd_fw_info_get_query_interval(cmd);
+ if (fw->query_interval == UINT_MAX)
+ return -ENXIO;
+
+ fw->max_query = ndctl_cmd_fw_info_get_max_query_time(cmd);
+ if (fw->max_query == UINT_MAX)
+ return -ENXIO;
+
+ fw->run_version = ndctl_cmd_fw_info_get_run_version(cmd);
+ if (fw->run_version == ULLONG_MAX)
+ return -ENXIO;
+
+ rc = verify_fw_size(uctx);
+ ndctl_cmd_unref(cmd);
+ return rc;
+}
+
+static int submit_start_firmware_upload(struct update_context *uctx)
+{
+ struct ndctl_cmd *cmd;
+ int rc;
+ enum ND_FW_STATUS status;
+ struct fw_info *fw = &uctx->dimm_fw;
+
+ cmd = ndctl_dimm_cmd_new_fw_start_update(uctx->dimm);
+ if (!cmd)
+ return -ENXIO;
+
+ rc = ndctl_cmd_submit(cmd);
+ if (rc < 0)
+ return rc;
+
+ status = ndctl_cmd_fw_xlat_firmware_status(cmd);
+ if (status != FW_SUCCESS) {
+ error("START FIRMWARE UPDATE failed: %#x\n", status);
+ if (status == FW_EBUSY)
+ error("Another firmware upload in progress or finished.\n");
+ return -ENXIO;
+ }
+
+ fw->context = ndctl_cmd_fw_start_get_context(cmd);
+ if (fw->context == UINT_MAX)
+ return -ENXIO;
+
+ uctx->start = cmd;
+
+ return 0;
+}
+
+static int get_fw_data_from_file(int fd, void *buf, uint32_t len,
+ uint32_t offset)
+{
+ ssize_t rc, total = len;
+
+ while (len) {
+ rc = pread(fd, buf, len, offset);
+ if (rc < 0)
+ return -errno;
+ len -= rc;
+ }
+
+ return total;
+}
+
+static int send_firmware(struct update_context *uctx)
+{
+ struct ndctl_cmd *cmd = NULL;
+ ssize_t read;
+ int rc;
+ enum ND_FW_STATUS status;
+ struct fw_info *fw = &uctx->dimm_fw;
+ uint32_t copied = 0, len, remain;
+ void *buf;
+
+ buf = malloc(fw->update_size);
+ if (!buf)
+ return -ENOMEM;
+
+ remain = uctx->fw_size;
+
+ while (remain) {
+ len = min(fw->update_size, remain);
+ read = get_fw_data_from_file(uctx->fw_fd, buf, len, copied);
+ if (read < 0) {
+ rc = read;
+ goto cleanup;
+ }
+
+ cmd = ndctl_dimm_cmd_new_fw_send(uctx->start, copied, read,
+ buf);
+ if (!cmd) {
+ rc = -ENXIO;
+ goto cleanup;
+ }
+
+ rc = ndctl_cmd_submit(cmd);
+ if (rc < 0)
+ goto cleanup;
+
+ status = ndctl_cmd_fw_xlat_firmware_status(cmd);
+ if (status != FW_SUCCESS) {
+ error("SEND FIRMWARE failed: %#x\n", status);
+ rc = -ENXIO;
+ goto cleanup;
+ }
+
+ copied += read;
+ remain -= read;
+
+ ndctl_cmd_unref(cmd);
+ cmd = NULL;
+ }
+
+cleanup:
+ if (cmd)
+ ndctl_cmd_unref(cmd);
+ free(buf);
+ return rc;
+}
+
+static int submit_finish_firmware(struct update_context *uctx)
+{
+ struct ndctl_cmd *cmd;
+ int rc;
+ enum ND_FW_STATUS status;
+
+ cmd = ndctl_dimm_cmd_new_fw_finish(uctx->start);
+ if (!cmd)
+ return -ENXIO;
+
+ rc = ndctl_cmd_submit(cmd);
+ if (rc < 0)
+ goto out;
+
+ status = ndctl_cmd_fw_xlat_firmware_status(cmd);
+ if (status != FW_SUCCESS) {
+ error("FINISH FIRMWARE UPDATE failed: %#x\n", status);
+ rc = -ENXIO;
+ goto out;
+ }
+
+out:
+ ndctl_cmd_unref(cmd);
+ return rc;
+}
+
+static int submit_abort_firmware(struct update_context *uctx)
+{
+ struct ndctl_cmd *cmd;
+ int rc;
+ enum ND_FW_STATUS status;
+
+ cmd = ndctl_dimm_cmd_new_fw_abort(uctx->start);
+ if (!cmd)
+ return -ENXIO;
+
+ rc = ndctl_cmd_submit(cmd);
+ if (rc < 0)
+ goto out;
+
+ status = ndctl_cmd_fw_xlat_firmware_status(cmd);
+ if (!(status & ND_CMD_STATUS_FIN_ABORTED)) {
+ error("FW update abort failed: %#x\n", status);
+ rc = -ENXIO;
+ goto out;
+ }
+
+out:
+ ndctl_cmd_unref(cmd);
+ return rc;
+}
+
+static int query_fw_finish_status(struct update_context *uctx)
+{
+ struct ndctl_cmd *cmd;
+ int rc;
+ enum ND_FW_STATUS status;
+ struct fw_info *fw = &uctx->dimm_fw;
+ bool done = false;
+ struct timespec now, before, after;
+ uint64_t ver;
+
+ cmd = ndctl_dimm_cmd_new_fw_finish_query(uctx->start);
+ if (!cmd)
+ return -ENXIO;
+
+ rc = clock_gettime(CLOCK_MONOTONIC, &before);
+ if (rc < 0)
+ goto out;
+
+ now.tv_nsec = fw->query_interval / 1000;
+ now.tv_sec = 0;
+
+ do {
+ rc = ndctl_cmd_submit(cmd);
+ if (rc < 0)
+ break;
+
+ status = ndctl_cmd_fw_xlat_firmware_status(cmd);
+ switch (status) {
+ case FW_SUCCESS:
+ ver = ndctl_cmd_fw_fquery_get_fw_rev(cmd);
+ if (ver == 0) {
+ printf("No firmware updated\n");
+ rc = -ENXIO;
+ goto out;
+ }
+
+ printf("Image %s updated successfully to DIMM %s\n",
+ uctx->fw_path, uctx->dimm_id);
+ printf("Firmware version %#lx.\n", ver);
+ printf("Reboot to activate.\n");
+ done = true;
+ rc = 0;
+ break;
+ case FW_EBUSY:
+ /* Still on going, continue */
+ rc = clock_gettime(CLOCK_MONOTONIC, &after);
+ if (rc < 0) {
+ rc = -errno;
+ goto out;
+ }
+
+ /*
+ * If we expire max query time,
+ * we timed out
+ */
+ if (after.tv_sec - before.tv_sec >
+ fw->max_query / 1000000) {
+ rc = -ETIMEDOUT;
+ goto out;
+ }
+
+ /*
+ * Sleep the interval dictated by firmware
+ * before query again.
+ */
+ rc = nanosleep(&now, NULL);
+ if (rc < 0) {
+ rc = -errno;
+ goto out;
+ }
+ break;
+ case FW_EBADFW:
+ printf("Image failed to verify by DIMM\n");
+ case FW_EINVAL_CTX:
+ case FW_ESEQUENCE:
+ done = true;
+ rc = -ENXIO;
+ goto out;
+ case FW_ENORES:
+ printf("Firmware update sequence timed out\n");
+ rc = -ETIMEDOUT;
+ done = true;
+ goto out;
+ default:
+ rc = -EINVAL;
+ done = true;
+ goto out;
+ }
+ } while (!done);
+
+out:
+ ndctl_cmd_unref(cmd);
+ return rc;
+}
+
+static int update_firmware(struct update_context *uctx)
+{
+ int rc;
+
+ rc = submit_get_firmware_info(uctx);
+ if (rc < 0)
+ return rc;
+
+ rc = submit_start_firmware_upload(uctx);
+ if (rc < 0)
+ return rc;
+
+ printf("Uploading %s to DIMM %s\n", uctx->fw_path, uctx->dimm_id);
+
+ rc = send_firmware(uctx);
+ if (rc < 0) {
+ error("Firmware send failed. Aborting...\n");
+ rc = submit_abort_firmware(uctx);
+ if (rc < 0)
+ error("Aborting update sequence failed\n");
+ return rc;
+ }
+
+ rc = submit_finish_firmware(uctx);
+ if (rc < 0) {
+ error("Unable to end update sequence\n");
+ rc = submit_abort_firmware(uctx);
+ if (rc < 0)
+ error("Aborting update sequence failed\n");
+ return rc;
+ }
+
+ rc = query_fw_finish_status(uctx);
+ if (rc < 0)
+ return rc;
+
+ return 0;
+}
+
+static int get_ndctl_dimm(struct update_context *uctx, void *ctx)
+{
+ struct ndctl_dimm *dimm;
+ struct ndctl_bus *bus;
+
+ ndctl_bus_foreach(ctx, bus)
+ ndctl_dimm_foreach(bus, dimm) {
+ if (!util_dimm_filter(dimm, uctx->dimm_id))
+ continue;
+ uctx->dimm = dimm;
+ return 0;
+ }
+
+ return -ENODEV;
+}
+
+static int verify_fw_file(struct update_context *uctx)
+{
+ struct stat st;
+ int rc;
+
+ uctx->fw_fd = open(uctx->fw_path, O_RDONLY);
+ if (uctx->fw_fd < 0)
+ return -errno;
+
+ rc = flock(uctx->fw_fd, LOCK_EX | LOCK_NB);
+ if (rc < 0) {
+ rc = -errno;
+ goto cleanup;
+ }
+
+ if (fstat(uctx->fw_fd, &st) < 0) {
+ rc = -errno;
+ goto cleanup;
+ }
+
+ if (!S_ISREG(st.st_mode)) {
+ rc = -EINVAL;
+ goto cleanup;
+ }
+
+ uctx->fw_size = st.st_size;
+ if (uctx->fw_size == 0) {
+ rc = -EINVAL;
+ goto cleanup;
+ }
+
+ return 0;
+
+cleanup:
+ close(uctx->fw_fd);
+ return rc;
+}
+
+int cmd_update_firmware(int argc, const char **argv, void *ctx)
+{
+ struct update_context uctx = { 0 };
+ const struct option options[] = {
+ OPT_STRING('f', "firmware", &uctx.fw_path,
+ "file-name", "name of firmware"),
+ OPT_STRING('d', "dimm", &uctx.dimm_id, "dimm-id",
+ "dimm to be updated"),
+ OPT_END(),
+ };
+ const char * const u[] = {
+ "ndctl update_firmware [<options>]",
+ NULL
+ };
+ int i, rc;
+
+ argc = parse_options(argc, argv, options, u, 0);
+ for (i = 0; i < argc; i++)
+ error("unknown parameter \"%s\"\n", argv[i]);
+ if (argc)
+ usage_with_options(u, options);
+
+ if (!uctx.fw_path) {
+ error("No firmware file provided\n");
+ usage_with_options(u, options);
+ return -EINVAL;
+ }
+
+ if (!uctx.dimm_id) {
+ error("No DIMM ID provided\n");
+ usage_with_options(u, options);
+ return -EINVAL;
+ }
+
+ rc = verify_fw_file(&uctx);
+ if (rc < 0)
+ return rc;
+
+ rc = get_ndctl_dimm(&uctx, ctx);
+ if (rc < 0)
+ return rc;
+
+ rc = update_firmware(&uctx);
+ if (rc < 0)
+ return rc;
+
+ if (uctx.start)
+ ndctl_cmd_unref(uctx.start);
+
+ return 0;
+}
4 years, 4 months
[PATCH v4 1/2] libnvdimm, testing: Add emulation for smart injection commands
by Vishal Verma
Add support for the smart injection command in the nvdimm unit test
framework. This allows for directly injecting to smart fields and flags
that are supported in the injection command. If the injected values are
past the threshold, then an acpi notification is also triggered.
Cc: Dan Williams <dan.j.williams(a)intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma(a)intel.com>
---
tools/testing/nvdimm/test/nfit.c | 38 ++++++++++++++++++++++++++++++++++-
tools/testing/nvdimm/test/nfit_test.h | 16 +++++++++++++++
2 files changed, 53 insertions(+), 1 deletion(-)
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 42ee1798971d..1df6131d569f 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -708,7 +708,9 @@ static void smart_notify(struct device *bus_dev,
>= thresh->media_temperature)
|| ((thresh->alarm_control & ND_INTEL_SMART_CTEMP_TRIP)
&& smart->ctrl_temperature
- >= thresh->ctrl_temperature)) {
+ >= thresh->ctrl_temperature)
+ || (smart->health != ND_INTEL_SMART_NON_CRITICAL_HEALTH)
+ || (smart->shutdown_state != 0)) {
device_lock(bus_dev);
__acpi_nvdimm_notify(dimm_dev, 0x81);
device_unlock(bus_dev);
@@ -734,6 +736,32 @@ static int nfit_test_cmd_smart_set_threshold(
return 0;
}
+static int nfit_test_cmd_smart_inject(
+ struct nd_intel_smart_inject *inj,
+ unsigned int buf_len,
+ struct nd_intel_smart_threshold *thresh,
+ struct nd_intel_smart *smart,
+ struct device *bus_dev, struct device *dimm_dev)
+{
+ if (buf_len != sizeof(*inj))
+ return -EINVAL;
+
+ if (inj->mtemp_enable)
+ smart->media_temperature = inj->media_temperature;
+ if (inj->spare_enable)
+ smart->spares = inj->spares;
+ if (inj->fatal_enable)
+ smart->health = ND_INTEL_SMART_FATAL_HEALTH;
+ if (inj->unsafe_shutdown_enable) {
+ smart->shutdown_state = 1;
+ smart->shutdown_count++;
+ }
+ inj->status = 0;
+ smart_notify(bus_dev, dimm_dev, smart, thresh);
+
+ return 0;
+}
+
static void uc_error_notify(struct work_struct *work)
{
struct nfit_test *t = container_of(work, typeof(*t), work);
@@ -934,6 +962,13 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
t->dcr_idx],
&t->smart[i - t->dcr_idx],
&t->pdev.dev, t->dimm_dev[i]);
+ case ND_INTEL_SMART_INJECT:
+ return nfit_test_cmd_smart_inject(buf,
+ buf_len,
+ &t->smart_threshold[i -
+ t->dcr_idx],
+ &t->smart[i - t->dcr_idx],
+ &t->pdev.dev, t->dimm_dev[i]);
default:
return -ENOTTY;
}
@@ -2015,6 +2050,7 @@ static void nfit_test0_setup(struct nfit_test *t)
set_bit(ND_INTEL_SMART, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_INTEL_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_INTEL_SMART_SET_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
+ set_bit(ND_INTEL_SMART_INJECT, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h
index 428344519cdf..33752e06ff8d 100644
--- a/tools/testing/nvdimm/test/nfit_test.h
+++ b/tools/testing/nvdimm/test/nfit_test.h
@@ -93,6 +93,7 @@ struct nd_cmd_ars_err_inj_stat {
#define ND_INTEL_FW_FINISH_UPDATE 15
#define ND_INTEL_FW_FINISH_QUERY 16
#define ND_INTEL_SMART_SET_THRESHOLD 17
+#define ND_INTEL_SMART_INJECT 18
#define ND_INTEL_SMART_HEALTH_VALID (1 << 0)
#define ND_INTEL_SMART_SPARES_VALID (1 << 1)
@@ -111,6 +112,10 @@ struct nd_cmd_ars_err_inj_stat {
#define ND_INTEL_SMART_NON_CRITICAL_HEALTH (1 << 0)
#define ND_INTEL_SMART_CRITICAL_HEALTH (1 << 1)
#define ND_INTEL_SMART_FATAL_HEALTH (1 << 2)
+#define ND_INTEL_SMART_INJECT_MTEMP (1 << 0)
+#define ND_INTEL_SMART_INJECT_SPARE (1 << 1)
+#define ND_INTEL_SMART_INJECT_FATAL (1 << 2)
+#define ND_INTEL_SMART_INJECT_SHUTDOWN (1 << 3)
struct nd_intel_smart {
__u32 status;
@@ -158,6 +163,17 @@ struct nd_intel_smart_set_threshold {
__u32 status;
} __packed;
+struct nd_intel_smart_inject {
+ __u64 flags;
+ __u8 mtemp_enable;
+ __u16 media_temperature;
+ __u8 spare_enable;
+ __u8 spares;
+ __u8 fatal_enable;
+ __u8 unsafe_shutdown_enable;
+ __u32 status;
+} __packed;
+
#define INTEL_FW_STORAGE_SIZE 0x100000
#define INTEL_FW_MAX_SEND_LEN 0xFFEC
#define INTEL_FW_QUERY_INTERVAL 250000
--
2.14.3
4 years, 4 months
[PATCH v3] libnvdimm, testing: Add emulation for smart injection commands
by Vishal Verma
Add support for the smart injection command in the nvdimm unit test
framework. This allows for directly injecting to smart fields and flags
that are supported in the injection command. If the injected values are
past the threshold, then an acpi notification is also triggered.
Also update the default smart ctrl_temperature to start out below the
default threshold instead of at it. This prevents arbitrary smart
injections from triggering an acpi notification
Cc: Dan Williams <dan.j.williams(a)intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma(a)intel.com>
---
tools/testing/nvdimm/test/nfit.c | 43 +++++++++++++++++++++++++++++++++--
tools/testing/nvdimm/test/nfit_test.h | 16 +++++++++++++
2 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 42ee1798971d..b57104ad3bac 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -708,7 +708,9 @@ static void smart_notify(struct device *bus_dev,
>= thresh->media_temperature)
|| ((thresh->alarm_control & ND_INTEL_SMART_CTEMP_TRIP)
&& smart->ctrl_temperature
- >= thresh->ctrl_temperature)) {
+ >= thresh->ctrl_temperature)
+ || (smart->health != ND_INTEL_SMART_NON_CRITICAL_HEALTH)
+ || (smart->shutdown_state != 0)) {
device_lock(bus_dev);
__acpi_nvdimm_notify(dimm_dev, 0x81);
device_unlock(bus_dev);
@@ -734,6 +736,35 @@ static int nfit_test_cmd_smart_set_threshold(
return 0;
}
+static int nfit_test_cmd_smart_inject(
+ struct nd_intel_smart_inject *inj,
+ unsigned int buf_len,
+ struct nd_intel_smart_threshold *thresh,
+ struct nd_intel_smart *smart,
+ struct device *bus_dev, struct device *dimm_dev)
+{
+ if (buf_len != sizeof(*inj)) {
+ pr_err("TEST: size mismatch. buf = %d, struct = %d\n",
+ buf_len, sizeof(*inj));
+ return -EINVAL;
+ }
+
+ if (inj->mtemp_enable)
+ smart->media_temperature = inj->media_temperature;
+ if (inj->spare_enable)
+ smart->spares = inj->spares;
+ if (inj->fatal_enable)
+ smart->health = ND_INTEL_SMART_FATAL_HEALTH;
+ if (inj->unsafe_shutdown_enable) {
+ smart->shutdown_state = 1;
+ smart->shutdown_count++;
+ }
+ inj->status = 0;
+ smart_notify(bus_dev, dimm_dev, smart, thresh);
+
+ return 0;
+}
+
static void uc_error_notify(struct work_struct *work)
{
struct nfit_test *t = container_of(work, typeof(*t), work);
@@ -934,6 +965,13 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
t->dcr_idx],
&t->smart[i - t->dcr_idx],
&t->pdev.dev, t->dimm_dev[i]);
+ case ND_INTEL_SMART_INJECT:
+ return nfit_test_cmd_smart_inject(buf,
+ buf_len,
+ &t->smart_threshold[i -
+ t->dcr_idx],
+ &t->smart[i - t->dcr_idx],
+ &t->pdev.dev, t->dimm_dev[i]);
default:
return -ENOTTY;
}
@@ -1221,7 +1259,7 @@ static void smart_init(struct nfit_test *t)
| ND_INTEL_SMART_MTEMP_VALID,
.health = ND_INTEL_SMART_NON_CRITICAL_HEALTH,
.media_temperature = 23 * 16,
- .ctrl_temperature = 30 * 16,
+ .ctrl_temperature = 25 * 16,
.pmic_temperature = 40 * 16,
.spares = 75,
.alarm_flags = ND_INTEL_SMART_SPARE_TRIP
@@ -2015,6 +2053,7 @@ static void nfit_test0_setup(struct nfit_test *t)
set_bit(ND_INTEL_SMART, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_INTEL_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_INTEL_SMART_SET_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
+ set_bit(ND_INTEL_SMART_INJECT, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h
index 428344519cdf..33752e06ff8d 100644
--- a/tools/testing/nvdimm/test/nfit_test.h
+++ b/tools/testing/nvdimm/test/nfit_test.h
@@ -93,6 +93,7 @@ struct nd_cmd_ars_err_inj_stat {
#define ND_INTEL_FW_FINISH_UPDATE 15
#define ND_INTEL_FW_FINISH_QUERY 16
#define ND_INTEL_SMART_SET_THRESHOLD 17
+#define ND_INTEL_SMART_INJECT 18
#define ND_INTEL_SMART_HEALTH_VALID (1 << 0)
#define ND_INTEL_SMART_SPARES_VALID (1 << 1)
@@ -111,6 +112,10 @@ struct nd_cmd_ars_err_inj_stat {
#define ND_INTEL_SMART_NON_CRITICAL_HEALTH (1 << 0)
#define ND_INTEL_SMART_CRITICAL_HEALTH (1 << 1)
#define ND_INTEL_SMART_FATAL_HEALTH (1 << 2)
+#define ND_INTEL_SMART_INJECT_MTEMP (1 << 0)
+#define ND_INTEL_SMART_INJECT_SPARE (1 << 1)
+#define ND_INTEL_SMART_INJECT_FATAL (1 << 2)
+#define ND_INTEL_SMART_INJECT_SHUTDOWN (1 << 3)
struct nd_intel_smart {
__u32 status;
@@ -158,6 +163,17 @@ struct nd_intel_smart_set_threshold {
__u32 status;
} __packed;
+struct nd_intel_smart_inject {
+ __u64 flags;
+ __u8 mtemp_enable;
+ __u16 media_temperature;
+ __u8 spare_enable;
+ __u8 spares;
+ __u8 fatal_enable;
+ __u8 unsafe_shutdown_enable;
+ __u32 status;
+} __packed;
+
#define INTEL_FW_STORAGE_SIZE 0x100000
#define INTEL_FW_MAX_SEND_LEN 0xFFEC
#define INTEL_FW_QUERY_INTERVAL 250000
--
2.14.3
4 years, 4 months
[PATCH v2] libnvdimm, testing: Add emulation for smart injection commands
by Vishal Verma
Add support for the smart injection command in the nvdimm unit test
framework. This allows for directly injecting to smart fields and flags
that are supported in the injection command. If the injected values are
past the threshold, then an acpi notification is also triggered.
Cc: Dan Williams <dan.j.williams(a)intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma(a)intel.com>
---
tools/testing/nvdimm/test/nfit.c | 43 +++++++++++++++++++++++++++++++++--
tools/testing/nvdimm/test/nfit_test.h | 16 +++++++++++++
2 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 42ee1798971d..90aefef4065f 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -708,7 +708,9 @@ static void smart_notify(struct device *bus_dev,
>= thresh->media_temperature)
|| ((thresh->alarm_control & ND_INTEL_SMART_CTEMP_TRIP)
&& smart->ctrl_temperature
- >= thresh->ctrl_temperature)) {
+ >= thresh->ctrl_temperature)
+ || (smart->health != ND_INTEL_SMART_NON_CRITICAL_HEALTH)
+ || (smart->shutdown_state != 0)) {
device_lock(bus_dev);
__acpi_nvdimm_notify(dimm_dev, 0x81);
device_unlock(bus_dev);
@@ -734,6 +736,35 @@ static int nfit_test_cmd_smart_set_threshold(
return 0;
}
+static int nfit_test_cmd_smart_inject(
+ struct nd_intel_smart_inject *inj,
+ unsigned int buf_len,
+ struct nd_intel_smart_threshold *thresh,
+ struct nd_intel_smart *smart,
+ struct device *bus_dev, struct device *dimm_dev)
+{
+ if (buf_len != sizeof(*inj)) {
+ pr_err("TEST: size mismatch. buf = %d, struct = %d\n",
+ buf_len, sizeof(*inj));
+ return -EINVAL;
+ }
+
+ if (inj->mtemp_enable)
+ smart->media_temperature = inj->media_temperature;
+ if (inj->spare_enable)
+ smart->spares = inj->spares;
+ if (inj->fatal_enable)
+ smart->health = ND_INTEL_SMART_FATAL_HEALTH;
+ if (inj->unsafe_shutdown_enable) {
+ smart->shutdown_state = 1;
+ smart->shutdown_count++;
+ }
+ inj->status = 0;
+ smart_notify(bus_dev, dimm_dev, smart, thresh);
+
+ return 0;
+}
+
static void uc_error_notify(struct work_struct *work)
{
struct nfit_test *t = container_of(work, typeof(*t), work);
@@ -934,6 +965,13 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
t->dcr_idx],
&t->smart[i - t->dcr_idx],
&t->pdev.dev, t->dimm_dev[i]);
+ case ND_INTEL_SMART_INJECT:
+ return nfit_test_cmd_smart_inject(buf,
+ buf_len,
+ &t->smart_threshold[i -
+ t->dcr_idx],
+ &t->smart[i - t->dcr_idx],
+ &t->pdev.dev, t->dimm_dev[i]);
default:
return -ENOTTY;
}
@@ -1209,7 +1247,7 @@ static void smart_init(struct nfit_test *t)
.alarm_control = ND_INTEL_SMART_SPARE_TRIP
| ND_INTEL_SMART_TEMP_TRIP,
.media_temperature = 40 * 16,
- .ctrl_temperature = 30 * 16,
+ .ctrl_temperature = 35 * 16,
.spares = 5,
};
const struct nd_intel_smart smart_data = {
@@ -2015,6 +2053,7 @@ static void nfit_test0_setup(struct nfit_test *t)
set_bit(ND_INTEL_SMART, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_INTEL_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_INTEL_SMART_SET_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
+ set_bit(ND_INTEL_SMART_INJECT, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h
index 428344519cdf..33752e06ff8d 100644
--- a/tools/testing/nvdimm/test/nfit_test.h
+++ b/tools/testing/nvdimm/test/nfit_test.h
@@ -93,6 +93,7 @@ struct nd_cmd_ars_err_inj_stat {
#define ND_INTEL_FW_FINISH_UPDATE 15
#define ND_INTEL_FW_FINISH_QUERY 16
#define ND_INTEL_SMART_SET_THRESHOLD 17
+#define ND_INTEL_SMART_INJECT 18
#define ND_INTEL_SMART_HEALTH_VALID (1 << 0)
#define ND_INTEL_SMART_SPARES_VALID (1 << 1)
@@ -111,6 +112,10 @@ struct nd_cmd_ars_err_inj_stat {
#define ND_INTEL_SMART_NON_CRITICAL_HEALTH (1 << 0)
#define ND_INTEL_SMART_CRITICAL_HEALTH (1 << 1)
#define ND_INTEL_SMART_FATAL_HEALTH (1 << 2)
+#define ND_INTEL_SMART_INJECT_MTEMP (1 << 0)
+#define ND_INTEL_SMART_INJECT_SPARE (1 << 1)
+#define ND_INTEL_SMART_INJECT_FATAL (1 << 2)
+#define ND_INTEL_SMART_INJECT_SHUTDOWN (1 << 3)
struct nd_intel_smart {
__u32 status;
@@ -158,6 +163,17 @@ struct nd_intel_smart_set_threshold {
__u32 status;
} __packed;
+struct nd_intel_smart_inject {
+ __u64 flags;
+ __u8 mtemp_enable;
+ __u16 media_temperature;
+ __u8 spare_enable;
+ __u8 spares;
+ __u8 fatal_enable;
+ __u8 unsafe_shutdown_enable;
+ __u32 status;
+} __packed;
+
#define INTEL_FW_STORAGE_SIZE 0x100000
#define INTEL_FW_MAX_SEND_LEN 0xFFEC
#define INTEL_FW_QUERY_INTERVAL 250000
--
2.14.3
4 years, 4 months
[PATCH] libnvdimm, testing: Add emulation for smart injection commands
by Vishal Verma
Add support for the smart injection command in the nvdimm unit test
framework. This allows for directly injecting to smart fields and flags
that are supported in the injection command. If the injected values are
past the threshold, then an acpi notification is also triggered.
Cc: Dan Williams <dan.j.williams(a)intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma(a)intel.com>
---
tools/testing/nvdimm/test/nfit.c | 41 ++++++++++++++++++++++++++++++++++-
tools/testing/nvdimm/test/nfit_test.h | 16 ++++++++++++++
2 files changed, 56 insertions(+), 1 deletion(-)
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index 42ee1798971d..9896c4ddd3b8 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -708,7 +708,9 @@ static void smart_notify(struct device *bus_dev,
>= thresh->media_temperature)
|| ((thresh->alarm_control & ND_INTEL_SMART_CTEMP_TRIP)
&& smart->ctrl_temperature
- >= thresh->ctrl_temperature)) {
+ >= thresh->ctrl_temperature)
+ || (smart->health != ND_INTEL_SMART_NON_CRITICAL_HEALTH)
+ || (smart->shutdown_state != 0)) {
device_lock(bus_dev);
__acpi_nvdimm_notify(dimm_dev, 0x81);
device_unlock(bus_dev);
@@ -734,6 +736,35 @@ static int nfit_test_cmd_smart_set_threshold(
return 0;
}
+static int nfit_test_cmd_smart_inject(
+ struct nd_intel_smart_inject *inj,
+ unsigned int buf_len,
+ struct nd_intel_smart_threshold *thresh,
+ struct nd_intel_smart *smart,
+ struct device *bus_dev, struct device *dimm_dev)
+{
+ if (buf_len != sizeof(*inj)) {
+ pr_err("TEST: size mismatch. buf = %d, struct = %d\n",
+ buf_len, sizeof(*inj));
+ return -EINVAL;
+ }
+
+ if (inj->mtemp_enable)
+ smart->media_temperature = inj->media_temperature;
+ if (inj->spare_enable)
+ smart->spares = inj->spares;
+ if (inj->fatal_enable)
+ smart->health = ND_INTEL_SMART_FATAL_HEALTH;
+ if (inj->unsafe_shutdown_enable) {
+ smart->shutdown_state = 1;
+ smart->shutdown_count++;
+ }
+ inj->status = 0;
+ smart_notify(bus_dev, dimm_dev, smart, thresh);
+
+ return 0;
+}
+
static void uc_error_notify(struct work_struct *work)
{
struct nfit_test *t = container_of(work, typeof(*t), work);
@@ -934,6 +965,13 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
t->dcr_idx],
&t->smart[i - t->dcr_idx],
&t->pdev.dev, t->dimm_dev[i]);
+ case ND_INTEL_SMART_INJECT:
+ return nfit_test_cmd_smart_inject(buf,
+ buf_len,
+ &t->smart_threshold[i -
+ t->dcr_idx],
+ &t->smart[i - t->dcr_idx],
+ &t->pdev.dev, t->dimm_dev[i]);
default:
return -ENOTTY;
}
@@ -2015,6 +2053,7 @@ static void nfit_test0_setup(struct nfit_test *t)
set_bit(ND_INTEL_SMART, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_INTEL_SMART_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_INTEL_SMART_SET_THRESHOLD, &acpi_desc->dimm_cmd_force_en);
+ set_bit(ND_INTEL_SMART_INJECT, &acpi_desc->dimm_cmd_force_en);
set_bit(ND_CMD_ARS_CAP, &acpi_desc->bus_cmd_force_en);
set_bit(ND_CMD_ARS_START, &acpi_desc->bus_cmd_force_en);
set_bit(ND_CMD_ARS_STATUS, &acpi_desc->bus_cmd_force_en);
diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h
index 428344519cdf..33752e06ff8d 100644
--- a/tools/testing/nvdimm/test/nfit_test.h
+++ b/tools/testing/nvdimm/test/nfit_test.h
@@ -93,6 +93,7 @@ struct nd_cmd_ars_err_inj_stat {
#define ND_INTEL_FW_FINISH_UPDATE 15
#define ND_INTEL_FW_FINISH_QUERY 16
#define ND_INTEL_SMART_SET_THRESHOLD 17
+#define ND_INTEL_SMART_INJECT 18
#define ND_INTEL_SMART_HEALTH_VALID (1 << 0)
#define ND_INTEL_SMART_SPARES_VALID (1 << 1)
@@ -111,6 +112,10 @@ struct nd_cmd_ars_err_inj_stat {
#define ND_INTEL_SMART_NON_CRITICAL_HEALTH (1 << 0)
#define ND_INTEL_SMART_CRITICAL_HEALTH (1 << 1)
#define ND_INTEL_SMART_FATAL_HEALTH (1 << 2)
+#define ND_INTEL_SMART_INJECT_MTEMP (1 << 0)
+#define ND_INTEL_SMART_INJECT_SPARE (1 << 1)
+#define ND_INTEL_SMART_INJECT_FATAL (1 << 2)
+#define ND_INTEL_SMART_INJECT_SHUTDOWN (1 << 3)
struct nd_intel_smart {
__u32 status;
@@ -158,6 +163,17 @@ struct nd_intel_smart_set_threshold {
__u32 status;
} __packed;
+struct nd_intel_smart_inject {
+ __u64 flags;
+ __u8 mtemp_enable;
+ __u16 media_temperature;
+ __u8 spare_enable;
+ __u8 spares;
+ __u8 fatal_enable;
+ __u8 unsafe_shutdown_enable;
+ __u32 status;
+} __packed;
+
#define INTEL_FW_STORAGE_SIZE 0x100000
#define INTEL_FW_MAX_SEND_LEN 0xFFEC
#define INTEL_FW_QUERY_INTERVAL 250000
--
2.14.3
4 years, 4 months
[LSF/MM TOPIC] Native NVMM file systems
by Andiry Xu
PMEM/DAX should allow for significant improvements in file system
performance and enable new programming models that allow direct,
efficient access to PMEM from userspace. Achieving these gains in
existing file systems built for block devices (e.g., XFS and EXT4…)
presents a range of challenges (e.g.,
https://lkml.org/lkml/2016/9/11/159) and has been the subject of a lot
of recent work on ext4 and xfs.
An alternative is to build a NVMM-aware file system from scratch that
takes full advantage of the performance that PMEM offers and avoids
the complexity that block-based file systems include to maximize
performance on slow storage (e.g., relaxing atomicity constraints on
many operations). Of course, it also brings with it the complexity of
another file system.
We recently sent out a patch set for one-such “clean slate” NVMM-aware
file system called NOVA. NOVA is log-structured DAX file system with
several nice features:
* High performance, especially in metadata operations due to efficient
fine-grained logging
* High scalability with per-CPU memory pool and per-inode logging
* Strong metadata and data atomicity guarantees for all operations
* Full filesystem snapshot support with DAX-mmap
* Metadata replication/checksums and RAID-4 style data protection
At the summit, we would like to discuss the trade-offs between
adapting NVMM features to existing file systems vs. creating/adopting
a purpose-built file system for NVMM. NOVA serves as useful starting
point for that discussion by demonstrating what’s possible. It may
also suggest some features that could be adapted to other file systems
to improve NVMM performance.
We welcome people that are interested in file systems and NVM/DAX.
Particular people that would be useful to have in attendance are Dan
Williams, Dave Chinner, and Matthew Wilcox.
Thanks,
Andiry
4 years, 4 months
[PATCH] memremap: fix softlockup reports at teardown
by Dan Williams
The cond_resched() currently in the setup path needs to be duplicated in
the teardown path. Rather than require each instance of
for_each_device_pfn() to open code the same sequence, embed it in the
helper.
Link: https://github.com/intel/ixpdimm_sw/issues/11
Cc: "Jérôme Glisse" <jglisse(a)redhat.com>
Cc: Michal Hocko <mhocko(a)suse.com>
Cc: Christoph Hellwig <hch(a)lst.de>
Cc: <stable(a)vger.kernel.org>
Fixes: 71389703839e ("mm, zone_device: Replace {get, put}_zone_device_page()...")
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
kernel/memremap.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/kernel/memremap.c b/kernel/memremap.c
index 4849be5f9b3c..4dd4274cabe2 100644
--- a/kernel/memremap.c
+++ b/kernel/memremap.c
@@ -275,8 +275,15 @@ static unsigned long pfn_end(struct dev_pagemap *pgmap)
return (res->start + resource_size(res)) >> PAGE_SHIFT;
}
+static unsigned long pfn_next(unsigned long pfn)
+{
+ if (pfn % 1024 == 0)
+ cond_resched();
+ return pfn + 1;
+}
+
#define for_each_device_pfn(pfn, map) \
- for (pfn = pfn_first(map); pfn < pfn_end(map); pfn++)
+ for (pfn = pfn_first(map); pfn < pfn_end(map); pfn = pfn_next(pfn))
static void devm_memremap_pages_release(void *data)
{
@@ -337,10 +344,10 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
resource_size_t align_start, align_size, align_end;
struct vmem_altmap *altmap = pgmap->altmap_valid ?
&pgmap->altmap : NULL;
+ struct resource *res = &pgmap->res;
unsigned long pfn, pgoff, order;
pgprot_t pgprot = PAGE_KERNEL;
- int error, nid, is_ram, i = 0;
- struct resource *res = &pgmap->res;
+ int error, nid, is_ram;
align_start = res->start & ~(SECTION_SIZE - 1);
align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE)
@@ -409,8 +416,6 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
list_del(&page->lru);
page->pgmap = pgmap;
percpu_ref_get(pgmap->ref);
- if (!(++i % 1024))
- cond_resched();
}
devm_add_action(dev, devm_memremap_pages_release, pgmap);
4 years, 4 months
[PATCH 0/3] vfio, dax: disable filesystem-dax and minor fixups
by Dan Williams
Alex, here is a change to vaddr_get_pfn() that we discussed in this
thread: https://lists.nongnu.org/archive/html/qemu-devel/2018-01/msg07117.html
Namely, drop support for passing Filesystem-DAX mappings through to
guests. Perhaps in the future we can create some para-virtualized
passthrough interface to coordinate guest-DMA vs host-filesystem
operations. For now, this needs to be disabled for data-integrity and
guaranteeing forward progress of filesystem operations.
If you want to take this through your tree please grab the other dax
fixups as well. Otherwise, let me know and I'll take the lot through the
nvdimm tree.
---
Dan Williams (3):
dax: fix S_DAX definition
dax: short circuit vma_is_fsdax() in the CONFIG_FS_DAX=n case
vfio: disable filesystem-dax page pinning
drivers/vfio/vfio_iommu_type1.c | 18 +++++++++++++++---
include/linux/fs.h | 4 +++-
2 files changed, 18 insertions(+), 4 deletions(-)
4 years, 4 months