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(a)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;