]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme: fail on busy namespace
authorOlaf Schmerse <olaf.schmerse@ionos.com>
Mon, 18 Oct 2021 13:42:29 +0000 (15:42 +0200)
committerOlaf Schmerse <olaf.schmerse@ionos.com>
Mon, 18 Oct 2021 16:02:44 +0000 (18:02 +0200)
To avoid formarting a busy namespace accidently a new function called
open_exclusive() is implemented. Instead of opening it always it opens
the device file in exclusive mode (O_EXCL). If this fails with the error EBUSY an error
messages hints to the --force command line option. By calling nvme format with the --force option it
will continue formating the namespace.

This patch fixes issue: #1095
Signed-off-by: Olaf Schmerse <olaf.schmerse@ionos.com>
nvme.c

diff --git a/nvme.c b/nvme.c
index 25420775cafcba77e48f03b133d5dd5c2e3bae3c..d654493df0fb957458738c6c436fd06ebea4ce07 100644 (file)
--- a/nvme.c
+++ b/nvme.c
@@ -149,12 +149,12 @@ static bool is_blkdev(void)
        return S_ISBLK(nvme_stat.st_mode);
 }
 
-static int open_dev(char *dev)
+static int open_dev(char *dev, int flags)
 {
        int err, fd;
 
        devicename = basename(dev);
-       err = open(dev, O_RDONLY);
+       err = open(dev, flags);
        if (err < 0)
                goto perror;
        fd = err;
@@ -185,7 +185,7 @@ static int check_arg_dev(int argc, char **argv)
        return 0;
 }
 
-static int get_dev(int argc, char **argv)
+static int get_dev(int argc, char **argv, int flags)
 {
        int ret;
 
@@ -193,7 +193,7 @@ static int get_dev(int argc, char **argv)
        if (ret)
                return ret;
 
-       return open_dev(argv[optind]);
+       return open_dev(argv[optind], flags);
 }
 
 int parse_and_open(int argc, char **argv, const char *desc,
@@ -205,13 +205,23 @@ int parse_and_open(int argc, char **argv, const char *desc,
        if (ret)
                return ret;
 
-       ret = get_dev(argc, argv);
+       ret = get_dev(argc, argv, O_RDONLY);
        if (ret < 0)
                argconfig_print_help(desc, opts);
 
        return ret;
 }
 
+int open_exclusive(int argc, char **argv, int force)
+{
+    int flags = O_RDONLY;
+
+       if (!force)
+               flags |= O_EXCL;
+
+    return get_dev(argc, argv, flags);
+}
+
 enum nvme_print_flags validate_output_format(const char *format)
 {
        if (!format)
@@ -3498,6 +3508,24 @@ static int format(int argc, char **argv, struct command *cmd, struct plugin *plu
                OPT_END()
        };
 
+       err = argconfig_parse(argc, argv, desc, opts);
+       if (err)
+               goto ret;
+
+       err = fd = open_exclusive(argc, argv, cfg.force);
+       if (fd < 0) {
+               if (errno == EBUSY) {
+                       fprintf(stderr, "Failed to open %s.\n",
+                basename(argv[optind]));
+                       fprintf(stderr,
+                               "Namespace is currently busy.\n"
+                               "Use the force [--force|-f] option to ignore that.\n");
+               } else {
+                       argconfig_print_help(desc, opts);
+               }
+               goto ret;
+       }
+
        err = fd = parse_and_open(argc, argv, desc, opts);
        if (fd < 0)
                goto ret;