[systemd-devel] 60-persistent-storage.rules: add NVMe disks and partitions (again)

Per Bergqvist per at bst.lu
Sat May 16 01:18:47 PDT 2015


Lennart,

Thank you for all the comments. 

I have changed everything except the 'No space between function name and opening “(“‘.
Cannot find anything about that in CODING_STYLE or evidence in other sources.
Kept the call to nvme_identify more or less as before, please let me know if it has to be changed.

Please find the new patch below.

BR
Per

From 6cf318688baead0b4a737cf2c2d7618b6a131954 Mon Sep 17 00:00:00 2001
From: Per Bergqvist <per at bst.lu>
Date: Sat, 16 May 2015 11:01:17 +0200
Subject: [PATCH] nvme_id following CODING_STYLE

---
 Makefile.am                       |  11 +++
 rules/60-persistent-storage.rules |   5 ++
 src/udev/nvme_id/nvme_id.c        | 149 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 165 insertions(+)
 create mode 100644 src/udev/nvme_id/nvme_id.c

diff --git a/Makefile.am b/Makefile.am
index bf04d31..0de0d18 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3904,6 +3904,17 @@ dist_udevrules_DATA += \
 	rules/60-persistent-v4l.rules
 
 # ------------------------------------------------------------------------------
+nvme_id_SOURCES = \
+	src/udev/nvme_id/nvme_id.c
+
+nvme_id_LDADD = \
+	libudev-internal.la \
+	libsystemd-shared.la
+
+udevlibexec_PROGRAMS += \
+	nvme_id
+
+# ------------------------------------------------------------------------------
 accelerometer_SOURCES = \
 	src/udev/accelerometer/accelerometer.c
 
diff --git a/rules/60-persistent-storage.rules b/rules/60-persistent-storage.rules
index 25b44a5..d3368a5 100644
--- a/rules/60-persistent-storage.rules
+++ b/rules/60-persistent-storage.rules
@@ -42,6 +42,11 @@ KERNEL=="cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}!="?*", IMPORT{program}="s
 KERNEL=="sd*|sr*|cciss*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}"
 KERNEL=="sd*|cciss*", ENV{DEVTYPE}=="partition", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/$env{ID_BUS}-$env{ID_SERIAL}-part%n"
 
+# NVMe
+KERNEL=="nvme*", ENV{ID_SERIAL}!="?*", IMPORT{program}="nvme_id --export $devnode"
+KERNEL=="nvme*", ENV{DEVTYPE}=="disk", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}"
+KERNEL=="nvme*", ENV{DEVTYPE}=="partition", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/nvme-$env{ID_SERIAL}-part%n"
+
 # firewire
 KERNEL=="sd*[!0-9]|sr*", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394-$attr{ieee1394_id}"
 KERNEL=="sd*[0-9]", ATTRS{ieee1394_id}=="?*", SYMLINK+="disk/by-id/ieee1394-$attr{ieee1394_id}-part%n"
diff --git a/src/udev/nvme_id/nvme_id.c b/src/udev/nvme_id/nvme_id.c
new file mode 100644
index 0000000..8941977
--- /dev/null
+++ b/src/udev/nvme_id/nvme_id.c
@@ -0,0 +1,149 @@
+/* -*- mode:c; tab-width:8; intent-tabs-mode:nil;  -*-
+ *
+ * nvme_id - reads model/serial/firmware revision numbers from nvme drives
+ *
+ * Copyright (C) 2015 Per Bergqvist <per at bst.lu>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <linux/nvme.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "libudev.h"
+#include "libudev-private.h"
+#include "udev-util.h"
+#include "log.h"
+
+static int nvme_identify(struct udev *udev, int fd, void *buf, __u32 buf_len) {
+        struct nvme_admin_cmd command = {
+                .opcode   = nvme_admin_identify,
+                .addr     = (unsigned long)buf,
+                .data_len = buf_len,
+                .cdw10    = 1 };
+
+        if (ioctl(fd, NVME_IOCTL_ADMIN_CMD, &command) < 0)
+                return -errno;
+
+        return 0;
+}
+
+int main(int argc, char *argv[]) {
+        _cleanup_udev_unref_ struct udev *udev = NULL;
+
+        struct nvme_id_ctrl nvme_id_ctrl = { .vid = 0 };
+
+        char model[sizeof(nvme_id_ctrl.mn)+1];
+        char model_enc[4*sizeof(nvme_id_ctrl.mn)+1];
+        char serial[sizeof(nvme_id_ctrl.sn)+1];
+        char revision[sizeof(nvme_id_ctrl.fr)+1];
+
+        const char *node = NULL;
+        int export = 0;
+
+        _cleanup_close_ int fd = -1;
+
+        static const struct option options[] = {
+                { "export", no_argument, NULL, 'x' },
+                { "help", no_argument, NULL, 'h' },
+                {}
+        };
+
+        log_parse_environment();
+        log_open();
+
+        udev = udev_new();
+        if (udev == NULL)
+                return EXIT_SUCCESS;
+
+        while (1) {
+                int option;
+
+                option = getopt_long(argc, argv, "xh", options, NULL);
+                if (option == -1)
+                        break;
+
+                switch (option) {
+                case 'x':
+                        export = 1;
+                        break;
+                case 'h':
+                        printf("Usage: nvme_id [--export] [--help] <device>\n"
+                               "  -x,--export    print values as environment keys\n"
+                               "  -h,--help      print this help text\n\n");
+                        return EXIT_SUCCESS;
+                }
+        }
+
+        node = argv[optind];
+        if (node == NULL) {
+                log_error("no node specified");
+                return EXIT_FAILURE;
+        }
+
+        fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC);
+        if (fd < 0) {
+                log_error_errno(errno, "Unable to open '%s': %m", node);
+                return -errno;
+        }
+
+        if (nvme_identify(udev, fd, &nvme_id_ctrl, sizeof(struct nvme_id_ctrl)) == 0) {
+                memcpy (model, nvme_id_ctrl.mn, sizeof(nvme_id_ctrl.mn));
+                model[sizeof(nvme_id_ctrl.mn)] = '\0';
+                strstrip(model);
+                udev_util_encode_string(model, model_enc, sizeof(model_enc));
+                util_replace_whitespace((char *) nvme_id_ctrl.mn, model, sizeof(nvme_id_ctrl.mn));
+                util_replace_chars(model, NULL);
+                util_replace_whitespace((char *) nvme_id_ctrl.sn, serial, sizeof(nvme_id_ctrl.sn));
+                util_replace_chars(serial, NULL);
+                util_replace_whitespace((char *) nvme_id_ctrl.fr, revision, sizeof(nvme_id_ctrl.fr));
+                util_replace_chars(revision, NULL);
+        } else {
+                log_debug_errno(errno, "nvme_identify failed for '%s': %m", node);
+                return EXIT_FAILURE;
+        }
+
+
+        if (export) {
+                printf("ID_TYPE=nvme\n");
+                printf("ID_MODEL=%s\n", model);
+                printf("ID_MODEL_ENC=%s\n", model_enc);
+                printf("ID_REVISION=%s\n", revision);
+                if (serial[0] != '\0') {
+                        printf("ID_SERIAL=%s_%s\n", model, serial);
+                        printf("ID_SERIAL_SHORT=%s\n", serial);
+                } else {
+                        printf("ID_SERIAL=%s\n", model);
+                }
+
+        } else {
+                if (serial[0] != '\0')
+                        printf("%s_%s\n", model, serial);
+                else
+                        printf("%s\n", model);
+        }
+
+        return EXIT_SUCCESS;
+}
-- 
2.4.0


On 15 May 2015, at 21:15 , Lennart Poettering <lennart at poettering.net> wrote:

> On Fri, 15.05.15 20:53, Per Bergqvist (per at bst.lu) wrote:
> 
>> Hej,
>> 
>> Please (finally) find a patched for v219 to add a nvme_id utility
>> and add support for NVMe disks in 60-persistent-storage.rules.
> 
> I figure Kay and Tom have to decide if this goes in, but here's a
> quick code review, in case they are in favour:
> 
>> +static int nvme_identify(struct udev *udev,
>> +                         int fd,
>> +                         void *ptr)
>> +{
> 
> Please see CODING_STYLE. We tend to place the opening bracket on the
> same line as the function name. (yes some older code in the systemd
> tree does not follow this rule, but please try to follow this for new
> code).
> 
>> +	struct nvme_admin_cmd command;
>> +	memset(&command, 0, sizeof(command));
> 
> See CODING_STYLE, we tend to prefer initializing structures on the
> stack via structure initializers, so that we don't need explicit
> memset(). i.e.
> 
> struct nvme_admin_cmd command = {
>        .opcode = ...,
> }
> 
>> +	
>> +	command.opcode = nvme_admin_identify;
>> +	command.nsid = 0;
>> +	command.addr = (unsigned long)ptr;
>> +	command.data_len = sizeof(struct nvme_id_ctrl);
>> +        command.cdw10 = 1;
> 
> Indenting is weird. Please strictly use 8ch space indenting.
> 
>> +        return ioctl(fd, NVME_IOCTL_ADMIN_CMD, &command);
>> +}
> 
> We generally try to follow the rule to return kernel-style negative
> errno error codes from the functions we define, even if the underlying
> syscalls don't. Hence, please rewrite this as:
> 
>        if (ioctl(...) < 0)
>                return -errno;
> 
>        return 0;
> 
>> +
>> +int main(int argc, char *argv[])
>> +{
> 
> The opening bracket on the same line as the function name please.
> 
>> +        _cleanup_udev_unref_ struct udev *udev = NULL;
>> +
>> +	struct nvme_id_ctrl nvme_ctrl;
>> +	
>> +        char model[41];
>> +        char model_enc[256];
>> +        char serial[21];
>> +        char revision[9];
> 
> Weird indenting...
> 
>> +
>> +        while (1) {
>> +                int option;
>> +
>> +                option = getopt_long(argc, argv, "xh", options, NULL);
>> +                if (option == -1)
>> +                        break;
>> +
>> +                switch (option) {
>> +                case 'x':
>> +                        export = 1;
>> +                        break;
>> +                case 'h':
>> +                        printf("Usage: nvme_id [--export] [--help] <device>\n"
>> +                               "  -x,--export    print values as environment keys\n"
>> +                               "  -h,--help      print this help text\n\n");
>> +                        return 0;
>> +                }
>> +        }
>> +
>> +        node = argv[optind];
>> +        if (node == NULL) {
>> +                log_error("no node specified");
>> +                return 1;
> 
> Please use libc's EXIT_FAILURE define here.
> 
>> +        }
>> +
>> +        fd = open(node, O_RDONLY|O_NONBLOCK|O_CLOEXEC);
>> +        if (fd < 0) {
>> +                log_error("unable to open '%s'", node);
>> +                return 1;
>> +        }
> 
> Similar here.
> 
> Also, please use use this log_error_errno() syntax if there's an errno
> to report:
> 
> log_error_errno(errno, "Unable to open '%s': %m", node);
> 
> 
>> +
>> +	memset(&nvme_ctrl, 0, sizeof(struct nvme_id_ctrl));
> 
> Please initialize at time of declaration.
> 
>> +	
>> +        if (nvme_identify(udev, fd, &nvme_ctrl) == 0) {
>> +	       int i;
>> +	       memcpy (model, nvme_ctrl.mn, 40);
> 
> No space between function name and opening "(", please, see CODING_STYLE.
> 
>> +	       for(i=39;i>=0;i--) if (model[i]== ' ') model[i] = '\0';
>> else break;
> 
> Please use strstrip() for this.
> 
>> +	       model[40] = '\0';
>> +	       udev_util_encode_string(model, model_enc, sizeof(model_enc));
>> +	       util_replace_whitespace((char *) nvme_ctrl.mn, model,
>> 40);
> 
> Hmm, use "sizeof(model)" instead of "40"?
> 
>> +        if (export) {
>> +                printf("ID_TYPE=nvme\n");
>> +                printf("ID_MODEL=%s\n", model);
>> +                printf("ID_MODEL_ENC=%s\n", model_enc);
>> +                printf("ID_REVISION=%s\n", revision);
>> +                if (serial[0] != '\0') {
>> +                        printf("ID_SERIAL=%s_%s\n", model, serial);
>> +                        printf("ID_SERIAL_SHORT=%s\n", serial);
>> +                } else {
>> +                        printf("ID_SERIAL=%s\n", model);
>> +                }
>> +
>> +        } else {
>> +                if (serial[0] != '\0')
>> +                        printf("%s_%s\n", model, serial);
>> +                else
>> +                        printf("%s\n", model);
>> +        }
>> +
>> +        return 0;
> 
> Use EXIT_SUCCESS here...
> 
> Lennart
> 
> -- 
> Lennart Poettering, Red Hat





-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/systemd-devel/attachments/20150516/eb43b6f2/attachment-0001.html>


More information about the systemd-devel mailing list