[PATCH] ndctl: fix libdaxctl memory leak
by Dave Jiang
When daxctl_unref is releasing the context, we should make sure that the
regions and devices are also being released.
Signed-off-by: Dave Jiang <dave.jiang(a)intel.com>
---
daxctl/lib/libdaxctl.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
index 9e503201..0552f6d7 100644
--- a/daxctl/lib/libdaxctl.c
+++ b/daxctl/lib/libdaxctl.c
@@ -119,11 +119,18 @@ DAXCTL_EXPORT struct daxctl_ctx *daxctl_ref(struct daxctl_ctx *ctx)
*/
DAXCTL_EXPORT void daxctl_unref(struct daxctl_ctx *ctx)
{
+ struct daxctl_region *region;
+
if (ctx == NULL)
return;
ctx->refcount--;
if (ctx->refcount > 0)
return;
+
+ while ((region = list_top(&ctx->regions, struct daxctl_region, list)) !=
+ NULL)
+ daxctl_region_unref(region);
+
info(ctx, "context %p released\n", ctx);
free(ctx);
}
4 years, 2 months
[PATCH] ndctl: fix daxctl list memory leak
by Dave Jiang
daxctl list is not calling daxctl_unref() when executed succesfully. At the same
time, daxctl_region_unref() is not being called when daxctl_unref() executes.
Valgrind is reporting unfreed memory. Adding the appropriate calls to make sure
all memory allocated are freed for daxctl list.
Signed-off-by: Dave Jiang <dave.jiang(a)intel.com>
---
daxctl/lib/libdaxctl.c | 7 +++++++
daxctl/list.c | 1 +
2 files changed, 8 insertions(+)
diff --git a/daxctl/lib/libdaxctl.c b/daxctl/lib/libdaxctl.c
index 9e503201..0552f6d7 100644
--- a/daxctl/lib/libdaxctl.c
+++ b/daxctl/lib/libdaxctl.c
@@ -119,11 +119,18 @@ DAXCTL_EXPORT struct daxctl_ctx *daxctl_ref(struct daxctl_ctx *ctx)
*/
DAXCTL_EXPORT void daxctl_unref(struct daxctl_ctx *ctx)
{
+ struct daxctl_region *region;
+
if (ctx == NULL)
return;
ctx->refcount--;
if (ctx->refcount > 0)
return;
+
+ while ((region = list_top(&ctx->regions, struct daxctl_region, list)) !=
+ NULL)
+ daxctl_region_unref(region);
+
info(ctx, "context %p released\n", ctx);
free(ctx);
}
diff --git a/daxctl/list.c b/daxctl/list.c
index 254f0ac9..9b18ae8d 100644
--- a/daxctl/list.c
+++ b/daxctl/list.c
@@ -134,6 +134,7 @@ int cmd_list(int argc, const char **argv, void *ctx)
else if (jdevs)
util_display_json_array(stdout, jdevs, jflag);
+ daxctl_unref(ctx);
if (did_fail)
return -ENOMEM;
return 0;
4 years, 2 months
Identify Your Business With Unique Logo
by Kimberly Lee
Hello,
We are a team of creative professionals with a never say die attitude. When
you contact us for any of your web needs described below, you will see our
team efforts in the given time. We can also take up bulk orders for
designing all of your company’s websites and also websites of your
subsidies. You will be very happy to know about the rates for each service
that we provide as below –
Logo designing services for $75 and unlimited revisions
Web designing at $250 for 5 page html and $450 for a CMS-based website, and
SEO for $149 a month for five keywords,
You can see some of my logo samples below.
When you mail us with your individual requirements, we will send you the
list of services against their rates.
If you are a serial blogger who does not have time to optimize your blogs
or website, we can do that for you and we charge $10 for any 500 word
article or blog.
After all, if you are writing original and interesting content, your blog
sure deserves a larger audience and subscribers. That is where our team
comes in.
We will make sure that we use all the tools and techniques available in our
kitty and leverage the page rank of your blog or website and help your
business and blog gain more popularity. We charge $2.95 per month for
providing web hosting services.
If you have a wonderful product or if you have excellent skills and you are
unable to promote it yourself, you can contact us and let us do it for you.
Regards,
Kimberly Lee
4 years, 2 months
[RFC PATCH v4] ndctl: monitor: add ndctl monitor daemon
by QI Fuli
This is the v4 patch for ndctl monitor daemon, a tiny daemon to monitor the
smart events of nvdimm DIMMs. Users can run a monitor as a one-shot command
or a daemon in background by using the [--daemon] option. DIMMs to monitor
can be selected by [--dimm] [--bus] [--region] [--namespace] options.
When a smart event fires, monitor daemon will log the notification which
including dimm health status to syslog or a logfile by setting [--log] option.
The notification follows json format and can be consumed by log collectors
like Fluented.
For example, a monitor daemon can be started by the following command:
# ndctl monitor --dimm nmem1 --log /var/log/monitor.log --daemon daemon-name
Then check the monitor daemon status by using systemd:
# systemctl status ndctl-monitor(a)daemon-name.service
To stop the monitor daemon by:
# systemctl stop ndctl-monitor(a)daemon-name.service
Also, a monitor daemon can be started by systemd:
# systemctl start ndctl-monitor.service
Which monitors all dimms.
In this implemention, when a ndctl monitor starts with [--daemon] option, all
the arguments will be saved into a temp file named as daemon-name and placed
under /etc/sysconfig/ndctl/ directory. The temp file would be used as an
EnvironmentFile by systemd, and it would be deleted automatically when the
systemd service is stopped.
Due to the deletion the following commands will not work.
# systemctl enable ndctl-monitor(a)daemon-name.service
# systemctl restart ndctl-monitor(a)daemon-name.service
I am not sure whether these commands are needed for ndctl monitor daemon,
your comments will be appreciated.
Signed-off-by: QI Fuli <qi.fuli(a)jp.fujitsu.com>
Change log since v3:
- Removing create-monitor, show-monitor, list-monitor, destroy-monitor
- Adding [--daemon] option to run ndctl monitor as a daemon
- Using systemd to manage ndctl monitor daemon
- Replacing filter_monitor_dimm() with filter_dimm()
Change log since v2:
- Changing the interface of daemon to the ndctl command line
- Changing the name of daemon form "nvdimmd" to "monitor"
- Removing the config file, unit_file, nvdimmd dir
- Removing nvdimmd_test program
- Adding ndctl/monitor.c
Change log since v1:
- Adding a config file(/etc/nvdimmd/nvdimmd.conf)
- Using struct log_ctx instead of syslog()
- Using log_syslog() to save the notify messages to syslog
- Using log_file() to save the notify messages to special file
- Adding LOG_NOTICE level to log_priority
- Using automake instead of Makefile
- Adding a new util file(nvdimmd/util.c) including helper functions
needed for nvdimm daemon
- Adding nvdimmd_test program
---
builtin.h | 1 +
ndctl/Makefile.am | 13 +-
ndctl/monitor.c | 411 +++++++++++++++++++++++++++++++++++++++++++
ndctl/ndctl-monitor.service | 7 +
ndctl/ndctl-monitor@.service | 9 +
ndctl/ndctl.c | 1 +
util/filter.c | 5 +-
util/filter.h | 3 +
util/parse-options.h | 1 +
9 files changed, 448 insertions(+), 3 deletions(-)
create mode 100644 ndctl/monitor.c
create mode 100644 ndctl/ndctl-monitor.service
create mode 100644 ndctl/ndctl-monitor@.service
diff --git a/builtin.h b/builtin.h
index b24fc99..4b908f0 100644
--- a/builtin.h
+++ b/builtin.h
@@ -36,6 +36,7 @@ int cmd_write_labels(int argc, const char **argv, void *ctx);
int cmd_init_labels(int argc, const char **argv, void *ctx);
int cmd_check_labels(int argc, const char **argv, void *ctx);
int cmd_inject_error(int argc, const char **argv, void *ctx);
+int cmd_monitor(int argc, const char **argv, void *ctx);
int cmd_list(int argc, const char **argv, void *ctx);
#ifdef ENABLE_TEST
int cmd_test(int argc, const char **argv, void *ctx);
diff --git a/ndctl/Makefile.am b/ndctl/Makefile.am
index e0db97b..e364ef9 100644
--- a/ndctl/Makefile.am
+++ b/ndctl/Makefile.am
@@ -16,7 +16,8 @@ ndctl_SOURCES = ndctl.c \
util/json-firmware.c \
inject-error.c \
update.c \
- inject-smart.c
+ inject-smart.c \
+ monitor.c
if ENABLE_DESTRUCTIVE
ndctl_SOURCES += ../test/blk_namespaces.c \
@@ -41,3 +42,13 @@ ndctl_SOURCES += ../test/libndctl.c \
../test/multi-pmem.c \
../test/core.c
endif
+
+unitfiles =\
+ ndctl-monitor.service \
+ ndctl-monitor@.service
+
+unitdir = /usr/lib/systemd/system/
+
+unit_DATA = $(unitfiles)
+
+EXTRA_DIST = $(unitfiles)
diff --git a/ndctl/monitor.c b/ndctl/monitor.c
new file mode 100644
index 0000000..2164f27
--- /dev/null
+++ b/ndctl/monitor.c
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2018, FUJITSU LIMITED. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
+ * more details.
+ */
+#include <stdio.h>
+#include <json-c/json.h>
+#include <signal.h>
+#include <libgen.h>
+#include <dirent.h>
+#include <util/parse-options.h>
+#include <util/log.h>
+#include <util/json.h>
+#include <util/filter.h>
+#include <ndctl/lib/private.h>
+#include <ndctl/libndctl.h>
+#include <sys/stat.h>
+#define NUM_MAX_DIMM 1024
+#define BUF_SIZE 4096
+
+struct monitor_dimm {
+ struct ndctl_dimm *dimm;
+ int health_eventfd;
+ struct list_node list;
+};
+
+struct monitor_filter_arg {
+ struct list_head mdimm;
+ int maxfd;
+ fd_set fds;
+ int num_dimm;
+ unsigned long flags;
+};
+
+struct util_filter_params param;
+
+static char *conf_dir = "/etc/sysconfig/ndctl/";
+static char *def_log_dir = "/var/log/ndctl/";
+
+static char *concat(char *str1, char *str2)
+{
+ char *result = malloc(strlen(str1) + strlen(str2) + 1);
+ strcpy(result, str1);
+ strcat(result, str2);
+ return result;
+}
+
+static bool is_dir(char *filepath)
+{
+ DIR *dir = opendir(filepath);
+ if (dir) {
+ closedir(dir);
+ return true;
+ }
+ return false;
+}
+
+static int recur_mkdir(char *filepath, mode_t mode)
+{
+ char *p;
+ char *buf = (char *)malloc(strlen(filepath) + 4);
+
+ strcpy(buf, filepath);
+ for (p = strchr(buf + 1, '/'); p; p = strchr(p + 1, '/')) {
+ *p = '\0';
+ if (!is_dir(buf)) {
+ if (mkdir(buf, mode) < 0) {
+ free(buf);
+ return -1;
+ }
+ }
+ *p = '/';
+ }
+
+ free(buf);
+ return 0;
+}
+
+static void log_file(struct ndctl_ctx *ctx, int priority, const char *file,
+ int line, const char *fn, const char *format, va_list args)
+{
+ FILE *f;
+ char *log_name, *log_dir, *buf;
+ char *errmsg = (char *)malloc(BUF_SIZE);
+ char *tail = "/";
+
+ log_dir = dirname(strdup(param.log));
+ log_name = basename(strdup(param.log));
+ if (strcmp(log_dir, ".") == 0)
+ log_dir = def_log_dir;
+ else
+ log_dir = concat(log_dir, tail);
+ if (log_dir[0] != '/')
+ log_dir = concat(def_log_dir, log_dir);
+ log_name = concat(log_dir, log_name);
+
+ if (!is_dir(log_dir)) {
+ if (recur_mkdir(log_dir, 0744) != 0) {
+ sprintf(errmsg, "cannot create dir: %s", log_dir);
+ goto out;
+ }
+ }
+
+ f = fopen(log_name, "a+");
+ if (!f) {
+ sprintf(errmsg, "open %s failed", log_name);
+ goto out;
+ }
+
+ buf = (char *)malloc(BUF_SIZE);
+ if (!buf) {
+ sprintf(errmsg, "cannot get memory for log_file");
+ goto out;
+ }
+ vsnprintf(buf, BUF_SIZE, format, args);
+ fprintf(f, "%s\n", buf);
+ free(buf);
+ fclose(f);
+ return;
+out:
+ syslog(LOG_ERR, "%s\n", errmsg);
+ if (!param.fork)
+ error("%s\n", errmsg);
+ free(errmsg);
+ exit(EXIT_FAILURE);
+}
+
+static void log_syslog(struct ndctl_ctx *ctx, int priority, const char *file,
+ int line, const char *fn, const char *format, va_list args)
+{
+ char *buf = (char *)malloc(BUF_SIZE);
+ vsnprintf(buf, BUF_SIZE, format, args);
+ syslog(priority, "%s", buf);
+ free(buf);
+}
+
+#define fail(fmt, ...) \
+do { \
+ err(ctx, "ndctl-%s:%s:%d: " fmt, \
+ VERSION, __func__, __LINE__, ##__VA_ARGS__); \
+ if (!param.fork) \
+ fprintf(stderr, "ndctl-%s:%s:%d: " fmt, \
+ VERSION, __func__, __LINE__, ##__VA_ARGS__); \
+} while (0)
+
+static int notify_json_msg(struct ndctl_ctx *ctx, struct ndctl_dimm *dimm)
+{
+ time_t c_time;
+ char date[32];
+ struct json_object *jmsg, *jdatetime, *jpid, *jdimm, *jhealth;
+
+ jmsg = json_object_new_object();
+ if (!jmsg) {
+ fail("\n");
+ return -1;
+ }
+
+ c_time = time(NULL);
+ strftime(date, sizeof(date), "%Y-%m-%d %H:%M:%S", localtime(&c_time));
+ jdatetime = json_object_new_string(date);
+ if (!jdatetime) {
+ fail("\n");
+ return -1;
+ }
+ json_object_object_add(jmsg, "datetime", jdatetime);
+
+ jpid = json_object_new_int((int)getpid());
+ if (!jpid) {
+ fail("\n");
+ return -1;
+ }
+ json_object_object_add(jmsg, "pid", jpid);
+
+ jdimm = util_dimm_to_json(dimm, 0);
+ if (!dimm) {
+ fail("\n");
+ return -1;
+ }
+ json_object_object_add(jmsg, "dimm", jdimm);
+
+ jhealth = util_dimm_health_to_json(dimm);
+ if (!jhealth) {
+ fail("\n");
+ return -1;
+ }
+ json_object_object_add(jdimm, "health", jhealth);
+
+ notice(ctx, "%s",
+ json_object_to_json_string_ext(jmsg, JSON_C_TO_STRING_PLAIN));
+ if (!param.fork)
+ printf("%s\n", json_object_to_json_string_ext(jmsg,
+ JSON_C_TO_STRING_PRETTY));
+ return 0;
+}
+
+static void filter_dimm(struct ndctl_dimm *dimm, struct util_filter_ctx *ctx)
+{
+ struct monitor_filter_arg *mfa = (struct monitor_filter_arg *)ctx->arg;
+ int fd;
+ char buf[BUF_SIZE];
+
+ if (!ndctl_dimm_is_cmd_supported(dimm, ND_CMD_SMART_THRESHOLD))
+ return;
+
+ struct monitor_dimm *m_dimm = malloc(sizeof(*m_dimm));
+ m_dimm->dimm = dimm;
+ fd = ndctl_dimm_get_health_eventfd(dimm);
+ pread(fd, buf, sizeof(buf), 0);
+ m_dimm->health_eventfd = fd;
+ list_add_tail(&mfa->mdimm, &m_dimm->list);
+ FD_SET(fd, &mfa->fds);
+ if (fd > mfa->maxfd)
+ mfa->maxfd = fd;
+ mfa->num_dimm++;
+}
+
+static int monitor_smart_event(struct ndctl_ctx *ctx)
+{
+ struct util_filter_ctx fctx = { 0 };
+ struct monitor_filter_arg mfa = { 0 };
+ int rc;
+ char buf[BUF_SIZE];
+ char *errmsg = (char *)malloc(BUF_SIZE);
+
+ fctx.filter_dimm = filter_dimm;
+ fctx.arg = &mfa;
+ mfa.flags = 0;
+ list_head_init(&mfa.mdimm);
+ FD_ZERO(&mfa.fds);
+
+ rc = util_filter_walk(ctx, &fctx, ¶m);
+ if (rc)
+ goto out;
+ if (mfa.num_dimm == 0) {
+ errmsg = "no monitor dimms can be found";
+ goto out;
+ }
+
+ while(1){
+ rc = select(mfa.maxfd + 1, NULL, NULL, &mfa.fds, NULL);
+ if (rc < 1) {
+ errmsg = "select error";
+ if (rc == 0)
+ dbg(ctx, "select unexpected timeout\n");
+ else
+ dbg(ctx, "select %s\n", strerror(errno));
+ goto out;
+ }
+ struct monitor_dimm *m_dimm;
+ list_for_each(&mfa.mdimm, m_dimm, list) {
+ if (!FD_ISSET(m_dimm->health_eventfd, &mfa.fds)) {
+ FD_SET(m_dimm->health_eventfd, &mfa.fds);
+ continue;
+ }
+ if (notify_json_msg(ctx, m_dimm->dimm) != 0)
+ goto out;
+ pread(m_dimm->health_eventfd, buf, sizeof(buf), 0);
+ }
+ }
+ return 0;
+out:
+ if (errmsg) {
+ if (!param.fork)
+ error("%s\n", errmsg);
+ err(ctx, "%s\n", errmsg);
+ }
+ return 1;
+}
+
+static int create_confile(char *conf_path)
+{
+ FILE *f;
+ char *buf;
+
+ if (!is_dir(conf_dir)) {
+ if (recur_mkdir(conf_dir, 0744) != 0) {
+ error("cannot create dir: %s\n", conf_dir);
+ goto out;
+ }
+ }
+
+ f = fopen(conf_path, "w");
+ if (!f) {
+ error("open %s failed\n", conf_path);
+ goto out;
+ }
+
+ buf = (char *)malloc(BUF_SIZE);
+ if (!buf) {
+ error("cannot get memory for daemon config file\n");
+ goto out;
+ }
+ strcpy(buf, "OPTIONS=-f");
+ if (param.bus) {
+ strcat(buf, " -b ");
+ strcat(buf, param.bus);
+ }
+ if (param.dimm) {
+ strcat(buf, " -d ");
+ strcat(buf, param.dimm);
+ }
+ if (param.namespace) {
+ strcat(buf, " -n ");
+ strcat(buf, param.namespace);
+ }
+ if (param.region) {
+ strcat(buf, " -r ");
+ strcat(buf, param.region);
+ }
+ if (param.log) {
+ strcat(buf, " -l ");
+ strcat(buf, param.log);
+ }
+ fprintf(f, "%s", buf);
+ fclose(f);
+ free(buf);
+ return 0;
+out:
+ return 1;
+}
+
+static bool is_monitor_exist(void)
+{
+ char *conf_path = strdup(param.daemon);
+ conf_path = concat(conf_dir, conf_path);
+ FILE *f = fopen(conf_path, "r");
+ if (f) {
+ fclose(f);
+ return true;
+ }
+ return false;
+}
+
+int cmd_monitor(int argc, const char **argv, void *ctx)
+{
+ const struct option options[] = {
+ OPT_STRING('b', "bus", ¶m.bus, "bus-id", "filter by bus"),
+ OPT_STRING('r', "region", ¶m.region, "region-id",
+ "filter by region"),
+ OPT_STRING('d', "dimm", ¶m.dimm, "dimm-id",
+ "filter by dimm"),
+ OPT_STRING('n', "namespace", ¶m.namespace,
+ "namespace-id", "filter by namespace id"),
+ OPT_STRING('l', "log", ¶m.log, "log name",
+ "monitor logfile"),
+ OPT_STRING('D',"daemon", ¶m.daemon, "daemon-name",
+ "run ndctl monitor as a daemon"),
+ OPT_BOOLEAN_HID('f', ¶m.fork),
+ OPT_END(),
+ };
+ const char * const u[] = {
+ "ndctl monitor [<options>]",
+ NULL
+ };
+ argc = parse_options(argc, argv, options, u, 0);
+ for (int i = 0; i < argc; i++) {
+ error("unknown parameter \"%s\"\n", argv[i]);
+ goto out;
+ }
+ if (argc)
+ usage_with_options(u, options);
+
+ if (param.daemon) {
+ if (is_monitor_exist()) {
+ error("monitor %s is exist\n", param.daemon);
+ goto out;
+ }
+ char *conf_path = strdup(param.daemon);
+ conf_path = concat(conf_dir, conf_path);
+ if (create_confile(conf_path) != 0)
+ goto out;
+ char *sys_cmd = (char *)malloc(BUF_SIZE);
+ sprintf(sys_cmd, "systemctl start ndctl-monitor(a)%s.service",
+ param.daemon);
+ if (system(sys_cmd) != 0) {
+ free(sys_cmd);
+ remove(conf_path);
+ goto out;
+ }
+ free(sys_cmd);
+ return 0;
+ }
+
+ if (param.fork) {
+ if (daemon(0, 0) != 0) {
+ err((struct ndctl_ctx*)ctx, "daemon start failed\n");
+ goto out;
+ }
+ }
+
+ ndctl_set_log_priority((struct ndctl_ctx*)ctx, LOG_NOTICE);
+
+ if (!param.log || strcmp(param.log, "syslog") == 0)
+ ndctl_set_log_fn((struct ndctl_ctx*)ctx, log_syslog);
+ else
+ ndctl_set_log_fn((struct ndctl_ctx*)ctx, log_file);
+
+ if (monitor_smart_event((struct ndctl_ctx*)ctx) != 0)
+ goto out;
+
+ return 0;
+out:
+ return 1;
+}
diff --git a/ndctl/ndctl-monitor.service b/ndctl/ndctl-monitor.service
new file mode 100644
index 0000000..2f1417b
--- /dev/null
+++ b/ndctl/ndctl-monitor.service
@@ -0,0 +1,7 @@
+[Unit]
+Description=Ndctl Monitor Daemon
+
+[Service]
+Type=forking
+ExecStart=/usr/bin/ndctl monitor -f
+ExecStop=/usr/bin/kill ${MAINPID}
diff --git a/ndctl/ndctl-monitor@.service b/ndctl/ndctl-monitor@.service
new file mode 100644
index 0000000..91c85d9
--- /dev/null
+++ b/ndctl/ndctl-monitor@.service
@@ -0,0 +1,9 @@
+[Unit]
+Description=Ndctl Monitor Daemon
+
+[Service]
+Type=forking
+EnvironmentFile=/etc/sysconfig/ndctl/%i
+ExecStart=/usr/bin/ndctl monitor $OPTIONS
+ExecStop=/usr/bin/kill ${MAINPID}
+ExecStopPost=/usr/bin/rm /etc/sysconfig/ndctl/%i
diff --git a/ndctl/ndctl.c b/ndctl/ndctl.c
index d3c6db1..8938621 100644
--- a/ndctl/ndctl.c
+++ b/ndctl/ndctl.c
@@ -86,6 +86,7 @@ static struct cmd_struct commands[] = {
{ "inject-error", cmd_inject_error },
{ "update-firmware", cmd_update_firmware },
{ "inject-smart", cmd_inject_smart },
+ { "monitor", cmd_monitor },
{ "list", cmd_list },
{ "help", cmd_help },
#ifdef ENABLE_TEST
diff --git a/util/filter.c b/util/filter.c
index b0b7fdf..fba2197 100644
--- a/util/filter.c
+++ b/util/filter.c
@@ -315,7 +315,7 @@ int util_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx,
|| !util_bus_filter_by_namespace(bus, param->namespace))
continue;
- if (!fctx->filter_bus(bus, fctx))
+ if (fctx->filter_bus && !fctx->filter_bus(bus, fctx))
continue;
ndctl_dimm_foreach(bus, dimm) {
@@ -345,7 +345,8 @@ int util_filter_walk(struct ndctl_ctx *ctx, struct util_filter_ctx *fctx,
if (type && ndctl_region_get_type(region) != type)
continue;
- if (!fctx->filter_region(region, fctx))
+ if (fctx->filter_region &&
+ !fctx->filter_region(region, fctx))
continue;
ndctl_namespace_foreach(region, ndns) {
diff --git a/util/filter.h b/util/filter.h
index aea5a71..82f3b0d 100644
--- a/util/filter.h
+++ b/util/filter.h
@@ -77,6 +77,9 @@ struct util_filter_params {
const char *dimm;
const char *mode;
const char *namespace;
+ const char *log;
+ const char *daemon;
+ bool fork;
};
struct ndctl_ctx;
diff --git a/util/parse-options.h b/util/parse-options.h
index 6fd6b24..2262c42 100644
--- a/util/parse-options.h
+++ b/util/parse-options.h
@@ -123,6 +123,7 @@ struct option {
#define OPT_GROUP(h) { .type = OPTION_GROUP, .help = (h) }
#define OPT_BIT(s, l, v, h, b) { .type = OPTION_BIT, .short_name = (s), .long_name = (l), .value = check_vtype(v, int *), .help = (h), .defval = (b) }
#define OPT_BOOLEAN(s, l, v, h) { .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), .value = check_vtype(v, bool *), .help = (h) }
+#define OPT_BOOLEAN_HID(s, v) { .type = OPTION_BOOLEAN, .short_name = (s), .value = check_vtype(v, bool *), .flags = PARSE_OPT_HIDDEN}
#define OPT_BOOLEAN_SET(s, l, v, os, h) \
{ .type = OPTION_BOOLEAN, .short_name = (s), .long_name = (l), \
.value = check_vtype(v, bool *), .help = (h), \
--
2.9.5
4 years, 2 months
[ndctl PATCH 1/2] ndctl: s/memory/fsdax/ in some user visible places
by Ross Zwisler
Adding on to the work started by:
commit ebb4fb605e68 ("ndctl, create-namespace: introduce "fsdax" and "devdax" modes")
Signed-off-by: Ross Zwisler <ross.zwisler(a)linux.intel.com>
---
Documentation/ndctl/ndctl-inject-error.txt | 2 +-
ndctl/namespace.c | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/Documentation/ndctl/ndctl-inject-error.txt b/Documentation/ndctl/ndctl-inject-error.txt
index 01f6c22..94c4e69 100644
--- a/Documentation/ndctl/ndctl-inject-error.txt
+++ b/Documentation/ndctl/ndctl-inject-error.txt
@@ -45,7 +45,7 @@ OPTIONS
NOTE: The offset is interpreted in different ways based on the "mode"
of the namespace. For "raw" mode, the offset is the base namespace
- offset. For "memory" mode (i.e. a "pfn" namespace), the offset is
+ offset. For "fsdax" mode (i.e. a "pfn" namespace), the offset is
relative to the user-visible part of the namespace, and the offset
introduced by the kernel's metadata will be accounted for. For a
"sector" mode namespace (i.e. a "BTT" namespace), the offset is
diff --git a/ndctl/namespace.c b/ndctl/namespace.c
index f2c5644..e619dc1 100644
--- a/ndctl/namespace.c
+++ b/ndctl/namespace.c
@@ -103,7 +103,7 @@ OPT_STRING('n', "name", ¶m.name, "name", \
OPT_STRING('s', "size", ¶m.size, "size", \
"specify the namespace size in bytes (default: available capacity)"), \
OPT_STRING('m', "mode", ¶m.mode, "operation-mode", \
- "specify a mode for the namespace, 'sector', 'memory', or 'raw'"), \
+ "specify a mode for the namespace, 'sector', 'fsdax', or 'raw'"), \
OPT_STRING('M', "map", ¶m.map, "memmap-location", \
"specify 'mem' or 'dev' for the location of the memmap"), \
OPT_STRING('l', "sector-size", ¶m.sector_size, "lba-size", \
@@ -696,7 +696,7 @@ static int validate_namespace_options(struct ndctl_region *region,
if (ndns && p->mode != NDCTL_NS_MODE_MEMORY
&& p->mode != NDCTL_NS_MODE_DAX) {
- debug("%s: --map= only valid for memory mode namespace\n",
+ debug("%s: --map= only valid for fsdax mode namespace\n",
ndctl_namespace_get_devname(ndns));
return -EINVAL;
}
@@ -709,10 +709,10 @@ static int validate_namespace_options(struct ndctl_region *region,
struct ndctl_pfn *pfn = ndctl_region_get_pfn_seed(region);
if (!pfn && param.mode_default) {
- debug("%s memory mode not available\n", region_name);
+ debug("%s fsdax mode not available\n", region_name);
p->mode = NDCTL_NS_MODE_RAW;
} else if (!pfn) {
- error("operation failed, %s memory mode not available\n",
+ error("operation failed, %s fsdax mode not available\n",
region_name);
return -EINVAL;
}
--
2.14.3
4 years, 2 months
[PATCH] libnvdimm, of_pmem: workaround OF_NUMA=n build error
by Dan Williams
Stephen reports that an x86 allmodconfig build fails to build the
of_pmem driver due to a missing definition of of_node_to_nid(). That
helper is currently only exported in the OF_NUMA=y case. In other cases,
ppc and sparc, it is a weak symbol, and outside of those platforms it is
a static inline.
Until an OF_NUMA=n configuration can reliably support usage of
of_node_to_nid() in modules across architectures, mark this driver as
'bool' instead of 'tristate'.
Cc: Rob Herring <robh(a)kernel.org>
Cc: Oliver O'Halloran <oohall(a)gmail.com>
Reported-by: Stephen Rothwell <sfr(a)canb.auug.org.au>
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
drivers/nvdimm/Kconfig | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/nvdimm/Kconfig b/drivers/nvdimm/Kconfig
index 2d6862bf7436..f6c533c4d09b 100644
--- a/drivers/nvdimm/Kconfig
+++ b/drivers/nvdimm/Kconfig
@@ -103,7 +103,8 @@ config NVDIMM_DAX
Select Y if unsure
config OF_PMEM
- tristate "Device-tree support for persistent memory regions"
+ # FIXME: make tristate once OF_NUMA dependency removed
+ bool "Device-tree support for persistent memory regions"
depends on OF
default LIBNVDIMM
help
4 years, 2 months
Re: [Qemu-devel] [RFC] qemu: Add virtio pmem device
by David Hildenbrand
On 09.04.2018 05:26, Stefan Hajnoczi wrote:
> On Thu, Apr 05, 2018 at 08:09:26AM -0400, Pankaj Gupta wrote:
>>> Will this raw file already have the "disk information header" (no idea
>>> how that stuff is called) encoded? Are there any plans/possible ways to
>>>
>>> a) automatically create the headers? (if that's even possible)
>>
>> Its raw. Right now we are just supporting raw format.
>>
>> As this is direct mapping of memory into guest address space, I don't
>> think we can have an abstraction of headers for block specific features.
>> Or may be we can get opinion of others(Qemu block people) it is at all possible?
>
> memdev and the block layer are completely separate. The block layer
> isn't designed for memory-mapped access.
>
Not questioning if this is the right thing to do now. I was wondering if
we could expose any block device in the future as virtio-pmem. And I
think with quite some work it could be possible.
As you said, we will need some buffering. Maybe userfaultfd and friends
(WP) could allow to implement that.
> I think it makes sense to use memdev here. If the user wants a block
> device, they should use an emulated block device, not virtio-pmem,
> because buffering is necessary anyway when an image file format is used.
>
> Stefan
>
--
Thanks,
David / dhildenb
4 years, 2 months
[ndctl PATCH 1/2] libndctl: Add APIs for query and control of write_cache
by Vishal Verma
Add APIs to get the state of write_cache for pmem namespaces, and also
to enable or disable the write_cache.
Cc: Dan Williams <dan.j.williams(a)intel.com>
Signed-off-by: Vishal Verma <vishal.l.verma(a)intel.com>
---
ndctl/lib/libndctl.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++
ndctl/lib/libndctl.sym | 3 ++
ndctl/libndctl.h | 3 ++
3 files changed, 82 insertions(+)
diff --git a/ndctl/lib/libndctl.c b/ndctl/lib/libndctl.c
index 580a450..1f59e2a 100644
--- a/ndctl/lib/libndctl.c
+++ b/ndctl/lib/libndctl.c
@@ -3918,6 +3918,82 @@ NDCTL_EXPORT int ndctl_namespace_get_numa_node(struct ndctl_namespace *ndns)
return ndns->numa_node;
}
+static int __ndctl_namespace_set_write_cache(struct ndctl_namespace *ndns,
+ int state)
+{
+ struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns);
+ struct ndctl_pfn *pfn = ndctl_namespace_get_pfn(ndns);
+ char buf[SYSFS_ATTR_SIZE];
+ int len = ndns->buf_len;
+ const char *bdev;
+ char path[50];
+
+ if (state != 1 && state != 0)
+ return -ENXIO;
+ if (pfn)
+ bdev = ndctl_pfn_get_block_device(pfn);
+ else
+ bdev = ndctl_namespace_get_block_device(ndns);
+
+ if (!bdev)
+ return -ENXIO;
+
+ if (snprintf(path, len, "/sys/block/%s/dax/write_cache", bdev) >= len) {
+ err(ctx, "%s: buffer too small!\n",
+ ndctl_namespace_get_devname(ndns));
+ return -ENXIO;
+ }
+
+ sprintf(buf, "%d\n", state);
+ return sysfs_write_attr(ctx, path, buf);
+}
+
+NDCTL_EXPORT int ndctl_namespace_enable_write_cache(
+ struct ndctl_namespace *ndns)
+{
+ return __ndctl_namespace_set_write_cache(ndns, 1);
+}
+
+NDCTL_EXPORT int ndctl_namespace_disable_write_cache(
+ struct ndctl_namespace *ndns)
+{
+ return __ndctl_namespace_set_write_cache(ndns, 0);
+}
+
+NDCTL_EXPORT int ndctl_namespace_write_cache_is_enabled(
+ struct ndctl_namespace *ndns)
+{
+ struct ndctl_ctx *ctx = ndctl_namespace_get_ctx(ndns);
+ struct ndctl_pfn *pfn = ndctl_namespace_get_pfn(ndns);
+ int len = ndns->buf_len, wc;
+ char buf[SYSFS_ATTR_SIZE];
+ const char *bdev;
+ char path[50];
+
+ if (pfn)
+ bdev = ndctl_pfn_get_block_device(pfn);
+ else
+ bdev = ndctl_namespace_get_block_device(ndns);
+
+ if (!bdev)
+ return -ENXIO;
+
+ if (snprintf(path, len, "/sys/block/%s/dax/write_cache", bdev) >= len) {
+ err(ctx, "%s: buffer too small!\n",
+ ndctl_namespace_get_devname(ndns));
+ return -ENXIO;
+ }
+
+ if (sysfs_read_attr(ctx, path, buf) < 0)
+ return -ENXIO;
+
+ if (sscanf(buf, "%d", &wc) == 1)
+ if (wc)
+ return 1;
+
+ return 0;
+}
+
NDCTL_EXPORT int ndctl_namespace_delete(struct ndctl_namespace *ndns)
{
struct ndctl_region *region = ndctl_namespace_get_region(ndns);
diff --git a/ndctl/lib/libndctl.sym b/ndctl/lib/libndctl.sym
index 3209aef..4709c47 100644
--- a/ndctl/lib/libndctl.sym
+++ b/ndctl/lib/libndctl.sym
@@ -352,4 +352,7 @@ global:
ndctl_dimm_fw_update_supported;
ndctl_region_get_persistence_domain;
ndctl_bus_get_persistence_domain;
+ ndctl_namespace_write_cache_is_enabled;
+ ndctl_namespace_enable_write_cache;
+ ndctl_namespace_disable_write_cache;
} LIBNDCTL_14;
diff --git a/ndctl/libndctl.h b/ndctl/libndctl.h
index 684fcd4..1ecbabb 100644
--- a/ndctl/libndctl.h
+++ b/ndctl/libndctl.h
@@ -490,6 +490,9 @@ struct ndctl_bb *ndctl_namespace_injection_get_next_bb(
for (bb = ndctl_namespace_injection_get_first_bb(ndns); \
bb != NULL; \
bb = ndctl_namespace_injection_get_next_bb(ndns, bb))
+int ndctl_namespace_write_cache_is_enabled(struct ndctl_namespace *ndns);
+int ndctl_namespace_enable_write_cache(struct ndctl_namespace *ndns);
+int ndctl_namespace_disable_write_cache(struct ndctl_namespace *ndns);
struct ndctl_btt;
struct ndctl_btt *ndctl_btt_get_first(struct ndctl_region *region);
--
2.14.3
4 years, 2 months
[ndctl PATCH] ndctl, test: fix pmem-errors.sh vs new ARS rework
by Dan Williams
Due to locking constraints the nfit_test implementation is not able to
internally trigger ARS, so just run and wait for ARS manually in this
test. For example, here is what happens if nfit_test call
acpi_nfit_ars_rescan() from within the ioctl path.
WARNING: possible circular locking dependency detected
4.16.0-rc4+ #1686 Tainted: G OE
------------------------------------------------------
kworker/u80:0/6 is trying to acquire lock:
(&nvdimm_bus->reconfig_mutex){+.+.}, at: [<0000000048851014>] nvdimm_badblocks_populate+0x41/0x150 [libnvdimm]
but task is already holding lock:
(&acpi_desc->init_mutex){+.+.}, at: [<00000000016af3e5>] acpi_nfit_scrub+0x3b/0x2d0 [nfit]
which lock already depends on the new lock.
the existing dependency chain (in reverse order) is:
-> #1 (&acpi_desc->init_mutex){+.+.}:
acpi_nfit_ars_rescan+0x28/0x160 [nfit]
nfit_test_ctl+0x976/0x1040 [nfit_test]
__nd_ioctl+0x5d8/0x650 [libnvdimm]
nd_ioctl+0xa4/0xb0 [libnvdimm]
do_vfs_ioctl+0xa5/0x6d0
SyS_ioctl+0x74/0x80
do_syscall_64+0x79/0x230
entry_SYSCALL_64_after_hwframe+0x42/0xb7
-> #0 (&nvdimm_bus->reconfig_mutex){+.+.}:
__mutex_lock+0x7f/0xa00
nvdimm_badblocks_populate+0x41/0x150 [libnvdimm]
nd_region_notify+0x95/0xb0 [libnvdimm]
nd_device_notify+0x40/0x50 [libnvdimm]
ars_complete.isra.19+0x5d/0xb0 [nfit]
ars_complete_all+0x42/0x60 [nfit]
acpi_nfit_scrub+0x84/0x2d0 [nfit]
process_one_work+0x212/0x660
worker_thread+0x3a/0x390
kthread+0x11e/0x140
ret_from_fork+0x3a/0x50
Signed-off-by: Dan Williams <dan.j.williams(a)intel.com>
---
test/pmem-errors.sh | 1 +
1 file changed, 1 insertion(+)
diff --git a/test/pmem-errors.sh b/test/pmem-errors.sh
index 7c0487d1ac49..e0ab9e866b92 100755
--- a/test/pmem-errors.sh
+++ b/test/pmem-errors.sh
@@ -59,6 +59,7 @@ err_sector="$(((size/512) / 2))"
err_count=8
if ! read sector len < /sys/block/$blockdev/badblocks; then
$NDCTL inject-error --block="$err_sector" --count=$err_count $dev
+ $NDCTL start-scrub; $NDCTL wait-scrub
fi
read sector len < /sys/block/$blockdev/badblocks
[ $((sector * 2)) -ne $((size /512)) ] && echo "fail: $LINENO" && false
4 years, 2 months