From nobody Fri May 17 10:44:00 2024 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 1712887513932603.4373052234212; Thu, 11 Apr 2024 19:05:13 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id E0F4217C1; Thu, 11 Apr 2024 22:05:12 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id A8C7E17DA; Thu, 11 Apr 2024 22:03:20 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 38D9417D4; Thu, 11 Apr 2024 22:03:14 -0400 (EDT) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (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 8CADA17C8 for ; Thu, 11 Apr 2024 22:02:39 -0400 (EDT) Received: from pps.filterd (m0360083.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 43C1hm3L009960 for ; Fri, 12 Apr 2024 02:02:38 GMT Received: from ppma13.dal12v.mail.ibm.com (dd.9e.1632.ip4.static.sl-reverse.com [50.22.158.221]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3xeuhc80ux-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:02:38 +0000 Received: from pps.filterd (ppma13.dal12v.mail.ibm.com [127.0.0.1]) by ppma13.dal12v.mail.ibm.com (8.17.1.19/8.17.1.19) with ESMTP id 43BMtRig021556 for ; Fri, 12 Apr 2024 02:02:37 GMT Received: from smtprelay07.wdc07v.mail.ibm.com ([172.16.1.74]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 3xbjxm6ubv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:02:37 +0000 Received: from smtpav05.dal12v.mail.ibm.com (smtpav05.dal12v.mail.ibm.com [10.241.53.104]) by smtprelay07.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 43C22XLI40174074 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 12 Apr 2024 02:02:35 GMT Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8C1C15807E; Fri, 12 Apr 2024 02:02:31 +0000 (GMT) Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 60C8A58076; Fri, 12 Apr 2024 02:02:30 +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:30 +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 01/12] config: Introduce ThrottleGroup and ThrottleFilter Date: Thu, 11 Apr 2024 19:01:49 -0700 Message-Id: <20240412020200.2418776-2-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-ORIG-GUID: HANBUN2e1ELYePUJwxCLhCCdMtW7jtDT X-Proofpoint-GUID: HANBUN2e1ELYePUJwxCLhCCdMtW7jtDT 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 phishscore=0 bulkscore=0 clxscore=1015 impostorscore=0 mlxscore=0 suspectscore=0 adultscore=0 priorityscore=1501 spamscore=0 mlxlogscore=999 lowpriorityscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404120013 Message-ID-Hash: HOS5ENLWTWB2B6HWK7A3OYCMCVXHO6KZ X-Message-ID-Hash: HOS5ENLWTWB2B6HWK7A3OYCMCVXHO6KZ 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: 1712887516181100001 From: Chun Feng Wu * Define new structs 'virDomainThrottleGroupDef' and 'virDomainThrottleFilt= erDef' * Update _virDomainDef to include virDomainThrottleGroupDef * Update _virDomainDiskDef to include virDomainThrottleFilterDef * Support new resource operations for DOM XML and structs, corresponding "P= arse" and "Format" methods are provided Signed-off-by: Chun Feng Wu --- src/conf/domain_conf.c | 386 ++++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 54 ++++++ src/conf/virconftypes.h | 4 + 3 files changed, 444 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 48c5d546da..134a787dda 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3747,6 +3747,54 @@ virDomainIOThreadIDDefArrayInit(virDomainDef *def, } =20 =20 +static virDomainThrottleFilterDef * +virDomainThrottleFilterDefNew(void) +{ + virDomainThrottleFilterDef *def =3D g_new0(virDomainThrottleFilterDef,= 1); + + def->group_name =3D NULL; + + return def; +} + + +void +virDomainThrottleFilterDefFree(virDomainThrottleFilterDef *def) +{ + if (!def) + return; + VIR_FREE(def->group_name); + VIR_FREE(def->nodename); + virObjectUnref(def); +} + + +void +virDomainThrottleGroupDefFree(virDomainThrottleGroupDef *def) +{ + if (!def) + return; + g_free(def->group_name); + g_free(def); +} + + +static void +virDomainThrottleGroupDefArrayFree(virDomainThrottleGroupDef **def, + int nthrottlegroups) +{ + size_t i; + + if (!def) + return; + + for (i =3D 0; i < nthrottlegroups; i++) + virDomainThrottleGroupDefFree(def[i]); + + g_free(def); +} + + void virDomainResourceDefFree(virDomainResourceDef *resource) { @@ -4026,6 +4074,8 @@ void virDomainDefFree(virDomainDef *def) =20 virDomainIOThreadIDDefArrayFree(def->iothreadids, def->niothreadids); =20 + virDomainThrottleGroupDefArrayFree(def->throttlegroups, def->nthrottle= groups); + g_free(def->defaultIOThread); =20 virBitmapFree(def->cputune.emulatorpin); @@ -7694,6 +7744,165 @@ virDomainDiskDefIotuneParse(virDomainDiskDef *def, #undef PARSE_IOTUNE =20 =20 +static virDomainThrottleFilterDef * +virDomainDiskThrottleFilterDefParse(xmlNodePtr node, + xmlXPathContextPtr ctxt) +{ + g_autoptr(virDomainThrottleFilterDef) filter =3D virDomainThrottleFilt= erDefNew(); + + VIR_XPATH_NODE_AUTORESTORE(ctxt) + ctxt->node =3D node; + + filter->group_name =3D virXMLPropString(ctxt->node, "group"); + + return g_steal_pointer(&filter); +} + + +static int +virDomainDiskDefThrottleFilterChainParse(virDomainDiskDef *def, + xmlXPathContextPtr ctxt) +{ + size_t i; + int n =3D 0; + g_autofree xmlNodePtr *nodes =3D NULL; + + if ((n =3D virXPathNodeSet("./throttlefilters/throttlefilter", ctxt, &= nodes)) < 0) + return -1; + + if (n) + def->throttlefilters =3D g_new0(virDomainThrottleFilterDef *, n); + + for (i =3D 0; i < n; i++) { + g_autoptr(virDomainThrottleFilterDef) filter =3D NULL; + + if (!(filter =3D virDomainDiskThrottleFilterDefParse(nodes[i], ctx= t))) { + return -1; + } + + if (virDomainThrottleFilterFind(def, filter->group_name)) { + virReportError(VIR_ERR_XML_ERROR, + _("duplicate filter name '%1$s' found"), + filter->group_name); + return -1; + } + def->throttlefilters[def->nthrottlefilters++] =3D g_steal_pointer(= &filter); + } + return 0; +} + + +#define PARSE_THROTTLEGROUP(val) \ + if (virXPathULongLong("string(./" #val ")", \ + ctxt, &group->val) =3D=3D -2) { \ + virReportError(VIR_ERR_XML_ERROR, \ + _("throttle group field '%1$s' must be an integer")= , #val); \ + return NULL; \ + } + + +static virDomainThrottleGroupDef * +virDomainThrottleGroupDefParseXML(xmlNodePtr node, + xmlXPathContextPtr ctxt) +{ + g_autoptr(virDomainThrottleGroupDef) group =3D g_new0(virDomainThrottl= eGroupDef, 1); + + VIR_XPATH_NODE_AUTORESTORE(ctxt) + ctxt->node =3D node; + + PARSE_THROTTLEGROUP(total_bytes_sec); + PARSE_THROTTLEGROUP(read_bytes_sec); + PARSE_THROTTLEGROUP(write_bytes_sec); + PARSE_THROTTLEGROUP(total_iops_sec); + PARSE_THROTTLEGROUP(read_iops_sec); + PARSE_THROTTLEGROUP(write_iops_sec); + + PARSE_THROTTLEGROUP(total_bytes_sec_max); + PARSE_THROTTLEGROUP(read_bytes_sec_max); + PARSE_THROTTLEGROUP(write_bytes_sec_max); + PARSE_THROTTLEGROUP(total_iops_sec_max); + PARSE_THROTTLEGROUP(read_iops_sec_max); + PARSE_THROTTLEGROUP(write_iops_sec_max); + + PARSE_THROTTLEGROUP(size_iops_sec); + + PARSE_THROTTLEGROUP(total_bytes_sec_max_length); + PARSE_THROTTLEGROUP(read_bytes_sec_max_length); + PARSE_THROTTLEGROUP(write_bytes_sec_max_length); + PARSE_THROTTLEGROUP(total_iops_sec_max_length); + PARSE_THROTTLEGROUP(read_iops_sec_max_length); + PARSE_THROTTLEGROUP(write_iops_sec_max_length); + + group->group_name =3D virXPathString("string(./group_name)", ctxt); + + return g_steal_pointer(&group); +} +#undef PARSE_THROTTLEGROUP + + +int +virDomainThrottleGroupIndexByName(virDomainDef *def, + const char *name) +{ + virDomainThrottleGroupDef *tgroup; + size_t i; + int candidate =3D -1; + + for (i =3D 0; i < def->nthrottlegroups; i++) { + tgroup =3D def->throttlegroups[i]; + if (STREQ(tgroup->group_name, name)) + return i; + } + return candidate; +} + + +virDomainThrottleGroupDef * +virDomainThrottleGroupByName(virDomainDef *def, + const char *name) +{ + int idx =3D virDomainThrottleGroupIndexByName(def, name); + + if (idx < 0) + return NULL; + + return def->throttlegroups[idx]; +} + + +static int +virDomainDefThrottleGroupsParse(virDomainDef *def, + xmlXPathContextPtr ctxt) +{ + size_t i; + int n =3D 0; + g_autofree xmlNodePtr *nodes =3D NULL; + + if ((n =3D virXPathNodeSet("./throttlegroups/throttlegroup", ctxt, &no= des)) < 0) + return -1; + + if (n) + def->throttlegroups =3D g_new0(virDomainThrottleGroupDef *, n); + + for (i =3D 0; i < n; i++) { + g_autoptr(virDomainThrottleGroupDef) group =3D NULL; + + if (!(group =3D virDomainThrottleGroupDefParseXML(nodes[i], ctxt))= ) { + return -1; + } + + if (virDomainThrottleGroupFind(def, group->group_name)) { + virReportError(VIR_ERR_XML_ERROR, + _("duplicate group name '%1$s' found"), + group->group_name); + return -1; + } + def->throttlegroups[def->nthrottlegroups++] =3D g_steal_pointer(&g= roup); + } + return 0; +} + + static int virDomainDiskDefMirrorParse(virDomainDiskDef *def, xmlNodePtr cur, @@ -8184,6 +8393,9 @@ virDomainDiskDefParseXML(virDomainXMLOption *xmlopt, if (virDomainDiskDefIotuneParse(def, ctxt) < 0) return NULL; =20 + if (virDomainDiskDefThrottleFilterChainParse(def, ctxt) < 0) + return NULL; + def->domain_name =3D virXPathString("string(./backenddomain/@name)", c= txt); def->serial =3D virXPathString("string(./serial)", ctxt); def->wwn =3D virXPathString("string(./wwn)", ctxt); @@ -18857,6 +19069,9 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt, if (virDomainDefParseBootOptions(def, ctxt, xmlopt, flags) < 0) return NULL; =20 + if (virDomainDefThrottleGroupsParse(def, ctxt) < 0) + return NULL; + /* analysis of the disk devices */ if ((n =3D virXPathNodeSet("./devices/disk", ctxt, &nodes)) < 0) return NULL; @@ -22066,6 +22281,88 @@ virDomainIOThreadIDDel(virDomainDef *def, } =20 =20 +virDomainThrottleGroupDef * +virDomainThrottleGroupFind(const virDomainDef *def, + const char *name) +{ + size_t i; + + if (!def->throttlegroups || !def->nthrottlegroups) + return NULL; + + for (i =3D 0; i < def->nthrottlegroups; i++) { + if (STREQ(name, def->throttlegroups[i]->group_name)) + return def->throttlegroups[i]; + } + + return NULL; +} + + +virDomainThrottleFilterDef * +virDomainThrottleFilterFind(const virDomainDiskDef *def, + const char *name) +{ + size_t i; + + if (!def->throttlefilters || !def->nthrottlefilters) + return NULL; + + for (i =3D 0; i < def->nthrottlefilters; i++) { + if (STREQ(name, def->throttlefilters[i]->group_name)) + return def->throttlefilters[i]; + } + + return NULL; +} + + +virDomainThrottleGroupDef * +virDomainThrottleGroupAdd(virDomainDef *def, + virDomainThrottleGroupDef *throttle_group) +{ + virDomainThrottleGroupDef * new_group =3D g_new0(virDomainThrottleGro= upDef, 1); + virDomainThrottleGroupDefCopy(throttle_group, new_group); + VIR_APPEND_ELEMENT_COPY(def->throttlegroups, def->nthrottlegroups, new= _group); + return new_group; +} + + +void +virDomainThrottleGroupUpdate(virDomainDef *def, + virDomainThrottleGroupDef *info) +{ + size_t i; + + if (!info->group_name) + return; + + for (i =3D 0; i < def->nthrottlegroups; i++) { + virDomainThrottleGroupDef *t =3D def->throttlegroups[i]; + + if (STREQ_NULLABLE(t->group_name, info->group_name)) { + VIR_FREE(t->group_name); + virDomainThrottleGroupDefCopy(info, t); + } + } +} + + +void +virDomainThrottleGroupDel(virDomainDef *def, + const char *name) +{ + size_t i; + for (i =3D 0; i < def->nthrottlegroups; i++) { + if (STREQ_NULLABLE(def->throttlegroups[i]->group_name, name)) { + virDomainThrottleGroupDefFree(def->throttlegroups[i]); + VIR_DELETE_ELEMENT(def->throttlegroups, i, def->nthrottlegroup= s); + return; + } + } +} + + static int virDomainEventActionDefFormat(virBuffer *buf, int type, @@ -22682,6 +22979,21 @@ virDomainDiskDefFormatIotune(virBuffer *buf, #undef FORMAT_IOTUNE =20 =20 +static void +virDomainDiskDefFormatThrottleFilterChain(virBuffer *buf, + virDomainDiskDef *disk) +{ + size_t i; + g_auto(virBuffer) throttleChildBuf =3D VIR_BUFFER_INIT_CHILD(buf); + for (i =3D 0; i < disk->nthrottlefilters; i++) { + g_auto(virBuffer) throttleAttrBuf =3D VIR_BUFFER_INITIALIZER; + virBufferAsprintf(&throttleAttrBuf, " group=3D'%s'", disk->throttl= efilters[i]->group_name); + virXMLFormatElement(&throttleChildBuf, "throttlefilter", &throttle= AttrBuf, NULL); + } + virXMLFormatElement(buf, "throttlefilters", NULL, &throttleChildBuf); +} + + static void virDomainDiskDefFormatDriver(virBuffer *buf, virDomainDiskDef *disk) @@ -22968,6 +23280,8 @@ virDomainDiskDefFormat(virBuffer *buf, =20 virDomainDiskDefFormatIotune(&childBuf, def); =20 + virDomainDiskDefFormatThrottleFilterChain(&childBuf, def); + if (def->src->readonly) virBufferAddLit(&childBuf, "\n"); if (def->src->shared) @@ -27137,6 +27451,67 @@ virDomainDefIOThreadsFormat(virBuffer *buf, } =20 =20 +#define FORMAT_THROTTLE_GROUP(val) \ + if (group->val) { \ + virBufferAsprintf(&childBuf, "<" #val ">%llu\n", \ + group->val); \ + } + + +static void +virDomainThrottleGroupFormat(virBuffer *buf, + virDomainThrottleGroupDef *group) +{ + g_auto(virBuffer) childBuf =3D VIR_BUFFER_INIT_CHILD(buf); + + FORMAT_THROTTLE_GROUP(total_bytes_sec); + FORMAT_THROTTLE_GROUP(read_bytes_sec); + FORMAT_THROTTLE_GROUP(write_bytes_sec); + FORMAT_THROTTLE_GROUP(total_iops_sec); + FORMAT_THROTTLE_GROUP(read_iops_sec); + FORMAT_THROTTLE_GROUP(write_iops_sec); + + FORMAT_THROTTLE_GROUP(total_bytes_sec_max); + FORMAT_THROTTLE_GROUP(read_bytes_sec_max); + FORMAT_THROTTLE_GROUP(write_bytes_sec_max); + FORMAT_THROTTLE_GROUP(total_iops_sec_max); + FORMAT_THROTTLE_GROUP(read_iops_sec_max); + FORMAT_THROTTLE_GROUP(write_iops_sec_max); + FORMAT_THROTTLE_GROUP(size_iops_sec); + + if (group->group_name) { + virBufferEscapeString(&childBuf, "%s\n", + group->group_name); + } + + FORMAT_THROTTLE_GROUP(total_bytes_sec_max_length); + FORMAT_THROTTLE_GROUP(read_bytes_sec_max_length); + FORMAT_THROTTLE_GROUP(write_bytes_sec_max_length); + FORMAT_THROTTLE_GROUP(total_iops_sec_max_length); + FORMAT_THROTTLE_GROUP(read_iops_sec_max_length); + FORMAT_THROTTLE_GROUP(write_iops_sec_max_length); + + virXMLFormatElement(buf, "throttlegroup", NULL, &childBuf); +} + +#undef FORMAT_THROTTLE_GROUP + + +static void +virDomainDefThrottleGroupsFormat(virBuffer *buf, + const virDomainDef *def) +{ + g_auto(virBuffer) childrenBuf =3D VIR_BUFFER_INIT_CHILD(buf); + ssize_t n; + + for (n =3D 0; n < def->nthrottlegroups; n++) { + virDomainThrottleGroupFormat(&childrenBuf, def->throttlegroups[n]); + } + + virXMLFormatElement(buf, "throttlegroups", NULL, &childrenBuf); +} + + static void virDomainIOMMUDefFormat(virBuffer *buf, const virDomainIOMMUDef *iommu) @@ -27801,6 +28176,8 @@ virDomainDefFormatInternalSetRootName(virDomainDef = *def, =20 virDomainDefIOThreadsFormat(buf, def); =20 + virDomainDefThrottleGroupsFormat(buf, def); + if (virDomainCputuneDefFormat(buf, def, flags) < 0) return -1; =20 @@ -31034,6 +31411,15 @@ virDomainBlockIoTuneInfoCopy(const virDomainBlockI= oTuneInfo *src, } =20 =20 +void +virDomainThrottleGroupDefCopy(const virDomainThrottleGroupDef *src, + virDomainThrottleGroupDef *dst) +{ + *dst =3D *src; + dst->group_name =3D g_strdup(src->group_name); +} + + bool virDomainBlockIoTuneInfoEqual(const virDomainBlockIoTuneInfo *a, const virDomainBlockIoTuneInfo *b) diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 5925faaf1a..08e2a22aeb 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -464,6 +464,14 @@ struct _virDomainBlockIoTuneInfo { * virDomainBlockIoTuneInfoEqual. */ }; =20 +/* Stores information related to a ThrottleFilter resource. */ +struct _virDomainThrottleFilterDef { + virObject parent; + + unsigned int id; /* throttle filter identifier, 0 is unset */ + char *group_name; + char *nodename; /* node name of throttle filter object */ +}; =20 typedef enum { VIR_DOMAIN_DISK_MIRROR_STATE_NONE =3D 0, /* No job, or job still not s= ynced */ @@ -550,6 +558,9 @@ struct _virDomainDiskDef { =20 virDomainBlockIoTuneInfo blkdeviotune; =20 + size_t nthrottlefilters; + virDomainThrottleFilterDef **throttlefilters; + char *driverName; =20 char *serial; @@ -2992,6 +3003,9 @@ struct _virDomainDef { =20 virDomainDefaultIOThreadDef *defaultIOThread; =20 + size_t nthrottlegroups; + virDomainThrottleGroupDef **throttlegroups; + virDomainCputune cputune; =20 virDomainResctrlDef **resctrls; @@ -4504,3 +4518,43 @@ virDomainObjGetMessages(virDomainObj *vm, =20 bool virDomainDefHasSpiceGraphics(const virDomainDef *def); + +void +virDomainThrottleGroupDefFree(virDomainThrottleGroupDef *def); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainThrottleGroupDef, virDomainThrottle= GroupDefFree); + +void +virDomainThrottleFilterDefFree(virDomainThrottleFilterDef *def); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainThrottleFilterDef, virDomainThrottl= eFilterDefFree); + +virDomainThrottleGroupDef * +virDomainThrottleGroupAdd(virDomainDef *def, + virDomainThrottleGroupDef *throttle_group); + +void +virDomainThrottleGroupUpdate(virDomainDef *def, + virDomainThrottleGroupDef *info); + +virDomainThrottleGroupDef * +virDomainThrottleGroupFind(const virDomainDef *def, + const char *name); + +void +virDomainThrottleGroupDel(virDomainDef *def, + const char *name); + +virDomainThrottleFilterDef * +virDomainThrottleFilterFind(const virDomainDiskDef *def, + const char *name); + +int +virDomainThrottleGroupIndexByName(virDomainDef *def, + const char *name); + +virDomainThrottleGroupDef * +virDomainThrottleGroupByName(virDomainDef *def, + const char *name); + +void +virDomainThrottleGroupDefCopy(const virDomainThrottleGroupDef *src, + virDomainThrottleGroupDef *dst); diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h index 0779bc224b..1cf68b2814 100644 --- a/src/conf/virconftypes.h +++ b/src/conf/virconftypes.h @@ -80,6 +80,10 @@ typedef struct _virDomainBlkiotune virDomainBlkiotune; =20 typedef struct _virDomainBlockIoTuneInfo virDomainBlockIoTuneInfo; =20 +typedef struct _virDomainBlockIoTuneInfo virDomainThrottleGroupDef; + +typedef struct _virDomainThrottleFilterDef virDomainThrottleFilterDef; + typedef struct _virDomainCheckpointDef virDomainCheckpointDef; =20 typedef struct _virDomainCheckpointObj virDomainCheckpointObj; --=20 2.34.1 _______________________________________________ Devel mailing list -- devel@lists.libvirt.org To unsubscribe send an email to devel-leave@lists.libvirt.org From nobody Fri May 17 10:44:00 2024 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 1712887614661622.9919733303516; Thu, 11 Apr 2024 19:06:54 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 8DCAB17F7; Thu, 11 Apr 2024 22:06:53 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id DF8A318CF; Thu, 11 Apr 2024 22:03:24 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id D8EC617C3; Thu, 11 Apr 2024 22:03:16 -0400 (EDT) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (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 DB5D117DF for ; Thu, 11 Apr 2024 22:02:44 -0400 (EDT) Received: from pps.filterd (m0353727.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 43C1gcFe029646 for ; Fri, 12 Apr 2024 02:02:44 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 3xeuh9r174-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:02:43 +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 43C1KNPA029901 for ; Fri, 12 Apr 2024 02:02:42 GMT Received: from smtprelay03.dal12v.mail.ibm.com ([172.16.1.5]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 3xbj7mq0sq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:02:42 +0000 Received: from smtpav05.dal12v.mail.ibm.com (smtpav05.dal12v.mail.ibm.com [10.241.53.104]) by smtprelay03.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 43C22dpg21889770 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 12 Apr 2024 02:02:41 GMT Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2B5E158065; Fri, 12 Apr 2024 02:02:39 +0000 (GMT) Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 374125806B; Fri, 12 Apr 2024 02:02:38 +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:37 +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 02/12] qemu: monitor: Add support for ThrottleGroup operations Date: Thu, 11 Apr 2024 19:01:50 -0700 Message-Id: <20240412020200.2418776-3-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-ORIG-GUID: FT0zEhmL8uMTgHPz3hG_Ld0gegtBP6g_ X-Proofpoint-GUID: FT0zEhmL8uMTgHPz3hG_Ld0gegtBP6g_ 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 priorityscore=1501 lowpriorityscore=0 bulkscore=0 mlxscore=0 spamscore=0 clxscore=1015 suspectscore=0 adultscore=0 mlxlogscore=990 impostorscore=0 phishscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404120013 Message-ID-Hash: BHEZDCK4VEKJR3UD5Z6D3JDTMNKVP4K3 X-Message-ID-Hash: BHEZDCK4VEKJR3UD5Z6D3JDTMNKVP4K3 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: 1712887616413100001 From: Chun Feng Wu * ThrottleGroup is updated through "qemuMonitorJSONUpdateThrottleGroup" * ThrottleGroup is retrieved through "qemuMonitorJSONGetThrottleGroup" * ThrottleGroup is deleted by reusing "qemuMonitorDelObject" * ThrottleGroup is added by reusing "qemuMonitorAddObject" * "qemuMonitorMakeThrottleGroupLimits" will be used by building qemu cmd as= well Signed-off-by: Chun Feng Wu --- src/qemu/qemu_monitor.c | 34 ++++++++ src/qemu/qemu_monitor.h | 14 ++++ src/qemu/qemu_monitor_json.c | 151 +++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 14 ++++ 4 files changed, 213 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 34e2ccab97..2cd122ea9e 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2996,6 +2996,40 @@ qemuMonitorGetBlockIoThrottle(qemuMonitor *mon, } =20 =20 +int +qemuMonitorThrottleGroupLimits(virJSONValue *limits, + const virDomainThrottleGroupDef *group) +{ + return qemuMonitorMakeThrottleGroupLimits(limits, group); +} + + +int +qemuMonitorUpdateThrottleGroup(qemuMonitor *mon, + const char *qomid, + virDomainBlockIoTuneInfo *info) +{ + VIR_DEBUG("qomid=3D%s, info=3D%p", NULLSTR(qomid), info); + + QEMU_CHECK_MONITOR(mon); + + return qemuMonitorJSONUpdateThrottleGroup(mon, qomid, info); +} + + +int +qemuMonitorGetThrottleGroup(qemuMonitor *mon, + const char *groupname, + virDomainBlockIoTuneInfo *reply) +{ + VIR_DEBUG("throttle-group=3D%s, reply=3D%p", NULLSTR(groupname), reply= ); + + QEMU_CHECK_MONITOR(mon); + + return qemuMonitorJSONGetThrottleGroup(mon, groupname, reply); +} + + int qemuMonitorVMStatusToPausedReason(const char *status) { diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 6e81945201..9fbcd3f687 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1061,6 +1061,20 @@ int qemuMonitorGetBlockIoThrottle(qemuMonitor *mon, const char *qdevid, virDomainBlockIoTuneInfo *reply); =20 +int +qemuMonitorThrottleGroupLimits(virJSONValue *limits, + const virDomainThrottleGroupDef *group); + +int +qemuMonitorUpdateThrottleGroup(qemuMonitor *mon, + const char *qomid, + virDomainBlockIoTuneInfo *info); + +int +qemuMonitorGetThrottleGroup(qemuMonitor *mon, + const char *groupname, + virDomainBlockIoTuneInfo *reply); + int qemuMonitorSystemWakeup(qemuMonitor *mon); =20 int qemuMonitorGetVersion(qemuMonitor *mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index eb84a3d938..9abcb40df2 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -4633,6 +4633,157 @@ int qemuMonitorJSONGetBlockIoThrottle(qemuMonitor *= mon, return qemuMonitorJSONBlockIoThrottleInfo(devices, qdevid, reply); } =20 + +int +qemuMonitorMakeThrottleGroupLimits(virJSONValue *limits, + const virDomainThrottleGroupDef *group) +{ + if (virJSONValueObjectAppendNumberLong(limits, "bps-total", group->tot= al_bytes_sec)<0) + return -1; + if (virJSONValueObjectAppendNumberLong(limits, "bps-read", group->read= _bytes_sec)<0) + return -1; + if (virJSONValueObjectAppendNumberLong(limits, "bps-write", group->wri= te_bytes_sec)<0) + return -1; + if (virJSONValueObjectAppendNumberLong(limits, "iops-total", group->to= tal_iops_sec)<0) + return -1; + if (virJSONValueObjectAppendNumberLong(limits, "iops-read", group->rea= d_iops_sec)<0) + return -1; + if (virJSONValueObjectAppendNumberLong(limits, "iops-write", group->wr= ite_iops_sec)<0) + return -1; + if (virJSONValueObjectAppendNumberLong(limits, "bps-total-max", group-= >total_bytes_sec_max)<0) + return -1; + if (virJSONValueObjectAppendNumberLong(limits, "bps-read-max", group->= read_bytes_sec_max)<0) + return -1; + if (virJSONValueObjectAppendNumberLong(limits, "bps-write-max", group-= >write_bytes_sec_max)<0) + return -1; + if (virJSONValueObjectAppendNumberLong(limits, "iops-total-max", group= ->total_iops_sec_max)<0) + return -1; + if (virJSONValueObjectAppendNumberLong(limits, "iops-read-max", group-= >read_iops_sec_max)<0) + return -1; + if (virJSONValueObjectAppendNumberLong(limits, "iops-write-max", group= ->write_iops_sec_max)<0) + return -1; + if (virJSONValueObjectAppendNumberLong(limits, "iops-size", group->siz= e_iops_sec)<0) + return -1; + /* avoid error from QEMU: "the burst length cannot be 0" for throttlel= imits + * when setting max-length + */ + if (virJSONValueObjectAdd(&limits, "P:bps-total-max-length", group->to= tal_bytes_sec_max_length, NULL)<0) + return -1; + if (virJSONValueObjectAdd(&limits, "P:bps-read-max-length", group->rea= d_bytes_sec_max_length, NULL)<0) + return -1; + if (virJSONValueObjectAdd(&limits, "P:bps-write-max-length", group->wr= ite_bytes_sec_max_length, NULL)<0) + return -1; + if (virJSONValueObjectAdd(&limits, "P:iops-total-max-length", group->t= otal_iops_sec_max_length, NULL)<0) + return -1; + if (virJSONValueObjectAdd(&limits, "P:iops-read-max-length", group->re= ad_iops_sec_max_length, NULL)<0) + return -1; + if (virJSONValueObjectAdd(&limits, "P:iops-write-max-length", group->w= rite_iops_sec_max_length, NULL)<0) + return -1; + + return 0; +} + + +int +qemuMonitorJSONUpdateThrottleGroup(qemuMonitor *mon, + const char *qomid, + virDomainBlockIoTuneInfo *info) +{ + g_autoptr(virJSONValue) cmd =3D NULL; + g_autoptr(virJSONValue) result =3D NULL; + g_autoptr(virJSONValue) limits =3D virJSONValueNewObject(); + + if (qemuMonitorMakeThrottleGroupLimits(limits, info)<0) + return -1; + + if (!(cmd =3D qemuMonitorJSONMakeCommand("qom-set", + "s:property", "limits", + "s:path", qomid, + "a:value", &limits, + NULL))) + return -1; + + if (qemuMonitorJSONCommand(mon, cmd, &result) < 0) + return -1; + + if (qemuMonitorJSONCheckError(cmd, result) < 0) + return -1; + + return 0; +} + +#define GET_THROTTLE_GROUP_VALUE(FIELD, STORE) \ + if (virJSONValueObjectHasKey(ret, FIELD)) { \ + if (virJSONValueObjectGetNumberUlong(ret, FIELD, &reply->STORE) < = 0) { \ + virReportError(VIR_ERR_OPERATION_UNSUPPORTED, \ + _("throttle group field '%1$s' missing in qemu's ou= tput"), \ + #STORE); \ + return -1; \ + } \ + } + + +int +qemuMonitorJSONGetThrottleGroup(qemuMonitor *mon, + const char *gname, + virDomainBlockIoTuneInfo *reply) +{ + char fullpath[100]; + g_autoptr(virJSONValue) cmd =3D NULL; + g_autoptr(virJSONValue) result =3D NULL; + g_autofree char *groupCopy =3D NULL; + virJSONValue *ret; + + + g_snprintf(fullpath, sizeof(fullpath), "%s%s", "/objects/", gname); + if (!(cmd =3D qemuMonitorJSONMakeCommand("qom-get", + "s:path", fullpath, + "s:property", "limits", + NULL))) + return -1; + + if (qemuMonitorJSONCommand(mon, cmd, &result) < 0) + return -1; + + if (qemuMonitorJSONCheckError(cmd, result) < 0) + return -1; + + if (!(ret =3D qemuMonitorJSONGetReply(cmd, result, VIR_JSON_TYPE_OBJEC= T))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("throttle group entry was not in expected for= mat")); + return -1; + } + + GET_THROTTLE_GROUP_VALUE("bps-total", total_bytes_sec); + GET_THROTTLE_GROUP_VALUE("bps-read", read_bytes_sec); + GET_THROTTLE_GROUP_VALUE("bps-write", write_bytes_sec); + GET_THROTTLE_GROUP_VALUE("iops-total", total_iops_sec); + GET_THROTTLE_GROUP_VALUE("iops-read", read_iops_sec); + GET_THROTTLE_GROUP_VALUE("iops-write", write_iops_sec); + + GET_THROTTLE_GROUP_VALUE("bps-total-max", total_bytes_sec_max); + GET_THROTTLE_GROUP_VALUE("bps-read-max", read_bytes_sec_max); + GET_THROTTLE_GROUP_VALUE("bps-write-max", write_bytes_sec_max); + GET_THROTTLE_GROUP_VALUE("iops-total-max", total_iops_sec_max); + GET_THROTTLE_GROUP_VALUE("iops-read-max", read_iops_sec_max); + GET_THROTTLE_GROUP_VALUE("iops-write-max", write_iops_sec_max); + GET_THROTTLE_GROUP_VALUE("iops-size", size_iops_sec); + + GET_THROTTLE_GROUP_VALUE("bps-total-max-length", total_bytes_sec_max_l= ength); + GET_THROTTLE_GROUP_VALUE("bps-read-max-length", read_bytes_sec_max_len= gth); + GET_THROTTLE_GROUP_VALUE("bps-write-max-length", write_bytes_sec_max_l= ength); + GET_THROTTLE_GROUP_VALUE("iops-total-max-length", total_iops_sec_max_l= ength); + GET_THROTTLE_GROUP_VALUE("iops-read-max-length", read_iops_sec_max_len= gth); + GET_THROTTLE_GROUP_VALUE("iops-write-max-length", write_iops_sec_max_l= ength); + + groupCopy =3D g_strdup(gname); + reply->group_name =3D g_steal_pointer(&groupCopy); + + return 0; +} +#undef GET_THROTTLE_GROUP_VALUE + + int qemuMonitorJSONSystemWakeup(qemuMonitor *mon) { g_autoptr(virJSONValue) cmd =3D NULL; diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index 9684660d86..fa3138bbf9 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -404,6 +404,20 @@ qemuMonitorJSONSetBlockIoThrottle(qemuMonitor *mon, const char *qomid, virDomainBlockIoTuneInfo *info); =20 +int +qemuMonitorMakeThrottleGroupLimits(virJSONValue *limits, + const virDomainThrottleGroupDef *group); + +int +qemuMonitorJSONUpdateThrottleGroup(qemuMonitor *mon, + const char *qomid, + virDomainBlockIoTuneInfo *info); + +int +qemuMonitorJSONGetThrottleGroup(qemuMonitor *mon, + const char *gname, + virDomainBlockIoTuneInfo *reply); + int qemuMonitorJSONGetBlockIoThrottle(qemuMonitor *mon, const char *qdevid, --=20 2.34.1 _______________________________________________ Devel mailing list -- devel@lists.libvirt.org To unsubscribe send an email to devel-leave@lists.libvirt.org From nobody Fri May 17 10:44:00 2024 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 1712887719255595.2920931822358; Thu, 11 Apr 2024 19:08:39 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 388F91889; Thu, 11 Apr 2024 22:08:38 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 2A13018E1; Thu, 11 Apr 2024 22:03:29 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 4F7F217CE; Thu, 11 Apr 2024 22:03:22 -0400 (EDT) Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (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 79B5A1805 for ; Thu, 11 Apr 2024 22:02:50 -0400 (EDT) Received: from pps.filterd (m0353727.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 43C1ijob031566 for ; Fri, 12 Apr 2024 02:02:49 GMT Received: from ppma22.wdc07v.mail.ibm.com (5c.69.3da9.ip4.static.sl-reverse.com [169.61.105.92]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3xeuh9r178-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:02:48 +0000 Received: from pps.filterd (ppma22.wdc07v.mail.ibm.com [127.0.0.1]) by ppma22.wdc07v.mail.ibm.com (8.17.1.19/8.17.1.19) with ESMTP id 43C09baG019110 for ; Fri, 12 Apr 2024 02:02:47 GMT Received: from smtprelay07.wdc07v.mail.ibm.com ([172.16.1.74]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 3xbh40q9u2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:02:47 +0000 Received: from smtpav05.dal12v.mail.ibm.com (smtpav05.dal12v.mail.ibm.com [10.241.53.104]) by smtprelay07.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 43C22iiu62063050 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 12 Apr 2024 02:02:46 GMT Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6C3DC5806E; Fri, 12 Apr 2024 02:02:44 +0000 (GMT) Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6CA0D58052; Fri, 12 Apr 2024 02:02:43 +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:43 +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 03/12] remote: New APIs for ThrottleGroup lifecycle management Date: Thu, 11 Apr 2024 19:01:51 -0700 Message-Id: <20240412020200.2418776-4-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-ORIG-GUID: 97LRylzxt8fCFFHDjYMbMY5ZfIAH7iIn X-Proofpoint-GUID: 97LRylzxt8fCFFHDjYMbMY5ZfIAH7iIn 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 priorityscore=1501 lowpriorityscore=0 bulkscore=0 mlxscore=0 spamscore=0 clxscore=1015 suspectscore=0 adultscore=0 mlxlogscore=999 impostorscore=0 phishscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404120013 Message-ID-Hash: HZT3AZCI7TRXFZ25BA4TY3JS23D7DLGA X-Message-ID-Hash: HZT3AZCI7TRXFZ25BA4TY3JS23D7DLGA 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: 1712887720575100001 From: Chun Feng Wu Support throttlegroup lifecycle management by the following implementation: * New methods defined in "include/libvirt/libvirt-domain.h" * And they're exported in "src/libvirt_public.syms" * Corresponding internal API is defined in "src/driver-hypervisor.h" * Public API calls are implemented in "src/libvirt-domain.c" * Wire protocol is defined in "src/remote/remote_protocol.x" * RPC client implementation is in "src/remote/remote_driver.c" * Server side dispatch is implemented in "src/remote/remote_daemon_dispatch= .c" * Also "src/remote_protocol-structs" is updated * Yu Jie Gu helped add remote_domain_set_throttle_group_args in src/remote_protocol-structs to fix issue reported by check-remote_protocol Signed-off-by: Chun Feng Wu --- include/libvirt/libvirt-domain.h | 29 +++++ src/driver-hypervisor.h | 22 ++++ src/libvirt-domain.c | 190 ++++++++++++++++++++++++++++ src/libvirt_private.syms | 9 ++ src/libvirt_public.syms | 7 + src/remote/remote_daemon_dispatch.c | 61 +++++++++ src/remote/remote_driver.c | 49 +++++++ src/remote/remote_protocol.x | 50 +++++++- src/remote_protocol-structs | 30 +++++ 9 files changed, 446 insertions(+), 1 deletion(-) diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-dom= ain.h index 2f5b01bbfe..5435ab7fcb 100644 --- a/include/libvirt/libvirt-domain.h +++ b/include/libvirt/libvirt-domain.h @@ -5593,6 +5593,16 @@ typedef void (*virConnectDomainEventJobCompletedCall= back)(virConnectPtr conn, */ # define VIR_DOMAIN_TUNABLE_BLKDEV_WRITE_IOPS_SEC_MAX_LENGTH "blkdeviotune= .write_iops_sec_max_length" =20 +/** + * VIR_DOMAIN_THROTTLE_GROUP: + * + * Macro represents the name of throttle group for which the values are up= dated, + * as VIR_TYPED_PARAM_STRING. + * + * Since: 10.3.0 + */ +# define VIR_DOMAIN_THROTTLE_GROUP "throttlegroup.name" + /** * virConnectDomainEventTunableCallback: * @conn: connection object @@ -6525,4 +6535,23 @@ virDomainGraphicsReload(virDomainPtr domain, unsigned int type, unsigned int flags); =20 +int +virDomainSetThrottleGroup(virDomainPtr dom, + const char *group, + virTypedParameterPtr params, + int nparams, + unsigned int flags); +int +virDomainGetThrottleGroup(virDomainPtr dom, + const char *group, + virTypedParameterPtr params, + int *nparams, + unsigned int flags); + +int +virDomainDelThrottleGroup(virDomainPtr dom, + const char *group, + unsigned int flags); + + #endif /* LIBVIRT_DOMAIN_H */ diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h index 4ce8da078d..2c81fc8ad6 100644 --- a/src/driver-hypervisor.h +++ b/src/driver-hypervisor.h @@ -1453,6 +1453,25 @@ typedef int unsigned int type, unsigned int flags); =20 +typedef int +(*virDrvDomainSetThrottleGroup)(virDomainPtr dom, + const char *groupname, + virTypedParameterPtr params, + int nparams, + unsigned int flags); + +typedef int +(*virDrvDomainGetThrottleGroup)(virDomainPtr dom, + const char *groupname, + virTypedParameterPtr params, + int *nparams, + unsigned int flags); + +typedef int +(*virDrvDomainDelThrottleGroup)(virDomainPtr dom, + const char *groupname, + unsigned int flags); + typedef struct _virHypervisorDriver virHypervisorDriver; =20 /** @@ -1726,4 +1745,7 @@ struct _virHypervisorDriver { virDrvDomainStartDirtyRateCalc domainStartDirtyRateCalc; virDrvDomainFDAssociate domainFDAssociate; virDrvDomainGraphicsReload domainGraphicsReload; + virDrvDomainSetThrottleGroup domainSetThrottleGroup; + virDrvDomainGetThrottleGroup domainGetThrottleGroup; + virDrvDomainDelThrottleGroup domainDelThrottleGroup; }; diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c index 7c6b93963c..da88457601 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -14162,3 +14162,193 @@ virDomainGraphicsReload(virDomainPtr domain, virDispatchError(domain->conn); return -1; } + + +/** + * virDomainSetThrottleGroup: + * @dom: pointer to domain object + * @group: throttle group name + * @params: Pointer to blkio parameter objects + * @nparams: Number of blkio parameters (this value can be the same or + * less than the number of parameters supported) + * @flags: bitwise-OR of virDomainModificationImpact + * + * add or change throttle group. + * + * + * Returns -1 in case of error, 0 in case of success. + * + * Since: 10.3.0 + */ +int +virDomainSetThrottleGroup(virDomainPtr dom, + const char *group, + virTypedParameterPtr params, + int nparams, + unsigned int flags) +{ + virConnectPtr conn; + + VIR_DOMAIN_DEBUG(dom, "params=3D%p, nparams=3D%d, flags=3D0x%x", + params, nparams, flags); + VIR_TYPED_PARAMS_DEBUG(params, nparams); + + virResetLastError(); + + virCheckDomainReturn(dom, -1); + conn =3D dom->conn; + + virCheckReadOnlyGoto(conn->flags, error); + virCheckPositiveArgGoto(nparams, error); + virCheckNonNullArgGoto(params, error); + + if (virTypedParameterValidateSet(dom->conn, params, nparams) < 0) + goto error; + + if (conn->driver->domainSetThrottleGroup) { + int ret; + ret =3D conn->driver->domainSetThrottleGroup(dom, group, params, n= params, flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(dom->conn); + return -1; +} + + +/** + * virDomainGetThrottleGroup: + * @dom: pointer to domain object + * @group: throttle group name + * @params: Pointer to blkio parameter object + * (return value, allocated by the caller) + * @nparams: Pointer to number of blkio parameters + * @flags: bitwise-OR of virDomainModificationImpact and virTypedParameter= Flags + * + * Get all parameters for specific throttle group. On input, + * @nparams gives the size of the @params array; on output, @nparams + * gives how many slots were filled with parameter information, which + * might be less but will not exceed the input value. + * + * As a special case, calling with @params as NULL and @nparams as 0 + * on input will cause @nparams on output to contain the number of + * parameters supported by the hypervisor, either for the given @group + * or if @group is NULL, for all possible groups. The + * caller should then allocate @params array, + * i.e. (sizeof(@virTypedParameter) * @nparams) bytes and call the API + * again. See virDomainGetMemoryParameters() for more details. + * + * + * Returns -1 in case of error, 0 in case of success. + * + * Since: 10.3.0 + */ +int +virDomainGetThrottleGroup(virDomainPtr dom, + const char *group, + virTypedParameterPtr params, + int *nparams, + unsigned int flags) +{ + virConnectPtr conn; + int rc; + + VIR_DOMAIN_DEBUG(dom, "params=3D%p, nparams=3D%d, flags=3D0x%x", + params, (nparams) ? *nparams : -1, flags); + + virResetLastError(); + + virCheckDomainReturn(dom, -1); + + virCheckNonNullArgGoto(nparams, error); + virCheckNonNegativeArgGoto(*nparams, error); + if (*nparams !=3D 0) { + virCheckNonNullArgGoto(params, error); + virCheckNonNullArgGoto(group, error); + } + + rc =3D VIR_DRV_SUPPORTS_FEATURE(dom->conn->driver, dom->conn, + VIR_DRV_FEATURE_TYPED_PARAM_STRING); + if (rc < 0) + goto error; + if (rc) + flags |=3D VIR_TYPED_PARAM_STRING_OKAY; + + VIR_EXCLUSIVE_FLAGS_GOTO(VIR_DOMAIN_AFFECT_LIVE, + VIR_DOMAIN_AFFECT_CONFIG, + error); + + conn =3D dom->conn; + + if (conn->driver->domainGetThrottleGroup) { + int ret; + ret =3D conn->driver->domainGetThrottleGroup(dom, group, params, n= params, flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(dom->conn); + return -1; +} + + +/** + * virDomainDelThrottleGroup: + * @dom: pointer to domain object + * @group: throttle group name + * @flags: bitwise-OR of virDomainModificationImpact and virTypedParameter= Flags + * + * Delete specific throttle group + * + * Returns -1 in case of error, 0 in case of success. + * + * Since: 10.3.0 + */ +int +virDomainDelThrottleGroup(virDomainPtr dom, + const char *group, + unsigned int flags) +{ + virConnectPtr conn; + int rc; + + virResetLastError(); + + virCheckDomainReturn(dom, -1); + + rc =3D VIR_DRV_SUPPORTS_FEATURE(dom->conn->driver, dom->conn, + VIR_DRV_FEATURE_TYPED_PARAM_STRING); + if (rc < 0) + goto error; + if (rc) + flags |=3D VIR_TYPED_PARAM_STRING_OKAY; + + VIR_EXCLUSIVE_FLAGS_GOTO(VIR_DOMAIN_AFFECT_LIVE, + VIR_DOMAIN_AFFECT_CONFIG, + error); + + conn =3D dom->conn; + + if (conn->driver->domainDelThrottleGroup) { + int ret; + ret =3D conn->driver->domainDelThrottleGroup(dom, group, flags); + if (ret < 0) + goto error; + return ret; + } + + virReportUnsupportedError(); + + error: + virDispatchError(dom->conn); + return -1; +} diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 84e30b711c..291844d933 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -668,6 +668,15 @@ virDomainTaintMessageTypeFromString; virDomainTaintMessageTypeToString; virDomainTaintTypeFromString; virDomainTaintTypeToString; +virDomainThrottleFilterDefFree; +virDomainThrottleFilterFind; +virDomainThrottleGroupAdd; +virDomainThrottleGroupByName; +virDomainThrottleGroupDefCopy; +virDomainThrottleGroupDefFree; +virDomainThrottleGroupDel; +virDomainThrottleGroupFind; +virDomainThrottleGroupUpdate; virDomainTimerModeTypeFromString; virDomainTimerModeTypeToString; virDomainTimerNameTypeFromString; diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms index 7a3492d9d7..25560bb501 100644 --- a/src/libvirt_public.syms +++ b/src/libvirt_public.syms @@ -948,4 +948,11 @@ LIBVIRT_10.2.0 { virDomainGraphicsReload; } LIBVIRT_10.1.0; =20 +LIBVIRT_10.3.0 { + global: + virDomainSetThrottleGroup; + virDomainGetThrottleGroup; + virDomainDelThrottleGroup; +} LIBVIRT_10.2.0; + # .... define new API here using predicted next version number .... diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon= _dispatch.c index cfc1067e40..230c898b62 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -3614,6 +3614,67 @@ remoteDispatchDomainGetBlockIoTune(virNetServer *ser= ver G_GNUC_UNUSED, return rv; } =20 + +static int +remoteDispatchDomainGetThrottleGroup(virNetServer *server G_GNUC_UNUSED, + virNetServerClient *client, + virNetMessage *hdr G_GNUC_UNUSED, + struct virNetMessageError *rerr, + remote_domain_get_throttle_group_args= *args, + remote_domain_get_throttle_group_ret = *ret) +{ + virDomainPtr dom =3D NULL; + int rv =3D -1; + virTypedParameterPtr params =3D NULL; + int nparams =3D 0; + virConnectPtr conn =3D remoteGetHypervisorConn(client); + + if (!conn) + goto cleanup; + + if (args->nparams > REMOTE_DOMAIN_THROTTLE_GROUP_PARAMETERS_MAX) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"= )); + goto cleanup; + } + + if (args->nparams) + params =3D g_new0(virTypedParameter, args->nparams); + nparams =3D args->nparams; + + if (!(dom =3D get_nonnull_domain(conn, args->dom))) + goto cleanup; + + if (virDomainGetThrottleGroup(dom, args->group ? *args->group : NULL, + params, &nparams, args->flags) < 0) + goto cleanup; + + /* In this case, we need to send back the number of parameters + * supported + */ + if (args->nparams =3D=3D 0) { + ret->nparams =3D nparams; + goto success; + } + + /* Serialize the block I/O tuning parameters. */ + if (virTypedParamsSerialize(params, nparams, + REMOTE_DOMAIN_THROTTLE_GROUP_PARAMETERS_MA= X, + (struct _virTypedParameterRemote **) &ret-= >params.params_val, + &ret->params.params_len, + args->flags) < 0) + goto cleanup; + + success: + rv =3D 0; + + cleanup: + if (rv < 0) + virNetMessageSaveError(rerr); + virTypedParamsFree(params, nparams); + virObjectUnref(dom); + return rv; +} + /*-------------------------------------------------------------*/ =20 static int diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 7b73d97b7a..930cf666b5 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2583,6 +2583,52 @@ static int remoteDomainGetBlockIoTune(virDomainPtr d= omain, return 0; } =20 + +static int +remoteDomainGetThrottleGroup(virDomainPtr domain, + const char *group, + virTypedParameterPtr params, + int *nparams, + unsigned int flags) +{ + remote_domain_get_throttle_group_args args =3D {0}; + g_auto(remote_domain_get_throttle_group_ret) ret =3D {0}; + struct private_data *priv =3D domain->conn->privateData; + VIR_LOCK_GUARD lock =3D remoteDriverLock(priv); + + make_nonnull_domain(&args.dom, domain); + args.group =3D group ? (char **)&group : NULL; + args.nparams =3D *nparams; + args.flags =3D flags; + + if (call(domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_THROTTLE_GROUP, + (xdrproc_t) xdr_remote_domain_get_throttle_group_args, + (char *) &args, + (xdrproc_t) xdr_remote_domain_get_throttle_group_ret, + (char *) &ret) =3D=3D -1) { + return -1; + } + + /* Handle the case when the caller does not know the number of paramet= ers + * and is asking for the number of parameters supported + */ + if (*nparams =3D=3D 0) { + *nparams =3D ret.nparams; + return 0; + } + + if (virTypedParamsDeserialize((struct _virTypedParameterRemote *) ret.= params.params_val, + ret.params.params_len, + REMOTE_DOMAIN_THROTTLE_GROUP_PARAMETERS_= MAX, + ¶ms, + nparams) < 0) + return -1; + + return 0; + +} + + static int remoteDomainGetCPUStats(virDomainPtr domain, virTypedParameterPtr params, unsigned int nparams, @@ -7842,6 +7888,9 @@ static virHypervisorDriver hypervisor_driver =3D { .domainSetLaunchSecurityState =3D remoteDomainSetLaunchSecurityState, = /* 8.0.0 */ .domainFDAssociate =3D remoteDomainFDAssociate, /* 9.0.0 */ .domainGraphicsReload =3D remoteDomainGraphicsReload, /* 10.2.0 */ + .domainSetThrottleGroup =3D remoteDomainSetThrottleGroup, /* 10.3.0 */ + .domainGetThrottleGroup =3D remoteDomainGetThrottleGroup, /* 10.3.0 */ + .domainDelThrottleGroup =3D remoteDomainDelThrottleGroup, /* 10.3.0 */ }; =20 static virNetworkDriver network_driver =3D { diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 41c045ff78..4cb2c8b555 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -113,6 +113,9 @@ const REMOTE_DOMAIN_MEMORY_PARAMETERS_MAX =3D 16; /* Upper limit on list of blockio tuning parameters. */ const REMOTE_DOMAIN_BLOCK_IO_TUNE_PARAMETERS_MAX =3D 32; =20 +/* Upper limit on list of throttle group parameters. */ +const REMOTE_DOMAIN_THROTTLE_GROUP_PARAMETERS_MAX =3D 32; + /* Upper limit on list of numa parameters. */ const REMOTE_DOMAIN_NUMA_PARAMETERS_MAX =3D 16; =20 @@ -1475,6 +1478,31 @@ struct remote_domain_get_block_io_tune_ret { int nparams; }; =20 +struct remote_domain_set_throttle_group_args { + remote_nonnull_domain dom; + remote_nonnull_string group; + remote_typed_param params; + unsigned int flags; +}; + +struct remote_domain_get_throttle_group_args { + remote_nonnull_domain dom; + remote_string group; + int nparams; + unsigned int flags; +}; + +struct remote_domain_get_throttle_group_ret { + remote_typed_param params; + int nparams; +}; + +struct remote_domain_del_throttle_group_args { + remote_nonnull_domain dom; + remote_string group; + unsigned int flags; +}; + struct remote_domain_get_cpu_stats_args { remote_nonnull_domain dom; unsigned int nparams; @@ -7048,5 +7076,25 @@ enum remote_procedure { * @generate: both * @acl: domain:write */ - REMOTE_PROC_DOMAIN_GRAPHICS_RELOAD =3D 448 + REMOTE_PROC_DOMAIN_GRAPHICS_RELOAD =3D 448, + + /** + * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG + */ + REMOTE_PROC_DOMAIN_SET_THROTTLE_GROUP =3D 449, + + /** + * @generate: none + * @acl: domain:read + */ + REMOTE_PROC_DOMAIN_GET_THROTTLE_GROUP =3D 450, + + /** + * @generate: both + * @acl: domain:read + */ + REMOTE_PROC_DOMAIN_DEL_THROTTLE_GROUP =3D 451 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 4d3dc2d249..5adbea0336 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1050,6 +1050,33 @@ struct remote_domain_get_block_io_tune_ret { } params; int nparams; }; +struct remote_domain_set_throttle_group_args { + remote_nonnull_domain dom; + remote_nonnull_string group; + struct { + u_int params_len; + remote_typed_param * params_val; + } params; + u_int flags; +}; +struct remote_domain_get_throttle_group_args { + remote_nonnull_domain dom; + remote_string group; + int nparams; + u_int flags; +}; +struct remote_domain_get_throttle_group_ret { + struct { + u_int params_len; + remote_typed_param * params_val; + } params; + int nparams; +}; +struct remote_domain_del_throttle_group_args { + remote_nonnull_domain dom; + remote_string group; + u_int flags; +}; struct remote_domain_get_cpu_stats_args { remote_nonnull_domain dom; u_int nparams; @@ -3755,4 +3782,7 @@ enum remote_procedure { REMOTE_PROC_NETWORK_EVENT_CALLBACK_METADATA_CHANGE =3D 446, REMOTE_PROC_NODE_DEVICE_UPDATE =3D 447, REMOTE_PROC_DOMAIN_GRAPHICS_RELOAD =3D 448, + REMOTE_PROC_DOMAIN_SET_THROTTLE_GROUP =3D 449, + REMOTE_PROC_DOMAIN_GET_THROTTLE_GROUP =3D 450, + REMOTE_PROC_DOMAIN_DEL_THROTTLE_GROUP =3D 451, }; --=20 2.34.1 _______________________________________________ Devel mailing list -- devel@lists.libvirt.org To unsubscribe send an email to devel-leave@lists.libvirt.org From nobody Fri May 17 10:44:00 2024 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 From nobody Fri May 17 10:44:00 2024 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 1712888031577536.6733670224576; Thu, 11 Apr 2024 19:13:51 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 002831A7F; Thu, 11 Apr 2024 22:13:46 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 6290A1907; Thu, 11 Apr 2024 22:03:47 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 1769A17CE; Thu, 11 Apr 2024 22:03:39 -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 9B41817D0 for ; Thu, 11 Apr 2024 22:03:00 -0400 (EDT) Received: from pps.filterd (m0353722.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 43C1piio008770 for ; Fri, 12 Apr 2024 02:03:00 GMT Received: from ppma12.dal12v.mail.ibm.com (dc.9e.1632.ip4.static.sl-reverse.com [50.22.158.220]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3xeu1e822a-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:02:59 +0000 Received: from pps.filterd (ppma12.dal12v.mail.ibm.com [127.0.0.1]) by ppma12.dal12v.mail.ibm.com (8.17.1.19/8.17.1.19) with ESMTP id 43BNnjiA013544 for ; Fri, 12 Apr 2024 02:02:59 GMT Received: from smtprelay05.wdc07v.mail.ibm.com ([172.16.1.72]) by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 3xbgqtyc97-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:02:59 +0000 Received: from smtpav05.dal12v.mail.ibm.com (smtpav05.dal12v.mail.ibm.com [10.241.53.104]) by smtprelay05.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 43C22tR114090942 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 12 Apr 2024 02:02:57 GMT Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 575715806D; Fri, 12 Apr 2024 02:02:55 +0000 (GMT) Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2965F58052; Fri, 12 Apr 2024 02:02:54 +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:53 +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 05/12] qemu: hotplug: Support hot attach block disk along with throttle filters Date: Thu, 11 Apr 2024 19:01:53 -0700 Message-Id: <20240412020200.2418776-6-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: OcitvXwB8BEB1OYulDShHsX2dt5rZ2up X-Proofpoint-ORIG-GUID: OcitvXwB8BEB1OYulDShHsX2dt5rZ2up 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 phishscore=0 malwarescore=0 mlxscore=0 lowpriorityscore=0 adultscore=0 clxscore=1015 suspectscore=0 impostorscore=0 bulkscore=0 spamscore=0 priorityscore=1501 mlxlogscore=999 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404120013 Message-ID-Hash: SZ5CIAUCE5EFAYOCG3OZKI25SU5FYIKN X-Message-ID-Hash: SZ5CIAUCE5EFAYOCG3OZKI25SU5FYIKN 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: 1712888033469100001 From: Chun Feng Wu When attaching disk along with specified throttle groups, those groups will= be chained up by parent node name, this change includes service side codes: * Each filter references one throttle group by group name * Each filter has a nodename, and those filters are chained up in sequence * Filter nodename index is persistented in virDomainObj->privateData(qemuDo= mainObjPrivate) * During hotplug, filter is created through QMP request("blockdev-add" with= "driver":"throttle") to QEMU * Finally, "device_add"(attach) QMP request is adjusted to set "drive" to b= e top filter nodename in chain. Signed-off-by: Chun Feng Wu --- src/qemu/qemu_block.c | 131 ++++++++++++++++++ src/qemu/qemu_block.h | 53 +++++++ src/qemu/qemu_command.c | 64 +++++++++ src/qemu/qemu_command.h | 6 + src/qemu/qemu_domain.c | 71 ++++++++++ src/qemu/qemu_domain.h | 19 ++- src/qemu/qemu_hotplug.c | 24 ++++ .../qemustatusxml2xmldata/backup-pull-in.xml | 1 + .../blockjob-blockdev-in.xml | 1 + .../blockjob-mirror-in.xml | 1 + .../migration-in-params-in.xml | 1 + .../migration-out-nbd-bitmaps-in.xml | 1 + .../migration-out-nbd-out.xml | 1 + .../migration-out-nbd-tls-out.xml | 1 + .../migration-out-params-in.xml | 1 + tests/qemustatusxml2xmldata/modern-in.xml | 1 + tests/qemustatusxml2xmldata/upgrade-out.xml | 1 + .../qemustatusxml2xmldata/vcpus-multi-in.xml | 1 + 18 files changed, 375 insertions(+), 4 deletions(-) diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 738b72d7ea..c53de2465e 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -2739,6 +2739,137 @@ qemuBlockStorageSourceCreateDetectSize(GHashTable *= blockNamedNodeData, } =20 =20 +void +qemuBlockThrottleFilterSetNodename(virDomainThrottleFilterDef *filter, + char *nodename) +{ + g_free(filter->nodename); + filter->nodename =3D nodename; +} + + +const char * +qemuBlockThrottleFilterGetNodename(virDomainThrottleFilterDef *filter) +{ + return filter->nodename; +} + + +/** + * qemuBlockThrottleFilterGetProps: + * @filter: throttle filter + * @parentNodeName: parent nodename of @filter + * + * Build "arguments" part of "blockdev-add" QMP cmd. + * e.g. {"execute":"blockdev-add", "arguments":{"driver":"throttle", + * "node-name":"libvirt-2-filter", "throttle-group":"limits0", + * "file": "libvirt-1-format"}} + */ +virJSONValue * +qemuBlockThrottleFilterGetProps(virDomainThrottleFilterDef *filter, + const char *parentNodeName) +{ + g_autoptr(virJSONValue) props =3D NULL; + + if (virJSONValueObjectAdd(&props, + "s:driver", "throttle", + "s:node-name", qemuBlockThrottleFilterGetNod= ename(filter), + "s:throttle-group", filter->group_name, + "s:file", parentNodeName, + NULL) < 0) + return 0; + + return g_steal_pointer(&props); +} + + +void +qemuBlockThrottleFilterAttachDataFree(qemuBlockThrottleFilterAttachData *d= ata) +{ + if (!data) + return; + + virJSONValueFree(data->filterProps); + g_free(data); +} + + +qemuBlockThrottleFilterAttachData * +qemuBlockThrottleFilterAttachPrepareBlockdev(virDomainThrottleFilterDef *f= ilter, + const char *parentNodeName) +{ + g_autoptr(qemuBlockThrottleFilterAttachData) data =3D NULL; + + data =3D g_new0(qemuBlockThrottleFilterAttachData, 1); + + if (!(data->filterProps =3D qemuBlockThrottleFilterGetProps(filter, pa= rentNodeName))) + return NULL; + + data->filterNodeName =3D qemuBlockThrottleFilterGetNodename(filter); + data->filterAttached =3D true; + + return g_steal_pointer(&data); +} + + +void +qemuBlockThrottleFilterAttachRollback(qemuMonitor *mon, + qemuBlockThrottleFilterAttachData *d= ata) +{ + virErrorPtr orig_err; + + virErrorPreserveLast(&orig_err); + + if (data->filterAttached) + ignore_value(qemuMonitorBlockdevDel(mon, data->filterNodeName)); + + virErrorRestore(&orig_err); +} + + +void +qemuBlockThrottleFilterChainDataFree(qemuBlockThrottleFilterChainData *dat= a) +{ + size_t i; + + if (!data) + return; + + for (i =3D 0; i < data->nfilterdata; i++) + qemuBlockThrottleFilterAttachDataFree(data->filterdata[i]); + + g_free(data->filterdata); + g_free(data); +} + + +int +qemuBlockThrottleFilterChainAttach(qemuMonitor *mon, + qemuBlockThrottleFilterChainData *data) +{ + size_t i; + + for (i =3D 0; i < data->nfilterdata; i++) { + if (qemuMonitorBlockdevAdd(mon, &data->filterdata[i]->filterProps)= < 0) + return -1; + data->filterdata[i]->filterAttached =3D true; + } + + return 0; +} + + +void +qemuBlockThrottleFilterChainDetach(qemuMonitor *mon, + qemuBlockThrottleFilterChainData *data) +{ + size_t i; + + for (i =3D data->nfilterdata; i > 0; i--) + qemuBlockThrottleFilterAttachRollback(mon, data->filterdata[i-1]); +} + + int qemuBlockRemoveImageMetadata(virQEMUDriver *driver, virDomainObj *vm, diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h index f9e961d85d..09e2b9bdad 100644 --- a/src/qemu/qemu_block.h +++ b/src/qemu/qemu_block.h @@ -214,6 +214,59 @@ qemuBlockStorageSourceCreateDetectSize(GHashTable *blo= ckNamedNodeData, virStorageSource *src, virStorageSource *templ); =20 +void +qemuBlockThrottleFilterSetNodename(virDomainThrottleFilterDef *filter, + char *nodename); + +const char * +qemuBlockThrottleFilterGetNodename(virDomainThrottleFilterDef *filter); + +virJSONValue * +qemuBlockThrottleFilterGetProps(virDomainThrottleFilterDef *filter, + const char *parentNodeName); + +typedef struct qemuBlockThrottleFilterAttachData qemuBlockThrottleFilterAt= tachData; +struct qemuBlockThrottleFilterAttachData { + virJSONValue *filterProps; + const char *filterNodeName; + bool filterAttached; +}; + +qemuBlockThrottleFilterAttachData * +qemuBlockThrottleFilterAttachPrepareBlockdev(virDomainThrottleFilterDef *t= hrottlefilter, + const char *parentNodeName); + +void +qemuBlockThrottleFilterAttachDataFree(qemuBlockThrottleFilterAttachData *d= ata); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuBlockThrottleFilterAttachData, + qemuBlockThrottleFilterAttachDataFree); + +void +qemuBlockThrottleFilterAttachRollback(qemuMonitor *mon, + qemuBlockThrottleFilterAttachData *d= ata); + +struct _qemuBlockThrottleFilterChainData { + qemuBlockThrottleFilterAttachData **filterdata; + size_t nfilterdata; +}; + +typedef struct _qemuBlockThrottleFilterChainData qemuBlockThrottleFilterCh= ainData; + +void +qemuBlockThrottleFilterChainDataFree(qemuBlockThrottleFilterChainData *dat= a); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(qemuBlockThrottleFilterChainData, + qemuBlockThrottleFilterChainDataFree); + +int +qemuBlockThrottleFilterChainAttach(qemuMonitor *mon, + qemuBlockThrottleFilterChainData *data); + +void +qemuBlockThrottleFilterChainDetach(qemuMonitor *mon, + qemuBlockThrottleFilterChainData *data); + int qemuBlockRemoveImageMetadata(virQEMUDriver *driver, virDomainObj *vm, diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 9d4563861f..2d8036c3ae 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1577,6 +1577,13 @@ qemuDiskConfigBlkdeviotuneEnabled(const virDomainDis= kDef *disk) } =20 =20 +bool +qemuDiskConfigThrottleFilterChainEnabled(const virDomainDiskDef *disk) +{ + return disk->nthrottlefilters > 0; +} + + /** * qemuDiskBusIsSD: * @bus: disk bus @@ -1936,6 +1943,11 @@ qemuBuildDiskDeviceProps(const virDomainDef *def, } else { if (qemuDomainDiskGetBackendAlias(disk, &drive) < 0) return NULL; + + /* make sure device drive points to top throttle filter */ + if (qemuDiskConfigThrottleFilterChainEnabled(disk)) { + drive =3D g_strdup(disk->throttlefilters[disk->nthrottlefilter= s-1]->nodename); + } } =20 /* bootindex for floppies is configured via the fdc controller */ @@ -11026,6 +11038,58 @@ qemuBuildStorageSourceChainAttachPrepareBlockdevOn= e(qemuBlockStorageSourceChainD } =20 =20 +/** + * qemuBuildThrottleFilterChainAttachPrepareBlockdevOne: + * @data: filter chain data, which consists of array of filters and size o= f such array + * @throttlefilter: new filter to be added into filter array + * @parentNodeName: parent nodename for this new throttlefilter, which is = used to build "blockdev-add" QMP request + * + * Build filter node chain to provide more flexibility for block disk I/O = limits + */ +static int +qemuBuildThrottleFilterChainAttachPrepareBlockdevOne(qemuBlockThrottleFilt= erChainData *data, + virDomainThrottleFilt= erDef *throttlefilter, + const char *parentNod= eName) +{ + g_autoptr(qemuBlockThrottleFilterAttachData) elem =3D NULL; + + if (!(elem =3D qemuBlockThrottleFilterAttachPrepareBlockdev(throttlefi= lter, parentNodeName))) + return -1; + + VIR_APPEND_ELEMENT(data->filterdata, data->nfilterdata, elem); + return 0; +} + + +/** + * qemuBuildThrottleFilterChainAttachPrepareBlockdev: + * @disk: domain disk + * + * Build filter node chain to provide more flexibility for block disk I/O = limits + */ +qemuBlockThrottleFilterChainData * +qemuBuildThrottleFilterChainAttachPrepareBlockdev(virDomainDiskDef *disk) +{ + g_autoptr(qemuBlockThrottleFilterChainData) data =3D NULL; + size_t i; + const char * parentNodeName =3D NULL; + g_autofree char *tmp_nodename =3D NULL; + + data =3D g_new0(qemuBlockThrottleFilterChainData, 1); + /* get starting parentNodename, e.g. libvirt-1-format */ + parentNodeName =3D qemuBlockStorageSourceGetEffectiveNodename(disk->sr= c); + /* build filterdata, which contains all filters info and sequence info= through parentNodeName */ + for (i =3D 0; i < disk->nthrottlefilters; i++) { + tmp_nodename =3D g_strdup(parentNodeName); + if (qemuBuildThrottleFilterChainAttachPrepareBlockdevOne(data, dis= k->throttlefilters[i], tmp_nodename) < 0) + return NULL; + parentNodeName =3D disk->throttlefilters[i]->nodename; + } + + return g_steal_pointer(&data); +} + + /** * qemuBuildStorageSourceChainAttachPrepareBlockdev: * @top: storage source chain diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 341ec43f9a..e2dee47906 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -116,6 +116,12 @@ qemuBlockStorageSourceChainData * qemuBuildStorageSourceChainAttachPrepareBlockdevTop(virStorageSource *top, virStorageSource *back= ingStore); =20 +qemuBlockThrottleFilterChainData * +qemuBuildThrottleFilterChainAttachPrepareBlockdev(virDomainDiskDef *disk); + +bool +qemuDiskConfigThrottleFilterChainEnabled(const virDomainDiskDef *disk); + virJSONValue * qemuBuildDiskDeviceProps(const virDomainDef *def, virDomainDiskDef *disk, diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index b676f59c3a..0d80f15f05 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -684,6 +684,19 @@ qemuDomainStorageIDNew(qemuDomainObjPrivate *priv) } =20 =20 +/** + * qemuDomainThrottleFilterIDNew: + * @priv: qemu VM private data object. + * + * Generate a new unique id for throttle filter object. Useful for node na= me generation. + */ +static unsigned int +qemuDomainThrottleFilterIDNew(qemuDomainObjPrivate *priv) +{ + return ++priv->filternodenameindex; +} + + /** * qemuDomainStorageIDReset: * @priv: qemu VM private data object. @@ -698,6 +711,20 @@ qemuDomainStorageIDReset(qemuDomainObjPrivate *priv) } =20 =20 +/** + * qemuDomainThrottleFilterIDReset: + * @priv: qemu VM private data object. + * + * Resets the data for the node name generator. The node names need to be = unique + * for a single instance, so can be reset on VM shutdown. + */ +static void +qemuDomainThrottleFilterIDReset(qemuDomainObjPrivate *priv) +{ + priv->filternodenameindex =3D 0; +} + + /** * qemuDomainFDSetIDNew: * @priv: qemu VM private data object. @@ -1853,6 +1880,8 @@ qemuDomainObjPrivateDataClear(qemuDomainObjPrivate *p= riv) /* reset node name allocator */ qemuDomainStorageIDReset(priv); =20 + qemuDomainThrottleFilterIDReset(priv); + qemuDomainFDSetIDReset(priv); =20 priv->dbusDaemonRunning =3D false; @@ -2649,6 +2678,8 @@ qemuDomainObjPrivateXMLFormat(virBuffer *buf, =20 virBufferAsprintf(buf, "\n", priv->nodenamei= ndex); =20 + virBufferAsprintf(buf, "\n", priv->fil= ternodenameindex); + virBufferAsprintf(buf, "\n", priv->fdsetindex); =20 if (priv->memPrealloc) @@ -3376,6 +3407,7 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, return -1; =20 qemuDomainStorageIDReset(priv); + qemuDomainThrottleFilterIDReset(priv); if (virXPathULongLong("string(./nodename/@index)", ctxt, &priv->nodenameindex) =3D=3D -2) { virReportError(VIR_ERR_XML_ERROR, "%s", @@ -3383,6 +3415,13 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, return -1; } =20 + if (virXPathULongLong("string(./filternodename/@index)", ctxt, + &priv->filternodenameindex) =3D=3D -2) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("failed to parse filter node name index")); + return -1; + } + if (virXPathUInt("string(./fdset/@index)", ctxt, &priv->fdsetindex) = =3D=3D 0) priv->fdsetindexParsed =3D true; =20 @@ -11348,6 +11387,32 @@ qemuDomainPrepareStorageSourceBlockdevNodename(vir= DomainDiskDef *disk, } =20 =20 +int +qemuDomainPrepareThrottleFilterBlockdevNodename(virDomainThrottleFilterDef= *filter, + const char *nodenameprefix) +{ + char *nodename =3D g_strdup_printf("%s-filter", nodenameprefix); + + qemuBlockThrottleFilterSetNodename(filter, nodename); + + return 0; +} + + +int +qemuDomainPrepareThrottleFilterBlockdev(virDomainThrottleFilterDef *filter, + qemuDomainObjPrivate *priv) +{ + g_autofree char *nodenameprefix =3D NULL; + + filter->id =3D qemuDomainThrottleFilterIDNew(priv); + + nodenameprefix =3D g_strdup_printf("libvirt-%u", filter->id); + + return qemuDomainPrepareThrottleFilterBlockdevNodename(filter, nodena= meprefix); +} + + int qemuDomainPrepareStorageSourceBlockdev(virDomainDiskDef *disk, virStorageSource *src, @@ -11371,6 +11436,7 @@ qemuDomainPrepareDiskSourceBlockdev(virDomainDiskDe= f *disk, { qemuDomainDiskPrivate *diskPriv =3D QEMU_DOMAIN_DISK_PRIVATE(disk); virStorageSource *n; + size_t i; =20 if (disk->copy_on_read =3D=3D VIR_TRISTATE_SWITCH_ON && !diskPriv->nodeCopyOnRead) @@ -11381,6 +11447,11 @@ qemuDomainPrepareDiskSourceBlockdev(virDomainDiskD= ef *disk, return -1; } =20 + for (i =3D 0; i < disk->nthrottlefilters; i++) { + if (qemuDomainPrepareThrottleFilterBlockdev(disk->throttlefilters[= i], priv) < 0) + return -1; + } + return 0; } =20 diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index 49e4da435b..a6158b39a9 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -204,6 +204,9 @@ struct _qemuDomainObjPrivate { /* counter for generating node names for qemu disks */ unsigned long long nodenameindex; =20 + /* counter for generating node names for throttle filters */ + unsigned long long filternodenameindex; + /* counter for generating IDs of fdsets */ unsigned int fdsetindex; bool fdsetindexParsed; @@ -772,6 +775,18 @@ int qemuDomainPrepareStorageSourceBlockdev(virDomainDi= skDef *disk, qemuDomainObjPrivate *priv, virQEMUDriverConfig *cfg); =20 +int +qemuDomainPrepareThrottleFilterBlockdev(virDomainThrottleFilterDef *filter, + qemuDomainObjPrivate *priv); + +int +qemuDomainPrepareThrottleFilterBlockdevNodename(virDomainThrottleFilterDef= *filter, + const char *nodenameprefix= ); + +virDomainThrottleGroupDef * +qemuDomainThrottleGroupByName(virDomainDef *def, + const char *name); + void qemuDomainCleanupAdd(virDomainObj *vm, qemuDomainCleanupCallback cb); void qemuDomainCleanupRemove(virDomainObj *vm, @@ -880,10 +895,6 @@ 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_hotplug.c b/src/qemu/qemu_hotplug.c index 62dc879ed4..37d766b707 100644 --- a/src/qemu/qemu_hotplug.c +++ b/src/qemu/qemu_hotplug.c @@ -656,6 +656,7 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, virDomainAsyncJob asyncJob) { g_autoptr(qemuBlockStorageSourceChainData) data =3D NULL; + g_autoptr(qemuBlockThrottleFilterChainData) filterData =3D NULL; qemuDomainObjPrivate *priv =3D vm->privateData; g_autoptr(virJSONValue) devprops =3D NULL; bool extensionDeviceAttached =3D false; @@ -694,6 +695,19 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, if (rc < 0) goto rollback; =20 + /* Setup throttling filter chain + * add additional "blockdev-add"(throttle filter) between "blockdev= -add" (qemuBlockStorageSourceChainAttach) and "device_add" (qemuDomainAttac= hExtensionDevice) + */ + if ((filterData =3D qemuBuildThrottleFilterChainAttachPrepareBlock= dev(disk))) { + if (qemuDomainObjEnterMonitorAsync(vm, asyncJob) < 0) + return -1; + /* QMP requests("blockdev-add" with "driver":"throttle") to QE= MU */ + rc =3D qemuBlockThrottleFilterChainAttach(priv->mon, filterDat= a); + qemuDomainObjExitMonitor(vm); + if (rc < 0) + goto rollback; + } + if (disk->transient) { g_autoptr(qemuBlockStorageSourceAttachData) backend =3D NULL; g_autoptr(GHashTable) blockNamedNodeData =3D NULL; @@ -765,6 +779,8 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, if (extensionDeviceAttached) ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &disk->inf= o)); =20 + qemuBlockThrottleFilterChainDetach(priv->mon, filterData); + qemuBlockStorageSourceChainDetach(priv->mon, data); =20 qemuDomainObjExitMonitor(vm); @@ -4504,6 +4520,7 @@ qemuDomainRemoveDiskDevice(virQEMUDriver *driver, { qemuDomainDiskPrivate *diskPriv =3D QEMU_DOMAIN_DISK_PRIVATE(disk); g_autoptr(qemuBlockStorageSourceChainData) diskBackend =3D NULL; + g_autoptr(qemuBlockThrottleFilterChainData) filterData =3D NULL; size_t i; qemuDomainObjPrivate *priv =3D vm->privateData; int ret =3D -1; @@ -4542,6 +4559,13 @@ qemuDomainRemoveDiskDevice(virQEMUDriver *driver, } } =20 + qemuDomainObjEnterMonitor(vm); + /* QMP request("blockdev-del") to QEMU to delete throttle filter*/ + if ((filterData =3D qemuBuildThrottleFilterChainAttachPrepareBlockdev(= disk))) { + qemuBlockThrottleFilterChainDetach(priv->mon, filterData); + } + qemuDomainObjExitMonitor(vm); + qemuDomainObjEnterMonitor(vm); =20 if (diskBackend) diff --git a/tests/qemustatusxml2xmldata/backup-pull-in.xml b/tests/qemusta= tusxml2xmldata/backup-pull-in.xml index e7fdc6c478..0a7b8bc7ee 100644 --- a/tests/qemustatusxml2xmldata/backup-pull-in.xml +++ b/tests/qemustatusxml2xmldata/backup-pull-in.xml @@ -234,6 +234,7 @@ + diff --git a/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml b/tests/q= emustatusxml2xmldata/blockjob-blockdev-in.xml index 380ef053d2..c29bbaca81 100644 --- a/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml +++ b/tests/qemustatusxml2xmldata/blockjob-blockdev-in.xml @@ -233,6 +233,7 @@ + diff --git a/tests/qemustatusxml2xmldata/blockjob-mirror-in.xml b/tests/qem= ustatusxml2xmldata/blockjob-mirror-in.xml index 1bcdeffcb8..0e0f52fecf 100644 --- a/tests/qemustatusxml2xmldata/blockjob-mirror-in.xml +++ b/tests/qemustatusxml2xmldata/blockjob-mirror-in.xml @@ -23,6 +23,7 @@ + -2 diff --git a/tests/qemustatusxml2xmldata/migration-in-params-in.xml b/tests= /qemustatusxml2xmldata/migration-in-params-in.xml index 03773a089b..5510c139f8 100644 --- a/tests/qemustatusxml2xmldata/migration-in-params-in.xml +++ b/tests/qemustatusxml2xmldata/migration-in-params-in.xml @@ -257,6 +257,7 @@ + -2 diff --git a/tests/qemustatusxml2xmldata/migration-out-nbd-bitmaps-in.xml b= /tests/qemustatusxml2xmldata/migration-out-nbd-bitmaps-in.xml index 4ee44ffbd4..cd38bf3e30 100644 --- a/tests/qemustatusxml2xmldata/migration-out-nbd-bitmaps-in.xml +++ b/tests/qemustatusxml2xmldata/migration-out-nbd-bitmaps-in.xml @@ -343,6 +343,7 @@ + diff --git a/tests/qemustatusxml2xmldata/migration-out-nbd-out.xml b/tests/= qemustatusxml2xmldata/migration-out-nbd-out.xml index de92146eaa..0d8cb8be6a 100644 --- a/tests/qemustatusxml2xmldata/migration-out-nbd-out.xml +++ b/tests/qemustatusxml2xmldata/migration-out-nbd-out.xml @@ -260,6 +260,7 @@ + -2 diff --git a/tests/qemustatusxml2xmldata/migration-out-nbd-tls-out.xml b/te= sts/qemustatusxml2xmldata/migration-out-nbd-tls-out.xml index 6bdd128259..75b019cb23 100644 --- a/tests/qemustatusxml2xmldata/migration-out-nbd-tls-out.xml +++ b/tests/qemustatusxml2xmldata/migration-out-nbd-tls-out.xml @@ -289,6 +289,7 @@ + -2 diff --git a/tests/qemustatusxml2xmldata/migration-out-params-in.xml b/test= s/qemustatusxml2xmldata/migration-out-params-in.xml index 24ee86e4c0..1e786953e7 100644 --- a/tests/qemustatusxml2xmldata/migration-out-params-in.xml +++ b/tests/qemustatusxml2xmldata/migration-out-params-in.xml @@ -271,6 +271,7 @@ + -2 diff --git a/tests/qemustatusxml2xmldata/modern-in.xml b/tests/qemustatusxm= l2xmldata/modern-in.xml index f0f5df84ab..84240595ff 100644 --- a/tests/qemustatusxml2xmldata/modern-in.xml +++ b/tests/qemustatusxml2xmldata/modern-in.xml @@ -261,6 +261,7 @@ + -2 diff --git a/tests/qemustatusxml2xmldata/upgrade-out.xml b/tests/qemustatus= xml2xmldata/upgrade-out.xml index e663b3dbb5..2f33166579 100644 --- a/tests/qemustatusxml2xmldata/upgrade-out.xml +++ b/tests/qemustatusxml2xmldata/upgrade-out.xml @@ -259,6 +259,7 @@ + -2 diff --git a/tests/qemustatusxml2xmldata/vcpus-multi-in.xml b/tests/qemusta= tusxml2xmldata/vcpus-multi-in.xml index fa6a6a99f4..b07a04a840 100644 --- a/tests/qemustatusxml2xmldata/vcpus-multi-in.xml +++ b/tests/qemustatusxml2xmldata/vcpus-multi-in.xml @@ -309,6 +309,7 @@ + -2 --=20 2.34.1 _______________________________________________ Devel mailing list -- devel@lists.libvirt.org To unsubscribe send an email to devel-leave@lists.libvirt.org From nobody Fri May 17 10:44:00 2024 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 1712887910254868.4128684864536; Thu, 11 Apr 2024 19:11:50 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 339951A1F; Thu, 11 Apr 2024 22:11:49 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 1B9591905; Thu, 11 Apr 2024 22:03:43 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id D4EAB1889; Thu, 11 Apr 2024 22:03:36 -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 3735617C0 for ; Thu, 11 Apr 2024 22:03:06 -0400 (EDT) Received: from pps.filterd (m0360072.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 43C1Idv6011196 for ; Fri, 12 Apr 2024 02:03:05 GMT Received: from ppma21.wdc07v.mail.ibm.com (5b.69.3da9.ip4.static.sl-reverse.com [169.61.105.91]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3xeu1682mh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:03:05 +0000 Received: from pps.filterd (ppma21.wdc07v.mail.ibm.com [127.0.0.1]) by ppma21.wdc07v.mail.ibm.com (8.17.1.19/8.17.1.19) with ESMTP id 43C0QChm022560 for ; Fri, 12 Apr 2024 02:03:04 GMT Received: from smtprelay03.wdc07v.mail.ibm.com ([172.16.1.70]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 3xbhqpf4n5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:03:04 +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 43C231um23528002 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 12 Apr 2024 02:03:03 GMT Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5357B5806F; Fri, 12 Apr 2024 02:03:01 +0000 (GMT) Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5DC905806A; Fri, 12 Apr 2024 02:03:00 +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:03:00 +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 06/12] qemu: command: Support throttle groups and filters during qemuProcessLaunch Date: Thu, 11 Apr 2024 19:01:54 -0700 Message-Id: <20240412020200.2418776-7-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-ORIG-GUID: L8IS_LVyD8lVZtLpciFQTJdHXLGNUHLl X-Proofpoint-GUID: L8IS_LVyD8lVZtLpciFQTJdHXLGNUHLl 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 priorityscore=1501 malwarescore=0 suspectscore=0 spamscore=0 lowpriorityscore=0 bulkscore=0 phishscore=0 mlxlogscore=999 adultscore=0 clxscore=1015 impostorscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404120013 Message-ID-Hash: HNES6PSXLOPGDVYGVIRAVEGVAP63QTGS X-Message-ID-Hash: HNES6PSXLOPGDVYGVIRAVEGVAP63QTGS 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: 1712887911150100001 From: Chun Feng Wu * Add qemuBuildThrottleGroupCommandLine in qemuBuildCommandLine * Add qemuBuildThrottleFiltersCommandLine in qemuBuildDiskCommandLine * Make sure referenced throttle group exists Signed-off-by: Chun Feng Wu --- src/conf/domain_validate.c | 14 ++++++ src/qemu/qemu_command.c | 94 ++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_command.h | 3 ++ 3 files changed, 111 insertions(+) diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c index 395e036e8f..fffe274afc 100644 --- a/src/conf/domain_validate.c +++ b/src/conf/domain_validate.c @@ -663,6 +663,7 @@ virDomainDiskDefValidate(const virDomainDef *def, const virDomainDiskDef *disk) { virStorageSource *next; + size_t i; =20 /* disk target is used widely in other code so it must be validated fi= rst */ if (!disk->dst) { @@ -942,6 +943,19 @@ virDomainDiskDefValidate(const virDomainDef *def, return -1; } =20 + /* referenced group should be defined */ + for (i =3D 0; i < disk->nthrottlefilters; i++) { + virDomainThrottleFilterDef *filter =3D disk->throttlefilters[i]; + if (filter) { + if (!virDomainThrottleGroupFind(def, filter->group_name)) { + virReportError(VIR_ERR_XML_ERROR, + _("throttle group '%1$s' not found"), + filter->group_name); + return -1; + } + } + } + return 0; } =20 diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 2d8036c3ae..34164c098b 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1584,6 +1584,14 @@ qemuDiskConfigThrottleFilterChainEnabled(const virDo= mainDiskDef *disk) } =20 =20 +bool +qemuDiskConfigThrottleFilterEnabled(const virDomainThrottleGroupDef *group) +{ + return !!group->group_name && + virDomainBlockIoTuneInfoHasAny(group); +} + + /** * qemuDiskBusIsSD: * @bus: disk bus @@ -2221,6 +2229,45 @@ qemuBuildBlockStorageSourceAttachDataCommandline(vir= Command *cmd, } =20 =20 +static int +qemuBuildBlockThrottleFilterCommandline(virCommand *cmd, + qemuBlockThrottleFilterAttachData = *data) +{ + char *tmp; + + if (data->filterProps) { + if (!(tmp =3D virJSONValueToString(data->filterProps, false))) + return -1; + + virCommandAddArgList(cmd, "-blockdev", tmp, NULL); + VIR_FREE(tmp); + } + + return 0; +} + + +static int +qemuBuildThrottleFiltersCommandLine(virCommand *cmd, + virDomainDiskDef *disk) +{ + g_autoptr(qemuBlockThrottleFilterChainData) data =3D NULL; + size_t i; + + if (!(data =3D qemuBuildThrottleFilterChainAttachPrepareBlockdev(disk)= )) { + return -1; + } else { + for (i =3D 0; i < data->nfilterdata; i++) { + if (qemuBuildBlockThrottleFilterCommandline(cmd, + data->filterdata[i= ]) < 0) + return -1; + } + } + + return 0; +} + + static int qemuBuildDiskSourceCommandLine(virCommand *cmd, virDomainDiskDef *disk, @@ -2278,6 +2325,9 @@ qemuBuildDiskCommandLine(virCommand *cmd, if (qemuBuildDiskSourceCommandLine(cmd, disk, qemuCaps) < 0) return -1; =20 + if (qemuBuildThrottleFiltersCommandLine(cmd, disk) < 0) + return -1; + /* SD cards are currently instantiated via -drive if=3Dsd, so the -dev= ice * part must be skipped */ if (qemuDiskBusIsSD(disk->bus)) @@ -7451,6 +7501,47 @@ qemuBuildIOThreadCommandLine(virCommand *cmd, } =20 =20 +/** + * qemuBuildThrottleGroupCommandLine: + * @cmd: the command to modify + * @def: domain definition + * @qemuCaps: qemu capabilities object + * + * build throttle group object in json format + * e.g. -object '{"qom-type":"throttle-group","id":"limit0","limits":{"iop= s-total":200}}' + */ +static int +qemuBuildThrottleGroupCommandLine(virCommand *cmd, + const virDomainDef *def, + virQEMUCaps *qemuCaps) +{ + size_t i; + + for (i =3D 0; i < def->nthrottlegroups; i++) { + g_autoptr(virJSONValue) props =3D NULL; + g_autoptr(virJSONValue) limits =3D virJSONValueNewObject(); + virDomainThrottleGroupDef *group =3D def->throttlegroups[i]; + + if (!qemuDiskConfigThrottleFilterEnabled(group)) { + continue; + } + + if (qemuMonitorThrottleGroupLimits(limits, group)<0) + return -1; + + if (qemuMonitorCreateObjectProps(&props, "throttle-group", group->= group_name, + "a:limits", &limits, + NULL) < 0) + return -1; + + if (qemuBuildObjectCommandlineFromJSON(cmd, props, qemuCaps) < 0) + return -1; + } + + return 0; +} + + static int qemuBuildNumaCellCache(virCommand *cmd, const virDomainDef *def, @@ -10485,6 +10576,9 @@ qemuBuildCommandLine(virDomainObj *vm, if (qemuBuildIOThreadCommandLine(cmd, def, qemuCaps) < 0) return NULL; =20 + if (qemuBuildThrottleGroupCommandLine(cmd, def, qemuCaps) < 0) + return NULL; + if (virDomainNumaGetNodeCount(def->numa) && qemuBuildNumaCommandLine(cfg, def, cmd, priv) < 0) return NULL; diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index e2dee47906..9b8951d95f 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -122,6 +122,9 @@ qemuBuildThrottleFilterChainAttachPrepareBlockdev(virDo= mainDiskDef *disk); bool qemuDiskConfigThrottleFilterChainEnabled(const virDomainDiskDef *disk); =20 +bool +qemuDiskConfigThrottleFilterEnabled(const virDomainThrottleGroupDef *group= ); + virJSONValue * qemuBuildDiskDeviceProps(const virDomainDef *def, virDomainDiskDef *disk, --=20 2.34.1 _______________________________________________ Devel mailing list -- devel@lists.libvirt.org To unsubscribe send an email to devel-leave@lists.libvirt.org From nobody Fri May 17 10:44:00 2024 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 1712888134904363.9010775804446; Thu, 11 Apr 2024 19:15:34 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id D687618EF; Thu, 11 Apr 2024 22:15:33 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id A6F7A1982; Thu, 11 Apr 2024 22:04:16 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 168EB18A6; Thu, 11 Apr 2024 22:04:10 -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 6F87F17D1 for ; Thu, 11 Apr 2024 22:03:11 -0400 (EDT) Received: from pps.filterd (m0360072.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 43C17vTK029405 for ; Fri, 12 Apr 2024 02:03:11 GMT Received: from ppma13.dal12v.mail.ibm.com (dd.9e.1632.ip4.static.sl-reverse.com [50.22.158.221]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3xeu1682mn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:03:10 +0000 Received: from pps.filterd (ppma13.dal12v.mail.ibm.com [127.0.0.1]) by ppma13.dal12v.mail.ibm.com (8.17.1.19/8.17.1.19) with ESMTP id 43C1kfBX021501 for ; Fri, 12 Apr 2024 02:03:09 GMT Received: from smtprelay04.dal12v.mail.ibm.com ([172.16.1.6]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 3xbjxm6ue8-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Fri, 12 Apr 2024 02:03:09 +0000 Received: from smtpav05.dal12v.mail.ibm.com (smtpav05.dal12v.mail.ibm.com [10.241.53.104]) by smtprelay04.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 43C236mf62456152 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 12 Apr 2024 02:03:08 GMT Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C6CF55806B; Fri, 12 Apr 2024 02:03:06 +0000 (GMT) Received: from smtpav05.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D310858052; Fri, 12 Apr 2024 02:03:05 +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:03:05 +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 07/12] schema: Add new domain elements to support multiple throttle filters Date: Thu, 11 Apr 2024 19:01:55 -0700 Message-Id: <20240412020200.2418776-8-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> X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: i9exFMI6G5Gctagupv4GAWAuBUkKTOb9 X-Proofpoint-GUID: i9exFMI6G5Gctagupv4GAWAuBUkKTOb9 X-Proofpoint-UnRewURL: 0 URL was un-rewritten MIME-Version: 1.0 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 priorityscore=1501 malwarescore=0 suspectscore=0 spamscore=0 lowpriorityscore=0 bulkscore=0 phishscore=0 mlxlogscore=999 adultscore=0 clxscore=1015 impostorscore=0 mlxscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404120013 Message-ID-Hash: AJ67DHP5SJYBK4WLJSXWJ62F2AV7UGVN X-Message-ID-Hash: AJ67DHP5SJYBK4WLJSXWJ62F2AV7UGVN 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: 1712888135803100001 From: Chun Feng Wu * Add new elements '' and '' * contains defintions * can include multiple throttlegroup references to form f= ilter chain in qemu * Chained throttle filters feature in qemu is described at https://github.c= om/qemu/qemu/blob/master/docs/throttle.txt Signed-off-by: Chun Feng Wu --- docs/formatdomain.rst | 48 +++++++++ src/conf/schemas/domaincommon.rng | 164 +++++++++++++++++++++++++++++- 2 files changed, 211 insertions(+), 1 deletion(-) diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst index e2f66b982c..ee9ee8b10c 100644 --- a/docs/formatdomain.rst +++ b/docs/formatdomain.rst @@ -1957,6 +1957,34 @@ advertisements to the guest OS. (NB: Only qemu drive= r support) the guest OS itself can choose to circumvent the unavailability of the = sleep states (e.g. S4 by turning off completely). =20 +Throttle Group Management +------------------------- + +:since:`Since 10.3.0` it is possible to create multiple named throttle gro= ups +and then reference them within ``throttlefilters`` to form filter chain in= QEMU for +specific disk. The limits(throttlegroups) are shared within domain, hence = the same group +can be referenced by different filters. + +:: + + + ... + + + limit0 + 10000000 + 400000 + 100000 + + + ... + + +All throttlegroups are listed within the ``throttlegroups`` element + +``throttlegroup`` + It has the same sub-elements as ``iotune`` (See `Hard drives, floppy di= sks, CDROMs`_), + The difference is that is required. =20 Hypervisor features ------------------- @@ -2704,6 +2732,15 @@ paravirtualized driver is specified via the ``disk``= element. + + + + + + + + + ... =20 @@ -3185,6 +3222,17 @@ paravirtualized driver is specified via the ``disk``= element. :since:`since after 0.4.4`; "sata" attribute value :since:`since 0.9.7`; "removable" attribute value :since:`since 1.1.3`; "rotation_rate" attribute value :since:`since 7.3.0` +``throttlefilters`` + The optional ``throttlefilters`` element provides the ability to provid= e additional + per-device throttle chain :since:`Since 10.3.0` + For example, if we have four different disks and we want to limit I/O f= or each one + and we also want to limit combined I/O of all four disks, we can levera= ge + ``throttlefilters`` to achieve this goal by setting two ``throttlefilte= r`` for + each disk: disk's own filter and combined filter. ``throttlefilters`` a= nd ``iotune`` + should be used exclusively. + + ``throttlefilter`` + The optional ``throttlefilter`` element is to reference defined thro= ttle group. ``iotune`` The optional ``iotune`` element provides the ability to provide additio= nal per-device I/O tuning, with values that can vary for each device (contr= ast diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincom= mon.rng index f386e46fae..e77149c6ca 100644 --- a/src/conf/schemas/domaincommon.rng +++ b/src/conf/schemas/domaincommon.rng @@ -51,6 +51,7 @@ + @@ -1577,7 +1578,10 @@ - + + + + @@ -6637,6 +6641,164 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +