]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
nvme-cli: Wait for device file if not present after successful add_ctrl
authorJames Smart <jsmart2021@gmail.com>
Fri, 27 Apr 2018 17:29:39 +0000 (10:29 -0700)
committerKeith Busch <keith.busch@intel.com>
Fri, 27 Apr 2018 21:45:01 +0000 (15:45 -0600)
It's possible for the transport to return very quickly after add_ctrl
such that the cli may attempt to access the /dev/nvme? device file
before the udev event has propagated to user space to create the device
file. In these cases, the open fails with EAGAIN.

As the add_ctrl call was successful, thus there "should" be a device
file, if the open fails with EAGAIN delay 500ms and try again. Wait
for at most 2 seconds for the device file to come into existence.

Signed-off-by: James Smart <james.smart@broadcom.com>
Signed-off-by: Keith Busch <keith.busch@intel.com>
fabrics.c

index 7e9d56c61c45626ceee6dee35ac070c25422cd79..408afb0d453b5761c511e6cee0428e6a21aa8f74 100644 (file)
--- a/fabrics.c
+++ b/fabrics.c
@@ -171,6 +171,32 @@ static const char *cms_str(__u8 cm)
 
 static int do_discover(char *argstr, bool connect);
 
+#define OPEN_RETRIES   4
+#define OPEN_DELAY     500000          /* us units, thus 1/2 second */
+
+static void
+wait_for_devname(int instance)
+{
+       char *dev_name;
+       int retry = 0, fd;
+
+       if (asprintf(&dev_name, "/dev/nvme%d", instance) < 0)
+               return;
+
+       /* takes a little time for udev to make the dev node */
+       for ( ; retry < OPEN_RETRIES; retry++) {
+               fd = open(dev_name, O_RDWR);
+               if (fd >= 0) {
+                       close(fd);
+                       break;
+               }
+               if (errno != EAGAIN)
+                       break;
+               usleep(OPEN_DELAY);
+       }
+       free(dev_name);
+}
+
 static int add_ctrl(const char *argstr)
 {
        substring_t args[MAX_OPT_ARGS];
@@ -225,6 +251,8 @@ out_fail:
 out_close:
        close(fd);
 out:
+       if (ret >= 0)
+               wait_for_devname(ret);
        return ret;
 }