From nobody Fri May 17 09:01:46 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 1712719012094348.2939448503919; Tue, 9 Apr 2024 20:16:52 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 0F1BE1A19; Tue, 9 Apr 2024 23:16:51 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id A51C919BD; Tue, 9 Apr 2024 23:14:56 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 4ED2F19B6; Tue, 9 Apr 2024 23:14:49 -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 0505719C7 for ; Tue, 9 Apr 2024 23:14:19 -0400 (EDT) Received: from pps.filterd (m0353729.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 43A22pAV031198 for ; Wed, 10 Apr 2024 03:14:19 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 3xdhfx045k-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 10 Apr 2024 03:14:18 +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 43A0Ko66022560 for ; Wed, 10 Apr 2024 03:14:17 GMT Received: from smtprelay07.dal12v.mail.ibm.com ([172.16.1.9]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 3xbhqp29bn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 10 Apr 2024 03:14:17 +0000 Received: from smtpav03.dal12v.mail.ibm.com (smtpav03.dal12v.mail.ibm.com [10.241.53.102]) by smtprelay07.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 43A3EEmH41026056 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 10 Apr 2024 03:14:16 GMT Received: from smtpav03.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3B1C35803F; Wed, 10 Apr 2024 03:14:14 +0000 (GMT) Received: from smtpav03.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1590158056; Wed, 10 Apr 2024 03:14:13 +0000 (GMT) Received: from libvirt-dev-u221.fyre.ibm.com (unknown [9.112.252.183]) by smtpav03.dal12v.mail.ibm.com (Postfix) with ESMTP; Wed, 10 Apr 2024 03:14:12 +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 01/12] config: Introduce ThrottleGroup and ThrottleFilter Date: Tue, 9 Apr 2024 20:13:09 -0700 Message-Id: <20240410031320.1288203-2-wucf@linux.ibm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240410031320.1288203-1-wucf@linux.ibm.com> References: <20240410031320.1288203-1-wucf@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: pl_Fpjp-YExjjMzUnPhwhJ3xtLda3YAc X-Proofpoint-ORIG-GUID: pl_Fpjp-YExjjMzUnPhwhJ3xtLda3YAc 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-09_12,2024-04-09_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 malwarescore=0 phishscore=0 mlxlogscore=999 impostorscore=0 suspectscore=0 mlxscore=0 bulkscore=0 lowpriorityscore=0 clxscore=1015 adultscore=0 priorityscore=1501 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404100022 Message-ID-Hash: IZGA5LECC6ENQCDXXH4JATHGTTSHVUCL X-Message-ID-Hash: IZGA5LECC6ENQCDXXH4JATHGTTSHVUCL 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: 1712719014124100001 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 | 364 ++++++++++++++++++++++++++++++++++++++++ src/conf/domain_conf.h | 43 +++++ src/conf/virconftypes.h | 4 + 3 files changed, 411 insertions(+) diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 48c5d546da..e21c8076fd 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -3746,6 +3746,50 @@ virDomainIOThreadIDDefArrayInit(virDomainDef *def, return 0; } =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); +} + =20 void virDomainResourceDefFree(virDomainResourceDef *resource) @@ -4026,6 +4070,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); @@ -7693,6 +7739,157 @@ virDomainDiskDefIotuneParse(virDomainDiskDef *def, } #undef PARSE_IOTUNE =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; +} + =20 static int virDomainDiskDefMirrorParse(virDomainDiskDef *def, @@ -8184,6 +8381,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 +19057,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; @@ -22065,6 +22268,83 @@ virDomainIOThreadIDDel(virDomainDef *def, } } =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; + } + } +} =20 static int virDomainEventActionDefFormat(virBuffer *buf, @@ -22681,6 +22961,20 @@ virDomainDiskDefFormatIotune(virBuffer *buf, =20 #undef FORMAT_IOTUNE =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); +} + =20 static void virDomainDiskDefFormatDriver(virBuffer *buf, @@ -22968,6 +23262,8 @@ virDomainDiskDefFormat(virBuffer *buf, =20 virDomainDiskDefFormatIotune(&childBuf, def); =20 + virDomainDiskDefFormatThrottleFilterChain(&childBuf, def); + if (def->src->readonly) virBufferAddLit(&childBuf, "\n"); if (def->src->shared) @@ -27136,6 +27432,65 @@ virDomainDefIOThreadsFormat(virBuffer *buf, virDomainDefaultIOThreadDefFormat(buf, def); } =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); +} + + =20 static void virDomainIOMMUDefFormat(virBuffer *buf, @@ -27801,6 +28156,8 @@ virDomainDefFormatInternalSetRootName(virDomainDef = *def, =20 virDomainDefIOThreadsFormat(buf, def); =20 + virDomainDefThrottleGroupsFormat(buf, def); + if (virDomainCputuneDefFormat(buf, def, flags) < 0) return -1; =20 @@ -31033,6 +31390,13 @@ virDomainBlockIoTuneInfoCopy(const virDomainBlockI= oTuneInfo *src, dst->group_name =3D g_strdup(src->group_name); } =20 +void +virDomainThrottleGroupDefCopy(const virDomainThrottleGroupDef *src, + virDomainThrottleGroupDef *dst) +{ + *dst =3D *src; + dst->group_name =3D g_strdup(src->group_name); +} =20 bool virDomainBlockIoTuneInfoEqual(const virDomainBlockIoTuneInfo *a, diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 5925faaf1a..e22cebd03f 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,32 @@ 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 virDomainDis= kDef *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 09:01:46 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 1712721550629662.2651817459719; Tue, 9 Apr 2024 20:59:10 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 4CBF31A67; Tue, 9 Apr 2024 23:59:09 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 1E85C19AB; Tue, 9 Apr 2024 23:58:11 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 5BD6817FC; Tue, 9 Apr 2024 23:58:08 -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 A506C11E for ; Tue, 9 Apr 2024 23:58:07 -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 43A328e0013186 for ; Wed, 10 Apr 2024 03:14:22 GMT Received: from ppma11.dal12v.mail.ibm.com (db.9e.1632.ip4.static.sl-reverse.com [50.22.158.219]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 3xdg86g7ds-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 10 Apr 2024 03:14:21 +0000 Received: from pps.filterd (ppma11.dal12v.mail.ibm.com [127.0.0.1]) by ppma11.dal12v.mail.ibm.com (8.17.1.19/8.17.1.19) with ESMTP id 43A2ZaIB016996 for ; Wed, 10 Apr 2024 03:14:21 GMT Received: from smtprelay03.wdc07v.mail.ibm.com ([172.16.1.70]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 3xbke2htxp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 10 Apr 2024 03:14:21 +0000 Received: from smtpav03.dal12v.mail.ibm.com (smtpav03.dal12v.mail.ibm.com [10.241.53.102]) by smtprelay03.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 43A3EH9q14222036 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 10 Apr 2024 03:14:19 GMT Received: from smtpav03.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4EF975803F; Wed, 10 Apr 2024 03:14:17 +0000 (GMT) Received: from smtpav03.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5776D58056; Wed, 10 Apr 2024 03:14:16 +0000 (GMT) Received: from libvirt-dev-u221.fyre.ibm.com (unknown [9.112.252.183]) by smtpav03.dal12v.mail.ibm.com (Postfix) with ESMTP; Wed, 10 Apr 2024 03:14:16 +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 02/12] qemu: monitor: Add support for ThrottleGroup operations Date: Tue, 9 Apr 2024 20:13:10 -0700 Message-Id: <20240410031320.1288203-3-wucf@linux.ibm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240410031320.1288203-1-wucf@linux.ibm.com> References: <20240410031320.1288203-1-wucf@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: 5eDR3fJAU3MxOTJBIBmb2XorR2U5xFIG X-Proofpoint-ORIG-GUID: 5eDR3fJAU3MxOTJBIBmb2XorR2U5xFIG 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-09_12,2024-04-09_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 priorityscore=1501 impostorscore=0 mlxlogscore=998 spamscore=0 phishscore=0 clxscore=1015 lowpriorityscore=0 bulkscore=0 adultscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404100022 Message-ID-Hash: EZOG3PLODC4CUGAHMRAKXKE2NNIZCDXI X-Message-ID-Hash: EZOG3PLODC4CUGAHMRAKXKE2NNIZCDXI 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: 1712721552177100001 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 | 29 ++++++++ src/qemu/qemu_monitor.h | 10 +++ src/qemu/qemu_monitor_json.c | 135 +++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 13 ++++ 4 files changed, 187 insertions(+) diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 34e2ccab97..0c0bfe3449 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -2995,6 +2995,35 @@ qemuMonitorGetBlockIoThrottle(qemuMonitor *mon, return qemuMonitorJSONGetBlockIoThrottle(mon, qdevid, reply); } =20 +virJSONValue *qemuMonitorThrottleGroupLimits(const virDomainThrottleGroupD= ef *group) +{ + return qemuMonitorMakeThrottleGroupLimits(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); +} =20 int qemuMonitorVMStatusToPausedReason(const char *status) diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 6e81945201..37a0307d40 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1061,6 +1061,16 @@ int qemuMonitorGetBlockIoThrottle(qemuMonitor *mon, const char *qdevid, virDomainBlockIoTuneInfo *reply); =20 +virJSONValue *qemuMonitorThrottleGroupLimits(const virDomainThrottleGroupD= ef *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..ab7d2f1298 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -4633,6 +4633,141 @@ int qemuMonitorJSONGetBlockIoThrottle(qemuMonitor *= mon, return qemuMonitorJSONBlockIoThrottleInfo(devices, qdevid, reply); } =20 +static void virJSONValueLimitsAppendPositiveNumberLong(virJSONValue *limit= s, + const char *name, + unsigned long long = value) +{ + /* avoid error from QEMU: "the burst length cannot be 0" for throttlel= imits + * when seeting max-length + */ + if (value > 0) { + virJSONValueObjectAppendNumberLong(limits, name, value); + } +} + +virJSONValue * +qemuMonitorMakeThrottleGroupLimits(const virDomainThrottleGroupDef *group) +{ + g_autoptr(virJSONValue) limits =3D virJSONValueNewObject(); + + virJSONValueObjectAppendNumberLong(limits, "bps-total", group->total_b= ytes_sec); + virJSONValueObjectAppendNumberLong(limits, "bps-read", group->read_byt= es_sec); + virJSONValueObjectAppendNumberLong(limits, "bps-write", group->write_b= ytes_sec); + virJSONValueObjectAppendNumberLong(limits, "iops-total", group->total_= iops_sec); + virJSONValueObjectAppendNumberLong(limits, "iops-read", group->read_io= ps_sec); + virJSONValueObjectAppendNumberLong(limits, "iops-write", group->write_= iops_sec); + virJSONValueObjectAppendNumberLong(limits, "bps-total-max", group->tot= al_bytes_sec_max); + virJSONValueObjectAppendNumberLong(limits, "bps-read-max", group->read= _bytes_sec_max); + virJSONValueObjectAppendNumberLong(limits, "bps-write-max", group->wri= te_bytes_sec_max); + virJSONValueObjectAppendNumberLong(limits, "iops-total-max", group->to= tal_iops_sec_max); + virJSONValueObjectAppendNumberLong(limits, "iops-read-max", group->rea= d_iops_sec_max); + virJSONValueObjectAppendNumberLong(limits, "iops-write-max", group->wr= ite_iops_sec_max); + virJSONValueObjectAppendNumberLong(limits, "iops-size", group->size_io= ps_sec); + virJSONValueLimitsAppendPositiveNumberLong(limits, "bps-total-max-leng= th", group->total_bytes_sec_max_length); + virJSONValueLimitsAppendPositiveNumberLong(limits, "bps-read-max-lengt= h", group->read_bytes_sec_max_length); + virJSONValueLimitsAppendPositiveNumberLong(limits, "bps-write-max-leng= th", group->write_bytes_sec_max_length); + virJSONValueLimitsAppendPositiveNumberLong(limits, "iops-total-max-len= gth", group->total_iops_sec_max_length); + virJSONValueLimitsAppendPositiveNumberLong(limits, "iops-read-max-leng= th", group->read_iops_sec_max_length); + virJSONValueLimitsAppendPositiveNumberLong(limits, "iops-write-max-len= gth", group->write_iops_sec_max_length); + + return g_steal_pointer(&limits); +} + +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 NULL; + + limits =3D qemuMonitorMakeThrottleGroupLimits(info); + + 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..b8ebb77b72 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -404,6 +404,19 @@ qemuMonitorJSONSetBlockIoThrottle(qemuMonitor *mon, const char *qomid, virDomainBlockIoTuneInfo *info); =20 +virJSONValue * +qemuMonitorMakeThrottleGroupLimits(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 09:01:46 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 1712721102538307.9525778628413; Tue, 9 Apr 2024 20:51:42 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 5E026172D; Tue, 9 Apr 2024 23:51:41 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 5DF991AFA; Tue, 9 Apr 2024 23:47:40 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id E1D9C19A6; Tue, 9 Apr 2024 23:47:34 -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 291F91991 for ; Tue, 9 Apr 2024 23:47:33 -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 43A2mbio011629 for ; Wed, 10 Apr 2024 03:14:27 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 3xdja381qd-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 10 Apr 2024 03:14:26 +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 43A0fFAo029904 for ; Wed, 10 Apr 2024 03:14:26 GMT Received: from smtprelay04.dal12v.mail.ibm.com ([172.16.1.6]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 3xbj7ma5dh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 10 Apr 2024 03:14:26 +0000 Received: from smtpav03.dal12v.mail.ibm.com (smtpav03.dal12v.mail.ibm.com [10.241.53.102]) by smtprelay04.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 43A3ENBL26084018 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 10 Apr 2024 03:14:25 GMT Received: from smtpav03.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id EA22458063; Wed, 10 Apr 2024 03:14:22 +0000 (GMT) Received: from smtpav03.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8D4F25805A; Wed, 10 Apr 2024 03:14:21 +0000 (GMT) Received: from libvirt-dev-u221.fyre.ibm.com (unknown [9.112.252.183]) by smtpav03.dal12v.mail.ibm.com (Postfix) with ESMTP; Wed, 10 Apr 2024 03:14:21 +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 03/12] remote: New APIs for ThrottleGroup lifecycle management Date: Tue, 9 Apr 2024 20:13:11 -0700 Message-Id: <20240410031320.1288203-4-wucf@linux.ibm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240410031320.1288203-1-wucf@linux.ibm.com> References: <20240410031320.1288203-1-wucf@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: o0wUeV4_Jmfx4Sg4vxFSThMfd5Afqs3j X-Proofpoint-GUID: o0wUeV4_Jmfx4Sg4vxFSThMfd5Afqs3j 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-09_12,2024-04-09_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 spamscore=0 lowpriorityscore=0 adultscore=0 clxscore=1015 impostorscore=0 mlxlogscore=999 phishscore=0 bulkscore=0 suspectscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404100022 Message-ID-Hash: DKMKYBOV7PGE2VRWZXXLLJ7T7ZOHJE4M X-Message-ID-Hash: DKMKYBOV7PGE2VRWZXXLLJ7T7ZOHJE4M 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: 1712721104388100001 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 Signed-off-by: Chun Feng Wu --- include/libvirt/libvirt-domain.h | 29 ++ src/driver-hypervisor.h | 22 ++ src/libvirt-domain.c | 188 ++++++++++ src/libvirt_private.syms | 9 + src/libvirt_public.syms | 7 + src/qemu/qemu_domain.c | 12 + src/qemu/qemu_domain.h | 2 + src/qemu/qemu_driver.c | 515 ++++++++++++++++++++++++++++ src/remote/remote_daemon_dispatch.c | 60 ++++ src/remote/remote_driver.c | 46 +++ src/remote/remote_protocol.x | 50 ++- src/remote_protocol-structs | 21 ++ 12 files changed, 960 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..61c67e2392 100644 --- a/src/libvirt-domain.c +++ b/src/libvirt-domain.c @@ -14162,3 +14162,191 @@ 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/qemu/qemu_domain.c b/src/qemu/qemu_domain.c index 6b869797a8..7d1c1430ab 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -10245,6 +10245,18 @@ qemuDomainDiskByName(virDomainDef *def, return ret; } =20 +virDomainThrottleGroupDef * +qemuDomainThrottleGroupByName(virDomainDef *def, + const char *name) +{ + virDomainThrottleGroupDef *ret; + + if (!(ret =3D virDomainThrottleGroupByName(def, name))) { + return NULL; + } + + return ret; +} =20 int qemuDomainPrepareChannel(virDomainChrDef *channel, diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h index bd37cb245a..6343383bf7 100644 --- a/src/qemu/qemu_domain.h +++ b/src/qemu/qemu_domain.h @@ -880,6 +880,8 @@ 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..097366cefb 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -19995,6 +19995,518 @@ 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 NULL; + + + 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); + if (cur_info !=3D NULL) { // update existing group + 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{ + limits =3D qemuMonitorThrottleGroupLimits(&info); + 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 +20757,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 diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon= _dispatch.c index cfc1067e40..7d28d30e22 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -3614,6 +3614,66 @@ 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 *r= et) +{ + 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..4250729e27 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -2583,6 +2583,49 @@ 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 +7885,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..a7aa3d2d74 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..0319a5690d 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -1050,6 +1050,24 @@ struct remote_domain_get_block_io_tune_ret { } params; int nparams; }; +struct remote_domain_get_throttle_group_ret { + struct { + u_int params_len; + remote_typed_param * params_val; + } params; + int nparams; +}; +struct remote_domain_get_throttle_group_args { + remote_nonnull_domain dom; + remote_string group; + int nparams; + u_int flags; +}; +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 +3773,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 09:01:46 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 1712721306389832.4560010511332; Tue, 9 Apr 2024 20:55:06 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 33ADE1A2A; Tue, 9 Apr 2024 23:55:05 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id 3354919D1; Tue, 9 Apr 2024 23:53:11 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 3930817FC; Tue, 9 Apr 2024 23:53:09 -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 D02341873 for ; Tue, 9 Apr 2024 23:53:07 -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 43A2mbip011629 for ; Wed, 10 Apr 2024 03:14:29 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 3xdja381qh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 10 Apr 2024 03:14:29 +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 43A20lQS021523 for ; Wed, 10 Apr 2024 03:14:28 GMT Received: from smtprelay02.dal12v.mail.ibm.com ([172.16.1.4]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 3xbjxkt0t7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 10 Apr 2024 03:14:28 +0000 Received: from smtpav03.dal12v.mail.ibm.com (smtpav03.dal12v.mail.ibm.com [10.241.53.102]) by smtprelay02.dal12v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 43A3EPAl46465716 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 10 Apr 2024 03:14:27 GMT Received: from smtpav03.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AB5E958064; Wed, 10 Apr 2024 03:14:25 +0000 (GMT) Received: from smtpav03.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B1E225803F; Wed, 10 Apr 2024 03:14:24 +0000 (GMT) Received: from libvirt-dev-u221.fyre.ibm.com (unknown [9.112.252.183]) by smtpav03.dal12v.mail.ibm.com (Postfix) with ESMTP; Wed, 10 Apr 2024 03:14:24 +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 04/12] qemu: hotplug: Support hot attach block disk along with throttle filters Date: Tue, 9 Apr 2024 20:13:12 -0700 Message-Id: <20240410031320.1288203-5-wucf@linux.ibm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240410031320.1288203-1-wucf@linux.ibm.com> References: <20240410031320.1288203-1-wucf@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: 3R7bioiBf7N2stR4u_bhqvwwaphYJ4T3 X-Proofpoint-GUID: 3R7bioiBf7N2stR4u_bhqvwwaphYJ4T3 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-09_12,2024-04-09_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 mlxscore=0 spamscore=0 lowpriorityscore=0 adultscore=0 clxscore=1015 impostorscore=0 mlxlogscore=999 phishscore=0 bulkscore=0 suspectscore=0 malwarescore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404100022 Message-ID-Hash: KTYH7SINE4P465YDBMKDDASR6RD6IPIQ X-Message-ID-Hash: KTYH7SINE4P465YDBMKDDASR6RD6IPIQ 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: 1712721307200100001 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 | 121 ++++++++++++++++++ src/qemu/qemu_block.h | 53 ++++++++ src/qemu/qemu_command.c | 61 +++++++++ src/qemu/qemu_command.h | 6 + src/qemu/qemu_domain.c | 67 ++++++++++ src/qemu/qemu_domain.h | 12 +- src/qemu/qemu_hotplug.c | 23 ++++ .../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, 352 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_block.c b/src/qemu/qemu_block.c index 738b72d7ea..3c784d36ea 100644 --- a/src/qemu/qemu_block.c +++ b/src/qemu/qemu_block.c @@ -2738,6 +2738,127 @@ qemuBlockStorageSourceCreateDetectSize(GHashTable *= blockNamedNodeData, return 0; } =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 *da= ta) +{ + 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]); +} =20 int qemuBlockRemoveImageMetadata(virQEMUDriver *driver, diff --git a/src/qemu/qemu_block.h b/src/qemu/qemu_block.h index f9e961d85d..66bf7a97c3 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 *da= ta); + +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..278b706616 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1576,6 +1576,12 @@ qemuDiskConfigBlkdeviotuneEnabled(const virDomainDis= kDef *disk) virDomainBlockIoTuneInfoHasAny(&disk->blkdeviotune); } =20 +bool +qemuDiskConfigThrottleFilterChainEnabled(const virDomainDiskDef *disk) +{ + return disk->nthrottlefilters > 0; +} + =20 /** * qemuDiskBusIsSD: @@ -1936,6 +1942,10 @@ 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 */ @@ -11025,6 +11035,57 @@ qemuBuildStorageSourceChainAttachPrepareBlockdevOn= e(qemuBlockStorageSourceChainD return 0; } =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, + virDomainThrottleFilte= rDef *throttlefilter, + const char *parentNode= Name) +{ + 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); +} + + =20 /** * qemuBuildStorageSourceChainAttachPrepareBlockdev: 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 7d1c1430ab..c2f5d17c15 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -683,6 +683,17 @@ qemuDomainStorageIDNew(qemuDomainObjPrivate *priv) return ++priv->nodenameindex; } =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; +} =20 /** * qemuDomainStorageIDReset: @@ -697,6 +708,20 @@ qemuDomainStorageIDReset(qemuDomainObjPrivate *priv) priv->nodenameindex =3D 0; } =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; +} + + =20 /** * qemuDomainFDSetIDNew: @@ -1853,6 +1878,8 @@ qemuDomainObjPrivateDataClear(qemuDomainObjPrivate *p= riv) /* reset node name allocator */ qemuDomainStorageIDReset(priv); =20 + qemuDomainThrottleFilterIDReset(priv); + qemuDomainFDSetIDReset(priv); =20 priv->dbusDaemonRunning =3D false; @@ -2649,6 +2676,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 +3405,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 +3413,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 @@ -11345,6 +11382,30 @@ qemuDomainPrepareStorageSourceBlockdevNodename(vir= DomainDiskDef *disk, return 0; } =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); +} + =20 int qemuDomainPrepareStorageSourceBlockdev(virDomainDiskDef *disk, @@ -11369,6 +11430,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) @@ -11379,6 +11441,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 6343383bf7..ce5f5dfb6e 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,13 @@ int qemuDomainPrepareStorageSourceBlockdev(virDomainDi= skDef *disk, qemuDomainObjPrivate *priv, virQEMUDriverConfig *cfg); =20 +int qemuDomainPrepareThrottleFilterBlockdev(virDomainThrottleFilterDef *fi= lter, + 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,8 +890,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..491d8b03ea 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; @@ -693,6 +694,18 @@ qemuDomainAttachDiskGeneric(virDomainObj *vm, =20 if (rc < 0) goto rollback; + /* 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; + } =20 if (disk->transient) { g_autoptr(qemuBlockStorageSourceAttachData) backend =3D NULL; @@ -765,6 +778,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 +4519,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 +4558,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 09:01:46 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 171272024454552.258717344169554; Tue, 9 Apr 2024 20:37:24 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 6B4D619B9; Tue, 9 Apr 2024 23:37:23 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id C93E21AA5; Tue, 9 Apr 2024 23:35:54 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id BB8521884; Tue, 9 Apr 2024 23:35:47 -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 1D40A1895 for ; Tue, 9 Apr 2024 23:35:47 -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 43A31ihi010087 for ; Wed, 10 Apr 2024 03:14:33 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 3xdg86g7e9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 10 Apr 2024 03:14:33 +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 439NnH1h019110 for ; Wed, 10 Apr 2024 03:14:32 GMT Received: from smtprelay02.wdc07v.mail.ibm.com ([172.16.1.69]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 3xbh40afdv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 10 Apr 2024 03:14:32 +0000 Received: from smtpav03.dal12v.mail.ibm.com (smtpav03.dal12v.mail.ibm.com [10.241.53.102]) by smtprelay02.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 43A3ET1j6161134 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 10 Apr 2024 03:14:31 GMT Received: from smtpav03.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4D8AA5805A; Wed, 10 Apr 2024 03:14:29 +0000 (GMT) Received: from smtpav03.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5E2C35803F; Wed, 10 Apr 2024 03:14:28 +0000 (GMT) Received: from libvirt-dev-u221.fyre.ibm.com (unknown [9.112.252.183]) by smtpav03.dal12v.mail.ibm.com (Postfix) with ESMTP; Wed, 10 Apr 2024 03:14:28 +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 05/12] qemu: command: Support throttle groups and filters during qemuProcessLaunch Date: Tue, 9 Apr 2024 20:13:13 -0700 Message-Id: <20240410031320.1288203-6-wucf@linux.ibm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240410031320.1288203-1-wucf@linux.ibm.com> References: <20240410031320.1288203-1-wucf@linux.ibm.com> MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Proofpoint-GUID: BylXJWXpojCezD5okQdofDwfgo8zQDD3 X-Proofpoint-ORIG-GUID: BylXJWXpojCezD5okQdofDwfgo8zQDD3 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-09_12,2024-04-09_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 priorityscore=1501 impostorscore=0 mlxlogscore=999 spamscore=0 phishscore=0 clxscore=1015 lowpriorityscore=0 bulkscore=0 adultscore=0 mlxscore=0 suspectscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404100022 Message-ID-Hash: LBXSKIFRKXOP2P2BLYLHK5WPZPZYECLE X-Message-ID-Hash: LBXSKIFRKXOP2P2BLYLHK5WPZPZYECLE 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: 1712720245275100001 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 | 87 ++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_command.h | 3 ++ 3 files changed, 104 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 278b706616..e7cb20fd71 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1582,6 +1582,13 @@ qemuDiskConfigThrottleFilterChainEnabled(const virDo= mainDiskDef *disk) return disk->nthrottlefilters > 0; } =20 +bool +qemuDiskConfigThrottleFilterEnabled(const virDomainThrottleGroupDef *group) +{ + return !!group->group_name && + virDomainBlockIoTuneInfoHasAny(group); +} + =20 /** * qemuDiskBusIsSD: @@ -2218,6 +2225,42 @@ qemuBuildBlockStorageSourceAttachDataCommandline(vir= Command *cmd, return 0; } =20 +static int +qemuBuildBlockThrottleFilterCommandline(virCommand *cmd, + qemuBlockThrottleFilterAt= tachData *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; +} =20 static int qemuBuildDiskSourceCommandLine(virCommand *cmd, @@ -2276,6 +2319,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)) @@ -7448,6 +7494,44 @@ qemuBuildIOThreadCommandLine(virCommand *cmd, return 0; } =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 NULL; + virDomainThrottleGroupDef *group =3D def->throttlegroups[i]; + + if (!qemuDiskConfigThrottleFilterEnabled(group)) { + continue; + } + + limits =3D qemuMonitorThrottleGroupLimits(group); + + 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; +} =20 static int qemuBuildNumaCellCache(virCommand *cmd, @@ -10483,6 +10567,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 09:01:46 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 1712719102670592.8380367512527; Tue, 9 Apr 2024 20:18:22 -0700 (PDT) Received: by lists.libvirt.org (Postfix, from userid 996) id 8D990167A; Tue, 9 Apr 2024 23:18:21 -0400 (EDT) Received: from lists.libvirt.org (localhost [IPv6:::1]) by lists.libvirt.org (Postfix) with ESMTP id BCB351A31; Tue, 9 Apr 2024 23:15:16 -0400 (EDT) Received: by lists.libvirt.org (Postfix, from userid 996) id B1DAD1920; Tue, 9 Apr 2024 23:15:09 -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 498B71A6D for ; Tue, 9 Apr 2024 23:14:38 -0400 (EDT) Received: from pps.filterd (m0353726.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.17.1.19/8.17.1.19) with ESMTP id 43A2xMLs011356 for ; Wed, 10 Apr 2024 03:14:37 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 3xdj9qr12m-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 10 Apr 2024 03:14:36 +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 43A0fFAr029904 for ; Wed, 10 Apr 2024 03:14:35 GMT Received: from smtprelay05.wdc07v.mail.ibm.com ([172.16.1.72]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 3xbj7ma5dw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT) for ; Wed, 10 Apr 2024 03:14:35 +0000 Received: from smtpav03.dal12v.mail.ibm.com (smtpav03.dal12v.mail.ibm.com [10.241.53.102]) by smtprelay05.wdc07v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 43A3EWdw27722426 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Wed, 10 Apr 2024 03:14:34 GMT Received: from smtpav03.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4072E58056; Wed, 10 Apr 2024 03:14:32 +0000 (GMT) Received: from smtpav03.dal12v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 50FB15803F; Wed, 10 Apr 2024 03:14:31 +0000 (GMT) Received: from libvirt-dev-u221.fyre.ibm.com (unknown [9.112.252.183]) by smtpav03.dal12v.mail.ibm.com (Postfix) with ESMTP; Wed, 10 Apr 2024 03:14:31 +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 06/12] schema: Add new domain elements to support multiple throttle filters Date: Tue, 9 Apr 2024 20:13:14 -0700 Message-Id: <20240410031320.1288203-7-wucf@linux.ibm.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20240410031320.1288203-1-wucf@linux.ibm.com> References: <20240410031320.1288203-1-wucf@linux.ibm.com> X-TM-AS-GCONF: 00 X-Proofpoint-ORIG-GUID: D-qOGh5r2mzoDIzDIf4aCsLMZGZeFIYW X-Proofpoint-GUID: D-qOGh5r2mzoDIzDIf4aCsLMZGZeFIYW 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-09_12,2024-04-09_01,2023-05-22_02 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 mlxlogscore=999 mlxscore=0 adultscore=0 priorityscore=1501 spamscore=0 clxscore=1015 lowpriorityscore=0 suspectscore=0 phishscore=0 malwarescore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.12.0-2404010000 definitions=main-2404100022 Message-ID-Hash: A3PQD7PTD2LALKGAYCI2W4YPQS6OIQX5 X-Message-ID-Hash: A3PQD7PTD2LALKGAYCI2W4YPQS6OIQX5 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: 1712719104473100001 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +