diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index addd03dab9..6b8be38a90 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -16374,10 +16374,8 @@ qemuDomainBlockJobImpl(virDomainObjPtr vm, } /* Convert bandwidth MiB to bytes, if needed */ - if ((mode == BLOCK_JOB_SPEED && - !(flags & VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_BYTES)) || - (mode == BLOCK_JOB_PULL && - !(flags & VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES))) { + if (mode == BLOCK_JOB_PULL && + !(flags & VIR_DOMAIN_BLOCK_PULL_BANDWIDTH_BYTES)) { if (speed > LLONG_MAX >> 20) { virReportError(VIR_ERR_OVERFLOW, _("bandwidth must be less than %llu"), @@ -16568,23 +16566,69 @@ qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path, return ret; } + static int -qemuDomainBlockJobSetSpeed(virDomainPtr dom, const char *path, - unsigned long bandwidth, unsigned int flags) +qemuDomainBlockJobSetSpeed(virDomainPtr dom, + const char *path, + unsigned long bandwidth, + unsigned int flags) { + virQEMUDriverPtr driver = dom->conn->privateData; + int ret = -1; virDomainObjPtr vm; + bool modern; + const char *device; + unsigned long long speed = bandwidth; + virCheckFlags(VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_BYTES, -1); + /* Convert bandwidth MiB to bytes, if needed */ + if (!(flags & VIR_DOMAIN_BLOCK_JOB_SPEED_BANDWIDTH_BYTES)) { + if (speed > LLONG_MAX >> 20) { + virReportError(VIR_ERR_OVERFLOW, + _("bandwidth must be less than %llu"), + LLONG_MAX >> 20); + return -1; + } + speed <<= 20; + } + if (!(vm = qemuDomObjFromDomain(dom))) return -1; - if (virDomainBlockJobSetSpeedEnsureACL(dom->conn, vm->def) < 0) { - qemuDomObjEndAPI(&vm); - return -1; + if (virDomainBlockJobSetSpeedEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + if (qemuDomainSupportsBlockJobs(vm, &modern) < 0) + goto cleanup; + + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) + goto cleanup; + + if (!virDomainObjIsActive(vm)) { + virReportError(VIR_ERR_OPERATION_INVALID, "%s", + _("domain is not running")); + goto endjob; } - return qemuDomainBlockJobImpl(vm, dom->conn, path, NULL, bandwidth, - BLOCK_JOB_SPEED, flags); + if (!(device = qemuDiskPathToAlias(vm, path, NULL))) + goto endjob; + + qemuDomainObjEnterMonitor(driver, vm); + ret = qemuMonitorBlockJobSetSpeed(qemuDomainGetMonitor(vm), + device, + speed, + modern); + if (qemuDomainObjExitMonitor(driver, vm) < 0) + ret = -1; + + endjob: + qemuDomainObjEndJob(driver, vm); + + cleanup: + qemuDomObjEndAPI(&vm); + + return ret; } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 2b0e1a5a15..3a6a746a24 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3602,6 +3602,25 @@ qemuMonitorBlockJob(qemuMonitorPtr mon, } +int +qemuMonitorBlockJobSetSpeed(qemuMonitorPtr mon, + const char *device, + unsigned long long bandwidth, + bool modern) +{ + VIR_DEBUG("mon=%p, device=%s, bandwidth=%lluB, modern=%d", + mon, device, bandwidth, modern); + + if (!mon->json) { + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s", + _("block jobs require JSON monitor")); + return -1; + } + + return qemuMonitorJSONBlockJobSetSpeed(mon, device, bandwidth, modern); +} + + int qemuMonitorBlockJobInfo(qemuMonitorPtr mon, const char *device, diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index a3514cf42e..78f4648e67 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -757,7 +757,6 @@ int qemuMonitorSendKey(qemuMonitorPtr mon, typedef enum { BLOCK_JOB_ABORT, - BLOCK_JOB_SPEED, BLOCK_JOB_PULL, } qemuMonitorBlockJobCmd; @@ -770,6 +769,11 @@ int qemuMonitorBlockJob(qemuMonitorPtr mon, bool modern) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +int qemuMonitorBlockJobSetSpeed(qemuMonitorPtr mon, + const char *device, + unsigned long long bandwidth, + bool modern); + int qemuMonitorBlockJobInfo(qemuMonitorPtr mon, const char *device, virDomainBlockJobInfoPtr info, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index f449d0ea30..948298296c 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -4328,14 +4328,6 @@ qemuMonitorJSONBlockJob(qemuMonitorPtr mon, NULL); break; - case BLOCK_JOB_SPEED: - cmd_name = modern ? "block-job-set-speed" : "block_job_set_speed"; - cmd = qemuMonitorJSONMakeCommand(cmd_name, - "s:device", device, - modern ? "J:speed" : "J:value", speed, - NULL); - break; - case BLOCK_JOB_PULL: cmd_name = modern ? "block-stream" : "block_stream"; cmd = qemuMonitorJSONMakeCommand(cmd_name, @@ -4364,6 +4356,39 @@ qemuMonitorJSONBlockJob(qemuMonitorPtr mon, return ret; } + +int +qemuMonitorJSONBlockJobSetSpeed(qemuMonitorPtr mon, + const char *device, + unsigned long long speed, + bool modern) +{ + int ret = -1; + virJSONValuePtr cmd; + virJSONValuePtr reply = NULL; + const char *cmd_name = modern ? "block-job-set-speed" : "block_job_set_speed"; + + if (!(cmd = qemuMonitorJSONMakeCommand(cmd_name, + "s:device", device, + modern ? "J:speed" : "J:value", speed, + NULL))) + return -1; + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + goto cleanup; + + if (qemuMonitorJSONBlockJobError(reply, cmd_name, device) < 0) + goto cleanup; + + ret = 0; + + cleanup: + virJSONValueFree(cmd); + virJSONValueFree(reply); + return ret; +} + + int qemuMonitorJSONOpenGraphics(qemuMonitorPtr mon, const char *protocol, const char *fdname, diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index fd86447df1..5185bbfe36 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -306,6 +306,12 @@ int qemuMonitorJSONBlockJob(qemuMonitorPtr mon, bool modern) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); +int qemuMonitorJSONBlockJobSetSpeed(qemuMonitorPtr mon, + const char *device, + unsigned long long speed, + bool modern) + ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); + int qemuMonitorJSONBlockJobInfo(qemuMonitorPtr mon, const char *device, virDomainBlockJobInfoPtr info,