Hello community, here is the log from the commit of package nvme-cli for openSUSE:Factory checked in at 2019-05-06 13:18:09 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nvme-cli (Old) and /work/SRC/openSUSE:Factory/.nvme-cli.new.5148 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nvme-cli" Mon May 6 13:18:09 2019 rev:32 rq:699825 version:1.7 Changes: -------- --- /work/SRC/openSUSE:Factory/nvme-cli/nvme-cli.changes 2019-04-02 09:18:13.700525434 +0200 +++ /work/SRC/openSUSE:Factory/.nvme-cli.new.5148/nvme-cli.changes 2019-05-06 13:18:25.924123970 +0200 @@ -1,0 +2,12 @@ +Fri Apr 12 08:45:04 UTC 2019 - Simon Schricker <sschric...@suse.com> + +- Add new 'ontapdevices' command and corresponding documentation. + Requested in (bsc#1131930). + + 0011-nvme-cli-add-netapp-ontapdevices-command.patch + + 0012-nvme-cli-add-netapp-ontapdevices-man-page.patch + + 0104-nvme-cli-Fix-documentation-syntax-and-typo.patch +- Revert stop-on-failure patch for connect-all, which caused + unintended behaviour (bsc#1132124) + + 0013-nvme-cli-Revert-stop-on-failure-with-connect-all.patch + +------------------------------------------------------------------- New: ---- 0011-nvme-cli-add-netapp-ontapdevices-command.patch 0012-nvme-cli-add-netapp-ontapdevices-man-page.patch 0013-nvme-cli-Revert-stop-on-failure-with-connect-all.patch 0104-nvme-cli-Fix-documentation-syntax-and-typo.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nvme-cli.spec ++++++ --- /var/tmp/diff_new_pack.2DVP9V/_old 2019-05-06 13:18:29.972134898 +0200 +++ /var/tmp/diff_new_pack.2DVP9V/_new 2019-05-06 13:18:29.976134909 +0200 @@ -35,10 +35,14 @@ Patch8: 0008-nvme-cli-minor-cleanup-for-submit_io.patch Patch9: 0009-Regen-documentation.patch Patch10: 0010-nvme-cli-fix-fc-trtype-string.patch +Patch11: 0011-nvme-cli-add-netapp-ontapdevices-command.patch +Patch12: 0012-nvme-cli-add-netapp-ontapdevices-man-page.patch +Patch13: 0013-nvme-cli-Revert-stop-on-failure-with-connect-all.patch Patch100: 0100-nvme_fc-auto-connect-scripts.patch Patch101: 0101-71-nvme-iopolicy-netapp.rules-add-default-rules-for-.patch Patch102: 0102-Add-nvmefc-connect.target.patch Patch103: 0103-Change-service-to-type-simple.patch +Patch104: 0104-nvme-cli-Fix-documentation-syntax-and-typo.patch BuildRequires: libuuid-devel BuildRequires: pkgconfig BuildRequires: xmlto @@ -62,10 +66,14 @@ %patch8 -p1 %patch9 -p1 %patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 %patch100 -p1 %patch101 -p1 %patch102 -p1 %patch103 -p1 +%patch104 -p1 %build echo %{version} > version ++++++ 0011-nvme-cli-add-netapp-ontapdevices-command.patch ++++++ >From 70bfe077af40aeace6c9e2b628b20cf8a34c1def Mon Sep 17 00:00:00 2001 From: Martin George <mart...@netapp.com> Date: Mon, 1 Apr 2019 09:39:56 -0700 Subject: [PATCH] nvme-cli: add netapp ontapdevices command Add a new ontapdevices command to the NetApp plugin for NetApp ONTAP devices. Signed-off-by: Martin George <mart...@netapp.com> Reviewed-by: Steve Schremmer <sschr...@netapp.com> --- plugins/netapp/netapp-nvme.c | 342 +++++++++++++++++++++++++++++++++++++++++++ plugins/netapp/netapp-nvme.h | 1 + 2 files changed, 343 insertions(+) diff --git a/plugins/netapp/netapp-nvme.c b/plugins/netapp/netapp-nvme.c index 416e74e..2951311 100644 --- a/plugins/netapp/netapp-nvme.c +++ b/plugins/netapp/netapp-nvme.c @@ -21,6 +21,7 @@ #include <unistd.h> #include <errno.h> #include <string.h> +#include <sys/ioctl.h> #include "nvme.h" #include "nvme-ioctl.h" @@ -31,12 +32,28 @@ #define CREATE_CMD #include "netapp-nvme.h" +#define ONTAP_C2_LOG_ID 0xC2 +#define ONTAP_C2_LOG_SIZE 4096 +#define ONTAP_LABEL_LEN 260 +#define ONTAP_NS_PATHLEN 520 + enum { NNORMAL, NJSON, NCOLUMN, }; +enum { + ONTAP_C2_LOG_SUPPORTED_LSP = 0x0, + ONTAP_C2_LOG_NSINFO_LSP = 0x1, +}; + +enum { + ONTAP_VSERVER_TLV = 0x11, + ONTAP_VOLUME_TLV = 0x12, + ONTAP_NS_TLV = 0x13, +}; + static const char *dev_path = "/dev/"; struct smdevice_info { @@ -46,6 +63,15 @@ struct smdevice_info { char dev[265]; }; +struct ontapdevice_info { + int nsid; + struct nvme_id_ctrl ctrl; + struct nvme_id_ns ns; + char nsdesc[4096]; + unsigned char log_data[ONTAP_C2_LOG_SIZE]; + char dev[265]; +}; + #define ARRAY_LABEL_LEN 60 #define VOLUME_LABEL_LEN 60 @@ -77,6 +103,100 @@ static void netapp_nguid_to_str(char *str, __u8 *nguid) str += sprintf(str, "%02x", nguid[i]); } +static void netapp_get_ns_size(char *size, long long *lba, + struct nvme_id_ns *ns) +{ + *lba = 1 << ns->lbaf[(ns->flbas & 0x0F)].ds; + double nsze = le64_to_cpu(ns->nsze) * (*lba); + const char *s_suffix = suffix_si_get(&nsze); + + sprintf(size, "%.2f%sB", nsze, s_suffix); +} + +static void netapp_uuid_to_str(char *str, void *data) +{ +#ifdef LIBUUID + uuid_t uuid; + struct nvme_ns_id_desc *desc = data; + + memcpy(uuid, data + sizeof(*desc), 16); + uuid_unparse_lower(uuid, str); +#endif +} + +static void ontap_labels_to_str(char *dst, char *src, int count) +{ + int i; + + memset(dst, 0, ONTAP_LABEL_LEN); + for (i = 0; i < count; i++) { + if (src[i] >= '!' && src[i] <= '~') + dst[i] = src[i]; + else + break; + } + dst[i] = '\0'; +} + +static void netapp_get_ontap_labels(char *vsname, char *nspath, + unsigned char *log_data) +{ + int lsp, tlv, label_len; + char *vserver_name, *volume_name, *namespace_name; + char vol_name[ONTAP_LABEL_LEN], ns_name[ONTAP_LABEL_LEN]; + const char *ontap_vol = "/vol/"; + int i, j; + + /* get the lsp */ + lsp = (*(__u8 *)&log_data[16]) & 0x0F; + if (lsp != ONTAP_C2_LOG_NSINFO_LSP) + /* lsp not related to nsinfo */ + return; + + /* get the vserver tlv and name */ + tlv = *(__u8 *)&log_data[32]; + if (tlv == ONTAP_VSERVER_TLV) { + label_len = (*(__u16 *)&log_data[34]) * 4; + vserver_name = (char *)&log_data[36]; + ontap_labels_to_str(vsname, vserver_name, label_len); + } else { + /* not the expected vserver tlv */ + fprintf(stderr, "Unable to fetch ONTAP vserver name\n"); + return; + } + + i = 36 + label_len; + j = i + 2; + /* get the volume tlv and name */ + tlv = *(__u8 *)&log_data[i]; + if (tlv == ONTAP_VOLUME_TLV) { + label_len = (*(__u16 *)&log_data[j]) * 4; + volume_name = (char *)&log_data[j + 2]; + ontap_labels_to_str(vol_name, volume_name, label_len); + } else { + /* not the expected volume tlv */ + fprintf(stderr, "Unable to fetch ONTAP volume name\n"); + return; + } + + i += 4 + label_len; + j += 4 + label_len; + /* get the namespace tlv and name */ + tlv = *(__u8 *)&log_data[i]; + if (tlv == ONTAP_NS_TLV) { + label_len = (*(__u16 *)&log_data[j]) * 4; + namespace_name = (char *)&log_data[j + 2]; + ontap_labels_to_str(ns_name, namespace_name, label_len); + } else { + /* not the expected namespace tlv */ + fprintf(stderr, "Unable to fetch ONTAP namespace name\n"); + return; + } + + snprintf(nspath, ONTAP_NS_PATHLEN, "%s%s%s%s", ontap_vol, + vol_name, "/", ns_name); +} + static void netapp_smdevice_json(struct json_array *devices, char *devname, char *arrayname, char *volname, int nsid, char *nguid, char *ctrl, char *astate, char *size, long long lba, @@ -99,6 +219,25 @@ static void netapp_smdevice_json(struct json_array *devices, char *devname, json_array_add_value_object(devices, device_attrs); } +static void netapp_ontapdevice_json(struct json_array *devices, char *devname, + char *vsname, char *nspath, int nsid, char *uuid, + char *size, long long lba, long long nsze) +{ + struct json_object *device_attrs; + + device_attrs = json_create_object(); + json_object_add_value_string(device_attrs, "Device", devname); + json_object_add_value_string(device_attrs, "Vserver", vsname); + json_object_add_value_string(device_attrs, "Namespace_Path", nspath); + json_object_add_value_int(device_attrs, "NSID", nsid); + json_object_add_value_string(device_attrs, "UUID", uuid); + json_object_add_value_string(device_attrs, "Size", size); + json_object_add_value_int(device_attrs, "LBA_Data_Size", lba); + json_object_add_value_int(device_attrs, "Namespace_Size", nsze); + + json_array_add_value_object(devices, device_attrs); +} + static void netapp_smdevices_print(struct smdevice_info *devices, int count, int format) { struct json_object *root = NULL; @@ -161,6 +300,94 @@ static void netapp_smdevices_print(struct smdevice_info *devices, int count, int } } +static void netapp_ontapdevices_print(struct ontapdevice_info *devices, + int count, int format) +{ + struct json_object *root = NULL; + struct json_array *json_devices = NULL; + char vsname[ONTAP_LABEL_LEN] = " "; + char nspath[ONTAP_NS_PATHLEN] = " "; + long long lba; + char size[128]; + char uuid_str[37] = " "; + int i; + + char basestr[] = "%s, Vserver %s, Namespace Path %s, NSID %d, UUID %s, %s\n"; + char columnstr[] = "%-16s %-25s %-50s %-4d %-38s %-9s\n"; + + /* default to 'normal' output format */ + char *formatstr = basestr; + + if (format == NCOLUMN) { + /* change output string and print column headers */ + formatstr = columnstr; + printf("%-16s %-25s %-50s %-4s %-38s %-9s\n", + "Device", "Vserver", "Namespace Path", + "NSID", "UUID", "Size"); + printf("%-16s %-25s %-50s %-4s %-38s %-9s\n", + "----------------", "-------------------------", + "--------------------------------------------------", + "----", "--------------------------------------", + "---------"); + } else if (format == NJSON) { + /* prepare for json output */ + root = json_create_object(); + json_devices = json_create_array(); + } + + for (i = 0; i < count; i++) { + + netapp_get_ns_size(size, &lba, &devices[i].ns); + netapp_uuid_to_str(uuid_str, devices[i].nsdesc); + netapp_get_ontap_labels(vsname, nspath, devices[i].log_data); + + if (format == NJSON) { + netapp_ontapdevice_json(json_devices, devices[i].dev, + vsname, nspath, devices[i].nsid, + uuid_str, size, lba, + le64_to_cpu(devices[i].ns.nsze)); + } else + printf(formatstr, devices[i].dev, vsname, nspath, + devices[i].nsid, uuid_str, size); + } + + if (format == NJSON) { + /* complete the json output */ + json_object_add_value_array(root, "ONTAPdevices", json_devices); + json_print_object(root, NULL); + } +} + +static int nvme_get_ontap_c2_log(int fd, __u32 nsid, void *buf, __u32 buflen) +{ + struct nvme_admin_cmd get_log; + int err; + + memset(buf, 0, buflen); + memset(&get_log, 0, sizeof(struct nvme_admin_cmd)); + + get_log.opcode = nvme_admin_get_log_page; + get_log.nsid = nsid; + get_log.addr = (__u64)(uintptr_t)buf; + get_log.data_len = buflen; + + __u32 numd = (get_log.data_len >> 2) - 1; + __u32 numdu = numd >> 16; + __u32 numdl = numd & 0xFFFF; + + get_log.cdw10 = ONTAP_C2_LOG_ID | (numdl << 16); + get_log.cdw10 |= ONTAP_C2_LOG_NSINFO_LSP << 8; + get_log.cdw11 = numdu; + + err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &get_log); + if (err) { + fprintf(stderr, "ioctl error %0x\n", err); + return 1; + } + + return 0; +} + static int netapp_smdevices_get_info(int fd, struct smdevice_info *item, const char *dev) { @@ -188,6 +415,50 @@ static int netapp_smdevices_get_info(int fd, struct smdevice_info *item, return 1; } +static int netapp_ontapdevices_get_info(int fd, struct ontapdevice_info *item, + const char *dev) +{ + int err; + + err = nvme_identify_ctrl(fd, &item->ctrl); + if (err) { + fprintf(stderr, "Identify Controller failed to %s (%s)\n", + dev, strerror(err)); + return 0; + } + + if (strncmp("NetApp ONTAP Controller", item->ctrl.mn, 23) != 0) + /* not the right controller model */ + return 0; + + item->nsid = nvme_get_nsid(fd); + + err = nvme_identify_ns(fd, item->nsid, 0, &item->ns); + if (err) { + fprintf(stderr, "Unable to identify namespace for %s (%s)\n", + dev, strerror(err)); + return 0; + } + + err = nvme_identify_ns_descs(fd, item->nsid, item->nsdesc); + if (err) { + fprintf(stderr, "Unable to identify namespace descriptor for %s (%s)\n", + dev, strerror(err)); + return 0; + } + + err = nvme_get_ontap_c2_log(fd, item->nsid, item->log_data, ONTAP_C2_LOG_SIZE); + if (err) { + fprintf(stderr, "Unable to get log page data for %s (%s)\n", + dev, strerror(err)); + return 0; + } + + strncpy(item->dev, dev, sizeof(item->dev)); + + return 1; +} + static int netapp_nvme_filter(const struct dirent *d) { char path[264]; @@ -294,3 +565,74 @@ static int netapp_smdevices(int argc, char **argv, struct command *command, free(smdevices); return 0; } + +/* handler for 'nvme netapp ontapdevices' */ +static int netapp_ontapdevices(int argc, char **argv, struct command *command, + struct plugin *plugin) +{ + const char *desc = "Display information about ONTAP devices."; + struct config { + char *output_format; + }; + struct config cfg = { + .output_format = "normal", + }; + struct dirent **devices; + int num, i, fd, ret, fmt; + struct ontapdevice_info *ontapdevices; + char path[264]; + int num_ontapdevices = 0; + + const struct argconfig_commandline_options opts[] = { + {"output-format", 'o', "FMT", CFG_STRING, &cfg.output_format, + required_argument, "Output Format: normal|json|column"}, + {NULL} + }; + + ret = argconfig_parse(argc, argv, desc, opts, &cfg, sizeof(cfg)); + if (ret < 0) + return ret; + + fmt = netapp_output_format(cfg.output_format); + if (fmt != NNORMAL && fmt != NCOLUMN && fmt != NJSON) { + fprintf(stderr, "Unrecognized output format: %s\n", cfg.output_format); + return -EINVAL; + } + + num = scandir(dev_path, &devices, netapp_nvme_filter, alphasort); + if (num <= 0) { + fprintf(stderr, "No NVMe devices detected.\n"); + return num; + } + + ontapdevices = calloc(num, sizeof(*ontapdevices)); + if (!ontapdevices) { + fprintf(stderr, "Unable to allocate memory for devices.\n"); + return -ENOMEM; + } + + for (i = 0; i < num; i++) { + snprintf(path, sizeof(path), "%s%s", dev_path, + devices[i]->d_name); + fd = open(path, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Unable to open %s: %s\n", path, + strerror(errno)); + continue; + } + + num_ontapdevices += netapp_ontapdevices_get_info(fd, + &ontapdevices[num_ontapdevices], path); + + close(fd); + } + + if (num_ontapdevices) + netapp_ontapdevices_print(ontapdevices, num_ontapdevices, fmt); + + for (i = 0; i < num; i++) + free(devices[i]); + free(devices); + free(ontapdevices); + return 0; +} diff --git a/plugins/netapp/netapp-nvme.h b/plugins/netapp/netapp-nvme.h index 3dd019e..d4eebd6 100644 --- a/plugins/netapp/netapp-nvme.h +++ b/plugins/netapp/netapp-nvme.h @@ -9,6 +9,7 @@ PLUGIN(NAME("netapp", "NetApp vendor specific extensions"), COMMAND_LIST( ENTRY("smdevices", "NetApp SMdevices", netapp_smdevices) + ENTRY("ontapdevices", "NetApp ONTAPdevices", netapp_ontapdevices) ) ); -- 2.16.4 ++++++ 0012-nvme-cli-add-netapp-ontapdevices-man-page.patch ++++++ ++++ 960 lines (skipped) ++++++ 0013-nvme-cli-Revert-stop-on-failure-with-connect-all.patch ++++++ >From 4a6c247971ce8e7a4af7f976be8906c907ef13cf Mon Sep 17 00:00:00 2001 From: James Smart <jsmart2...@gmail.com> Date: Tue, 9 Apr 2019 13:51:54 -0700 Subject: [PATCH] nvme-cli: Revert stop-on-failure with connect-all The patch that added special treatment for EALREADY connect failures also changed the behavior on what happens if a discovery log contains an entry that is not connectable by the system or host port. If it encounters a log entry that can't be connected to, it will not attempt to connect to any log entries beyond it. This can leave lots of devices unconnected to. Revert the stop-on-failure introduced by the previous patch. Specifically, this failed for me on an FC array that had a discovery log entry for a port that was not visible via zoning for the initiator port being used. Fixes: 1a922e0e121d7 ("connect-all: special treatment to EALREADY afetr write to /dev/nvme-fabrics" Signed-off-by: James Smart <jsmart2...@gmail.com> CC: Eyal Ben David <eya...@il.ibm.com> CC: Martin George <martin.geo...@netapp.com> --- fabrics.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fabrics.c b/fabrics.c index 2b08be5..aad399d 100644 --- a/fabrics.c +++ b/fabrics.c @@ -817,9 +817,12 @@ static int connect_ctrls(struct nvmf_disc_rsp_page_hdr *log, int numrec) continue; } - /* otherwise error */ - ret = -instance; - break; + /* + * don't error out. The Discovery Log may contain + * devices that aren't necessarily connectable via + * the system/host transport port. Let those items + * fail and continue on to the next log element. + */ } return ret; -- 2.16.4 ++++++ 0104-nvme-cli-Fix-documentation-syntax-and-typo.patch ++++++ >From 711762f31494772a0e7f08499e1b2992836e66e5 Mon Sep 17 00:00:00 2001 From: Simon Schricker <sschric...@suse.de> Date: Thu, 11 Apr 2019 10:52:14 +0200 Subject: [PATCH] nvme-cli: Fix documentation syntax and typo Both changes are already upstream or sent upstream. Commit of Keith Busch: 5a7ccf9d Co-authored-by: Keith Busch <keith.bu...@intel.com> Signed-off-by: Simon Schricker <sschric...@suse.de> --- Documentation/nvme-netapp-ontapdevices.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/nvme-netapp-ontapdevices.txt b/Documentation/nvme-netapp-ontapdevices.txt index 09369f1..c292758 100644 --- a/Documentation/nvme-netapp-ontapdevices.txt +++ b/Documentation/nvme-netapp-ontapdevices.txt @@ -1,5 +1,5 @@ nvme-netapp-ontapdevices(1) -======================== +=========================== NAME ---- @@ -13,7 +13,7 @@ SYNOPSIS DESCRIPTION ----------- Display information about ONTAP devices on the host. The ONTAP devices are -are identified using the Identify Controller data. +identified using the Identify Controller data. OPTIONS ------- -- 2.16.4