On Thu, Aug 31, 2017 at 6:45 PM, Qi, Fuli <qi.fuli(a)jp.fujitsu.com> wrote:
Libnvdimmd.c provides functions which are used by nvdimm daemon, and
currently it just supports for logging.
Libnvdimmd.h is a head file of libnvdimmd.c.
Since I do not use automake, I defined gentenv.h to compile instead of it temporarily.
So I suppose more good way is necessary.
Signed-off-by: QI Fuli <qi.fuli(a)jp.fujitsu.com>
---
nvdimmd/Makefile | 7 +++
nvdimmd/getenv.h | 1 +
nvdimmd/libnvdimmd.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++++
nvdimmd/libnvdimmd.h | 31 +++++++++++
4 files changed, 180 insertions(+)
diff --git a/nvdimmd/Makefile b/nvdimmd/Makefile
new file mode 100644
index 0000000..a20a747
--- /dev/null
+++ b/nvdimmd/Makefile
@@ -0,0 +1,7 @@
+CC = gcc
+IDIR = -I../ -I../ndctl
+
+libnvdimmd.o: libnvdimmd.c
+ $(CC) -o libnvdimmd.o $(IDIR) -c libnvdimmd.c
+clean:
+ rm -rf *.o
diff --git a/nvdimmd/getenv.h b/nvdimmd/getenv.h
new file mode 100644
index 0000000..45747b4
--- /dev/null
+++ b/nvdimmd/getenv.h
@@ -0,0 +1 @@
+#define HAVE_SECURE_GETENV 1
diff --git a/nvdimmd/libnvdimmd.c b/nvdimmd/libnvdimmd.c
new file mode 100644
index 0000000..89ff701
--- /dev/null
+++ b/nvdimmd/libnvdimmd.c
This doesn't need to be a separate library, just roll it into nvdimmd directly.
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+/*
+ * This program is used to provide nvdimm daemon necessary functions.
+ */
+
+#include "getenv.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <syslog.h>
+#include <ndctl/libndctl.h>
+#include <ndctl/lib/libndctl-private.h>
+#include "libnvdimmd.h"
+#define BUF_SIZE 4096
+
+static int get_health_info(threshold_dimm *t_dimm)
+{
+ struct ndctl_cmd *cmd;
+ int rc;
+ unsigned int flags;
+ char *msg = "nvdimm warning: dimm over threshold notify";
+ char *err_msg;
+
+ cmd = ndctl_dimm_cmd_new_smart(t_dimm->dimm);
+ if (!cmd) {
+ err_msg = "failed to prepare command to get health info";
+ syslog(LOG_WARNING, "%s [%s], %s\n", msg, t_dimm->devname,
err_msg);
+ return -1;
Let's use the same logging scheme as libndctl where we have 'struct
log_ctx' and the the log function can be set to a custom routine. That
way we can redirect log messages to syslog or structured json output
simply by changing log_ctx.log_fn.
+ }
+
+ rc = ndctl_cmd_submit(cmd);
+ if (rc || ndctl_cmd_get_firmware_status(cmd)) {
+ err_msg = "failed to submit command to get health info";
+ syslog(LOG_WARNING, "%s [%s], %s\n", msg, t_dimm->devname,
err_msg);
+ ndctl_cmd_unref(cmd);
+ return -1;
+ }
+
+ flags = ndctl_cmd_smart_get_flags(cmd);
+ if (flags & ND_SMART_HEALTH_VALID) {
+ unsigned int health = ndctl_cmd_smart_get_health(cmd);
+ if (health & ND_SMART_FATAL_HEALTH)
+ t_dimm->health_state = "fatal";
+ else if (health & ND_SMART_CRITICAL_HEALTH)
+ t_dimm->health_state = "critical";
+ else if (health & ND_SMART_NON_CRITICAL_HEALTH)
+ t_dimm->health_state = "non-critical";
+ else
+ t_dimm->health_state = "ok";
+ } else {
+ t_dimm->health_state = "failed to get data";
+ }
+ if (flags & ND_SMART_SPARES_VALID)
+ t_dimm->spares = ndctl_cmd_smart_get_spares(cmd);
+ else
+ t_dimm->spares = -1;
+
+ ndctl_cmd_unref(cmd);
+ return 0;
+}
+
+int log_notify(threshold_dimm *t_dimm, int count_dimm, fd_set fds, int count_select)
+{
+ int log_notify = 0;
+ char *msg = "nvdimm warning: dimm over threshold notify";
+
+ for (int i = 0; i < count_dimm; i++) {
+ if (log_notify >= count_select)
+ break;
+
+ if (!FD_ISSET(t_dimm[i].health_eventfd, &fds))
+ continue;
+
+ log_notify++;
+ if (get_health_info(&t_dimm[i]))
+ continue;
+
+ if (t_dimm[i].spares == -1) {
+ syslog(LOG_WARNING,
+ "%s [%s]\nhealth_state: %s\n"
+ "spares_percentage: failed to get data\n",
+ msg, t_dimm[i].devname, t_dimm[i].health_state);
+ continue;
+ }
+ syslog(LOG_WARNING,"%s [%s]\nhealth_state: %s\nspares_percentage:
%d\n",
+ msg, t_dimm[i].devname, t_dimm[i].health_state,
t_dimm[i].spares);
+ }
+ return log_notify;
+}
+
+static struct ndctl_dimm *is_supported_threshold_notify(struct ndctl_dimm *dimm)
+{
+ if (ndctl_dimm_is_cmd_supported(dimm, ND_CMD_SMART_THRESHOLD))
+ return dimm;
+ return NULL;
+}
+
+int
+get_threshold_dimm(struct ndctl_ctx *ctx, threshold_dimm *t_dimm, fd_set *fds, int
*maxfd)
+{
+ struct ndctl_bus *bus;
+ struct ndctl_dimm *dimm;
+ char buf[BUF_SIZE];
+ int fd, count_dimm = 0;
+
+ ndctl_bus_foreach(ctx, bus) {
+ ndctl_dimm_foreach(bus, dimm) {
+
+ if (!is_supported_threshold_notify(dimm))
+ continue;
+ t_dimm[count_dimm].dimm = dimm;
+ t_dimm[count_dimm].devname = ndctl_dimm_get_devname(dimm);
+ fd = ndctl_dimm_get_health_eventfd(dimm);
+ read(fd, buf, sizeof(buf));
+ t_dimm[count_dimm].health_eventfd = fd;
+
+ if (fds)
+ FD_SET(fd, fds);
+ if (maxfd) {
+ if (*maxfd < fd)
+ *maxfd = fd;
+ }
+ count_dimm++;
+ }
+ }
+ return count_dimm;
+}
diff --git a/nvdimmd/libnvdimmd.h b/nvdimmd/libnvdimmd.h
new file mode 100644
index 0000000..78e5871
--- /dev/null
+++ b/nvdimmd/libnvdimmd.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017, 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.
+ */
+
+#ifndef _LIBNVDIMMD_H_
+#define _LIBBVDIMMD_H_
Extra 'B', but no need to fix since we can delete this header and
merge this file with nvdimmd.c.
+
+#include <stdio.h>
+#define NUM_MAX_DIMM 1024
+
+typedef struct {
+ struct ndctl_dimm *dimm;
+ const char *devname;
+ int health_eventfd;
+ int spares;
+ char *health_state;
+} threshold_dimm;
ndctl tries to follow Linux kernel coding style as much as possible,
so please type out the full struct name instead of using a typedef.
More background can be found here:
https://www.kernel.org/doc/html/v4.10/process/coding-style.html#typedefs
+int log_notify(threshold_dimm *t_dimm, int count_dimm, fd_set fds,
int count_select);
+int get_threshold_dimm(struct ndctl_ctx *ctx, threshold_dimm *t_dimm, fd_set *fds, int
*maxfd);