From 3005cacb690e7dcefd2c4977550e74634ba58e3b Mon Sep 17 00:00:00 2001 From: Michal Privoznik Date: Fri, 12 Aug 2011 15:29:37 +0200 Subject: [PATCH] qemu: Introduce job queue size limit This patch creates an optional BeginJob queue size limit. When active, all other attempts above level will fail. To set this feature assign desired value to max_queued variable in qemu.conf. Setting it to 0 turns it off. --- src/qemu/libvirtd_qemu.aug | 1 + src/qemu/qemu.conf | 7 +++++++ src/qemu/qemu_conf.c | 4 ++++ src/qemu/qemu_conf.h | 2 ++ src/qemu/qemu_domain.c | 17 +++++++++++++++++ src/qemu/qemu_domain.h | 2 ++ 6 files changed, 33 insertions(+) diff --git a/src/qemu/libvirtd_qemu.aug b/src/qemu/libvirtd_qemu.aug index d018ac259d..6c145c7d82 100644 --- a/src/qemu/libvirtd_qemu.aug +++ b/src/qemu/libvirtd_qemu.aug @@ -51,6 +51,7 @@ module Libvirtd_qemu = | bool_entry "set_process_name" | int_entry "max_processes" | str_entry "lock_manager" + | int_entry "max_queued" (* Each enty in the config is one of the following three ... *) let entry = vnc_entry diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf index 79c6e8510b..4da5d5a13f 100644 --- a/src/qemu/qemu.conf +++ b/src/qemu/qemu.conf @@ -309,3 +309,10 @@ # disk), uncomment this # # lock_manager = "sanlock" + +# Set limit of maximum APIs queued on one domain. All other APIs +# over this threshold will fail on acquiring job lock. Specially, +# setting to zero turns this feature off. +# Note, that job lock is per domain. +# +# max_queued = 0 diff --git a/src/qemu/qemu_conf.c b/src/qemu/qemu_conf.c index 443e08d7bb..d1bf075659 100644 --- a/src/qemu/qemu_conf.c +++ b/src/qemu/qemu_conf.c @@ -458,6 +458,10 @@ int qemudLoadDriverConfig(struct qemud_driver *driver, VIR_FREE(lockConf); } + p = virConfGetValue(conf, "max_queued"); + CHECK_TYPE("max_queued", VIR_CONF_LONG); + if (p) driver->max_queued = p->l; + virConfFree (conf); return 0; } diff --git a/src/qemu/qemu_conf.h b/src/qemu/qemu_conf.h index 5469a63abe..e8b92a4982 100644 --- a/src/qemu/qemu_conf.h +++ b/src/qemu/qemu_conf.h @@ -109,6 +109,8 @@ struct qemud_driver { int maxProcesses; + int max_queued; + virCapsPtr caps; virDomainEventStatePtr domainEventState; diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 675c6dff9b..982bad6c7e 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -713,6 +713,8 @@ qemuDomainObjBeginJobInternal(struct qemud_driver *driver, unsigned long long then; bool nested = job == QEMU_JOB_ASYNC_NESTED; + priv->jobs_queued++; + if (virTimeMs(&now) < 0) return -1; then = now + QEMU_JOB_WAIT_TIME; @@ -722,6 +724,11 @@ qemuDomainObjBeginJobInternal(struct qemud_driver *driver, qemuDriverUnlock(driver); retry: + if (driver->max_queued && + priv->jobs_queued > driver->max_queued) { + goto error; + } + while (!nested && !qemuDomainJobAllowed(priv, job)) { if (virCondWaitUntil(&priv->job.asyncCond, &obj->lock, then) < 0) goto error; @@ -761,9 +768,15 @@ error: if (errno == ETIMEDOUT) qemuReportError(VIR_ERR_OPERATION_TIMEOUT, "%s", _("cannot acquire state change lock")); + else if (driver->max_queued && + priv->jobs_queued > driver->max_queued) + qemuReportError(VIR_ERR_OPERATION_FAILED, + "%s", _("cannot acquire state change lock " + "due to max_queued limit")); else virReportSystemError(errno, "%s", _("cannot acquire job mutex")); + priv->jobs_queued--; if (driver_locked) { virDomainObjUnlock(obj); qemuDriverLock(driver); @@ -844,6 +857,8 @@ int qemuDomainObjEndJob(struct qemud_driver *driver, virDomainObjPtr obj) { qemuDomainObjPrivatePtr priv = obj->privateData; + priv->jobs_queued--; + qemuDomainObjResetJob(priv); qemuDomainObjSaveJob(driver, obj); virCondSignal(&priv->job.cond); @@ -856,6 +871,8 @@ qemuDomainObjEndAsyncJob(struct qemud_driver *driver, virDomainObjPtr obj) { qemuDomainObjPrivatePtr priv = obj->privateData; + priv->jobs_queued--; + qemuDomainObjResetAsyncJob(priv); qemuDomainObjSaveJob(driver, obj); virCondBroadcast(&priv->job.asyncCond); diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index e12ca8e8f6..55875fe4de 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -113,6 +113,8 @@ struct _qemuDomainObjPrivate { char *lockState; bool fakeReboot; + + int jobs_queued; }; struct qemuDomainWatchdogEvent