From nobody Thu Jul 10 04:51:10 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.25 as permitted sender) client-ip=209.132.183.25; envelope-from=libvir-list-bounces@redhat.com; helo=mx4-phx2.redhat.com; Authentication-Results: mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.25 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; Return-Path: Received: from mx4-phx2.redhat.com (mx4-phx2.redhat.com [209.132.183.25]) by mx.zohomail.com with SMTPS id 1486709091235233.18430985581892; Thu, 9 Feb 2017 22:44:51 -0800 (PST) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx4-phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v1A6fGJe017541; Fri, 10 Feb 2017 01:41:16 -0500 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id v1A6egcP009867 for ; Fri, 10 Feb 2017 01:40:42 -0500 Received: from mx1.redhat.com (ext-mx02.extmail.prod.ext.phx2.redhat.com [10.5.110.26]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v1A6egbK002232 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Fri, 10 Feb 2017 01:40:42 -0500 Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5636664A41; Fri, 10 Feb 2017 06:40:40 +0000 (UTC) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga102.jf.intel.com with ESMTP; 09 Feb 2017 22:40:38 -0800 Received: from s2600wt.sh.intel.com ([10.239.48.158]) by fmsmga001.fm.intel.com with ESMTP; 09 Feb 2017 22:40:37 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.35,139,1484035200"; d="scan'208";a="1105518427" From: Eli Qiao To: libvir-list@redhat.com Date: Fri, 10 Feb 2017 14:42:08 +0800 Message-Id: <1486708933-5731-5-git-send-email-liyong.qiao@intel.com> In-Reply-To: <1486708933-5731-1-git-send-email-liyong.qiao@intel.com> References: <1486708933-5731-1-git-send-email-liyong.qiao@intel.com> X-Greylist: Sender passed SPF test, Sender IP whitelisted by DNSRBL, ACL 200 matched, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 10 Feb 2017 06:40:41 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Fri, 10 Feb 2017 06:40:41 +0000 (UTC) for IP:'134.134.136.24' DOMAIN:'mga09.intel.com' HELO:'mga09.intel.com' FROM:'liyong.qiao@intel.com' RCPT:'' X-RedHat-Spam-Score: -4.222 (BAYES_50, RCVD_IN_DNSWL_HI, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, RP_MATCHES_RCVD, SPF_PASS) 134.134.136.24 mga09.intel.com 134.134.136.24 mga09.intel.com X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Scanned-By: MIMEDefang 2.78 on 10.5.110.26 X-loop: libvir-list@redhat.com Cc: mkletzan@redhat.com, qiaowei.ren@intel.com, mtosatti@redhat.com, qiaoliyong@gmail.com Subject: [libvirt] [v4 4/9] Resctrl: Add private interface to set cachebanks X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" virResCtrlSetCacheBanks: Set cache banks of a libvirt domain. It will create new resource domain under `/sys/fs/resctrl` and fill the schemata according the cache banks configration. virResCtrlUpdate: Update the schemata after libvirt domain destroy. Signed-off-by: Eli Qiao --- src/libvirt_private.syms | 6 +- src/util/virresctrl.c | 699 +++++++++++++++++++++++++++++++++++++++++++= +++- src/util/virresctrl.h | 6 +- 3 files changed, 705 insertions(+), 6 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index cc6c433..85b9e94 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2318,7 +2318,11 @@ virRandomInt; virResCtrlAvailable; virResCtrlGet; virResCtrlInit; - +virResCtrlSetCacheBanks; +virResCtrlTypeFromString; +virResCtrlTypeToString; +virResCtrlUpdate; +# =20 # util/virrotatingfile.h virRotatingFileReaderConsume; diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index b49e965..0d400a9 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -72,9 +72,59 @@ do { \ #define VIR_RESCTRL_SET_SCHEMATA(p, type, pos, val) \ p->schematas[type]->schemata_items[pos] =3D val =20 +/** + * a virResSchemata represents a schemata object under a resource control + * domain. + */ +typedef struct _virResSchemataItem virResSchemataItem; +typedef virResSchemataItem *virResSchemataItemPtr; +struct _virResSchemataItem { + unsigned int socket_no; + unsigned schemata; +}; + +typedef struct _virResSchemata virResSchemata; +typedef virResSchemata *virResSchemataPtr; +struct _virResSchemata { + unsigned int n_schemata_items; + virResSchemataItemPtr schemata_items; +}; + +/** + * a virResDomain represents a resource control domain. It's a double link= ed + * list. + */ + +typedef struct _virResDomain virResDomain; +typedef virResDomain *virResDomainPtr; + +struct _virResDomain { + char *name; + virResSchemataPtr schematas[VIR_RDT_RESOURCE_LAST]; + char **tasks; + size_t n_tasks; + size_t n_sockets; + virResDomainPtr pre; + virResDomainPtr next; +}; + +/* All resource control domains on this host*/ + +typedef struct _virResCtrlDomain virResCtrlDomain; +typedef virResCtrlDomain *virResCtrlDomainPtr; +struct _virResCtrlDomain { + unsigned int num_domains; + virResDomainPtr domains; +}; + =20 static unsigned int host_id; =20 +/* Global static struct to be maintained which is a interface */ +static virResCtrlDomain domainall; + +/* Global static struct array to be maintained which indicate + * resource status on a host */ static virResCtrl resctrlall[] =3D { { .name =3D "L3", @@ -94,6 +144,66 @@ static virResCtrl resctrlall[] =3D { }, }; =20 +/* + * How many bits is set in schemata + * eg: + * virResCtrlBitsNum(1011) =3D 2 */ +static int virResCtrlBitsContinuesNum(unsigned schemata) +{ + size_t i; + int ret =3D 0; + for (i =3D 0; i < MAX_CBM_BIT_LEN; i ++) { + if ((schemata & 0x1) =3D=3D 0x1) + ret++; + else + break; + schemata =3D schemata >> 1; + if (schemata =3D=3D 0) break; + } + return ret; +} + +static int virResCtrlGetStr(const char *domain_name, const char *item_name= , char **ret) +{ + char *path; + int rc =3D 0; + + CONSTRUCT_RESCTRL_PATH(domain_name, item_name); + + if (virFileReadAll(path, MAX_FILE_LEN, ret) < 0) { + rc =3D -1; + goto cleanup; + } + + cleanup: + VIR_FREE(path); + return rc; +} + +static int virResCtrlGetTasks(const char *domain_name, char **pids) +{ + return virResCtrlGetStr(domain_name, "tasks", pids); +} + +static int virResCtrlGetSchemata(const int type, const char *name, char **= schemata) +{ + int rc; + char *tmp, *end; + char *buf; + + if ((rc =3D virResCtrlGetStr(name, "schemata", &buf)) < 0) + return rc; + + tmp =3D strstr(buf, resctrlall[type].name); + end =3D strchr(tmp, '\n'); + *end =3D '\0'; + if (VIR_STRDUP(*schemata, tmp) < 0) + rc =3D -1; + + VIR_FREE(buf); + return rc; +} + static int virResCtrlGetInfoStr(const int type, const char *item, char **s= tr) { int ret =3D 0; @@ -114,6 +224,70 @@ static int virResCtrlGetInfoStr(const int type, const = char *item, char **str) return ret; } =20 +/* Return pointer of and ncount of schemata*/ +static virResSchemataPtr virParseSchemata(const char *schemata_str, size_t= *ncount) +{ + const char *p, *q; + int pos; + int ischemata; + virResSchemataPtr schemata; + virResSchemataItemPtr schemataitems, tmpitem; + unsigned int socket_no =3D 0; + char *tmp; + + if (VIR_ALLOC(schemata) < 0) + goto cleanup; + + p =3D q =3D schemata_str; + pos =3D strchr(schemata_str, ':') - p; + + /* calculate cpu socket count */ + *ncount =3D 1; + while ((q =3D strchr(p, ';')) !=3D 0) { + p =3D q + 1; + (*ncount)++; + } + + /* allocat an arrry to store schemata for each socket*/ + if (VIR_ALLOC_N_QUIET(tmpitem, *ncount) < 0) + goto cleanup; + + schemataitems =3D tmpitem; + + p =3D q =3D schemata_str + pos + 1; + + while (*p !=3D '\0') { + if (*p =3D=3D '=3D') { + q =3D p + 1; + + tmpitem->socket_no =3D socket_no++; + + while (*p !=3D ';' && *p !=3D '\0') p++; + + if (VIR_STRNDUP(tmp, q, p-q) < 0) + goto cleanup; + + if (virStrToLong_i(tmp, NULL, 16, &ischemata) < 0) + goto cleanup; + + VIR_FREE(tmp); + tmp =3D NULL; + tmpitem->schemata =3D ischemata; + tmpitem ++; + schemata->n_schemata_items +=3D 1; + } + p++; + } + + schemata->schemata_items =3D schemataitems; + return schemata; + + cleanup: + VIR_FREE(schemata); + VIR_FREE(tmpitem); + return NULL; +} + =20 static int virResCtrlGetCPUValue(const char *path, char **value) { @@ -251,6 +425,7 @@ static virResCacheBankPtr virResCtrlGetCacheBanks(int t= ype, int *n_sockets) =20 bank[s_id].cache_size =3D cache_size; bank[s_id].cache_min =3D cache_size / resctrlall[type].cbm_len; + bank[s_id].cache_left =3D cache_size - (bank[s_id].cache_min *= resctrlall[type].min_cbm_bits); } } return bank; @@ -267,7 +442,7 @@ static int virResCtrlGetConfig(int type) size_t i; char *str; =20 - /* Read min_cbm_bits from resctrl. + /* Read num_closids from resctrl. eg: /sys/fs/resctrl/info/L3/num_closids */ if ((ret =3D virResCtrlGetInfoStr(type, "num_closids", &str)) < 0) @@ -320,6 +495,519 @@ static int virResCtrlGetConfig(int type) return ret; } =20 +/* Remove the Domain from sysfs, this should only success no pids in tasks + * of a partition. + */ +static +int virResCtrlRemoveDomain(const char *name) +{ + char *path =3D NULL; + int rc =3D 0; + + if ((rc =3D virAsprintf(&path, "%s/%s", RESCTRL_DIR, name)) < 0) + return rc; + rc =3D rmdir(path); + VIR_FREE(path); + return rc; +} + +static +int virResCtrlDestroyDomain(virResDomainPtr p) +{ + size_t i; + int rc; + if ((rc =3D virResCtrlRemoveDomain(p->name)) < 0) + VIR_WARN("Failed to removed partition %s", p->name); + + VIR_FREE(p->name); + p->name =3D NULL; + for (i =3D 0; i < p->n_tasks; i ++) + VIR_FREE(p->tasks[i]); + VIR_FREE(p); + p =3D NULL; + return rc; +} + + +/* assemble schemata string*/ +static +char* virResCtrlAssembleSchemata(virResSchemataPtr schemata, int type) +{ + virBuffer buf =3D VIR_BUFFER_INITIALIZER; + size_t i; + + virBufferAsprintf(&buf, "%s:%u=3D%x", resctrlall[type].name, + schemata->schemata_items[0].socket_no, + schemata->schemata_items[0].schemata); + + for (i =3D 1; i < schemata->n_schemata_items; i++) { + virBufferAsprintf(&buf, ";%u=3D%x", + schemata->schemata_items[i].socket_no, + schemata->schemata_items[i].schemata); + } + + return virBufferContentAndReset(&buf); +} + +/* Refresh default domains' schemata + */ +static +int virResCtrlRefreshSchemata(void) +{ + size_t i, j, k; + unsigned int tmp_schemata; + unsigned int default_schemata; + + virResDomainPtr header, p; + + header =3D domainall.domains; + + if (!header) + return 0; + + for (i =3D 0; i < VIR_RDT_RESOURCE_LAST; i++) { + if (VIR_RESCTRL_ENABLED(i)) { + for (j =3D 0; j < header->schematas[i]->n_schemata_items; j ++= ) { + p =3D header->next; + default_schemata =3D VIR_RESCTRL_GET_SCHEMATA(resctrlall[i= ].cbm_len); + tmp_schemata =3D 0; + /* NOTEs: if only header domain, the schemata will be set = to default one*/ + for (k =3D 1; k < domainall.num_domains; k++) { + tmp_schemata |=3D p->schematas[i]->schemata_items[j].s= chemata; + p =3D p->next; + } + /* sys fs doens't let us use 0 */ + int min_bits =3D VIR_RESCTRL_GET_SCHEMATA(resctrlall[i].mi= n_cbm_bits); + if ((tmp_schemata & min_bits) =3D=3D min_bits) + tmp_schemata -=3D min_bits; + + default_schemata ^=3D tmp_schemata; + + int bitsnum =3D virResCtrlBitsContinuesNum(default_schemat= a); + // calcuate header's schemata + // NOTES: resctrl sysfs only allow us to set a continues s= chemata + header->schematas[i]->schemata_items[j].schemata =3D VIR_R= ESCTRL_GET_SCHEMATA(bitsnum); + resctrlall[i].cache_banks[j].cache_left =3D + (bitsnum - resctrlall[i].min_cbm_bits) * resctrlall[i]= .cache_banks[j].cache_min; + } + } + } + + return 0; + +} + +/* Refresh all domains', remove the domains which has no task ids. + * This will be used after VM pause, restart, destroy etc. + */ +static int +virResCtrlRefresh(void) +{ + size_t i; + char* tasks; + unsigned int origin_count =3D domainall.num_domains; + virResDomainPtr p, pre, del; + pre =3D domainall.domains; + p =3D del =3D NULL; + if (pre) + p =3D pre->next; + + for (i =3D 1; i < origin_count && p; i++) { + if (virResCtrlGetTasks(p->name, &tasks) < 0) { + VIR_WARN("Failed to get tasks from %s", p->name); + pre =3D p; + p =3D p->next; + } + if (virStringIsEmpty(tasks)) { + pre->next =3D p->next; + if (p->next !=3D NULL) + p->next->pre =3D pre; + + del =3D p; + p =3D p->next; + virResCtrlDestroyDomain(del); + domainall.num_domains -=3D 1; + } else { + pre =3D p; + p =3D p->next; + } + VIR_FREE(tasks); + + } + + return virResCtrlRefreshSchemata(); +} + +/* Get a domain ptr by domain's name*/ +static +virResDomainPtr virResCtrlGetDomain(const char* name) { + size_t i; + virResDomainPtr p =3D domainall.domains; + for (i =3D 0; i < domainall.num_domains; i++) { + if ((p->name) && STREQ(name, p->name)) + return p; + p =3D p->next; + } + return NULL; +} + +static int +virResCtrlAddTask(virResDomainPtr dom, pid_t pid) +{ + size_t maxtasks; + + if (VIR_RESIZE_N(dom->tasks, maxtasks, dom->n_tasks, 1) < 0) + return -1; + + if (virAsprintf(&(dom->tasks[dom->n_tasks]), "%llu", (long long)pid) <= 0) + return -1; + + dom->n_tasks +=3D 1; + return 0; +} + +static int +virResCtrlWrite(const char *name, const char *item, const char *content) +{ + char *path; + int writefd; + int rc =3D -1; + + CONSTRUCT_RESCTRL_PATH(name, item); + + if (!virFileExists(path)) + goto cleanup; + + if ((writefd =3D open(path, O_WRONLY | O_APPEND, S_IRUSR | S_IWUSR)) <= 0) + goto cleanup; + + if (safewrite(writefd, content, strlen(content)) < 0) + goto cleanup; + + rc =3D 0; + cleanup: + VIR_FREE(path); + VIR_FORCE_CLOSE(writefd); + return rc; +} + +/* if name =3D=3D NULL we load default schemata */ +static +virResDomainPtr virResCtrlLoadDomain(const char *name) +{ + char *schematas; + virResDomainPtr p; + size_t i; + + if (VIR_ALLOC(p) < 0) + goto cleanup; + + for (i =3D 0; i < VIR_RDT_RESOURCE_LAST; i++) { + if (VIR_RESCTRL_ENABLED(i)) { + if (virResCtrlGetSchemata(i, name, &schematas) < 0) + goto cleanup; + p->schematas[i] =3D virParseSchemata(schematas, &(p->n_sockets= )); + VIR_FREE(schematas); + } + } + + p->tasks =3D NULL; + p->n_tasks =3D 0; + + if ((name !=3D NULL) && (VIR_STRDUP(p->name, name)) < 0) + goto cleanup; + + return p; + + cleanup: + VIR_FREE(p); + return NULL; +} + +static +virResDomainPtr virResCtrlCreateDomain(const char *name) +{ + char *path; + mode_t mode =3D 0755; + virResDomainPtr p; + size_t i, j; + if (virAsprintf(&path, "%s/%s", RESCTRL_DIR, name) < 0) + return NULL; + + if (virDirCreate(path, mode, 0, 0, 0) < 0) + goto cleanup; + + if ((p =3D virResCtrlLoadDomain(name)) =3D=3D NULL) + return p; + + /* sys fs doens't let us use 0. + * reset schemata to min_bits*/ + for (i =3D 0; i < VIR_RDT_RESOURCE_LAST; i++) { + if (VIR_RESCTRL_ENABLED(i)) { + int min_bits =3D VIR_RESCTRL_GET_SCHEMATA(resctrlall[i].min_c= bm_bits); + for (j =3D 0; j < p->n_sockets; j++) + p->schematas[i]->schemata_items[j].schemata =3D min_bits; + } + } + + VIR_FREE(path); + return p; + + cleanup: + VIR_FREE(path); + return NULL; +} + +/* flush domains's information to sysfs*/ +static int +virResCtrlFlushDomainToSysfs(virResDomainPtr dom) +{ + size_t i; + char* schemata; + char* tmp; + int rc =3D -1; + virBuffer buf =3D VIR_BUFFER_INITIALIZER; + + for (i =3D 0; i < VIR_RDT_RESOURCE_LAST; i++) { + if (VIR_RESCTRL_ENABLED(i)) { + tmp =3D virResCtrlAssembleSchemata(dom->schematas[i], i); + virBufferAsprintf(&buf, "%s\n", tmp); + VIR_FREE(tmp); + } + } + + schemata =3D virBufferContentAndReset(&buf); + + if (virResCtrlWrite(dom->name, "schemata", schemata) < 0) + goto cleanup; + + if (dom->n_tasks > 0) { + for (i =3D 0; i < dom->n_tasks; i++) { + if (virResCtrlWrite(dom->name, "tasks", dom->tasks[i]) < 0) + goto cleanup; + } + } + + rc =3D 0; + + cleanup: + VIR_FREE(schemata); + return rc; +} + +static virResDomainPtr virResCtrlGetAllDomains(unsigned int *len) +{ + struct dirent *ent; + DIR *dp =3D NULL; + int direrr; + + *len =3D 0; + virResDomainPtr header, tmp, tmp_pre; + header =3D tmp =3D tmp_pre =3D NULL; + if (virDirOpenQuiet(&dp, RESCTRL_DIR) < 0) { + if (errno =3D=3D ENOENT) + return NULL; + VIR_ERROR(_("Unable to open %s (%d)"), RESCTRL_DIR, errno); + goto cleanup; + } + + header =3D virResCtrlLoadDomain(NULL); + if (header =3D=3D NULL) + goto cleanup; + + header->next =3D NULL; + + *len =3D 1; + + while ((direrr =3D virDirRead(dp, &ent, NULL)) > 0) { + if ((ent->d_type !=3D DT_DIR) || STREQ(ent->d_name, "info")) + continue; + + tmp =3D virResCtrlLoadDomain(ent->d_name); + if (tmp =3D=3D NULL) + goto cleanup; + + tmp->next =3D NULL; + + if (header->next =3D=3D NULL) + header->next =3D tmp; + + if (tmp_pre =3D=3D NULL) { + tmp->pre =3D header; + } else { + tmp->pre =3D tmp_pre; + tmp_pre->next =3D tmp; + } + + tmp_pre =3D tmp; + (*len) ++; + } + return header; + + cleanup: + VIR_DIR_CLOSE(dp); + tmp_pre =3D tmp =3D header; + while (tmp) { + tmp_pre =3D tmp; + tmp =3D tmp->next; + VIR_FREE(tmp_pre); + } + return NULL; +} + +static int +virResCtrlAppendDomain(virResDomainPtr dom) +{ + virResDomainPtr p =3D domainall.domains; + while (p->next !=3D NULL) p =3D p->next; + p->next =3D dom; + dom->pre =3D p; + domainall.num_domains +=3D 1; + return 0; +} + +static int +virResCtrlGetSocketIdByHostID(int type, unsigned int hostid) +{ + size_t i; + for (i =3D 0; i < resctrlall[type].num_banks; i++) { + if (resctrlall[type].cache_banks[i].host_id =3D=3D hostid) + return i; + } + return -1; +} + +static int +virResCtrlCalculateSchemata(int type, + int sid, + unsigned hostid, + unsigned long long size) +{ + size_t i; + int count; + virResDomainPtr p; + unsigned int tmp_schemata; + unsigned int schemata_sum =3D 0; + + if (resctrlall[type].cache_banks[sid].cache_left < size) { + VIR_ERROR(_("Not enough cache left on bank %u"), hostid); + return -1; + } + if ((count =3D size / resctrlall[type].cache_banks[sid].cache_min) <= =3D 0) { + VIR_ERROR(_("Error cache size %llu"), size); + return -1; + } + + tmp_schemata =3D VIR_RESCTRL_GET_SCHEMATA(count); + + p =3D domainall.domains; + p =3D p->next; + for (i =3D 1; i < domainall.num_domains; i ++) { + schemata_sum |=3D p->schematas[type]->schemata_items[sid].schemata; + p =3D p->next; + } + + tmp_schemata =3D tmp_schemata << (resctrlall[type].cbm_len - count); + + while ((tmp_schemata & schemata_sum) !=3D 0) + tmp_schemata =3D tmp_schemata >> 1; + return tmp_schemata; +} + +int virResCtrlSetCacheBanks(virDomainCachetunePtr cachetune, + unsigned char *uuid, pid_t *pids, int npid) +{ + size_t i; + char name[VIR_UUID_STRING_BUFLEN]; + virResDomainPtr p; + int type; + int sid; + int schemata; + + virUUIDFormat(uuid, name); + + for (i =3D 0; i < cachetune->n_banks; i++) { + VIR_DEBUG("cache_banks %u, %u, %llu, %s", + cachetune->cache_banks[i].id, + cachetune->cache_banks[i].host_id, + cachetune->cache_banks[i].size, + cachetune->cache_banks[i].type); + } + + if (cachetune->n_banks < 1) + return 0; + + p =3D virResCtrlGetDomain(name); + if (p =3D=3D NULL) { + VIR_DEBUG("no domain name %s found, create new one!", name); + p =3D virResCtrlCreateDomain(name); + } + + if (p !=3D NULL) { + for (i =3D 0; i < cachetune->n_banks; i++) { + if ((type =3D virResCtrlTypeFromString( + cachetune->cache_banks[i].type)) < 0) { + VIR_WARN("Ignore unknown cache type %s.", + cachetune->cache_banks[i].type); + continue; + } + + if ((sid =3D virResCtrlGetSocketIdByHostID( + type, cachetune->cache_banks[i].host_id)) < 0)= { + VIR_WARN("Can not find cache bank host id %u.", + cachetune->cache_banks[i].host_id); + continue; + } + + if ((schemata =3D virResCtrlCalculateSchemata( + type, sid, cachetune->cache_banks[i].host_id, + cachetune->cache_banks[i].size)) < 0) { + VIR_WARN("Failed to set schemata for cache bank id %u", + cachetune->cache_banks[i].id); + continue; + } + + p->schematas[type]->schemata_items[sid].schemata =3D schemata; + } + + for (i =3D 0; i < npid; i++) + virResCtrlAddTask(p, pids[i]); + + if (virResCtrlFlushDomainToSysfs(p) < 0) { + VIR_WARN("failed to flush domain %s to sysfs", name); + virResCtrlDestroyDomain(p); + return -1; + } + virResCtrlAppendDomain(p); + } else { + VIR_ERROR(_("Failed to create a domain in sysfs")); + return -1; + } + + virResCtrlRefresh(); + /* after refresh, flush header's schemata changes to sys fs */ + if (virResCtrlFlushDomainToSysfs(domainall.domains) < 0) + VIR_WARN("failed to flush domain to sysfs"); + + return 0; +} + +/* Should be called after pid disappeared, we recalculate + * schemata of default and flush it to sys fs. + */ +int virResCtrlUpdate(void) +{ + int rc; + + if ((rc =3D virResCtrlRefresh()) < 0) + VIR_WARN("failed to refresh rescontrol"); + + if ((rc =3D virResCtrlFlushDomainToSysfs(domainall.domains)) < 0) + VIR_WARN("failed to flush domain to sysfs"); + + return rc; +} + int virResCtrlInit(void) { @@ -333,13 +1021,18 @@ virResCtrlInit(void) return -1; } if (virFileExists(tmp)) { - if ((rc =3D virResCtrlGetConfig(i)) < 0) + if ((rc =3D virResCtrlGetConfig(i)) < 0) { VIR_ERROR(_("Failed to get resource control config")); return -1; + } } - VIR_FREE(tmp); } + + domainall.domains =3D virResCtrlGetAllDomains(&(domainall.num_domains)= ); + + if ((rc =3D virResCtrlRefresh()) < 0) + VIR_ERROR(_("Failed to refresh resource control")); return rc; } =20 diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 3f6fcae..ba5697e 100644 --- a/src/util/virresctrl.h +++ b/src/util/virresctrl.h @@ -26,6 +26,7 @@ =20 # include "virutil.h" # include "virbitmap.h" +# include "domain_conf.h" =20 enum { VIR_RDT_RESOURCE_L3, @@ -73,9 +74,10 @@ struct _virResCtrl { virResCacheBankPtr cache_banks; }; =20 - bool virResCtrlAvailable(void); int virResCtrlInit(void); virResCtrlPtr virResCtrlGet(int); - +int virResCtrlSetCacheBanks(virDomainCachetunePtr, + unsigned char *, pid_t *, int); +int virResCtrlUpdate(void); #endif --=20 1.9.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list