[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH 1/2]: Give /dev/disk/by-{id, path} a chance to exist



This patch is the same idea as my previous patch for giving
/dev/disk/by-{id,path} a chance to exist.  Currently libvirt can race with udev
creation of /dev/disk/by-{id,path}, so if we fail to open the directory, retry
up to 5 seconds.  This is only likely to happen on hosts that are:

1) diskless (so /dev/disk/by-{id,path} doesn't exist already), and
2) slow, and/or heavily loaded (meaning that udev can take some time to create
the /dev nodes).

Based on the feedback from Dan and Jim, I updated the patch to look more like
what is elsewhere in libvirt.

Signed-off-by: Chris Lalancette <clalance redhat com>
Index: src/storage_backend.c
===================================================================
RCS file: /data/cvs/libvirt/src/storage_backend.c,v
retrieving revision 1.29
diff -u -r1.29 storage_backend.c
--- a/src/storage_backend.c	17 Nov 2008 11:19:33 -0000	1.29
+++ b/src/storage_backend.c	26 Nov 2008 12:09:36 -0000
@@ -291,6 +291,7 @@
     DIR *dh;
     struct dirent *dent;
     char *stablepath;
+    int opentries = 0;
 
     /* Short circuit if pool has no target, or if its /dev */
     if (pool->def->target.path == NULL ||
@@ -304,12 +305,17 @@
     if (!STRPREFIX(pool->def->target.path, "/dev"))
         goto ret_strdup;
 
-    /* The pool is pointing somewhere like /dev/disk/by-path
-     * or /dev/disk/by-id, so we need to check all symlinks in
-     * the target directory and figure out which one points
-     * to this device node
+    /* We loop here because /dev/disk/by-{id,path} may not have existed
+     * before we started this operation, so we have to give it some time to
+     * get created.
      */
+ reopen:
     if ((dh = opendir(pool->def->target.path)) == NULL) {
+        opentries++;
+        if (errno == ENOENT && opentries < 50) {
+            usleep(100 * 1000);
+            goto reopen;
+        }
         virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
                               _("cannot read dir %s: %s"),
                               pool->def->target.path,
@@ -317,6 +323,11 @@
         return NULL;
     }
 
+    /* The pool is pointing somewhere like /dev/disk/by-path
+     * or /dev/disk/by-id, so we need to check all symlinks in
+     * the target directory and figure out which one points
+     * to this device node
+     */
     while ((dent = readdir(dh)) != NULL) {
         if (dent->d_name[0] == '.')
             continue;

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]