From nobody Sun May 19 09:23:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) client-ip=170.10.133.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=fail(p=none dis=none) header.from=huawei.com Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.zohomail.com with SMTPS id 1625203109994286.70128622127345; Thu, 1 Jul 2021 22:18:29 -0700 (PDT) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-472-wz8cgYu9PumgA2Drmgh1zw-1; Fri, 02 Jul 2021 01:18:27 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 99128100C609; Fri, 2 Jul 2021 05:18:21 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7122518AA1; Fri, 2 Jul 2021 05:18:18 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 0B2044EA29; Fri, 2 Jul 2021 05:18:12 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.rdu2.redhat.com [10.11.54.5]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 16259R82019800 for ; Fri, 2 Jul 2021 01:09:28 -0400 Received: by smtp.corp.redhat.com (Postfix) id D0FDC10727D; Fri, 2 Jul 2021 05:09:27 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast05.extmail.prod.ext.rdu2.redhat.com [10.11.55.21]) by smtp.corp.redhat.com (Postfix) with ESMTPS id CBD32108480 for ; Fri, 2 Jul 2021 05:09:25 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-2.mimecast.com [207.211.31.81]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id E2980802E5E for ; Fri, 2 Jul 2021 05:09:24 +0000 (UTC) Received: from szxga08-in.huawei.com (szxga08-in.huawei.com [45.249.212.255]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-419-lLax0iVJNDqDdREJSV8imw-1; Fri, 02 Jul 2021 01:09:21 -0400 Received: from dggemv704-chm.china.huawei.com (unknown [172.30.72.54]) by szxga08-in.huawei.com (SkyGuard) with ESMTP id 4GGMyy5DB8z1BRrJ for ; Fri, 2 Jul 2021 12:48:10 +0800 (CST) Received: from dggpeml500009.china.huawei.com (7.185.36.209) by dggemv704-chm.china.huawei.com (10.3.19.47) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.2; Fri, 2 Jul 2021 12:53:32 +0800 Received: from 90078.china.huawei.com (10.174.187.199) by dggpeml500009.china.huawei.com (7.185.36.209) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2176.2; Fri, 2 Jul 2021 12:53:32 +0800 X-MC-Unique: wz8cgYu9PumgA2Drmgh1zw-1 X-MC-Unique: lLax0iVJNDqDdREJSV8imw-1 From: Yang Fei To: Subject: [PATCH] domstats:add haltpolling time statistic interface Date: Fri, 2 Jul 2021 12:53:29 +0800 Message-ID: <20210702045329.32288-1-yangfei85@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.174.187.199] X-ClientProxiedBy: dggems702-chm.china.huawei.com (10.3.19.179) To dggpeml500009.china.huawei.com (7.185.36.209) X-CFilter-Loop: Reflected X-Mimecast-Impersonation-Protect: Policy=CLT - Impersonation Protection Definition; Similar Internal Domain=false; Similar Monitored External Domain=false; Custom External Domain=false; Mimecast External Domain=false; Newly Observed Domain=false; Internal User Name=false; Custom Display Name List=false; Reply-to Address Mismatch=false; Targeted Threat Dictionary=false; Mimecast Threat Dictionary=false; Custom Threat Dictionary=false X-Scanned-By: MIMEDefang 2.79 on 10.11.54.5 X-MIME-Autoconverted: from quoted-printable to 8bit by lists01.pubmisc.prod.ext.phx2.redhat.com id 16259R82019800 X-loop: libvir-list@redhat.com Cc: yangfei85@huawei.com, xiexiangyou@huawei.com 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: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=libvir-list-bounces@redhat.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This patch add the ability to statistic the halt polling time when VM execute HLT(arm is WFI). In actual services, the execution of the HLT instruction by the guest is an important cause of virtualization overhead. The halt polling feature is introduced to solve this problem. When a guest idle VM exit occurs, the host continues polling for a period of time to reduce the guest service delay. This mechanism may cause the CPU usage to be 100% when the physical CPU is idle. If the guest service model is woken up at an interval to process a small amount of traffic, and the interval is shorter than kvm halt_poll_ns. The host polls the block time of the entire VM and the CPU usage increases to 100%. The kernel provides the capability of collecting statistics on the halt polling time after v5.8, Introduced by commit . It is rendered in debugfs. Therefore, we can use this kernel feature to provide the halt poll time to the user to obtain a more accurate CPU usage as required. Signed-off-by: Yang Fei --- src/libvirt_private.syms | 2 + src/qemu/qemu_driver.c | 29 +++++++++++++ src/util/virutil.c | 89 ++++++++++++++++++++++++++++++++++++++++ src/util/virutil.h | 9 ++++ 4 files changed, 129 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 68e4b6aab8..f92213b8c2 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3479,6 +3479,8 @@ virDoesUserExist; virDoubleToStr; virFormatIntDecimal; virFormatIntPretty; +virGetCpuHaltPollTime; +virGetDebugFsKvmValue; virGetDeviceID; virGetDeviceUnprivSGIO; virGetGroupID; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 235f575901..3a2b530ecf 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -17812,6 +17812,32 @@ qemuDomainGetStatsCpuCache(virQEMUDriver *driver, return ret; } =20 +#ifdef __linux__ +static int +qemuDomainGetStatsCpuHaltPollTime(virDomainObj *dom, + virTypedParamList *params) +{ + unsigned long long haltPollSuccess =3D 0; + unsigned long long haltPollFail =3D 0; + pid_t pid =3D dom->pid; + + if (virGetCpuHaltPollTime(pid, &haltPollSuccess, &haltPollFail) !=3D 0) + return -1; + if (virTypedParamListAddULLong(params, haltPollSuccess, "haltpollsucce= ss.time") < 0) + return -1; + if (virTypedParamListAddULLong(params, haltPollFail, "haltpollfail.tim= e") < 0) + return -1; + + return 0; +} +#else +static int +qemuDomainGetStatsCpuHaltPollTime(virDomainObj *dom, + virTypedParamList *params) +{ + return -1; +} +#endif =20 static int qemuDomainGetStatsCpuCgroup(virDomainObj *dom, @@ -17852,6 +17878,9 @@ qemuDomainGetStatsCpu(virQEMUDriver *driver, if (qemuDomainGetStatsCpuCache(driver, dom, params) < 0) return -1; =20 + if (qemuDomainGetStatsCpuHaltPollTime(dom, params) < 0) + return -1; + return 0; } =20 diff --git a/src/util/virutil.c b/src/util/virutil.c index 311cbbf93a..8715deaca5 100644 --- a/src/util/virutil.c +++ b/src/util/virutil.c @@ -1936,3 +1936,92 @@ virPipeNonBlock(int fds[2]) { return virPipeImpl(fds, true, true); } + +int +virGetDebugFsKvmValue(struct dirent *ent, + const char *path, + const char *filename, + unsigned long long *value) +{ + g_autofree char *valToStr =3D NULL; + g_autofree char *valPath =3D NULL; + int rc =3D -1; + int ret =3D -1; + + valPath =3D g_strdup_printf("%s/%s/%s", path, ent->d_name, filename); + + if ((rc =3D virFileReadAll(valPath, 16, &valToStr)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to read from '%s'"), valPath); + goto cleanup; + } + + /* Terminated with '\n' has sometimes harmful effects to the caller */ + if (rc > 0 && (valToStr)[rc - 1] =3D=3D '\n') + (valToStr)[rc - 1] =3D '\0'; + + /* 10 is a Cardinality, must be between 2 and 36 inclusive, + * or special value 0. Used in fuction strtoull() + */ + if (virStrToLong_ull(valToStr, NULL, 10, value) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse '%s' as an integer"), valToStr); + goto cleanup; + } + + ret =3D 0; +cleanup: + return ret; +} + +int +virGetCpuHaltPollTime(pid_t pid, + unsigned long long *haltPollSuccess, + unsigned long long *haltPollFail) +{ + g_autofree char *pidToStr =3D NULL; + g_autofree char *debugFsPath =3D NULL; + g_autofree char *completePath =3D NULL; + struct dirent *ent =3D NULL; + DIR *dir =3D NULL; + int ret =3D -1; + int flag =3D 0; + + if (!(debugFsPath =3D virFileFindMountPoint("debugfs"))) { + virReportSystemError(errno, "%s", + _("unable to find debugfs mountpoint")); + goto cleanup; + } + + completePath =3D g_strdup_printf("%s/%s", debugFsPath, "kvm"); + if (virDirOpen(&dir, completePath) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s %s", "Can not open directory", completePath); + return ret; + } + + pidToStr =3D g_strdup_printf("%d", pid); + while (virDirRead(dir, &ent, NULL) > 0) { + if (strncmp(ent->d_name, pidToStr, strlen(pidToStr)) =3D=3D 0 && + ent->d_name[strlen(pidToStr)] =3D=3D '-') { + flag =3D 1; + break; + } + } + + if (flag =3D=3D 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Could not find VM(Pid %s) in '%s'"), pidToStr, c= ompletePath); + goto cleanup; + } + + if (virGetDebugFsKvmValue(ent, completePath, "halt_poll_success_ns", h= altPollSuccess) < 0 || + virGetDebugFsKvmValue(ent, completePath, "halt_poll_fail_ns", halt= PollFail) < 0) { + goto cleanup; + } + + ret =3D 0; +cleanup: + closedir(dir); + return ret; +} diff --git a/src/util/virutil.h b/src/util/virutil.h index 854b494890..b3c1e8a0bc 100644 --- a/src/util/virutil.h +++ b/src/util/virutil.h @@ -225,3 +225,12 @@ int virPipeQuiet(int fds[2]); * Returns: -1 on error, 0 on success */ int virPipeNonBlock(int fds[2]); + +int virGetDebugFsKvmValue(struct dirent *ent, + const char *path, + const char *filename, + unsigned long long *value); + +int virGetCpuHaltPollTime(pid_t pid, + unsigned long long *haltPollSuccess, + unsigned long long *haltPollFail); --=20 2.23.0