]> www.infradead.org Git - users/sagi/libnvme.git/commitdiff
Add logging functionality to libnvme
authorHannes Reinecke <hare@suse.de>
Mon, 14 Jun 2021 13:44:28 +0000 (15:44 +0200)
committerHannes Reinecke <hare@suse.de>
Wed, 16 Jun 2021 06:54:19 +0000 (08:54 +0200)
Port the logging functionality from nvme-cli to libnvme and
replace the 'verbose' option.

Signed-off-by: Hannes Reinecke <hare@suse.de>
src/Makefile
src/libnvme.h
src/nvme/cleanup.c [new file with mode: 0644]
src/nvme/cleanup.h [new file with mode: 0644]
src/nvme/fabrics.c
src/nvme/fabrics.h
src/nvme/log.c [new file with mode: 0644]
src/nvme/log.h [new file with mode: 0644]
src/nvme/tree.c
src/nvme/tree.h
src/nvme/util.c

index 4beb13d8db47d1dddb4b5f16534f828e778aaa79..19361f89ff296ab79e0d8ca0d87a6fadaa903153 100644 (file)
@@ -48,7 +48,7 @@ $(libccan_objs) $(libccan_sobjs): $(libccan_headers) $(CCANDIR)config.h
 
 libnvme_priv := nvme/private.h
 libnvme_api := libnvme.h nvme/types.h nvme/ioctl.h nvme/filters.h nvme/tree.h nvme/util.h nvme/fabrics.h
-libnvme_srcs := nvme/ioctl.c nvme/filters.c nvme/fabrics.c nvme/util.c nvme/tree.c
+libnvme_srcs := nvme/ioctl.c nvme/filters.c nvme/fabrics.c nvme/util.c nvme/tree.c nvme/log.c nvme/cleanup.c
 ifneq ($(CONFIG_JSONC),0)
 override libnvme_srcs += nvme/json.c
 endif
index bd60d0d8a5e2cddf888be8747d5c881bdc3c930f..00b1211e70194cc06edcadc024194d6b596a8872 100644 (file)
@@ -20,6 +20,7 @@ extern "C" {
 #include "nvme/filters.h"
 #include "nvme/tree.h"
 #include "nvme/util.h"
+#include "nvme/log.h"
 
 #ifdef __cplusplus
 }
diff --git a/src/nvme/cleanup.c b/src/nvme/cleanup.c
new file mode 100644 (file)
index 0000000..0d5d910
--- /dev/null
@@ -0,0 +1,4 @@
+#include <stdlib.h>
+#include "cleanup.h"
+
+DEFINE_CLEANUP_FUNC(cleanup_charp, char *, free);
diff --git a/src/nvme/cleanup.h b/src/nvme/cleanup.h
new file mode 100644 (file)
index 0000000..89a4984
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __CLEANUP_H
+#define __CLEANUP_H
+
+#define __cleanup__(fn) __attribute__((cleanup(fn)))
+
+#define DECLARE_CLEANUP_FUNC(name, type) \
+       void name(type *__p)
+
+#define DEFINE_CLEANUP_FUNC(name, type, free_fn)\
+DECLARE_CLEANUP_FUNC(name, type)               \
+{                                              \
+       if (*__p)                               \
+               free_fn(*__p);                  \
+}
+
+DECLARE_CLEANUP_FUNC(cleanup_charp, char *);
+
+#endif
index ad2fe7b994e2e441ba734130949bb3f5d050a95d..19cc18814691d0e8d186fc9c0ff99f886cf0a490 100644 (file)
@@ -32,6 +32,7 @@
 #include "fabrics.h"
 #include "ioctl.h"
 #include "util.h"
+#include "log.h"
 #include "private.h"
 
 #define NVMF_HOSTID_SIZE       37
@@ -158,7 +159,6 @@ static struct nvme_fabrics_config *merge_config(nvme_ctrl_t c,
        UPDATE_CFG_OPTION(ctrl_cfg, cfg, disable_sqflow, false);
        UPDATE_CFG_OPTION(ctrl_cfg, cfg, hdr_digest, false);
        UPDATE_CFG_OPTION(ctrl_cfg, cfg, data_digest, false);
-       UPDATE_CFG_OPTION(ctrl_cfg, cfg, verbose, false);
 
        return ctrl_cfg;
 }
@@ -215,6 +215,21 @@ static int build_options(nvme_ctrl_t c, char **argstr)
 {
        struct nvme_fabrics_config *cfg = nvme_ctrl_get_config(c);
        const char *transport = nvme_ctrl_get_transport(c);
+       const char *hostnqn, *hostid;
+
+       if (!transport) {
+               nvme_msg(LOG_ERR, "need a transport (-t) argument\n");
+               errno = EINVAL;
+               return -1;
+       }
+
+       if (strncmp(transport, "loop", 4)) {
+               if (!nvme_ctrl_get_traddr(c)) {
+                       nvme_msg(LOG_ERR, "need a address (-a) argument\n");
+                       errno = EINVAL;
+                       return -1;
+               }
+       }
 
        /* always specify nqn as first arg - this will init the string */
        if (asprintf(argstr, "nqn=%s",
@@ -273,21 +288,29 @@ static int __nvmf_add_ctrl(const char *argstr)
        char buf[0x1000], *options, *p;
 
        fd = open(nvmf_dev, O_RDWR);
-       if (fd < 0)
+       if (fd < 0) {
+               nvme_msg(LOG_ERR, "Failed to open %s: %s\n",
+                        nvmf_dev, strerror(errno));
                return -1;
+       }
 
+       nvme_msg(LOG_DEBUG, "connect ctrl, '%s'\n", argstr);
        ret = write(fd, argstr, len);
        if (ret != len) {
+               nvme_msg(LOG_NOTICE, "Failed to write to %s: %s\n",
+                        nvmf_dev, strerror(errno));
                ret = -1;
                goto out_close;
        }
 
        len = read(fd, buf, sizeof(buf));
        if (len < 0) {
+               nvme_msg(LOG_ERR, "Failed to read from %s: %s\n",
+                        nvmf_dev, strerror(errno));
                ret = -1;
                goto out_close;
        }
-
+       nvme_msg(LOG_DEBUG, "connect ctrl, response '%s'\n", buf);
        buf[len] = '\0';
        options = buf;
        while ((p = strsep(&options, ",\n")) != NULL) {
@@ -297,6 +320,7 @@ static int __nvmf_add_ctrl(const char *argstr)
                        goto out_close;
        }
 
+       nvme_msg(LOG_ERR, "Failed to parse ctrl info for \"%s\"\n", argstr);
        errno = EINVAL;
        ret = -1;
 out_close:
@@ -315,16 +339,10 @@ int nvmf_add_ctrl_opts(nvme_ctrl_t c, struct nvme_fabrics_config *cfg)
        if (ret)
                return ret;
 
-       if (cfg->verbose)
-               fprintf(stderr, "nvmf connect %s\n", argstr);
        ret = __nvmf_add_ctrl(argstr);
        free(argstr);
-       if (cfg->verbose) {
-               if (ret < 0)
-                       fprintf(stderr, "failed to add ctrl, error %d\n", errno);
-               else
-                       fprintf(stderr, "nvme%d: added ctrl\n", ret);
-       }
+       if (ret >= 0)
+               nvme_msg(LOG_INFO, "nvme%d: ctrl connected\n", ret);
        return ret;
 }
 
@@ -343,17 +361,12 @@ int nvmf_add_ctrl(nvme_host_t h, nvme_ctrl_t c,
        if (ret)
                return ret;
 
-       if (cfg->verbose)
-               fprintf(stderr, "nvmf connect %s\n", argstr);
        ret = __nvmf_add_ctrl(argstr);
        free(argstr);
-       if (ret < 0) {
-               if (cfg->verbose)
-                       fprintf(stderr, "failed to add ctrl, error %d\n", ret);
+       if (ret < 0)
                return ret;
-       }
-       if (cfg->verbose)
-               fprintf(stderr, "nvme%d: ctrl connected\n", ret);
+
+       nvme_msg(LOG_INFO, "nvme%d: ctrl connected\n", ret);
        return nvme_init_ctrl(h, c, ret);
 }
 
@@ -376,10 +389,8 @@ nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h,
        case NVME_NQN_NVME:
                break;
        default:
-               if (cfg->verbose)
-                       fprintf(stderr, "skipping discovery entry, "
-                              "invalid subsystem type %d\n",
-                              e->subtype);
+               nvme_msg(LOG_ERR, "skipping unsupported subtype %d\n",
+                        e->subtype);
                errno = EINVAL;
                return NULL;
        }
@@ -396,10 +407,8 @@ nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h,
                        trsvcid = e->trsvcid;
                        break;
                default:
-                       if (cfg->verbose)
-                               fprintf(stderr, "skipping discovery entry, "
-                                      "invalid address family %d\n",
-                                      e->trtype);
+                       nvme_msg(LOG_ERR, "skipping unsupported adrfam %d\n",
+                                e->adrfam);
                        errno = EINVAL;
                        return NULL;
                }
@@ -411,29 +420,31 @@ nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h,
                        traddr = e->traddr;
                        trsvcid = NULL;
                        break;
+               default:
+                       nvme_msg(LOG_ERR, "skipping unsupported adrfam %d\n",
+                                e->adrfam);
+                       errno = EINVAL;
+                       return NULL;
                }
        case NVMF_TRTYPE_LOOP:
                break;
        default:
-               if (cfg->verbose)
-                       fprintf(stderr, "skipping discovery entry, "
-                               "invalid transport type %d\n",
-                               e->trtype);
+               nvme_msg(LOG_ERR, "skipping unsupported transport %d\n",
+                        e->trtype);
                errno = EINVAL;
                return NULL;
        }
 
        transport = nvmf_trtype_str(e->trtype);
-       if (cfg->verbose)
-               fprintf(stderr, "lookup ctrl %s %s %s\n",
-                       transport, traddr, trsvcid);
 
+       nvme_msg(LOG_DEBUG, "lookup ctrl "
+                "(transport: %s, traddr: %s, trsvcid %s)\n",
+                transport, traddr, trsvcid);
        c = nvme_create_ctrl(e->subnqn, transport, traddr, NULL, trsvcid);
        if (!c) {
-               if (cfg->verbose)
-                       fprintf(stderr, "skipping discovery entry, "
-                               "failed to allocate controller on %s port %s\n",
-                               transport, traddr);
+               nvme_msg(LOG_DEBUG, "skipping discovery entry, "
+                        "failed to allocate %s controller with traddr %s\n",
+                        transport, traddr);
                errno = ENOMEM;
                return NULL;
        }
@@ -452,17 +463,14 @@ nvme_ctrl_t nvmf_connect_disc_entry(nvme_host_t h,
        if (errno == EINVAL && disable_sqflow) {
                errno = 0;
                /* disable_sqflow is unrecognized option on older kernels */
-               if (cfg->verbose)
-                       fprintf(stderr, "failed to connect controller, "
-                               "retry with disabling SQ flow control\n");
+               nvme_msg(LOG_INFO, "failed to connect controller, "
+                        "retry with disabling SQ flow control\n");
                disable_sqflow = false;
                ret = nvmf_add_ctrl(h, c, cfg, disable_sqflow);
                if (!ret)
                        return c;
        }
-       if (cfg->verbose)
-               fprintf(stderr, "failed to connect controller, "
-                       "error %d\n", errno);
+       nvme_msg(LOG_ERR, "failed to connect controller, error %d\n", errno);
        nvme_free_ctrl(c);
        return NULL;
 }
@@ -485,18 +493,18 @@ int nvmf_get_discovery_log(nvme_ctrl_t c, struct nvmf_discovery_log **logp,
        hdr = sizeof(struct nvmf_discovery_log);
        log = malloc(hdr);
        if (!log) {
+               nvme_msg(LOG_ERR,
+                        "could not allocate memory for discovery log header\n");
                errno = ENOMEM;
                return -1;
        }
        memset(log, 0, hdr);
 
-       if (nvme_ctrl_is_verbose(c))
-               fprintf(stderr, "%s: discover length %d\n", name, 0x100);
+       nvme_msg(LOG_DEBUG, "%s: discover length %d\n", name, 0x100);
        ret = nvme_discovery_log(nvme_ctrl_get_fd(c), 0x100, log);
        if (ret) {
-               if (nvme_ctrl_is_verbose(c))
-                       fprintf(stderr, "%s: discover failed, error %d\n",
-                              name, errno);
+               nvme_msg(LOG_INFO, "%s: discover failed, error %d\n",
+                        name, errno);
                goto out_free_log;
        }
 
@@ -515,48 +523,42 @@ int nvmf_get_discovery_log(nvme_ctrl_t c, struct nvmf_discovery_log **logp,
                free(log);
                log = malloc(size);
                if (!log) {
+                       nvme_msg(LOG_ERR,
+                                "could not alloc memory for discovery log page\n");
                        errno = ENOMEM;
                        return -1;
                }
                memset(log, 0, size);
 
-               if (nvme_ctrl_is_verbose(c))
-                       fprintf(stderr, "%s: discover length %d\n", name, size);
-
+               nvme_msg(LOG_DEBUG, "%s: discover length %d\n", name, size);
                ret = nvme_discovery_log(nvme_ctrl_get_fd(c), size, log);
                if (ret) {
-                       if (nvme_ctrl_is_verbose(c))
-                               fprintf(stderr, "%s: discover "
-                                       "try %d/%d failed, error %d\n",
-                                       name, retries, max_retries, errno);
+                       nvme_msg(LOG_INFO,
+                                "%s: discover try %d/%d failed, error %d\n",
+                                name, retries, max_retries, errno);
                        goto out_free_log;
                }
 
                genctr = le64_to_cpu(log->genctr);
-               if (nvme_ctrl_is_verbose(c))
-                       fprintf(stderr, "%s: discover genctr %lu, retry\n",
-                               name, genctr);
+               nvme_msg(LOG_DEBUG, "%s: discover genctr %lu, retry\n",
+                        name, genctr);
                ret = nvme_discovery_log(nvme_ctrl_get_fd(c), hdr, log);
                if (ret) {
-                       if (nvme_ctrl_is_verbose(c))
-                               fprintf(stderr, "%s: discover "
-                                       "try %d/%d failed, error %d\n",
-                                       name, retries, max_retries, errno);
+                       nvme_msg(LOG_INFO,
+                                "%s: discover try %d/%d failed, error %d\n",
+                                name, retries, max_retries, errno);
                        goto out_free_log;
                }
        } while (genctr != le64_to_cpu(log->genctr) &&
                 ++retries < max_retries);
 
        if (genctr != le64_to_cpu(log->genctr)) {
-               if (nvme_ctrl_is_verbose(c))
-                       fprintf(stderr, "%s: discover genctr mismatch\n", name);
+               nvme_msg(LOG_INFO, "%s: discover genctr mismatch\n", name);
                errno = EAGAIN;
                ret = -1;
        } else if (numrec != le64_to_cpu(log->numrec)) {
-               if (nvme_ctrl_is_verbose(c))
-                       fprintf(stderr,
-                               "%s: could only fetch %lu of %lu records\n",
-                               name, numrec, le64_to_cpu(log->numrec));
+               nvme_msg(LOG_INFO, "%s: could only fetch %lu of %lu records\n",
+                        name, numrec, le64_to_cpu(log->numrec));
                errno = EBADSLT;
                ret = -1;
        } else {
index 077e47311d13bc8fd2b8b25ba617200b6f86f927..c130339b15a9b2727ccbdab2878f81ceaeebe131 100644 (file)
@@ -30,7 +30,6 @@
  * @disable_sqflow:    Disable controller sq flow control
  * @hdr_digest:                Generate/verify header digest (TCP)
  * @data_digest:       Generate/verify data digest (TCP)
- * @verbose:            Verbose output
  */
 struct nvme_fabrics_config {
        int queue_size;
@@ -46,7 +45,6 @@ struct nvme_fabrics_config {
        bool disable_sqflow;
        bool hdr_digest;
        bool data_digest;
-       bool verbose;
 };
 
 /**
diff --git a/src/nvme/log.c b/src/nvme/log.c
new file mode 100644 (file)
index 0000000..66cf692
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2021 SUSE LLC
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version
+ * 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This file implements basic logging functionality.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <time.h>
+#define LOG_FUNCNAME 1
+#include "log.h"
+#include "cleanup.h"
+
+#ifndef LOG_CLOCK
+#define LOG_CLOCK CLOCK_MONOTONIC
+#endif
+
+int nvme_log_level = DEFAULT_LOGLEVEL;
+bool nvme_log_timestamp;
+bool nvme_log_pid;
+
+void __attribute__((format(printf, 3, 4)))
+__nvme_msg(int lvl, const char *func, const char *format, ...)
+{
+       va_list ap;
+       char pidbuf[16];
+       char timebuf[32];
+       static const char *const formats[] = {
+               "%s%s%s",
+               "%s%s%s: ",
+               "%s<%s>%s ",
+               "%s<%s> %s: ",
+               "[%s] %s%s ",
+               "[%s]%s %s: ",
+               "[%s] <%s>%s ",
+               "[%s] <%s> %s: ",
+       };
+       char *header __cleanup__(cleanup_charp) = NULL;
+       char *message __cleanup__(cleanup_charp) = NULL;
+       int idx;
+
+       if (lvl > nvme_log_level)
+               return;
+
+       if (nvme_log_timestamp) {
+               struct timespec now;
+
+               clock_gettime(LOG_CLOCK, &now);
+               snprintf(timebuf, sizeof(timebuf), "%6ld.%06ld",
+                        (long)now.tv_sec, now.tv_nsec / 1000);
+       } else
+               *timebuf = '\0';
+
+       if (nvme_log_pid)
+               snprintf(pidbuf, sizeof(pidbuf), "%ld", (long)getpid());
+       else
+               *pidbuf = '\0';
+
+       idx = ((nvme_log_timestamp ? 1 : 0) << 2) |
+               ((nvme_log_pid ? 1 : 0) << 1) | (func ? 1 : 0);
+
+       if (asprintf(&header, formats[idx], timebuf, pidbuf, func ? func : "")
+           == -1)
+               header = NULL;
+
+       va_start(ap, format);
+       if (vasprintf(&message, format, ap) == -1)
+               message = NULL;
+       va_end(ap);
+
+       fprintf(stderr, "%s%s", header ? header : "<error>",
+               message ? message : "<error>");
+
+}
diff --git a/src/nvme/log.h b/src/nvme/log.h
new file mode 100644 (file)
index 0000000..36f56e8
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2021 Martin Wilck, SUSE LLC
+ * SPDX-License-Identifier: LGPL-2.1-or-newer
+ */
+#ifndef _LOG_H
+#define _LOG_H
+
+#include <syslog.h>
+
+#ifndef MAX_LOGLEVEL
+#  define MAX_LOGLEVEL LOG_DEBUG
+#endif
+#ifndef DEFAULT_LOGLEVEL
+#  define DEFAULT_LOGLEVEL LOG_NOTICE
+#endif
+
+#if (LOG_FUNCNAME == 1)
+#define __nvme_log_func __func__
+#else
+#define __nvme_log_func NULL
+#endif
+
+extern int nvme_log_level;
+extern bool nvme_log_timestamp;
+extern bool nvme_log_pid;
+
+void __attribute__((format(printf, 3, 4)))
+__nvme_msg(int lvl, const char *func, const char *format, ...);
+
+#define nvme_msg(lvl, format, ...)                                     \
+       do {                                                            \
+               if ((lvl) <= MAX_LOGLEVEL)                              \
+                       __nvme_msg(lvl, __nvme_log_func,                \
+                                  format, ##__VA_ARGS__);              \
+       } while (0)
+
+#endif /* _LOG_H */
index 04c70742717f8c8935833c8f2ef33dc5b79930f5..896257dc27cf2a7b06e6ce7d24f1a64543a26a4f 100644 (file)
@@ -23,6 +23,7 @@
 #include "filters.h"
 #include "util.h"
 #include "fabrics.h"
+#include "log.h"
 #include "private.h"
 
 static struct nvme_host *default_host;
@@ -733,16 +734,6 @@ bool nvme_ctrl_is_persistent(nvme_ctrl_t c)
        return c->persistent;
 }
 
-void nvme_ctrl_set_verbosity(nvme_ctrl_t c, bool verbose)
-{
-       c->cfg.verbose = verbose;
-}
-
-bool nvme_ctrl_is_verbose(nvme_ctrl_t c)
-{
-       return c->cfg.verbose;
-}
-
 int nvme_ctrl_identify(nvme_ctrl_t c, struct nvme_id_ctrl *id)
 {
        return nvme_identify_ctrl(nvme_ctrl_get_fd(c), id);
@@ -774,16 +765,14 @@ int nvme_ctrl_disconnect(nvme_ctrl_t c)
 {
        int ret;
 
-       if (c->cfg.verbose)
-               fprintf(stderr, "%s: disconnect\n", c->name);
        ret = nvme_set_attr(nvme_ctrl_get_sysfs_dir(c),
                            "delete_controller", "1");
        if (ret < 0) {
-               if (c->cfg.verbose)
-                       fprintf(stderr, "%s: failed to disconnect, error %d\n",
-                               c->name, errno);
+               nvme_msg(LOG_ERR, "%s: failed to disconnect, error %d\n",
+                        c->name, errno);
                return ret;
        }
+       nvme_msg(LOG_INFO, "%s: disconnected\n", c->name);
        if (c->fd >= 0) {
                close(c->fd);
                c->fd = -1;
index 53f53e3f2c21fc46179ea1c407d5137204a91fa1..4983bbaec19955c6ab9943102392495111789a10 100644 (file)
@@ -834,23 +834,6 @@ bool nvme_ctrl_is_persistent(nvme_ctrl_t c);
  */
 void nvme_ctrl_disable_sqflow(nvme_ctrl_t c, bool disable_sqflow);
 
-/**
- * nvme_ctrl_set_verbosity() -
- * @c:
- * @verbose:
- *
- * Return:
- */
-void nvme_ctrl_set_verbosity(nvme_ctrl_t c, bool verbose);
-
-/**
- * nvme_ctrl_is_verbose() -
- * @c:
- *
- * Return:
- */
-bool nvme_ctrl_is_verbose(nvme_ctrl_t c);
-
 /**
  * nvme_ctrl_identify() -
  * @c:
index 8dbef2033b6bd2d3c26d22b293d9a6de84a599ab..761ae81cf8999698f9fa68f863b291e9106f851c 100644 (file)
@@ -24,6 +24,7 @@
 #include "filters.h"
 #include "util.h"
 #include "tree.h"
+#include "log.h"
 
 static inline __u8 nvme_generic_status_to_errno(__u16 status)
 {
@@ -562,9 +563,11 @@ static int __nvme_set_attr(const char *path, const char *value)
        int ret, fd;
 
        fd = open(path, O_WRONLY);
-       if (fd < 0)
+       if (fd < 0) {
+               nvme_msg(LOG_ERR, "Failed to open %s: %s\n", path,
+                        strerror(errno));
                return -1;
-
+       }
        ret = write(fd, value, strlen(value));
        close(fd);
        return ret;
@@ -590,8 +593,11 @@ static char *__nvme_get_attr(const char *path)
        int ret, fd;
 
        fd = open(path, O_RDONLY);
-       if (fd < 0)
+       if (fd < 0) {
+               nvme_msg(LOG_ERR, "Failed to open %s: %s\n", path,
+                        strerror(errno));
                return NULL;
+       }
 
        ret = read(fd, value, sizeof(value) - 1);
        if (ret < 0) {