[libvirt] [PATCH 1/8] Fix up the locking in the snapshot code.
Daniel Veillard
veillard at redhat.com
Tue Apr 27 12:26:18 UTC 2010
On Fri, Apr 23, 2010 at 01:27:45PM -0400, Chris Lalancette wrote:
> In particular I was forgetting to take the qemuMonitorPrivatePtr
> lock (via qemuDomainObjBeginJob), which would cause problems
> if two users tried to access the same domain at the same time.
> This patch also fixes a problem where I was forgetting to remove
> a transient domain from the list of domains.
>
> Thanks to Stephen Shaw for pointing out the problem and testing
> out the initial patch.
>
> Signed-off-by: Chris Lalancette <clalance at redhat.com>
> ---
> src/qemu/qemu_driver.c | 45 +++++++++++++++++++++++++++++++--------------
> 1 files changed, 31 insertions(+), 14 deletions(-)
>
> diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
> index 1ef15dd..2f889d9 100644
> --- a/src/qemu/qemu_driver.c
> +++ b/src/qemu/qemu_driver.c
> @@ -10690,7 +10690,6 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain,
> virDomainSnapshotPtr snapshot = NULL;
> char uuidstr[VIR_UUID_STRING_BUFLEN];
> virDomainSnapshotDefPtr def;
> - qemuDomainObjPrivatePtr priv;
> const char *qemuimgarg[] = { NULL, "snapshot", "-c", NULL, NULL, NULL };
> int i;
>
> @@ -10757,14 +10756,19 @@ static virDomainSnapshotPtr qemuDomainSnapshotCreateXML(virDomainPtr domain,
> }
> }
> else {
> + qemuDomainObjPrivatePtr priv;
> + int ret;
> +
> + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
> + goto cleanup;
> priv = vm->privateData;
> qemuDomainObjEnterMonitorWithDriver(driver, vm);
> - if (qemuMonitorCreateSnapshot(priv->mon, def->name) < 0) {
> - qemuDomainObjExitMonitorWithDriver(driver, vm);
> - goto cleanup;
> - }
> + ret = qemuMonitorCreateSnapshot(priv->mon, def->name);
> qemuDomainObjExitMonitorWithDriver(driver, vm);
> -
> + if (qemuDomainObjEndJob(vm) == 0)
> + vm = NULL;
> + if (ret < 0)
> + goto cleanup;
> }
>
> snap->def->state = vm->state;
> @@ -11037,18 +11041,18 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
> rc = qemuMonitorLoadSnapshot(priv->mon, snap->def->name);
> qemuDomainObjExitMonitorWithDriver(driver, vm);
> if (rc < 0)
> - goto cleanup;
> + goto endjob;
> }
> else {
> if (qemuDomainSnapshotSetActive(vm, driver->snapshotDir) < 0)
> - goto cleanup;
> + goto endjob;
>
> rc = qemudStartVMDaemon(snapshot->domain->conn, driver, vm, NULL,
> -1);
> if (qemuDomainSnapshotSetInactive(vm, driver->snapshotDir) < 0)
> - goto cleanup;
> + goto endjob;
> if (rc < 0)
> - goto cleanup;
> + goto endjob;
> }
>
> if (snap->def->state == VIR_DOMAIN_PAUSED) {
> @@ -11060,7 +11064,7 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
> rc = qemuMonitorStopCPUs(priv->mon);
> qemuDomainObjExitMonitorWithDriver(driver, vm);
> if (rc < 0)
> - goto cleanup;
> + goto endjob;
> }
>
> event = virDomainEventNewFromObj(vm,
> @@ -11083,20 +11087,26 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot,
> event = virDomainEventNewFromObj(vm,
> VIR_DOMAIN_EVENT_STOPPED,
> VIR_DOMAIN_EVENT_STOPPED_FROM_SNAPSHOT);
> + if (!vm->persistent) {
> + if (qemuDomainObjEndJob(vm) > 0)
> + virDomainRemoveInactive(&driver->domains, vm);
> + vm = NULL;
> + }
> }
>
> if (qemuDomainSnapshotSetActive(vm, driver->snapshotDir) < 0)
> - goto cleanup;
> + goto endjob;
> }
>
> vm->state = snap->def->state;
>
> ret = 0;
>
> -cleanup:
> +endjob:
> if (vm && qemuDomainObjEndJob(vm) == 0)
> vm = NULL;
>
> +cleanup:
> if (event)
> qemuDomainEventQueue(driver, event);
> if (vm)
> @@ -11250,6 +11260,9 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
> goto cleanup;
> }
>
> + if (qemuDomainObjBeginJobWithDriver(driver, vm) < 0)
> + goto cleanup;
> +
> if (flags & VIR_DOMAIN_SNAPSHOT_DELETE_CHILDREN) {
> rem.driver = driver;
> rem.vm = vm;
> @@ -11258,11 +11271,15 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot,
> virHashForEach(vm->snapshots.objs, qemuDomainSnapshotDiscardChildren,
> &rem);
> if (rem.err < 0)
> - goto cleanup;
> + goto endjob;
> }
>
> ret = qemuDomainSnapshotDiscard(driver, vm, snap);
>
> +endjob:
> + if (qemuDomainObjEndJob(vm) == 0)
> + vm = NULL;
> +
> cleanup:
> if (vm)
> virDomainObjUnlock(vm);
ACK, looks fine to me,
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel at veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
More information about the libvir-list
mailing list