[libvirt] [RFC PATCH] Prevent defining a domain has disk used by other domain

Osier Yang jyang at redhat.com
Fri Sep 23 07:59:04 UTC 2011


$subject + "If the disk is shared and readonly."

If the disk is not shared or readonly, the later started domain
will relabel the disk, thus the first domain will lose the permission
to write to the disk and be corrupt.

--
I'm not sure if it's the design to allow multiple domains use
same disk not shared and readonly. So this patch just gives a
demo of the implementation (it skips the checking of nbd disk,
and only changes qemu driver), to see whether if the pricinple
is right or not.
---
 src/conf/domain_conf.c   |   34 ++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h   |    2 ++
 src/libvirt_private.syms |    1 +
 src/qemu/qemu_driver.c   |   24 ++++++++++++++++++++++++
 4 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 7463d7c..b64450b 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -655,6 +655,40 @@ virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms,
     return obj;
 }
 
+static int
+virDomainObjListSearchDiskPath(const void *payload,
+                               const void *name ATTRIBUTE_UNUSED,
+                               const void *data)
+{
+    virDomainObjPtr obj = (virDomainObjPtr)payload;
+    int i;
+    int want = 0;
+    const char *path = NULL;
+
+    path = (const char *)data;
+
+    virDomainObjLock(obj);
+    for (i = 0; obj->def->ndisks; i++) {
+        if (STREQ(obj->def->disks[i]->src, path)) {
+            want = 1;
+            break;
+        }
+    }
+    virDomainObjUnlock(obj);
+
+    return want;
+}
+
+virDomainObjPtr
+virDomainFindByDiskPath(const virDomainObjListPtr doms,
+                        const char *path)
+{
+    virDomainObjPtr obj = NULL;
+    obj = virHashSearch(doms->objs, virDomainObjListSearchDiskPath, path);
+    if (obj)
+        virDomainObjLock(obj);
+    return obj;
+}
 
 bool virDomainObjTaint(virDomainObjPtr obj,
                        enum virDomainTaintFlags taint)
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 371f270..d7d42dd 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1549,6 +1549,8 @@ virDomainObjPtr virDomainFindByUUID(const virDomainObjListPtr doms,
                                     const unsigned char *uuid);
 virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms,
                                     const char *name);
+virDomainObjPtr virDomainFindByDiskPath(const virDomainObjListPtr doms,
+                                        const char *path);
 
 bool virDomainObjTaint(virDomainObjPtr obj,
                        enum virDomainTaintFlags taint);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 8235ea1..c33cb2d 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -302,6 +302,7 @@ virDomainFSTypeToString;
 virDomainFindByID;
 virDomainFindByName;
 virDomainFindByUUID;
+virDomainFindByDiskPath;
 virDomainGetRootFilesystem;
 virDomainGraphicsAuthConnectedTypeFromString;
 virDomainGraphicsAuthConnectedTypeToString;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0d0bea2..a448a0b 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -4796,6 +4796,7 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
     virDomainPtr dom = NULL;
     virDomainEventPtr event = NULL;
     int dupVM;
+    int i;
 
     qemuDriverLock(driver);
     if (!(def = virDomainDefParseString(driver->caps, xml,
@@ -4809,6 +4810,29 @@ static virDomainPtr qemudDomainDefine(virConnectPtr conn, const char *xml) {
     if ((dupVM = virDomainObjIsDuplicate(&driver->domains, def, 0)) < 0)
         goto cleanup;
 
+    /* Make sure no disk is used by other domain, if it's not
+     * either shareable or readonly.
+     */
+    for (i = 0; i < def->ndisks; i++) {
+        /* XXX: Do we also need to check if same host&port is used by
+         * other domain for disk of nbd type?
+         */
+        if (def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_NETWORK &&
+            def->disks[i]->protocol == VIR_DOMAIN_DISK_PROTOCOL_NBD)
+            continue;
+
+        if (!def->disks[i]->shared &&
+            !def->disks[i]->readonly &&
+            (vm = virDomainFindByDiskPath(&driver->domains,
+                                          def->disks[i]->src))) {
+            qemuReportError(VIR_ERR_INVALID_ARG,
+                            _("disk '%s' already used by domain '%s'"),
+                            def->disks[i]->src,
+                            vm->def->name);
+            goto cleanup;
+        }
+    }
+
     if (qemudCanonicalizeMachine(driver, def) < 0)
         goto cleanup;
 
-- 
1.7.6




More information about the libvir-list mailing list