On Thu, Aug 31, 2017 at 6:45 PM, Qi, Fuli <qi.f...@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.f...@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);
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

Reply via email to