From: Chun Feng Wu <wucf@xxxxxxxxxxxxx> * Define new structs 'virDomainThrottleGroupDef' and 'virDomainThrottleFilterDef' * Update _virDomainDef to include virDomainThrottleGroupDef * Update _virDomainDiskDef to include virDomainThrottleFilterDef * Support new resource operations for DOM XML and structs, corresponding "Parse" and "Format" methods are provided Signed-off-by: Chun Feng Wu <wucf@xxxxxxxxxxxxx> --- 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; } +static virDomainThrottleFilterDef * +virDomainThrottleFilterDefNew(void) +{ + virDomainThrottleFilterDef *def = g_new0(virDomainThrottleFilterDef, 1); + + def->group_name = 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 = 0; i < nthrottlegroups; i++) + virDomainThrottleGroupDefFree(def[i]); + + g_free(def); +} + void virDomainResourceDefFree(virDomainResourceDef *resource) @@ -4026,6 +4070,8 @@ void virDomainDefFree(virDomainDef *def) virDomainIOThreadIDDefArrayFree(def->iothreadids, def->niothreadids); + virDomainThrottleGroupDefArrayFree(def->throttlegroups, def->nthrottlegroups); + g_free(def->defaultIOThread); virBitmapFree(def->cputune.emulatorpin); @@ -7693,6 +7739,157 @@ virDomainDiskDefIotuneParse(virDomainDiskDef *def, } #undef PARSE_IOTUNE +static virDomainThrottleFilterDef * +virDomainDiskThrottleFilterDefParse(xmlNodePtr node, + xmlXPathContextPtr ctxt) +{ + g_autoptr(virDomainThrottleFilterDef) filter = virDomainThrottleFilterDefNew(); + + VIR_XPATH_NODE_AUTORESTORE(ctxt) + ctxt->node = node; + + filter->group_name = virXMLPropString(ctxt->node, "group"); + + return g_steal_pointer(&filter); +} + +static int +virDomainDiskDefThrottleFilterChainParse(virDomainDiskDef *def, + xmlXPathContextPtr ctxt) +{ + size_t i; + int n = 0; + g_autofree xmlNodePtr *nodes = NULL; + + if ((n = virXPathNodeSet("./throttlefilters/throttlefilter", ctxt, &nodes)) < 0) + return -1; + + if (n) + def->throttlefilters = g_new0(virDomainThrottleFilterDef *, n); + + for (i = 0; i < n; i++) { + g_autoptr(virDomainThrottleFilterDef) filter = NULL; + + if (!(filter = virDomainDiskThrottleFilterDefParse(nodes[i], ctxt))) { + 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++] = g_steal_pointer(&filter); + } + return 0; +} + +#define PARSE_THROTTLEGROUP(val) \ + if (virXPathULongLong("string(./" #val ")", \ + ctxt, &group->val) == -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 = g_new0(virDomainThrottleGroupDef, 1); + + VIR_XPATH_NODE_AUTORESTORE(ctxt) + ctxt->node = 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 = 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 = -1; + + for (i = 0; i < def->nthrottlegroups; i++) { + tgroup = def->throttlegroups[i]; + if (STREQ(tgroup->group_name, name)) + return i; + } + return candidate; +} + +virDomainThrottleGroupDef * +virDomainThrottleGroupByName(virDomainDef *def, + const char *name) +{ + int idx = virDomainThrottleGroupIndexByName(def, name); + + if (idx < 0) + return NULL; + + return def->throttlegroups[idx]; +} + +static int +virDomainDefThrottleGroupsParse(virDomainDef *def, + xmlXPathContextPtr ctxt) +{ + size_t i; + int n = 0; + g_autofree xmlNodePtr *nodes = NULL; + + if ((n = virXPathNodeSet("./throttlegroups/throttlegroup", ctxt, &nodes)) < 0) + return -1; + + if (n) + def->throttlegroups = g_new0(virDomainThrottleGroupDef *, n); + + for (i = 0; i < n; i++) { + g_autoptr(virDomainThrottleGroupDef) group = NULL; + + if (!(group = 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++] = g_steal_pointer(&group); + } + return 0; +} + static int virDomainDiskDefMirrorParse(virDomainDiskDef *def, @@ -8184,6 +8381,9 @@ virDomainDiskDefParseXML(virDomainXMLOption *xmlopt, if (virDomainDiskDefIotuneParse(def, ctxt) < 0) return NULL; + if (virDomainDiskDefThrottleFilterChainParse(def, ctxt) < 0) + return NULL; + def->domain_name = virXPathString("string(./backenddomain/@name)", ctxt); def->serial = virXPathString("string(./serial)", ctxt); def->wwn = virXPathString("string(./wwn)", ctxt); @@ -18857,6 +19057,9 @@ virDomainDefParseXML(xmlXPathContextPtr ctxt, if (virDomainDefParseBootOptions(def, ctxt, xmlopt, flags) < 0) return NULL; + if (virDomainDefThrottleGroupsParse(def, ctxt) < 0) + return NULL; + /* analysis of the disk devices */ if ((n = virXPathNodeSet("./devices/disk", ctxt, &nodes)) < 0) return NULL; @@ -22065,6 +22268,83 @@ virDomainIOThreadIDDel(virDomainDef *def, } } +virDomainThrottleGroupDef * +virDomainThrottleGroupFind(const virDomainDef *def, + const char *name) +{ + size_t i; + + if (!def->throttlegroups || !def->nthrottlegroups) + return NULL; + + for (i = 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 = 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 = g_new0(virDomainThrottleGroupDef, 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 = 0; i < def->nthrottlegroups; i++) { + virDomainThrottleGroupDef *t = 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 = 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->nthrottlegroups); + return; + } + } +} static int virDomainEventActionDefFormat(virBuffer *buf, @@ -22681,6 +22961,20 @@ virDomainDiskDefFormatIotune(virBuffer *buf, #undef FORMAT_IOTUNE +static void +virDomainDiskDefFormatThrottleFilterChain(virBuffer *buf, + virDomainDiskDef *disk) +{ + size_t i; + g_auto(virBuffer) throttleChildBuf = VIR_BUFFER_INIT_CHILD(buf); + for (i = 0; i < disk->nthrottlefilters; i++) { + g_auto(virBuffer) throttleAttrBuf = VIR_BUFFER_INITIALIZER; + virBufferAsprintf(&throttleAttrBuf, " group='%s'", disk->throttlefilters[i]->group_name); + virXMLFormatElement(&throttleChildBuf, "throttlefilter", &throttleAttrBuf, NULL); + } + virXMLFormatElement(buf, "throttlefilters", NULL, &throttleChildBuf); +} + static void virDomainDiskDefFormatDriver(virBuffer *buf, @@ -22968,6 +23262,8 @@ virDomainDiskDefFormat(virBuffer *buf, virDomainDiskDefFormatIotune(&childBuf, def); + virDomainDiskDefFormatThrottleFilterChain(&childBuf, def); + if (def->src->readonly) virBufferAddLit(&childBuf, "<readonly/>\n"); if (def->src->shared) @@ -27136,6 +27432,65 @@ virDomainDefIOThreadsFormat(virBuffer *buf, virDomainDefaultIOThreadDefFormat(buf, def); } +#define FORMAT_THROTTLE_GROUP(val) \ + if (group->val) { \ + virBufferAsprintf(&childBuf, "<" #val ">%llu</" #val ">\n", \ + group->val); \ + } + +static void +virDomainThrottleGroupFormat(virBuffer *buf, + virDomainThrottleGroupDef *group) +{ + g_auto(virBuffer) childBuf = 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, "<group_name>%s</group_name>\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 = VIR_BUFFER_INIT_CHILD(buf); + ssize_t n; + + for (n = 0; n < def->nthrottlegroups; n++) { + virDomainThrottleGroupFormat(&childrenBuf, def->throttlegroups[n]); + } + + virXMLFormatElement(buf, "throttlegroups", NULL, &childrenBuf); +} + + static void virDomainIOMMUDefFormat(virBuffer *buf, @@ -27801,6 +28156,8 @@ virDomainDefFormatInternalSetRootName(virDomainDef *def, virDomainDefIOThreadsFormat(buf, def); + virDomainDefThrottleGroupsFormat(buf, def); + if (virDomainCputuneDefFormat(buf, def, flags) < 0) return -1; @@ -31033,6 +31390,13 @@ virDomainBlockIoTuneInfoCopy(const virDomainBlockIoTuneInfo *src, dst->group_name = g_strdup(src->group_name); } +void +virDomainThrottleGroupDefCopy(const virDomainThrottleGroupDef *src, + virDomainThrottleGroupDef *dst) +{ + *dst = *src; + dst->group_name = g_strdup(src->group_name); +} 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. */ }; +/* 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 */ +}; typedef enum { VIR_DOMAIN_DISK_MIRROR_STATE_NONE = 0, /* No job, or job still not synced */ @@ -550,6 +558,9 @@ struct _virDomainDiskDef { virDomainBlockIoTuneInfo blkdeviotune; + size_t nthrottlefilters; + virDomainThrottleFilterDef **throttlefilters; + char *driverName; char *serial; @@ -2992,6 +3003,9 @@ struct _virDomainDef { virDomainDefaultIOThreadDef *defaultIOThread; + size_t nthrottlegroups; + virDomainThrottleGroupDef **throttlegroups; + virDomainCputune cputune; virDomainResctrlDef **resctrls; @@ -4504,3 +4518,32 @@ virDomainObjGetMessages(virDomainObj *vm, bool virDomainDefHasSpiceGraphics(const virDomainDef *def); + +void virDomainThrottleGroupDefFree(virDomainThrottleGroupDef *def); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainThrottleGroupDef, virDomainThrottleGroupDefFree); + +void virDomainThrottleFilterDefFree(virDomainThrottleFilterDef *def); +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainThrottleFilterDef, virDomainThrottleFilterDefFree); + +virDomainThrottleGroupDef *virDomainThrottleGroupAdd(virDomainDef *def, + virDomainThrottleGroupDef *throttle_group); + +void virDomainThrottleGroupUpdate(virDomainDef *def, + virDomainThrottleGroupDef *info); + +virDomainThrottleGroupDef *virDomainThrottleGroupFind(const virDomainDef *def, + const char *name); + +void virDomainThrottleGroupDel(virDomainDef *def, + const char *name); + +virDomainThrottleFilterDef *virDomainThrottleFilterFind(const virDomainDiskDef *def, + const char *name); + +int virDomainThrottleGroupIndexByName(virDomainDef *def, const char *name); + +virDomainThrottleGroupDef *virDomainThrottleGroupByName(virDomainDef *def, const char *name); + +void +virDomainThrottleGroupDefCopy(const virDomainThrottleGroupDef *src, + virDomainThrottleGroupDef *dst); diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h index 0779bc224b..1cf68b2814 100644 --- a/src/conf/virconftypes.h +++ b/src/conf/virconftypes.h @@ -80,6 +80,10 @@ typedef struct _virDomainBlkiotune virDomainBlkiotune; typedef struct _virDomainBlockIoTuneInfo virDomainBlockIoTuneInfo; +typedef struct _virDomainBlockIoTuneInfo virDomainThrottleGroupDef; + +typedef struct _virDomainThrottleFilterDef virDomainThrottleFilterDef; + typedef struct _virDomainCheckpointDef virDomainCheckpointDef; typedef struct _virDomainCheckpointObj virDomainCheckpointObj; -- 2.34.1 _______________________________________________ Devel mailing list -- devel@xxxxxxxxxxxxxxxxx To unsubscribe send an email to devel-leave@xxxxxxxxxxxxxxxxx