This prevents restoring the unpriv_sgio if the disk is shared,
and is being used by other active domain. Because we don't want
to fall into the corruption situation.
* src/conf/domain_conf.h (Declare virDomainDiskIsUsed, which is to
detect if a disk is using by domain)
* src/conf/domain_conf.c (Implement virDomainDiskIsUsed)
* src/libvirt_private.syms: (Export virDomainDIskIsUsed)
* src/qemu/qemu_process.c (Don't restore unpriv_sgio if the disk
is shared, and is being used by other
active domain).
---
src/conf/domain_conf.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 4 +++
src/libvirt_private.syms | 1 +
src/qemu/qemu_process.c | 11 +++++++
4 files changed, 82 insertions(+), 0 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b25229a..02df96e 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -15697,3 +15697,69 @@ virDomainDefAddSecurityLabelDef(virDomainDefPtr def, const char
*model)
return seclabel;
}
+
+struct virDomainDiskIsUsedData {
+ char *diskSrc;
+ char *name; /* Want to exclude some domain? */
+ bool active; /* Want to only iterate the active domains? */
+};
+
+static int
+virDomainObjListSearchDiskPath(const void *payload,
+ const void *name ATTRIBUTE_UNUSED,
+ const void *opaque)
+{
+ virDomainObjPtr obj = (virDomainObjPtr)payload;
+ const struct virDomainDiskIsUsedData *data = opaque;
+ int i;
+ int ret = 0;
+
+ virDomainObjLock(obj);
+
+ if (data->active &&
+ !virDomainObjIsActive(obj))
+ goto cleanup;
+
+ if (data->name &&
+ STREQ(data->name, obj->def->name))
+ goto cleanup;
+
+ for (i = 0; i < obj->def->ndisks; i++) {
+ virDomainDiskDefPtr disk = obj->def->disks[i];
+
+ if (STREQ(disk->src, data->diskSrc)) {
+ ret = 1;
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ virDomainObjUnlock(obj);
+ return ret;
+}
+
+/**
+ * virDomainDiskIsUsed:
+ * @doms: List of domain objects
+ * @name: The domain name want to exclude
+ * @diskSrc: The disk path
+ * @active: Whether to exclude inactive domains
+ *
+ * Returns true if the disk is being used. Otherwise returns false.
+ */
+bool
+virDomainDiskIsUsed(const virDomainObjList doms,
+ char *name,
+ char *diskSrc,
+ bool active)
+{
+ virDomainObjPtr obj;
+
+ struct virDomainDiskIsUsedData data = { diskSrc, name, active };
+
+ obj = virHashSearch(doms.objs, virDomainObjListSearchDiskPath, &data);
+ if (obj)
+ return true;
+
+ return false;
+}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 1a8de71..3105e05 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1874,6 +1874,10 @@ virDomainObjPtr virDomainFindByUUID(const virDomainObjListPtr
doms,
const unsigned char *uuid);
virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms,
const char *name);
+bool virDomainDiskIsUsed(const virDomainObjList doms,
+ char *name,
+ char *diskSrc,
+ bool active);
bool virDomainObjTaint(virDomainObjPtr obj,
enum virDomainTaintFlags taint);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index c756130..b9019b7 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -319,6 +319,7 @@ virDomainDefFormatInternal;
virDomainDefFree;
virDomainDefGetSecurityLabelDef;
virDomainDiskDefGetSecurityLabelDef;
+virDomainDiskIsUsed;
virDomainDefAddSecurityLabelDef;
virDomainDefParseFile;
virDomainDefParseNode;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index e48eed0..eeaaea0 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -4120,6 +4120,17 @@ void qemuProcessStop(struct qemud_driver *driver,
if (!disk->unpriv_sgio)
continue;
+ /* Don't try to restore the unpriv_sgio if the disk is shared
+ * by other active domain(s). We don't want to fall into the
+ * corruptions.
+ */
+ if (disk->shared &&
+ virDomainDiskIsUsed(driver->domains,
+ vm->def->name,
+ disk->src,
+ true))
+ continue;
+
if (virSetDeviceUnprivSGIO(disk->src, disk->old_unpriv_sgio) < 0)
VIR_WARN("Unable to restore unpriv_sgio for disk '%s'",
disk->src);
}
--
1.7.7.6