[libvirt] [PATCH v2 6/7] domain_lock: Implement metadata locking

Michal Privoznik mprivozn at redhat.com
Tue Aug 14 11:19:42 UTC 2018


In order for our drivers to lock resources for metadata change we
need set of new APIs. Fortunately, we don't have to care about
every possible device a domain can have. We care only about those
which can live on a network filesystem and hence can be accessed
by multiple daemons at the same time. These devices are covered
in virDomainLockMetadataLock() and only a small fraction of
those can be hotplugged (covered in the rest of the introduced
APIs).

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/libvirt_private.syms  |   8 ++
 src/locking/domain_lock.c | 304 ++++++++++++++++++++++++++++++++++++++++++----
 src/locking/domain_lock.h |  28 +++++
 3 files changed, 317 insertions(+), 23 deletions(-)

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index ca4a192a4a..720ae12301 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1284,6 +1284,14 @@ virDomainLockImageAttach;
 virDomainLockImageDetach;
 virDomainLockLeaseAttach;
 virDomainLockLeaseDetach;
+virDomainLockMetadataDiskLock;
+virDomainLockMetadataDiskUnlock;
+virDomainLockMetadataImageLock;
+virDomainLockMetadataImageUnlock;
+virDomainLockMetadataLock;
+virDomainLockMetadataMemLock;
+virDomainLockMetadataMemUnlock;
+virDomainLockMetadataUnlock;
 virDomainLockProcessInquire;
 virDomainLockProcessPause;
 virDomainLockProcessResume;
diff --git a/src/locking/domain_lock.c b/src/locking/domain_lock.c
index 705b132457..19a097fb25 100644
--- a/src/locking/domain_lock.c
+++ b/src/locking/domain_lock.c
@@ -69,7 +69,8 @@ static int virDomainLockManagerAddLease(virLockManagerPtr lock,
 
 
 static int virDomainLockManagerAddImage(virLockManagerPtr lock,
-                                        virStorageSourcePtr src)
+                                        virStorageSourcePtr src,
+                                        bool metadataOnly)
 {
     unsigned int diskFlags = 0;
     int type = virStorageSourceGetActualType(src);
@@ -82,10 +83,14 @@ static int virDomainLockManagerAddImage(virLockManagerPtr lock,
           type == VIR_STORAGE_TYPE_DIR))
         return 0;
 
-    if (src->readonly)
-        diskFlags |= VIR_LOCK_MANAGER_RESOURCE_READONLY;
-    if (src->shared)
-        diskFlags |= VIR_LOCK_MANAGER_RESOURCE_SHARED;
+    if (metadataOnly) {
+        diskFlags = VIR_LOCK_MANAGER_RESOURCE_METADATA;
+    } else {
+        if (src->readonly)
+            diskFlags |= VIR_LOCK_MANAGER_RESOURCE_READONLY;
+        if (src->shared)
+            diskFlags |= VIR_LOCK_MANAGER_RESOURCE_SHARED;
+    }
 
     VIR_DEBUG("Add disk %s", src->path);
     if (virLockManagerAddResource(lock,
@@ -101,13 +106,68 @@ static int virDomainLockManagerAddImage(virLockManagerPtr lock,
 }
 
 
+static int
+virDomainLockManagerAddMemory(virLockManagerPtr lock,
+                              const virDomainMemoryDef *mem)
+{
+    const char *path = NULL;
+
+    switch ((virDomainMemoryModel) mem->model) {
+    case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
+        path = mem->nvdimmPath;
+        break;
+
+    case VIR_DOMAIN_MEMORY_MODEL_DIMM:
+    case VIR_DOMAIN_MEMORY_MODEL_LAST:
+    case VIR_DOMAIN_MEMORY_MODEL_NONE:
+        break;
+    }
+
+    if (!path)
+        return 0;
+
+    VIR_DEBUG("Adding memory %s", path);
+    if (virLockManagerAddResource(lock,
+                                  VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK,
+                                  path,
+                                  0,
+                                  NULL,
+                                  VIR_LOCK_MANAGER_RESOURCE_METADATA) < 0)
+        return -1;
+
+    return 0;
+}
+
+
+static int
+virDomainLockManagerAddFile(virLockManagerPtr lock,
+                            const char *file)
+{
+    if (!file)
+        return 0;
+
+    VIR_DEBUG("Adding file %s", file);
+    if (virLockManagerAddResource(lock,
+                                  VIR_LOCK_MANAGER_RESOURCE_TYPE_DISK,
+                                  file,
+                                  0,
+                                  NULL,
+                                  VIR_LOCK_MANAGER_RESOURCE_METADATA) < 0)
+        return -1;
+
+    return 0;
+}
+
+
 static virLockManagerPtr virDomainLockManagerNew(virLockManagerPluginPtr plugin,
                                                  const char *uri,
                                                  virDomainObjPtr dom,
                                                  bool withResources,
+                                                 bool metadataOnly,
                                                  unsigned int flags)
 {
     virLockManagerPtr lock;
+    const virDomainDef *def = dom->def;
     size_t i;
     virLockManagerParam params[] = {
         { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UUID,
@@ -115,11 +175,11 @@ static virLockManagerPtr virDomainLockManagerNew(virLockManagerPluginPtr plugin,
         },
         { .type = VIR_LOCK_MANAGER_PARAM_TYPE_STRING,
           .key = "name",
-          .value = { .str = dom->def->name },
+          .value = { .str = def->name },
         },
         { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UINT,
           .key = "id",
-          .value = { .iv = dom->def->id },
+          .value = { .iv = def->id },
         },
         { .type = VIR_LOCK_MANAGER_PARAM_TYPE_UINT,
           .key = "pid",
@@ -133,7 +193,7 @@ static virLockManagerPtr virDomainLockManagerNew(virLockManagerPluginPtr plugin,
     VIR_DEBUG("plugin=%p dom=%p withResources=%d",
               plugin, dom, withResources);
 
-    memcpy(params[0].value.uuid, dom->def->uuid, VIR_UUID_BUFLEN);
+    memcpy(params[0].value.uuid, def->uuid, VIR_UUID_BUFLEN);
 
     if (!(lock = virLockManagerNew(virLockManagerPluginGetDriver(plugin),
                                    VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN,
@@ -144,19 +204,46 @@ static virLockManagerPtr virDomainLockManagerNew(virLockManagerPluginPtr plugin,
 
     if (withResources) {
         VIR_DEBUG("Adding leases");
-        for (i = 0; i < dom->def->nleases; i++)
-            if (virDomainLockManagerAddLease(lock, dom->def->leases[i]) < 0)
+        for (i = 0; i < def->nleases; i++)
+            if (virDomainLockManagerAddLease(lock, def->leases[i]) < 0)
                 goto error;
+    }
 
+    if (withResources || metadataOnly) {
         VIR_DEBUG("Adding disks");
-        for (i = 0; i < dom->def->ndisks; i++) {
-            virDomainDiskDefPtr disk = dom->def->disks[i];
+        for (i = 0; i < def->ndisks; i++) {
+            virDomainDiskDefPtr disk = def->disks[i];
 
-            if (virDomainLockManagerAddImage(lock, disk->src) < 0)
+            if (virDomainLockManagerAddImage(lock, disk->src, metadataOnly) < 0)
                 goto error;
         }
     }
 
+    if (metadataOnly) {
+        for (i = 0; i < def->nmems; i++) {
+            virDomainMemoryDefPtr mem = def->mems[i];
+
+            if (virDomainLockManagerAddMemory(lock, mem) < 0)
+                goto error;
+        }
+
+        if (def->os.loader &&
+            virDomainLockManagerAddFile(lock, def->os.loader->nvram) < 0)
+            goto error;
+
+        if (virDomainLockManagerAddFile(lock, def->os.kernel) < 0)
+            goto error;
+
+        if (virDomainLockManagerAddFile(lock, def->os.initrd) < 0)
+            goto error;
+
+        if (virDomainLockManagerAddFile(lock, def->os.dtb) < 0)
+            goto error;
+
+        if (virDomainLockManagerAddFile(lock, def->os.slic_table) < 0)
+            goto error;
+    }
+
     return lock;
 
  error:
@@ -178,7 +265,7 @@ int virDomainLockProcessStart(virLockManagerPluginPtr plugin,
     VIR_DEBUG("plugin=%p dom=%p paused=%d fd=%p",
               plugin, dom, paused, fd);
 
-    if (!(lock = virDomainLockManagerNew(plugin, uri, dom, true,
+    if (!(lock = virDomainLockManagerNew(plugin, uri, dom, true, false,
                                          VIR_LOCK_MANAGER_NEW_STARTED)))
         return -1;
 
@@ -203,7 +290,7 @@ int virDomainLockProcessPause(virLockManagerPluginPtr plugin,
     VIR_DEBUG("plugin=%p dom=%p state=%p",
               plugin, dom, state);
 
-    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, true, 0)))
+    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, true, false, 0)))
         return -1;
 
     ret = virLockManagerRelease(lock, state, 0);
@@ -223,7 +310,7 @@ int virDomainLockProcessResume(virLockManagerPluginPtr plugin,
     VIR_DEBUG("plugin=%p dom=%p state=%s",
               plugin, dom, NULLSTR(state));
 
-    if (!(lock = virDomainLockManagerNew(plugin, uri, dom, true, 0)))
+    if (!(lock = virDomainLockManagerNew(plugin, uri, dom, true, false, 0)))
         return -1;
 
     ret = virLockManagerAcquire(lock, state, 0, dom->def->onLockFailure, NULL);
@@ -242,7 +329,7 @@ int virDomainLockProcessInquire(virLockManagerPluginPtr plugin,
     VIR_DEBUG("plugin=%p dom=%p state=%p",
               plugin, dom, state);
 
-    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, true, 0)))
+    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, true, false, 0)))
         return -1;
 
     ret = virLockManagerInquire(lock, state, 0);
@@ -262,10 +349,10 @@ int virDomainLockImageAttach(virLockManagerPluginPtr plugin,
 
     VIR_DEBUG("plugin=%p dom=%p src=%p", plugin, dom, src);
 
-    if (!(lock = virDomainLockManagerNew(plugin, uri, dom, false, 0)))
+    if (!(lock = virDomainLockManagerNew(plugin, uri, dom, false, false, 0)))
         return -1;
 
-    if (virDomainLockManagerAddImage(lock, src) < 0)
+    if (virDomainLockManagerAddImage(lock, src, false) < 0)
         goto cleanup;
 
     if (virLockManagerAcquire(lock, NULL, 0,
@@ -299,10 +386,10 @@ int virDomainLockImageDetach(virLockManagerPluginPtr plugin,
 
     VIR_DEBUG("plugin=%p dom=%p src=%p", plugin, dom, src);
 
-    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, false, 0)))
+    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, false, false, 0)))
         return -1;
 
-    if (virDomainLockManagerAddImage(lock, src) < 0)
+    if (virDomainLockManagerAddImage(lock, src, false) < 0)
         goto cleanup;
 
     if (virLockManagerRelease(lock, NULL, 0) < 0)
@@ -336,7 +423,7 @@ int virDomainLockLeaseAttach(virLockManagerPluginPtr plugin,
     VIR_DEBUG("plugin=%p dom=%p lease=%p",
               plugin, dom, lease);
 
-    if (!(lock = virDomainLockManagerNew(plugin, uri, dom, false, 0)))
+    if (!(lock = virDomainLockManagerNew(plugin, uri, dom, false, false, 0)))
         return -1;
 
     if (virDomainLockManagerAddLease(lock, lease) < 0)
@@ -364,7 +451,7 @@ int virDomainLockLeaseDetach(virLockManagerPluginPtr plugin,
     VIR_DEBUG("plugin=%p dom=%p lease=%p",
               plugin, dom, lease);
 
-    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, false, 0)))
+    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, false, false, 0)))
         return -1;
 
     if (virDomainLockManagerAddLease(lock, lease) < 0)
@@ -380,3 +467,174 @@ int virDomainLockLeaseDetach(virLockManagerPluginPtr plugin,
 
     return ret;
 }
+
+
+int
+virDomainLockMetadataLock(virLockManagerPluginPtr plugin,
+                          virDomainObjPtr dom)
+{
+    virLockManagerPtr lock;
+    const unsigned int flags = 0;
+    int ret = -1;
+
+    VIR_DEBUG("plugin=%p dom=%p", plugin, dom);
+
+    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, false, true, 0)))
+        return -1;
+
+    if (virLockManagerAcquire(lock, NULL, flags,
+                              VIR_DOMAIN_LOCK_FAILURE_DEFAULT, NULL) < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    virLockManagerFree(lock);
+    return ret;
+}
+
+
+int
+virDomainLockMetadataUnlock(virLockManagerPluginPtr plugin,
+                            virDomainObjPtr dom)
+{
+    virLockManagerPtr lock;
+    const unsigned int flags = 0;
+    int ret = -1;
+
+    VIR_DEBUG("plugin=%p dom=%p", plugin, dom);
+
+    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, false, true, 0)))
+        return -1;
+
+    if (virLockManagerRelease(lock, NULL, flags) < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    virLockManagerFree(lock);
+    return ret;
+}
+
+
+int
+virDomainLockMetadataImageLock(virLockManagerPluginPtr plugin,
+                               virDomainObjPtr dom,
+                               virStorageSourcePtr src)
+{
+    virLockManagerPtr lock;
+    int ret = -1;
+
+    VIR_DEBUG("plugin=%p dom=%p src=%p", plugin, dom, src);
+
+    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, false, false, 0)))
+        return -1;
+
+    if (virDomainLockManagerAddImage(lock, src, true) < 0)
+        goto cleanup;
+
+    if (virLockManagerAcquire(lock, NULL, 0,
+                              VIR_DOMAIN_LOCK_FAILURE_DEFAULT, NULL) < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    virLockManagerFree(lock);
+    return ret;
+}
+
+
+int
+virDomainLockMetadataImageUnlock(virLockManagerPluginPtr plugin,
+                                 virDomainObjPtr dom,
+                                 virStorageSourcePtr src)
+{
+    virLockManagerPtr lock;
+    int ret = -1;
+
+    VIR_DEBUG("plugin=%p dom=%p src=%p", plugin, dom, src);
+
+    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, false, false, 0)))
+        return -1;
+
+    if (virDomainLockManagerAddImage(lock, src, true) < 0)
+        goto cleanup;
+
+    if (virLockManagerRelease(lock, NULL, 0) < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    virLockManagerFree(lock);
+    return ret;
+}
+
+
+int
+virDomainLockMetadataDiskLock(virLockManagerPluginPtr plugin,
+                              virDomainObjPtr dom,
+                              virDomainDiskDefPtr disk)
+{
+    return virDomainLockMetadataImageLock(plugin, dom, disk->src);
+}
+
+
+int
+virDomainLockMetadataDiskUnlock(virLockManagerPluginPtr plugin,
+                                virDomainObjPtr dom,
+                                virDomainDiskDefPtr disk)
+{
+    return virDomainLockMetadataImageUnlock(plugin, dom, disk->src);
+}
+
+
+int
+virDomainLockMetadataMemLock(virLockManagerPluginPtr plugin,
+                             virDomainObjPtr dom,
+                             virDomainMemoryDefPtr mem)
+{
+    virLockManagerPtr lock;
+    int ret = -1;
+
+    VIR_DEBUG("plugin=%p dom=%p mem=%p", plugin, dom, mem);
+
+    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, false, false, 0)))
+        return -1;
+
+    if (virDomainLockManagerAddMemory(lock, mem) < 0)
+        goto cleanup;
+
+    if (virLockManagerAcquire(lock, NULL, 0,
+                              VIR_DOMAIN_LOCK_FAILURE_DEFAULT, NULL) < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    virLockManagerFree(lock);
+    return ret;
+}
+
+
+int
+virDomainLockMetadataMemUnlock(virLockManagerPluginPtr plugin,
+                               virDomainObjPtr dom,
+                               virDomainMemoryDefPtr mem)
+{
+    virLockManagerPtr lock;
+    int ret = -1;
+
+    VIR_DEBUG("plugin=%p dom=%p mem=%p", plugin, dom, mem);
+
+    if (!(lock = virDomainLockManagerNew(plugin, NULL, dom, false, false, 0)))
+        return -1;
+
+    if (virDomainLockManagerAddMemory(lock, mem) < 0)
+        goto cleanup;
+
+    if (virLockManagerRelease(lock, NULL, 0) < 0)
+        goto cleanup;
+
+    ret = 0;
+ cleanup:
+    virLockManagerFree(lock);
+    return ret;
+}
diff --git a/src/locking/domain_lock.h b/src/locking/domain_lock.h
index fb4910230c..fbd3ee1d4e 100644
--- a/src/locking/domain_lock.h
+++ b/src/locking/domain_lock.h
@@ -66,4 +66,32 @@ int virDomainLockLeaseDetach(virLockManagerPluginPtr plugin,
                              virDomainObjPtr dom,
                              virDomainLeaseDefPtr lease);
 
+int virDomainLockMetadataLock(virLockManagerPluginPtr plugin,
+                              virDomainObjPtr dom);
+
+int virDomainLockMetadataUnlock(virLockManagerPluginPtr plugin,
+                                virDomainObjPtr dom);
+
+int virDomainLockMetadataDiskLock(virLockManagerPluginPtr plugin,
+                                  virDomainObjPtr dom,
+                                  virDomainDiskDefPtr disk);
+int virDomainLockMetadataDiskUnlock(virLockManagerPluginPtr plugin,
+                                    virDomainObjPtr dom,
+                                    virDomainDiskDefPtr disk);
+
+int virDomainLockMetadataImageLock(virLockManagerPluginPtr plugin,
+                                   virDomainObjPtr dom,
+                                   virStorageSourcePtr src);
+
+int virDomainLockMetadataImageUnlock(virLockManagerPluginPtr plugin,
+                                     virDomainObjPtr dom,
+                                     virStorageSourcePtr src);
+
+int virDomainLockMetadataMemLock(virLockManagerPluginPtr plugin,
+                                 virDomainObjPtr dom,
+                                 virDomainMemoryDefPtr mem);
+int virDomainLockMetadataMemUnlock(virLockManagerPluginPtr plugin,
+                                   virDomainObjPtr dom,
+                                   virDomainMemoryDefPtr mem);
+
 #endif /* __VIR_DOMAIN_LOCK_H__ */
-- 
2.16.4




More information about the libvir-list mailing list