From d20d6b1bb05f131c3f4285940caef66ed35e821f Mon Sep 17 00:00:00 2001 From: Chris Lalancette Date: Fri, 28 Nov 2008 07:42:21 +0000 Subject: [PATCH] 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). Signed-off-by: Chris Lalancette --- ChangeLog | 4 ++++ src/storage_backend.c | 19 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index ab1593e2b3..20d0a379d6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +Fri Nov 28 08:40:00 CET 2008 Chris Lalancette + * src/storage_backend.c: Wait up to 5 seconds for + /dev/disk/by-{id,path} to exist in virStorageBackendStablePath + Thu Nov 27 17:15:10 CET 2008 Daniel Veillard * src/xen_unified.c: use preferably xend method to update diff --git a/src/storage_backend.c b/src/storage_backend.c index c4396e120a..9266e5cdc6 100644 --- a/src/storage_backend.c +++ b/src/storage_backend.c @@ -291,6 +291,7 @@ virStorageBackendStablePath(virConnectPtr conn, 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 @@ virStorageBackendStablePath(virConnectPtr conn, 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 @@ virStorageBackendStablePath(virConnectPtr conn, 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;