Instead of relying solely on polling for /dev devices to appear in libvirt, we
really should be synchronizing against udev. This is generally done by a call to udevsettle, which is exactly what this patch implements for the storage backends that are likely to create new /dev nodes. I believe I've read that even after udevsettle, you are not guaranteed that devices are all the way created, so we still need the polling in the rest of the sources, but this should give us a much better chance of things existing as we expect. Signed-off-by: Chris Lalancette <clalance@redhat.com>
This commit is contained in:
parent
d20d6b1bb0
commit
a9567e09ef
@ -115,11 +115,17 @@ AC_PATH_PROG([DNSMASQ], [dnsmasq], [dnsmasq],
|
|||||||
[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
|
[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
|
||||||
AC_PATH_PROG([BRCTL], [brctl], [brctl],
|
AC_PATH_PROG([BRCTL], [brctl], [brctl],
|
||||||
[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
|
[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
|
||||||
|
AC_PATH_PROG([UDEVADM], [udevadm], [],
|
||||||
|
[/sbin:/usr/sbin:/usr/local/sbin:$PATH])
|
||||||
|
|
||||||
AC_DEFINE_UNQUOTED([DNSMASQ],["$DNSMASQ"],
|
AC_DEFINE_UNQUOTED([DNSMASQ],["$DNSMASQ"],
|
||||||
[Location or name of the dnsmasq program])
|
[Location or name of the dnsmasq program])
|
||||||
AC_DEFINE_UNQUOTED([BRCTL],["$BRCTL"],
|
AC_DEFINE_UNQUOTED([BRCTL],["$BRCTL"],
|
||||||
[Location or name of the brctl program (see bridge-utils)])
|
[Location or name of the brctl program (see bridge-utils)])
|
||||||
|
if test -n "$UDEVADM"; then
|
||||||
|
AC_DEFINE_UNQUOTED([UDEVADM],["$UDEVADM"],
|
||||||
|
[Location or name of the udevadm program])
|
||||||
|
fi
|
||||||
|
|
||||||
dnl Specific dir for HTML output ?
|
dnl Specific dir for HTML output ?
|
||||||
AC_ARG_WITH([html-dir], [AC_HELP_STRING([--with-html-dir=path],
|
AC_ARG_WITH([html-dir], [AC_HELP_STRING([--with-html-dir=path],
|
||||||
|
@ -270,6 +270,27 @@ virStorageBackendUpdateVolInfoFD(virConnectPtr conn,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef UDEVADM
|
||||||
|
void virStorageBackendWaitForDevices(virConnectPtr conn)
|
||||||
|
{
|
||||||
|
const char *const settleprog[] = { UDEVADM, "settle", NULL };
|
||||||
|
int exitstatus;
|
||||||
|
|
||||||
|
if (access(UDEVADM, X_OK) != 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NOTE: we ignore errors here; this is just to make sure that any device
|
||||||
|
* nodes that are being created finish before we try to scan them.
|
||||||
|
* If this fails for any reason, we still have the backup of polling for
|
||||||
|
* 5 seconds for device nodes.
|
||||||
|
*/
|
||||||
|
virRun(conn, settleprog, &exitstatus);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
void virStorageBackendWaitForDevices(virConnectPtr conn ATTRIBUTE_UNUSED) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Given a volume path directly in /dev/XXX, iterate over the
|
* Given a volume path directly in /dev/XXX, iterate over the
|
||||||
* entries in the directory pool->def->target.path and find the
|
* entries in the directory pool->def->target.path and find the
|
||||||
|
@ -69,6 +69,8 @@ int virStorageBackendUpdateVolInfoFD(virConnectPtr conn,
|
|||||||
int fd,
|
int fd,
|
||||||
int withCapacity);
|
int withCapacity);
|
||||||
|
|
||||||
|
void virStorageBackendWaitForDevices(virConnectPtr conn);
|
||||||
|
|
||||||
char *virStorageBackendStablePath(virConnectPtr conn,
|
char *virStorageBackendStablePath(virConnectPtr conn,
|
||||||
virStoragePoolObjPtr pool,
|
virStoragePoolObjPtr pool,
|
||||||
const char *devpath);
|
const char *devpath);
|
||||||
|
@ -262,6 +262,8 @@ virStorageBackendDiskRefreshPool(virConnectPtr conn,
|
|||||||
VIR_FREE(pool->def->source.devices[0].freeExtents);
|
VIR_FREE(pool->def->source.devices[0].freeExtents);
|
||||||
pool->def->source.devices[0].nfreeExtent = 0;
|
pool->def->source.devices[0].nfreeExtent = 0;
|
||||||
|
|
||||||
|
virStorageBackendWaitForDevices(conn);
|
||||||
|
|
||||||
return virStorageBackendDiskReadPartitions(conn, pool, NULL);
|
return virStorageBackendDiskReadPartitions(conn, pool, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,6 +603,8 @@ virStorageBackendISCSIRefreshPool(virConnectPtr conn,
|
|||||||
|
|
||||||
pool->def->allocation = pool->def->capacity = pool->def->available = 0;
|
pool->def->allocation = pool->def->capacity = pool->def->available = 0;
|
||||||
|
|
||||||
|
virStorageBackendWaitForDevices(conn);
|
||||||
|
|
||||||
if ((session = virStorageBackendISCSISession(conn, pool)) == NULL)
|
if ((session = virStorageBackendISCSISession(conn, pool)) == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
if (virStorageBackendISCSIRescanLUNs(conn, pool, session) < 0)
|
if (virStorageBackendISCSIRescanLUNs(conn, pool, session) < 0)
|
||||||
|
@ -470,6 +470,8 @@ virStorageBackendLogicalRefreshPool(virConnectPtr conn,
|
|||||||
};
|
};
|
||||||
int exitstatus;
|
int exitstatus;
|
||||||
|
|
||||||
|
virStorageBackendWaitForDevices(conn);
|
||||||
|
|
||||||
/* Get list of all logical volumes */
|
/* Get list of all logical volumes */
|
||||||
if (virStorageBackendLogicalFindLVs(conn, pool, NULL) < 0) {
|
if (virStorageBackendLogicalFindLVs(conn, pool, NULL) < 0) {
|
||||||
virStoragePoolObjClearVols(pool);
|
virStoragePoolObjClearVols(pool);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user