When libvirt starts up all storage pools default to the inactive
state, even if the underlying storage is already active on the
host. This introduces a new API into the internal storage backend
drivers that checks whether a storage pool is already active. If
the pool is active at libvirtd startup, the volume list will be
immediately populated.
* src/storage/storage_backend.h: New internal API for checking
storage pool state
* src/storage/storage_driver.c: Check whether a pool is active
upon driver startup
* src/storage/storage_backend_fs.c, src/storage/storage_backend_iscsi.c,
src/storage/storage_backend_logical.c, src/storage/storage_backend_mpath.c,
src/storage/storage_backend_scsi.c: Add checks for pool state
---
src/storage/storage_backend.h | 3 ++
src/storage/storage_backend_fs.c | 29 +++++++++++++++++++++++++++-
src/storage/storage_backend_iscsi.c | 34 +++++++++++++++++++++++++++++++++
src/storage/storage_backend_logical.c | 24 +++++++++++++++++++++++
src/storage/storage_backend_mpath.c | 20 +++++++++++++++++++
src/storage/storage_backend_scsi.c | 25 ++++++++++++++++++++++++
src/storage/storage_driver.c | 31 ++++++++++++++++++++++-------
7 files changed, 157 insertions(+), 9 deletions(-)
diff --git a/src/storage/storage_backend.h b/src/storage/storage_backend.h
index 1165a45..6f395c7 100644
--- a/src/storage/storage_backend.h
+++ b/src/storage/storage_backend.h
@@ -25,10 +25,12 @@
# define __VIR_STORAGE_BACKEND_H__
# include <stdint.h>
+# include <stdbool.h>
# include "internal.h"
# include "storage_conf.h"
typedef char * (*virStorageBackendFindPoolSources)(virConnectPtr conn, const char
*srcSpec, unsigned int flags);
+typedef int (*virStorageBackendCheckPool)(virConnectPtr conn, virStoragePoolObjPtr pool,
bool *active);
typedef int (*virStorageBackendStartPool)(virConnectPtr conn, virStoragePoolObjPtr
pool);
typedef int (*virStorageBackendBuildPool)(virConnectPtr conn, virStoragePoolObjPtr pool,
unsigned int flags);
typedef int (*virStorageBackendRefreshPool)(virConnectPtr conn, virStoragePoolObjPtr
pool);
@@ -65,6 +67,7 @@ struct _virStorageBackend {
int type;
virStorageBackendFindPoolSources findPoolSources;
+ virStorageBackendCheckPool checkPool;
virStorageBackendStartPool startPool;
virStorageBackendBuildPool buildPool;
virStorageBackendRefreshPool refreshPool;
diff --git a/src/storage/storage_backend_fs.c b/src/storage/storage_backend_fs.c
index c2bc6c4..8cdf7c0 100644
--- a/src/storage/storage_backend_fs.c
+++ b/src/storage/storage_backend_fs.c
@@ -479,6 +479,31 @@ virStorageBackendFileSystemUnmount(virStoragePoolObjPtr pool) {
#endif /* WITH_STORAGE_FS */
+static int
+virStorageBackendFileSystemCheck(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ bool *isActive)
+{
+ *isActive = false;
+ if (pool->def->type == VIR_STORAGE_POOL_DIR) {
+ struct stat sb;
+ if (stat(pool->def->target.path, &sb) == 0)
+ *isActive = true;
+#if WITH_STORAGE_FS
+ } else {
+ int ret;
+ if ((ret = virStorageBackendFileSystemIsMounted(pool)) != 0) {
+ if (ret < 0)
+ return -1;
+ *isActive = true;
+ }
+#endif /* WITH_STORAGE_FS */
+ }
+
+ return 0;
+}
+
+#if WITH_STORAGE_FS
/**
* @conn connection to report errors against
* @pool storage pool to start
@@ -489,7 +514,6 @@ virStorageBackendFileSystemUnmount(virStoragePoolObjPtr pool) {
*
* Returns 0 on success, -1 on error
*/
-#if WITH_STORAGE_FS
static int
virStorageBackendFileSystemStart(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool)
@@ -937,6 +961,7 @@ virStorageBackend virStorageBackendDirectory = {
.type = VIR_STORAGE_POOL_DIR,
.buildPool = virStorageBackendFileSystemBuild,
+ .checkPool = virStorageBackendFileSystemCheck,
.refreshPool = virStorageBackendFileSystemRefresh,
.deletePool = virStorageBackendFileSystemDelete,
.buildVol = virStorageBackendFileSystemVolBuild,
@@ -951,6 +976,7 @@ virStorageBackend virStorageBackendFileSystem = {
.type = VIR_STORAGE_POOL_FS,
.buildPool = virStorageBackendFileSystemBuild,
+ .checkPool = virStorageBackendFileSystemCheck,
.startPool = virStorageBackendFileSystemStart,
.refreshPool = virStorageBackendFileSystemRefresh,
.stopPool = virStorageBackendFileSystemStop,
@@ -965,6 +991,7 @@ virStorageBackend virStorageBackendNetFileSystem = {
.type = VIR_STORAGE_POOL_NETFS,
.buildPool = virStorageBackendFileSystemBuild,
+ .checkPool = virStorageBackendFileSystemCheck,
.startPool = virStorageBackendFileSystemStart,
.findPoolSources = virStorageBackendFileSystemNetFindPoolSources,
.refreshPool = virStorageBackendFileSystemRefresh,
diff --git a/src/storage/storage_backend_iscsi.c b/src/storage/storage_backend_iscsi.c
index a67a428..2dcf714 100644
--- a/src/storage/storage_backend_iscsi.c
+++ b/src/storage/storage_backend_iscsi.c
@@ -639,6 +639,39 @@ cleanup:
}
static int
+virStorageBackendISCSICheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ bool *isActive)
+{
+ char *session = NULL;
+ int ret = -1;
+
+ *isActive = false;
+
+ if (pool->def->source.host.name == NULL) {
+ virStorageReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing source host"));
+ return -1;
+ }
+
+ if (pool->def->source.ndevice != 1 ||
+ pool->def->source.devices[0].path == NULL) {
+ virStorageReportError(VIR_ERR_INTERNAL_ERROR,
+ "%s", _("missing source device"));
+ return -1;
+ }
+
+ if ((session = virStorageBackendISCSISession(pool, 1)) != NULL) {
+ *isActive = true;
+ VIR_FREE(session);
+ }
+ ret = 0;
+
+ return ret;
+}
+
+
+static int
virStorageBackendISCSIStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool)
{
@@ -735,6 +768,7 @@ cleanup:
virStorageBackend virStorageBackendISCSI = {
.type = VIR_STORAGE_POOL_ISCSI,
+ .checkPool = virStorageBackendISCSICheckPool,
.startPool = virStorageBackendISCSIStartPool,
.refreshPool = virStorageBackendISCSIRefreshPool,
.stopPool = virStorageBackendISCSIStopPool,
diff --git a/src/storage/storage_backend_logical.c
b/src/storage/storage_backend_logical.c
index e6c6938..c5bfda1 100644
--- a/src/storage/storage_backend_logical.c
+++ b/src/storage/storage_backend_logical.c
@@ -24,6 +24,7 @@
#include <config.h>
#include <sys/wait.h>
+#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <regex.h>
@@ -361,6 +362,28 @@ virStorageBackendLogicalFindPoolSources(virConnectPtr conn
ATTRIBUTE_UNUSED,
static int
+virStorageBackendLogicalCheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ bool *isActive)
+{
+ char *path;
+
+ *isActive = false;
+ if (virAsprintf(&path, "/dev/%s", pool->def->source.name) < 0)
{
+ virReportOOMError();
+ return -1;
+ }
+
+ struct stat sb;
+ if (stat(path, &sb) == 0)
+ *isActive = true;
+
+ VIR_FREE(path);
+
+ return 0;
+}
+
+static int
virStorageBackendLogicalStartPool(virConnectPtr conn ATTRIBUTE_UNUSED,
virStoragePoolObjPtr pool)
{
@@ -684,6 +707,7 @@ virStorageBackend virStorageBackendLogical = {
.type = VIR_STORAGE_POOL_LOGICAL,
.findPoolSources = virStorageBackendLogicalFindPoolSources,
+ .checkPool = virStorageBackendLogicalCheckPool,
.startPool = virStorageBackendLogicalStartPool,
.buildPool = virStorageBackendLogicalBuildPool,
.refreshPool = virStorageBackendLogicalRefreshPool,
diff --git a/src/storage/storage_backend_mpath.c b/src/storage/storage_backend_mpath.c
index 79ad4b8..d55a1c4 100644
--- a/src/storage/storage_backend_mpath.c
+++ b/src/storage/storage_backend_mpath.c
@@ -27,6 +27,8 @@
#include <stdio.h>
#include <dirent.h>
#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#include <libdevmapper.h>
@@ -291,6 +293,23 @@ out:
return retval;
}
+static int
+virStorageBackendMpathCheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool ATTRIBUTE_UNUSED,
+ bool *isActive)
+{
+ const char *path = "/dev/mpath";
+
+ *isActive = false;
+
+ struct stat sb;
+ if (stat(path, &sb) == 0)
+ *isActive = true;
+
+ return 0;
+}
+
+
static int
virStorageBackendMpathRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
@@ -313,5 +332,6 @@ virStorageBackendMpathRefreshPool(virConnectPtr conn
ATTRIBUTE_UNUSED,
virStorageBackend virStorageBackendMpath = {
.type = VIR_STORAGE_POOL_MPATH,
+ .checkPool = virStorageBackendMpathCheckPool,
.refreshPool = virStorageBackendMpathRefreshPool,
};
diff --git a/src/storage/storage_backend_scsi.c b/src/storage/storage_backend_scsi.c
index 28d6ac6..0d6b1ac 100644
--- a/src/storage/storage_backend_scsi.c
+++ b/src/storage/storage_backend_scsi.c
@@ -27,6 +27,9 @@
#include <stdio.h>
#include <dirent.h>
#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
#include "virterror_internal.h"
#include "storage_backend_scsi.h"
@@ -587,6 +590,27 @@ out:
return retval;
}
+static int
+virStorageBackendSCSICheckPool(virConnectPtr conn ATTRIBUTE_UNUSED,
+ virStoragePoolObjPtr pool,
+ bool *isActive)
+{
+ char *path;
+
+ *isActive = false;
+ if (virAsprintf(&path, "/sys/class/scsi_host/%s",
pool->def->source.adapter) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ struct stat sb;
+ if (stat(path, &sb) == 0)
+ *isActive = true;
+
+ VIR_FREE(path);
+
+ return 0;
+}
static int
virStorageBackendSCSIRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
@@ -621,5 +645,6 @@ out:
virStorageBackend virStorageBackendSCSI = {
.type = VIR_STORAGE_POOL_SCSI,
+ .checkPool = virStorageBackendSCSICheckPool,
.refreshPool = virStorageBackendSCSIRefreshPool,
};
diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
index f6672d9..9912429 100644
--- a/src/storage/storage_driver.c
+++ b/src/storage/storage_driver.c
@@ -68,17 +68,29 @@ storageDriverAutostart(virStorageDriverStatePtr driver) {
for (i = 0 ; i < driver->pools.count ; i++) {
virStoragePoolObjPtr pool = driver->pools.objs[i];
+ virStorageBackendPtr backend;
+ bool started = false;
virStoragePoolObjLock(pool);
- if (pool->autostart &&
- !virStoragePoolObjIsActive(pool)) {
- virStorageBackendPtr backend;
- if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
- VIR_ERROR(_("Missing backend %d"), pool->def->type);
- virStoragePoolObjUnlock(pool);
- continue;
- }
+ if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
+ VIR_ERROR(_("Missing backend %d"), pool->def->type);
+ virStoragePoolObjUnlock(pool);
+ continue;
+ }
+ if (backend->checkPool &&
+ backend->checkPool(NULL, pool, &started) < 0) {
+ virErrorPtr err = virGetLastError();
+ VIR_ERROR(_("Failed to initialize storage pool '%s': %s"),
+ pool->def->name, err ? err->message :
+ "no error message found");
+ virStoragePoolObjUnlock(pool);
+ continue;
+ }
+
+ if (!started &&
+ pool->autostart &&
+ !virStoragePoolObjIsActive(pool)) {
if (backend->startPool &&
backend->startPool(NULL, pool) < 0) {
virErrorPtr err = virGetLastError();
@@ -88,7 +100,10 @@ storageDriverAutostart(virStorageDriverStatePtr driver) {
virStoragePoolObjUnlock(pool);
continue;
}
+ started = true;
+ }
+ if (started) {
if (backend->refreshPool(NULL, pool) < 0) {
virErrorPtr err = virGetLastError();
if (backend->stopPool)
--
1.7.2.3