From nobody Mon Feb 9 08:57:59 2026 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 1486093816301722.1683041535656; Thu, 2 Feb 2017 19:50:16 -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 v133kZvH014502; Thu, 2 Feb 2017 22:46:35 -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 v133jrmT029372 for ; Thu, 2 Feb 2017 22:45:53 -0500 Received: from mx1.redhat.com (ext-mx10.extmail.prod.ext.phx2.redhat.com [10.5.110.39]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id v133jqoO021265 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=NO); Thu, 2 Feb 2017 22:45:52 -0500 Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) (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 9E90761B86; Fri, 3 Feb 2017 03:45:50 +0000 (UTC) Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga104.fm.intel.com with ESMTP; 02 Feb 2017 19:45:49 -0800 Received: from s2600wt.sh.intel.com ([10.239.48.158]) by orsmga005.jf.intel.com with ESMTP; 02 Feb 2017 19:45:48 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,327,1477983600"; d="scan'208";a="60338034" From: Eli Qiao To: libvir-list@redhat.com Date: Fri, 3 Feb 2017 11:47:15 +0800 Message-Id: <1486093636-63999-5-git-send-email-liyong.qiao@intel.com> In-Reply-To: <1486093636-63999-1-git-send-email-liyong.qiao@intel.com> References: <1486093636-63999-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.39]); Fri, 03 Feb 2017 03:45:51 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Fri, 03 Feb 2017 03:45:51 +0000 (UTC) for IP:'192.55.52.120' DOMAIN:'mga04.intel.com' HELO:'mga04.intel.com' FROM:'liyong.qiao@intel.com' RCPT:'' X-RedHat-Spam-Score: -1.922 (BAYES_50, DCC_REPUT_00_12, RCVD_IN_DNSWL_MED, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, RP_MATCHES_RCVD, SPF_PASS) 192.55.52.120 mga04.intel.com 192.55.52.120 mga04.intel.com X-Scanned-By: MIMEDefang 2.68 on 10.5.11.24 X-Scanned-By: MIMEDefang 2.78 on 10.5.110.39 X-loop: libvir-list@redhat.com Cc: mkletzan@redhat.com, qiaowei.ren@intel.com, mtosatti@redhat.com, qiaoliyong@gmail.com Subject: [libvirt] [V2 4/5] 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 | 2 + src/util/virresctrl.c | 641 +++++++++++++++++++++++++++++++++++++++++++= +++- src/util/virresctrl.h | 47 +++- 3 files changed, 688 insertions(+), 2 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 08a0bc4..2b3278a 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2319,6 +2319,8 @@ virResCtrlInit; virResCtrlGet; virResCtrlTypeFromString; virResCtrlTypeToString; +virResCtrlSetCacheBanks; +virResCtrlUpdate; =20 =20 # util/virrotatingfile.h diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index 76d4ab8..6be581c 100644 --- a/src/util/virresctrl.c +++ b/src/util/virresctrl.c @@ -68,6 +68,11 @@ do { \ =20 static unsigned int host_id =3D 0; =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", @@ -87,6 +92,64 @@ static virResCtrl ResCtrlAll[] =3D { }, }; =20 +/* + * How many bits is set in schemata + * eg: + * virResCtrlBitsNum(1011) =3D 2 */ +static int virResCtrlBitsContinuesNum(unsigned schemata) { + int ret =3D 0; + for (int 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; @@ -109,6 +172,70 @@ cleanup: return ret; } =20 +/* Return pointer of and ncount of schemata*/ +static virResSchemataPtr virParseSchemata(const char* schemata_str, int* n= count) +{ + 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 +=3D1; + } + 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) { @@ -252,6 +379,7 @@ static virResCacheBankPtr virResCtrlGetCacheBanks(int t= ype, int* n_sockets) } 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; @@ -268,7 +396,7 @@ static int virResCtrlGetConfig(int type) int 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) { @@ -325,6 +453,512 @@ 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 virRscctrlRemoveDomain(const char *name) +{ + char *path =3D NULL; + int rc =3D 0; + + if ((rc =3D asprintf(&path, "%s/%s", RESCTRL_DIR, name)) < 0) + return rc; + rc =3D rmdir(path); + VIR_FREE(path); + return rc; +} + +/* assemble schemata string*/ +static +char* virResCtrlAssembleSchemata(virResSchemataPtr schemata, int type) +{ + virBuffer buf =3D VIR_BUFFER_INITIALIZER; + + virBufferAsprintf(&buf, "%s:%u=3D%x", ResCtrlAll[type].name, + schemata->schemata_items[0].socket_no, + schemata->schemata_items[0].schemata); + + for(int 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) +{ + int i; + int j; + int k; + unsigned int tmp_schemata; + unsigned int default_schemata; + + virResDomainPtr header, p; + + header =3D DomainAll.domains; + + for (i =3D 0; i < RDT_NUM_RESOURCES; 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].m= in_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) +{ + int i; + char* tasks; + unsigned int origin_count =3D DomainAll.num_domains; + virResDomainPtr p, pre, del=3DNULL; + pre =3D DomainAll.domains; + p =3D pre->next; + + for (i =3D 1; i < origin_count; 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; + if(virRscctrlRemoveDomain(del->name) < 0) + VIR_WARN("Failed to remove partition %s", p->name); + + VIR_DEBUG("Remove partition %s", del->name); + + VIR_FREE(del->name); + VIR_FREE(del->tasks); + VIR_FREE(del); + del =3D NULL; + + DomainAll.num_domains -=3D1; + } 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) { + int i; + virResDomainPtr p =3D DomainAll.domains; + for(i =3D 0; i < DomainAll.num_domains; i++) + { + if((p->name) && (strcmp(name, p->name) =3D=3D 0)) { + return p; + } + p =3D p->next; + } + return NULL; +} + +static int +virResCtrlAddTask(virResDomainPtr dom, pid_t pid) +{ + virBuffer buf =3D VIR_BUFFER_INITIALIZER; + if(dom->tasks =3D=3D NULL) { + virBufferAsprintf(&buf, "%lld\n", (long long)pid); + } else { + virBufferAsprintf(&buf, "%s%lld\n", dom->tasks, (long long)pid); + VIR_FREE(dom->tasks); + } + dom->tasks =3D virBufferContentAndReset(&buf); + 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; + char* tasks =3D NULL; + virResDomainPtr p; + + if(VIR_ALLOC(p) < 0) + goto cleanup; + + if(name !=3D NULL && virResCtrlGetTasks(name, &tasks) < 0) + goto cleanup; + + for(int i =3D 0; i < RDT_NUM_RESOURCES; 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 tasks; + + 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; + if (asprintf(&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(int i =3D 0; i < RDT_NUM_RESOURCES; i++) { + if(VIR_RESCTRL_ENABLED(i)) { + int min_bits =3D VIR_RESCTRL_GET_SCHEMATA(ResCtrlAll[i].min_c= bm_bits); + for(int 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; +} + +static +int virResCtrlDestroyDomain(virResDomainPtr p) +{ + char *path; + if (asprintf(&path, "%s/%s", RESCTRL_DIR, p->name) < 0) + return -1; + rmdir(path); + + VIR_FREE(p->name); + p->name =3D NULL; + VIR_FREE(p->tasks); + VIR_FREE(p); + p =3D NULL; + return 0; +} + +/* flush domains's information to sysfs*/ +static int +virResCtrlFlushDomainToSysfs(virResDomainPtr dom) +{ + int i; + char* schemata; + char* tmp; + int rc =3D -1; + virBuffer buf =3D VIR_BUFFER_INITIALIZER; + + for(i =3D 0; i < RDT_NUM_RESOURCES; 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(!virStringIsEmpty(dom->tasks) + && virResCtrlWrite(dom->name, "tasks", dom->tasks) < 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=3Dp->next; + p->next =3D dom; + dom->pre =3D p; + DomainAll.num_domains +=3D1; + return 0; +} + +static int +virResCtrlGetSocketIdByHostID(int type, unsigned int hostid) +{ + int 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) +{ + int 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("Note 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 pid) +{ + 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); + } + + 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; + } + + virResCtrlAddTask(p, pid); + + 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) { int i =3D 0; char *tmp; @@ -341,6 +975,11 @@ int virResCtrlInit(void) { =20 VIR_FREE(tmp); } + + DomainAll.domains =3D virResCtrlGetAllDomains(&(DomainAll.num_domains)= ); + + if((rc =3D virResCtrlRefresh()) < 0) + VIR_WARN("failed to refresh resource control"); return rc; } =20 diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index 3cc41da..11f43d8 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 #define RESCTRL_DIR "/sys/fs/resctrl" #define RESCTRL_INFO_DIR "/sys/fs/resctrl/info" @@ -82,9 +83,53 @@ struct _virResCtrl { virResCacheBankPtr cache_banks; }; =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[RDT_NUM_RESOURCES]; + char* tasks; + int 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 bool virResCtrlAvailable(void); int virResCtrlInit(void); virResCtrlPtr virResCtrlGet(int); - +int virResCtrlSetCacheBanks(virDomainCachetunePtr, unsigned char*, pid_t); +int virResCtrlUpdate(void); #endif --=20 1.9.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list