[libvirt] [PATCH 08/11] Check whether pools are already active upon libvirtd startup

Daniel P. Berrange berrange at redhat.com
Fri Nov 12 16:22:41 UTC 2010


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




More information about the libvir-list mailing list