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.
This commit is contained in:
Michal Privoznik 2011-08-12 15:29:37 +02:00
parent 597fe3cee6
commit 3005cacb69
6 changed files with 33 additions and 0 deletions

View File

@ -51,6 +51,7 @@ module Libvirtd_qemu =
| bool_entry "set_process_name" | bool_entry "set_process_name"
| int_entry "max_processes" | int_entry "max_processes"
| str_entry "lock_manager" | str_entry "lock_manager"
| int_entry "max_queued"
(* Each enty in the config is one of the following three ... *) (* Each enty in the config is one of the following three ... *)
let entry = vnc_entry let entry = vnc_entry

View File

@ -309,3 +309,10 @@
# disk), uncomment this # disk), uncomment this
# #
# lock_manager = "sanlock" # 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

View File

@ -458,6 +458,10 @@ int qemudLoadDriverConfig(struct qemud_driver *driver,
VIR_FREE(lockConf); VIR_FREE(lockConf);
} }
p = virConfGetValue(conf, "max_queued");
CHECK_TYPE("max_queued", VIR_CONF_LONG);
if (p) driver->max_queued = p->l;
virConfFree (conf); virConfFree (conf);
return 0; return 0;
} }

View File

@ -109,6 +109,8 @@ struct qemud_driver {
int maxProcesses; int maxProcesses;
int max_queued;
virCapsPtr caps; virCapsPtr caps;
virDomainEventStatePtr domainEventState; virDomainEventStatePtr domainEventState;

View File

@ -713,6 +713,8 @@ qemuDomainObjBeginJobInternal(struct qemud_driver *driver,
unsigned long long then; unsigned long long then;
bool nested = job == QEMU_JOB_ASYNC_NESTED; bool nested = job == QEMU_JOB_ASYNC_NESTED;
priv->jobs_queued++;
if (virTimeMs(&now) < 0) if (virTimeMs(&now) < 0)
return -1; return -1;
then = now + QEMU_JOB_WAIT_TIME; then = now + QEMU_JOB_WAIT_TIME;
@ -722,6 +724,11 @@ qemuDomainObjBeginJobInternal(struct qemud_driver *driver,
qemuDriverUnlock(driver); qemuDriverUnlock(driver);
retry: retry:
if (driver->max_queued &&
priv->jobs_queued > driver->max_queued) {
goto error;
}
while (!nested && !qemuDomainJobAllowed(priv, job)) { while (!nested && !qemuDomainJobAllowed(priv, job)) {
if (virCondWaitUntil(&priv->job.asyncCond, &obj->lock, then) < 0) if (virCondWaitUntil(&priv->job.asyncCond, &obj->lock, then) < 0)
goto error; goto error;
@ -761,9 +768,15 @@ error:
if (errno == ETIMEDOUT) if (errno == ETIMEDOUT)
qemuReportError(VIR_ERR_OPERATION_TIMEOUT, qemuReportError(VIR_ERR_OPERATION_TIMEOUT,
"%s", _("cannot acquire state change lock")); "%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 else
virReportSystemError(errno, virReportSystemError(errno,
"%s", _("cannot acquire job mutex")); "%s", _("cannot acquire job mutex"));
priv->jobs_queued--;
if (driver_locked) { if (driver_locked) {
virDomainObjUnlock(obj); virDomainObjUnlock(obj);
qemuDriverLock(driver); qemuDriverLock(driver);
@ -844,6 +857,8 @@ int qemuDomainObjEndJob(struct qemud_driver *driver, virDomainObjPtr obj)
{ {
qemuDomainObjPrivatePtr priv = obj->privateData; qemuDomainObjPrivatePtr priv = obj->privateData;
priv->jobs_queued--;
qemuDomainObjResetJob(priv); qemuDomainObjResetJob(priv);
qemuDomainObjSaveJob(driver, obj); qemuDomainObjSaveJob(driver, obj);
virCondSignal(&priv->job.cond); virCondSignal(&priv->job.cond);
@ -856,6 +871,8 @@ qemuDomainObjEndAsyncJob(struct qemud_driver *driver, virDomainObjPtr obj)
{ {
qemuDomainObjPrivatePtr priv = obj->privateData; qemuDomainObjPrivatePtr priv = obj->privateData;
priv->jobs_queued--;
qemuDomainObjResetAsyncJob(priv); qemuDomainObjResetAsyncJob(priv);
qemuDomainObjSaveJob(driver, obj); qemuDomainObjSaveJob(driver, obj);
virCondBroadcast(&priv->job.asyncCond); virCondBroadcast(&priv->job.asyncCond);

View File

@ -113,6 +113,8 @@ struct _qemuDomainObjPrivate {
char *lockState; char *lockState;
bool fakeReboot; bool fakeReboot;
int jobs_queued;
}; };
struct qemuDomainWatchdogEvent struct qemuDomainWatchdogEvent