From nobody Sun Feb 8 07:08:03 2026 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=linux.microsoft.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 1639168528974871.1379321216864; Fri, 10 Dec 2021 12:35:28 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-158-gonkoO74MH2hlvzNkvXeTw-1; Fri, 10 Dec 2021 15:35:24 -0500 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 1E827192FDA2; Fri, 10 Dec 2021 20:35:20 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id F3AED45D61; Fri, 10 Dec 2021 20:35:19 +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 B2A0E180B617; Fri, 10 Dec 2021 20:35:19 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 1BAKYvAh008341 for ; Fri, 10 Dec 2021 15:34:57 -0500 Received: by smtp.corp.redhat.com (Postfix) id 8ECB3400E127; Fri, 10 Dec 2021 20:34:57 +0000 (UTC) Received: from mimecast-mx02.redhat.com (mimecast08.extmail.prod.ext.rdu2.redhat.com [10.11.55.24]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 8A5A0400F3F1 for ; Fri, 10 Dec 2021 20:34:57 +0000 (UTC) Received: from us-smtp-1.mimecast.com (us-smtp-1.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 6A28D39D30B9 for ; Fri, 10 Dec 2021 20:34:57 +0000 (UTC) Received: from linux.microsoft.com (linux.microsoft.com [13.77.154.182]) by relay.mimecast.com with ESMTP id us-mta-143-z_qiVSZjPpinCrrTHEARAQ-1; Fri, 10 Dec 2021 15:34:55 -0500 Received: from prapal-ch2.oiwy50ateaxezb1sqsoezlib2f.xx.internal.cloudapp.net (unknown [20.80.162.67]) by linux.microsoft.com (Postfix) with ESMTPSA id 34A3220B717A; Fri, 10 Dec 2021 12:34:54 -0800 (PST) X-MC-Unique: gonkoO74MH2hlvzNkvXeTw-1 X-MC-Unique: z_qiVSZjPpinCrrTHEARAQ-1 DKIM-Filter: OpenDKIM Filter v2.11.0 linux.microsoft.com 34A3220B717A From: Praveen K Paladugu To: libvir-list@redhat.com Subject: [libvirt PATCH v3 01/13] util: Helper functions to get process info Date: Fri, 10 Dec 2021 20:34:36 +0000 Message-Id: <20211210203448.1579606-2-prapal@linux.microsoft.com> In-Reply-To: <20211210203448.1579606-1-prapal@linux.microsoft.com> References: <20211210203448.1579606-1-prapal@linux.microsoft.com> MIME-Version: 1.0 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.84 on 10.11.54.2 X-MIME-Autoconverted: from quoted-printable to 8bit by lists01.pubmisc.prod.ext.phx2.redhat.com id 1BAKYvAh008341 X-loop: libvir-list@redhat.com Cc: william.douglas@intel.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 X-ZM-MESSAGEID: 1639168529554100001 Content-Type: text/plain; charset="utf-8" Move qemuGetProcessInfo and qemuGetSchedInfo methods to util and share them with ch driver. Signed-off-by: Praveen K Paladugu Reviewed-by: Michal Privoznik --- src/libvirt_private.syms | 2 + src/qemu/qemu_driver.c | 116 ++------------------------------------- src/util/virprocess.c | 108 ++++++++++++++++++++++++++++++++++++ src/util/virprocess.h | 5 ++ 4 files changed, 120 insertions(+), 111 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index da27ee7b53..56adc192cd 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3101,8 +3101,10 @@ virProcessGetAffinity; virProcessGetMaxMemLock; virProcessGetNamespaces; virProcessGetPids; +virProcessGetSchedInfo; virProcessGetStartTime; virProcessGetStat; +virProcessGetStatInfo; virProcessGroupGet; virProcessGroupKill; virProcessKill; diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index e444ad2d45..ba3efef42b 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -1317,113 +1317,6 @@ qemuGetSchedstatDelay(unsigned long long *cpudelay, return 0; } =20 - -static int -qemuGetSchedInfo(unsigned long long *cpuWait, - pid_t pid, pid_t tid) -{ - g_autofree char *proc =3D NULL; - g_autofree char *data =3D NULL; - g_auto(GStrv) lines =3D NULL; - size_t i; - double val; - - *cpuWait =3D 0; - - /* In general, we cannot assume pid_t fits in int; but /proc parsing - * is specific to Linux where int works fine. */ - if (tid) - proc =3D g_strdup_printf("/proc/%d/task/%d/sched", (int)pid, (int)= tid); - else - proc =3D g_strdup_printf("/proc/%d/sched", (int)pid); - if (!proc) - return -1; - - /* The file is not guaranteed to exist (needs CONFIG_SCHED_DEBUG) */ - if (access(proc, R_OK) < 0) { - return 0; - } - - if (virFileReadAll(proc, (1<<16), &data) < 0) - return -1; - - lines =3D g_strsplit(data, "\n", 0); - if (!lines) - return -1; - - for (i =3D 0; lines[i] !=3D NULL; i++) { - const char *line =3D lines[i]; - - /* Needs CONFIG_SCHEDSTATS. The second check - * is the old name the kernel used in past */ - if (STRPREFIX(line, "se.statistics.wait_sum") || - STRPREFIX(line, "se.wait_sum")) { - line =3D strchr(line, ':'); - if (!line) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Missing separator in sched info '%s'"), - lines[i]); - return -1; - } - line++; - while (*line =3D=3D ' ') - line++; - - if (virStrToDouble(line, NULL, &val) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Unable to parse sched info value '%s'"), - line); - return -1; - } - - *cpuWait =3D (unsigned long long)(val * 1000000); - break; - } - } - - return 0; -} - - -static int -qemuGetProcessInfo(unsigned long long *cpuTime, int *lastCpu, long *vm_rss, - pid_t pid, pid_t tid) -{ - g_auto(GStrv) proc_stat =3D virProcessGetStat(pid, tid); - unsigned long long usertime =3D 0, systime =3D 0; - long rss =3D 0; - int cpu =3D 0; - - if (!proc_stat || - virStrToLong_ullp(proc_stat[VIR_PROCESS_STAT_UTIME], NULL, 10, &us= ertime) < 0 || - virStrToLong_ullp(proc_stat[VIR_PROCESS_STAT_STIME], NULL, 10, &sy= stime) < 0 || - virStrToLong_l(proc_stat[VIR_PROCESS_STAT_RSS], NULL, 10, &rss) < = 0 || - virStrToLong_i(proc_stat[VIR_PROCESS_STAT_PROCESSOR], NULL, 10, &c= pu) < 0) { - VIR_WARN("cannot parse process status data"); - } - - /* We got jiffies - * We want nanoseconds - * _SC_CLK_TCK is jiffies per second - * So calculate thus.... - */ - if (cpuTime) - *cpuTime =3D 1000ull * 1000ull * 1000ull * (usertime + systime) - / (unsigned long long)sysconf(_SC_CLK_TCK); - if (lastCpu) - *lastCpu =3D cpu; - - if (vm_rss) - *vm_rss =3D rss * virGetSystemPageSizeKB(); - - - VIR_DEBUG("Got status for %d/%d user=3D%llu sys=3D%llu cpu=3D%d rss=3D= %ld", - (int)pid, tid, usertime, systime, cpu, rss); - - return 0; -} - - static int qemuDomainHelperGetVcpus(virDomainObj *vm, virVcpuInfoPtr info, @@ -1463,7 +1356,7 @@ qemuDomainHelperGetVcpus(virDomainObj *vm, vcpuinfo->number =3D i; vcpuinfo->state =3D VIR_VCPU_RUNNING; =20 - if (qemuGetProcessInfo(&vcpuinfo->cpuTime, + if (virProcessGetStatInfo(&vcpuinfo->cpuTime, &vcpuinfo->cpu, NULL, vm->pid, vcpupid) < 0) { virReportSystemError(errno, "%s", @@ -1483,7 +1376,7 @@ qemuDomainHelperGetVcpus(virDomainObj *vm, } =20 if (cpuwait) { - if (qemuGetSchedInfo(&(cpuwait[ncpuinfo]), vm->pid, vcpupid) <= 0) + if (virProcessGetSchedInfo(&(cpuwait[ncpuinfo]), vm->pid, vcpu= pid) < 0) return -1; } =20 @@ -2626,7 +2519,8 @@ qemuDomainGetInfo(virDomainPtr dom, } =20 if (virDomainObjIsActive(vm)) { - if (qemuGetProcessInfo(&(info->cpuTime), NULL, NULL, vm->pid, 0) <= 0) { + if (virProcessGetStatInfo(&(info->cpuTime), NULL, NULL, + vm->pid, 0) < 0) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("cannot read cputime for domain")); goto cleanup; @@ -10623,7 +10517,7 @@ qemuDomainMemoryStatsInternal(virQEMUDriver *driver, ret =3D 0; } =20 - if (qemuGetProcessInfo(NULL, NULL, &rss, vm->pid, 0) < 0) { + if (virProcessGetStatInfo(NULL, NULL, &rss, vm->pid, 0) < 0) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("cannot get RSS for domain")); } else { diff --git a/src/util/virprocess.c b/src/util/virprocess.c index 7b0ad9c97b..3be9080b67 100644 --- a/src/util/virprocess.c +++ b/src/util/virprocess.c @@ -1764,3 +1764,111 @@ virProcessGetStat(pid_t pid, =20 return ret; } + + +int +virProcessGetStatInfo(unsigned long long *cpuTime, int *lastCpu, long *vm_= rss, + pid_t pid, pid_t tid) +{ + g_auto(GStrv) proc_stat =3D virProcessGetStat(pid, tid); + unsigned long long usertime =3D 0, systime =3D 0; + long rss =3D 0; + int cpu =3D 0; + + if (!proc_stat || + virStrToLong_ullp(proc_stat[VIR_PROCESS_STAT_UTIME], NULL, 10, + &usertime) < 0 + || virStrToLong_ullp(proc_stat[VIR_PROCESS_STAT_STIME], NULL, 10, + &systime) < 0 + || virStrToLong_l(proc_stat[VIR_PROCESS_STAT_RSS], NULL, 10, &rss)= < 0 + || virStrToLong_i(proc_stat[VIR_PROCESS_STAT_PROCESSOR], NULL, 10, + &cpu) < 0) { + VIR_WARN("cannot parse process status data"); + } + + /* We got jiffies + * We want nanoseconds + * _SC_CLK_TCK is jiffies per second + * So calculate thus.... + */ + if (cpuTime) + *cpuTime =3D 1000ull * 1000ull * 1000ull * (usertime + systime) + / (unsigned long long) sysconf(_SC_CLK_TCK); + if (lastCpu) + *lastCpu =3D cpu; + + if (vm_rss) + *vm_rss =3D rss * virGetSystemPageSizeKB(); + + + VIR_DEBUG("Got status for %d/%d user=3D%llu sys=3D%llu cpu=3D%d rss=3D= %ld", + (int) pid, tid, usertime, systime, cpu, rss); + + return 0; +} + +int +virProcessGetSchedInfo(unsigned long long *cpuWait, pid_t pid, pid_t tid) +{ + g_autofree char *proc =3D NULL; + g_autofree char *data =3D NULL; + + g_auto(GStrv) lines =3D NULL; + size_t i; + double val; + + *cpuWait =3D 0; + + /* In general, we cannot assume pid_t fits in int; but /proc parsing + * is specific to Linux where int works fine. */ + if (tid) + proc =3D g_strdup_printf("/proc/%d/task/%d/sched", (int) pid, (int= ) tid); + else + proc =3D g_strdup_printf("/proc/%d/sched", (int) pid); + if (!proc) + return -1; + + /* The file is not guaranteed to exist (needs CONFIG_SCHED_DEBUG) */ + if (access(proc, R_OK) < 0) { + return 0; + } + + if (virFileReadAll(proc, (1 << 16), &data) < 0) + return -1; + + lines =3D g_strsplit(data, "\n", 0); + if (!lines) + return -1; + + for (i =3D 0; lines[i] !=3D NULL; i++) { + const char *line =3D lines[i]; + + /* Needs CONFIG_SCHEDSTATS. The second check + * is the old name the kernel used in past */ + if (STRPREFIX(line, "se.statistics.wait_sum") || + STRPREFIX(line, "se.wait_sum")) { + line =3D strchr(line, ':'); + if (!line) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Missing separator in sched info '%s'"), + lines[i]); + return -1; + } + line++; + while (*line =3D=3D ' ') + line++; + + if (virStrToDouble(line, NULL, &val) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unable to parse sched info value '%s'"), + line); + return -1; + } + + *cpuWait =3D (unsigned long long) (val * 1000000); + break; + } + } + + return 0; +} diff --git a/src/util/virprocess.h b/src/util/virprocess.h index 82b7403964..d9d27c29b8 100644 --- a/src/util/virprocess.h +++ b/src/util/virprocess.h @@ -193,3 +193,8 @@ typedef enum { } virProcessNamespaceFlags; =20 int virProcessNamespaceAvailable(unsigned int ns); + +int virProcessGetStatInfo(unsigned long long *cpuTime, int *lastCpu, + long *vm_rss, pid_t pid, pid_t tid); +int virProcessGetSchedInfo(unsigned long long *cpuWait, pid_t pid, + pid_t tid); --=20 2.27.0