From nobody Sun Feb 8 18:30:13 2026 Delivered-To: importer@patchew.org Received-SPF: none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; spf=none (zohomail.com: 8.43.85.245 is neither permitted nor denied by domain of lists.libvirt.org) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=fail(p=reject dis=none) header.from=linux.ibm.com Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1712887850104287.57859364977844; Thu, 11 Apr 2024 19:10:50 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id F34B91711; Thu, 11 Apr 2024 22:10:48 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id AE71217B2; Thu, 11 Apr 2024 22:03:32 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id A8105180D; Thu, 11 Apr 2024 22:03:26 -0400 (EDT) Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 50F63180D for ; Thu, 11 Apr 2024 22:02:53 -0400 (EDT) Received: from pps.filterd (m0353723.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 43C21UBl006445 for ; Fri, 12 Apr 2024 02:02:52 GMT Received: from ppma23.wdc07v.mail.ibm.com (5d.69.3da9.ip4.static.sl-reverse.com [169.61.105.93]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3xeup2r0ck-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:02:52 +0000 Received: from pps.filterd (ppma23.wdc07v.mail.ibm.com [127.0.0.1]) by ppma23.wdc07v.mail.ibm.com (8.17.1.19/8.17.1.19) with ESMTP id 43C11UjJ029904 for ; Fri, 12 Apr 2024 02:02:51 GMT Received: from smtprelay03.wdc07v.mail.ibm.com ([172.16.1.70]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 3xbj7mq0tj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:02:51 +0000 Received: from smtpav05.dal12v.mail.ibm.com (smtpav05.dal12v.mail.ibm.com [10.241.53.104]) by smtprelay03.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 43C22mW423593494 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 12 Apr 2024 02:02:50 GMT Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7316658069; Fri, 12 Apr 2024 02:02:48 +0000 (GMT) Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 72D7458052; Fri, 12 Apr 2024 02:02:47 +0000 (GMT) Received: from libvirt-dev-u221.fyre.ibm.com (unknown [9.112.252.183]) by smtpav05.dal12v.mail.ibm.com (Postfix) with ESMTP; Fri, 12 Apr 2024 02:02:47 +0000 (GMT) X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-0.7 required=5.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RCVD_IN_MSPIKE_H4,RCVD_IN_MSPIKE_WL,SPF_HELO_NONE autolearn=unavailable autolearn_force=no version=3.4.4 From: wucf@linux.ibm.com To: devel@lists.libvirt.org Cc: Chun Feng Wu Subject: [PATCH RFC v2 04/12] qemu: Implement qemu driver for throttle API Date: Thu, 11 Apr 2024 19:01:52 -0700 Message-Id: <20240412020200.2418776-5-wucf@linux.ibm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240412020200.2418776-1-wucf@linux.ibm.com> References: <20240412020200.2418776-1-wucf@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: 04RRlJT1TnDp8JJPTMQhyo1jT-dvRexU X-Proofpoint-ORIG-GUID: 04RRlJT1TnDp8JJPTMQhyo1jT-dvRexU X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.272,Aquarius:18.0.1011,Hydra:6.0.619,FMLib:17.11.176.26 definitions=2024-04-11_14,2024-04-09_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 clxscore=1015 priorityscore=1501 adultscore=0 impostorscore=0 mlxlogscore=999 spamscore=0 mlxscore=0 bulkscore=0 lowpriorityscore=0 phishscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404120013 Message-ID-Hash: JCSJMOXS5HMK7Z2BTNRIA4HC3YXIEFFY X-Message-ID-Hash: JCSJMOXS5HMK7Z2BTNRIA4HC3YXIEFFY X-MailFrom: wucf@linux.ibm.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; header-match-config-1; header-match-config-2; header-match-config-3; header-match-devel.lists.libvirt.org-0; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; suspicious-header X-Mailman-Version: 3.2.2 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Post: List-Subscribe: List-Unsubscribe: Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-ZM-MESSAGEID: 1712887851092100001 From: Chun Feng Wu Implement the following methods: * virDomainSetThrottleGroup * virDomainGetThrottleGroup * virDomainDelThrottleGroup Signed-off-by: Chun Feng Wu --- src/qemu/qemu_domain.c | 14 ++ src/qemu/qemu_domain.h | 4 + src/qemu/qemu_driver.c | 523 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 541 insertions(+) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 6b869797a8..b676f59c3a 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -10246,6 +10246,20 @@ qemuDomainDiskByName(virDomainDef *def, } =20 =20 +virDomainThrottleGroupDef * +qemuDomainThrottleGroupByName(virDomainDef *def, + const char *name) +{ + virDomainThrottleGroupDef *ret; + + if (!(ret =3D virDomainThrottleGroupByName(def, name))) { + return NULL; + } + + return ret; +} + + int qemuDomainPrepareChannel(virDomainChrDef *channel, const char *domainChannelTargetDir) diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index bd37cb245a..49e4da435b 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -880,6 +880,10 @@ int qemuDomainSetPrivatePaths(virQEMUDriver *driver, =20 virDomainDiskDef *qemuDomainDiskByName(virDomainDef *def, const char *name= ); =20 +virDomainThrottleGroupDef * +qemuDomainThrottleGroupByName(virDomainDef *def, + const char *name); + char *qemuDomainGetMasterKeyFilePath(const char *libDir); =20 int qemuDomainMasterKeyReadFile(qemuDomainObjPrivate *priv); diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d01f788aea..da0f9590db 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19995,6 +19995,526 @@ qemuDomainGraphicsReload(virDomainPtr domain, return ret; } =20 + +/* wrapper of qemuDomainSetBlockIoTuneDefaults for throttle group since th= ey use the same data structure */ +static int +qemuDomainSetThrottleGroupDefaults(virDomainBlockIoTuneInfo *newinfo, + virDomainBlockIoTuneInfo *oldinfo, + qemuBlockIoTuneSetFlags set_fields) +{ + return qemuDomainSetBlockIoTuneDefaults(newinfo, oldinfo, set_fields); +} + + +static int +qemuDomainCheckThrottleGroupReset(const char *groupname, + virDomainBlockIoTuneInfo *newiotune) +{ + if (virDomainBlockIoTuneInfoHasAny(newiotune)) + return 0; + + if (newiotune->group_name && + STRNEQ_NULLABLE(newiotune->group_name, groupname)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("creating a new group/updating existing with all = parameters zero is not supported")); + return -1; + } + + /* all zero means remove any throttling and remove from group for qemu= */ + VIR_FREE(newiotune->group_name); + + return 0; +} + + +static int +qemuDomainSetThrottleGroup(virDomainPtr dom, + const char *groupname, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + virQEMUDriver *driver =3D dom->conn->privateData; + virDomainObj *vm =3D NULL; + virDomainDef *def =3D NULL; + virDomainDef *persistentDef =3D NULL; + virDomainThrottleGroupDef info =3D { 0 }; + virDomainThrottleGroupDef conf_info =3D { 0 }; + int ret =3D -1; + size_t i; + qemuBlockIoTuneSetFlags set_fields =3D 0; + g_autoptr(virQEMUDriverConfig) cfg =3D NULL; + virObjectEvent *event =3D NULL; + virTypedParameterPtr eventParams =3D NULL; + int eventNparams =3D 0; + int eventMaxparams =3D 0; + virDomainThrottleGroupDef *cur_info; + virDomainThrottleGroupDef *conf_cur_info; + int rc =3D 0; + g_autoptr(virJSONValue) props =3D NULL; + g_autoptr(virJSONValue) limits =3D virJSONValueNewObject(); + + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG, -1); + if (virTypedParamsValidate(params, nparams, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_SIZE_IOPS_SEC, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME, + VIR_TYPED_PARAM_STRING, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_BYTES_SEC_MAX= _LENGTH, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_READ_BYTES_SEC_MAX_= LENGTH, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_BYTES_SEC_MAX= _LENGTH, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_TOTAL_IOPS_SEC_MAX_= LENGTH, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_READ_IOPS_SEC_MAX_L= ENGTH, + VIR_TYPED_PARAM_ULLONG, + VIR_DOMAIN_BLOCK_IOTUNE_WRITE_IOPS_SEC_MAX_= LENGTH, + VIR_TYPED_PARAM_ULLONG, + NULL) < 0) + return -1; + + if (!(vm =3D qemuDomainObjFromDomain(dom))) + return -1; + + if (virDomainSetThrottleGroupEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + + cfg =3D virQEMUDriverGetConfig(driver); + + if (virDomainObjBeginJob(vm, VIR_JOB_MODIFY) < 0) + goto cleanup; + + if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0) + goto endjob; + + if (virTypedParamsAddString(&eventParams, &eventNparams, &eventMaxpara= ms, + VIR_DOMAIN_THROTTLE_GROUP, groupname) < 0) + goto endjob; + +#define SET_THROTTLE_FIELD(FIELD, BOOL, CONST) \ + if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_##CONST)) { \ + info.FIELD =3D param->value.ul; \ + set_fields |=3D QEMU_BLOCK_IOTUNE_SET_##BOOL; \ + if (virTypedParamsAddULLong(&eventParams, &eventNparams, \ + &eventMaxparams, \ + VIR_DOMAIN_TUNABLE_BLKDEV_##CONST, \ + param->value.ul) < 0) \ + goto endjob; \ + continue; \ + } + + for (i =3D 0; i < nparams; i++) { + virTypedParameterPtr param =3D ¶ms[i]; + + if (param->value.ul > QEMU_BLOCK_IOTUNE_MAX) { + virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, + _("throttle group value must be no more than %1= $llu"), + QEMU_BLOCK_IOTUNE_MAX); + goto endjob; + } + + SET_THROTTLE_FIELD(total_bytes_sec, BYTES, TOTAL_BYTES_SEC); + SET_THROTTLE_FIELD(read_bytes_sec, BYTES, READ_BYTES_SEC); + SET_THROTTLE_FIELD(write_bytes_sec, BYTES, WRITE_BYTES_SEC); + SET_THROTTLE_FIELD(total_iops_sec, IOPS, TOTAL_IOPS_SEC); + SET_THROTTLE_FIELD(read_iops_sec, IOPS, READ_IOPS_SEC); + SET_THROTTLE_FIELD(write_iops_sec, IOPS, WRITE_IOPS_SEC); + + SET_THROTTLE_FIELD(total_bytes_sec_max, BYTES_MAX, + TOTAL_BYTES_SEC_MAX); + SET_THROTTLE_FIELD(read_bytes_sec_max, BYTES_MAX, + READ_BYTES_SEC_MAX); + SET_THROTTLE_FIELD(write_bytes_sec_max, BYTES_MAX, + WRITE_BYTES_SEC_MAX); + SET_THROTTLE_FIELD(total_iops_sec_max, IOPS_MAX, + TOTAL_IOPS_SEC_MAX); + SET_THROTTLE_FIELD(read_iops_sec_max, IOPS_MAX, + READ_IOPS_SEC_MAX); + SET_THROTTLE_FIELD(write_iops_sec_max, IOPS_MAX, + WRITE_IOPS_SEC_MAX); + SET_THROTTLE_FIELD(size_iops_sec, SIZE_IOPS, SIZE_IOPS_SEC); + + if (STREQ(param->field, VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME)) { + info.group_name =3D g_strdup(param->value.s); + set_fields |=3D QEMU_BLOCK_IOTUNE_SET_GROUP_NAME; + if (virTypedParamsAddString(&eventParams, &eventNparams, + &eventMaxparams, + VIR_DOMAIN_TUNABLE_BLKDEV_GROUP_NA= ME, + param->value.s) < 0) + goto endjob; + continue; + } + + SET_THROTTLE_FIELD(total_bytes_sec_max_length, BYTES_MAX_LENGTH, + TOTAL_BYTES_SEC_MAX_LENGTH); + SET_THROTTLE_FIELD(read_bytes_sec_max_length, BYTES_MAX_LENGTH, + READ_BYTES_SEC_MAX_LENGTH); + SET_THROTTLE_FIELD(write_bytes_sec_max_length, BYTES_MAX_LENGTH, + WRITE_BYTES_SEC_MAX_LENGTH); + SET_THROTTLE_FIELD(total_iops_sec_max_length, IOPS_MAX_LENGTH, + TOTAL_IOPS_SEC_MAX_LENGTH); + SET_THROTTLE_FIELD(read_iops_sec_max_length, IOPS_MAX_LENGTH, + READ_IOPS_SEC_MAX_LENGTH); + SET_THROTTLE_FIELD(write_iops_sec_max_length, IOPS_MAX_LENGTH, + WRITE_IOPS_SEC_MAX_LENGTH); + } + +#undef SET_THROTTLE_FIELD + + if ((info.total_bytes_sec && info.read_bytes_sec) || + (info.total_bytes_sec && info.write_bytes_sec)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("total and read/write of bytes_sec cannot be set = at the same time")); + goto endjob; + } + + if ((info.total_iops_sec && info.read_iops_sec) || + (info.total_iops_sec && info.write_iops_sec)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("total and read/write of iops_sec cannot be set a= t the same time")); + goto endjob; + } + + if ((info.total_bytes_sec_max && info.read_bytes_sec_max) || + (info.total_bytes_sec_max && info.write_bytes_sec_max)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("total and read/write of bytes_sec_max cannot be = set at the same time")); + goto endjob; + } + + if ((info.total_iops_sec_max && info.read_iops_sec_max) || + (info.total_iops_sec_max && info.write_iops_sec_max)) { + virReportError(VIR_ERR_INVALID_ARG, "%s", + _("total and read/write of iops_sec_max cannot be s= et at the same time")); + goto endjob; + } + + virDomainThrottleGroupDefCopy(&info, &conf_info); + + if (def) { + if (qemuDomainCheckThrottleGroupReset(groupname, &info) < 0) + goto endjob; + +#define CHECK_MAX(val, _bool) \ + do { \ + if (info.val##_max) { \ + if (!info.val) { \ + if (QEMU_BLOCK_IOTUNE_SET_##_bool) { \ + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \ + _("cannot reset '%1$s' when '%2$s' = is set"), \ + #val, #val "_max"); \ + } else { \ + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \ + _("value '%1$s' cannot be set if '%= 2$s' is not set"), \ + #val "_max", #val); \ + } \ + goto endjob; \ + } \ + if (info.val##_max < info.val) { \ + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, \ + _("value '%1$s' cannot be smaller than = '%2$s'"), \ + #val "_max", #val); \ + goto endjob; \ + } \ + } \ + } while (false) + + CHECK_MAX(total_bytes_sec, BYTES); + CHECK_MAX(read_bytes_sec, BYTES); + CHECK_MAX(write_bytes_sec, BYTES); + CHECK_MAX(total_iops_sec, IOPS); + CHECK_MAX(read_iops_sec, IOPS); + CHECK_MAX(write_iops_sec, IOPS); + +#undef CHECK_MAX + + cur_info =3D qemuDomainThrottleGroupByName(def, groupname); + /* Update existing group. */ + if (cur_info !=3D NULL) { + if (qemuDomainSetThrottleGroupDefaults(&info, cur_info, + set_fields) < 0) + goto endjob; + qemuDomainObjEnterMonitor(vm); + rc =3D qemuMonitorUpdateThrottleGroup(qemuDomainGetMonitor(vm), + groupname, + &info); + qemuDomainObjExitMonitor(vm); + if (rc < 0) + goto endjob; + virDomainThrottleGroupUpdate(def, &info); + }else{ + if (qemuMonitorThrottleGroupLimits(limits, &info)<0) + goto endjob; + if (qemuMonitorCreateObjectProps(&props, + "throttle-group", groupname, + "a:limits", &limits, + NULL) < 0) + goto endjob; + qemuDomainObjEnterMonitor(vm); + rc =3D qemuMonitorAddObject(qemuDomainGetMonitor(vm), &props, = NULL); + qemuDomainObjExitMonitor(vm); + if (rc < 0) + goto endjob; + virDomainThrottleGroupAdd(def, &info); + } + + qemuDomainSaveStatus(vm); + + if (eventNparams) { + event =3D virDomainEventTunableNewFromDom(dom, &eventParams, e= ventNparams); + virObjectEventStateQueue(driver->domainEventState, event); + } + } + + if (persistentDef) { + conf_cur_info =3D qemuDomainThrottleGroupByName(persistentDef, gro= upname); + + if (qemuDomainCheckThrottleGroupReset(groupname, &conf_info) < 0) + goto endjob; + + if (conf_cur_info !=3D NULL) { + if (qemuDomainSetThrottleGroupDefaults(&conf_info, conf_cur_in= fo, + set_fields) < 0) + goto endjob; + virDomainThrottleGroupUpdate(persistentDef, &conf_info); + }else{ + virDomainThrottleGroupAdd(persistentDef, &conf_info); + } + + + if (virDomainDefSave(persistentDef, driver->xmlopt, + cfg->configDir) < 0) + goto endjob; + } + + ret =3D 0; + endjob: + virDomainObjEndJob(vm); + + cleanup: + virDomainObjEndAPI(&vm); + virTypedParamsFree(eventParams, eventNparams); + return ret; +} + + +static int +qemuDomainGetThrottleGroup(virDomainPtr dom, + const char *groupname, + virTypedParameterPtr params, + int *nparams, + unsigned int flags) +{ + virDomainObj *vm =3D NULL; + virDomainDef *def =3D NULL; + virDomainDef *persistentDef =3D NULL; + virDomainThrottleGroupDef groupDef =3D { 0 }; + virDomainThrottleGroupDef *reply =3D &groupDef; + int ret =3D -1; + int maxparams; + int rc =3D 0; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG | + VIR_TYPED_PARAM_STRING_OKAY, -1); + + /* We don't return strings, and thus trivially support this flag. */ + flags &=3D ~VIR_TYPED_PARAM_STRING_OKAY; + + if (!(vm =3D qemuDomainObjFromDomain(dom))) + return -1; + + if (virDomainGetThrottleGroupEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + if (virDomainObjBeginJob(vm, VIR_JOB_QUERY) < 0) + goto cleanup; + + /* the API check guarantees that only one of the definitions will be s= et */ + if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0) + goto endjob; + + maxparams =3D QEMU_NB_BLOCK_IO_TUNE_ALL_PARAMS; + + if (*nparams =3D=3D 0) { + *nparams =3D maxparams; + ret =3D 0; + goto endjob; + } + if (*nparams < maxparams) + maxparams =3D *nparams; + + if (def) { + qemuDomainObjEnterMonitor(vm); + rc =3D qemuMonitorGetThrottleGroup(qemuDomainGetMonitor(vm), group= name, reply); + qemuDomainObjExitMonitor(vm); + + if (rc < 0) + goto endjob; + } + + if (persistentDef) { + reply =3D qemuDomainThrottleGroupByName(persistentDef, groupname); + if (reply =3D=3D NULL) { + virReportError(VIR_ERR_INVALID_ARG, + _("throttle group '%1$s' was not found in the d= omain config"), + groupname); + goto endjob; + } + reply->group_name =3D g_strdup(groupname); + } + + *nparams =3D 0; + +#define THROTTLE_GROUP_ASSIGN(name, var) \ + if (*nparams < maxparams && \ + virTypedParameterAssign(¶ms[(*nparams)++], \ + VIR_DOMAIN_BLOCK_IOTUNE_ ## name, \ + VIR_TYPED_PARAM_ULLONG, \ + reply->var) < 0) \ + goto endjob; + + if (*nparams < maxparams) { + if (virTypedParameterAssign(¶ms[(*nparams)++], + VIR_DOMAIN_BLOCK_IOTUNE_GROUP_NAME, + VIR_TYPED_PARAM_STRING, + reply->group_name) < 0) + goto endjob; + } + + THROTTLE_GROUP_ASSIGN(TOTAL_BYTES_SEC, total_bytes_sec); + THROTTLE_GROUP_ASSIGN(READ_BYTES_SEC, read_bytes_sec); + THROTTLE_GROUP_ASSIGN(WRITE_BYTES_SEC, write_bytes_sec); + + THROTTLE_GROUP_ASSIGN(TOTAL_IOPS_SEC, total_iops_sec); + THROTTLE_GROUP_ASSIGN(READ_IOPS_SEC, read_iops_sec); + THROTTLE_GROUP_ASSIGN(WRITE_IOPS_SEC, write_iops_sec); + + THROTTLE_GROUP_ASSIGN(TOTAL_BYTES_SEC_MAX, total_bytes_sec_max); + THROTTLE_GROUP_ASSIGN(READ_BYTES_SEC_MAX, read_bytes_sec_max); + THROTTLE_GROUP_ASSIGN(WRITE_BYTES_SEC_MAX, write_bytes_sec_max); + + THROTTLE_GROUP_ASSIGN(TOTAL_IOPS_SEC_MAX, total_iops_sec_max); + THROTTLE_GROUP_ASSIGN(READ_IOPS_SEC_MAX, read_iops_sec_max); + THROTTLE_GROUP_ASSIGN(WRITE_IOPS_SEC_MAX, write_iops_sec_max); + + THROTTLE_GROUP_ASSIGN(SIZE_IOPS_SEC, size_iops_sec); + + THROTTLE_GROUP_ASSIGN(TOTAL_BYTES_SEC_MAX_LENGTH, total_bytes_sec_max_= length); + THROTTLE_GROUP_ASSIGN(READ_BYTES_SEC_MAX_LENGTH, read_bytes_sec_max_le= ngth); + THROTTLE_GROUP_ASSIGN(WRITE_BYTES_SEC_MAX_LENGTH, write_bytes_sec_max_= length); + + THROTTLE_GROUP_ASSIGN(TOTAL_IOPS_SEC_MAX_LENGTH, total_iops_sec_max_le= ngth); + THROTTLE_GROUP_ASSIGN(READ_IOPS_SEC_MAX_LENGTH, read_iops_sec_max_leng= th); + THROTTLE_GROUP_ASSIGN(WRITE_IOPS_SEC_MAX_LENGTH, write_iops_sec_max_le= ngth); +#undef THROTTLE_GROUP_ASSIGN + + ret =3D 0; + + endjob: + virDomainObjEndJob(vm); + + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + + +static int +qemuDomainDelThrottleGroup(virDomainPtr dom, + const char *groupname, + unsigned int flags) +{ + virQEMUDriver *driver =3D dom->conn->privateData; + virDomainObj *vm =3D NULL; + virDomainDef *def =3D NULL; + virDomainDef *persistentDef =3D NULL; + g_autoptr(virQEMUDriverConfig) cfg =3D NULL; + int ret =3D -1; + + virCheckFlags(VIR_DOMAIN_AFFECT_LIVE | + VIR_DOMAIN_AFFECT_CONFIG | + VIR_TYPED_PARAM_STRING_OKAY, -1); + + /* We don't return strings, and thus trivially support this flag. */ + flags &=3D ~VIR_TYPED_PARAM_STRING_OKAY; + + if (!(vm =3D qemuDomainObjFromDomain(dom))) + return -1; + + cfg =3D virQEMUDriverGetConfig(driver); + + if (virDomainDelThrottleGroupEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + if (virDomainObjBeginJob(vm, VIR_JOB_QUERY) < 0) + goto cleanup; + + /* the API check guarantees that only one of the definitions will be s= et */ + if (virDomainObjGetDefs(vm, flags, &def, &persistentDef) < 0) + goto endjob; + + + if (def) { + int rc =3D 0; + + qemuDomainObjEnterMonitor(vm); + rc =3D qemuMonitorDelObject(qemuDomainGetMonitor(vm), groupname, t= rue); + qemuDomainObjExitMonitor(vm); + + if (rc < 0) + goto endjob; + + virDomainThrottleGroupDel(def, groupname); + qemuDomainSaveStatus(vm); + } + + if (persistentDef) { + virDomainThrottleGroupDel(persistentDef, groupname); + if (virDomainDefSave(persistentDef, driver->xmlopt, + cfg->configDir) < 0) + goto endjob; + } + + ret =3D 0; + + endjob: + virDomainObjEndJob(vm); + + cleanup: + virDomainObjEndAPI(&vm); + return ret; +} + + static virHypervisorDriver qemuHypervisorDriver =3D { .name =3D QEMU_DRIVER_NAME, .connectURIProbe =3D qemuConnectURIProbe, @@ -20245,6 +20765,9 @@ static virHypervisorDriver qemuHypervisorDriver =3D= { .domainSetLaunchSecurityState =3D qemuDomainSetLaunchSecurityState, /*= 8.0.0 */ .domainFDAssociate =3D qemuDomainFDAssociate, /* 9.0.0 */ .domainGraphicsReload =3D qemuDomainGraphicsReload, /* 10.2.0 */ + .domainSetThrottleGroup =3D qemuDomainSetThrottleGroup, /* 10.3.0 */ + .domainGetThrottleGroup =3D qemuDomainGetThrottleGroup, /* 10.3.0 */ + .domainDelThrottleGroup =3D qemuDomainDelThrottleGroup, /* 10.3.0 */ }; =20 =20 --=20 2.34.1 _______________________________________________ Devel mailing list -- devel@lists.libvirt.org To unsubscribe send an email to devel-leave@lists.libvirt.org