From nobody Sat Feb 7 15:48:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1562138490; cv=none; d=zoho.com; s=zohoarc; b=hvDXPIoOsOHkka28d3MfON6Yme+Io+YsE5Fyi6kjcXaMJ8Xh7KZYBpRMW5SQSl8tjDgBScDHy2ycMSbZrPFnPrgCzNnbw3ETL/f0T5GPQtuIAzsnl3Deh8IuG+GN1ha7bLYTn5NzfMcevGY3khmaEghMP3Ht/+L4alW4z1p9WgU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1562138490; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=K1ACnfu5YX5LECRoPeLov8h1jcFbmNHTDLgbFTNpJFU=; b=Ewg51wPaV/TM9ZlJqtih4rzswc2MGDvTFOZFLKyNvEPdm9vtdLQCSxDDifSni3y0aOJTptGTRPWXWSjODP+dA4xiZQic0TPRWUhY2XB7jg5YY55ZzULdOLQA/mFjV8MTc1bzkdspM4RufmNx7tj5IG8lrtAJRhIpBeGxG/OgFMA= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1562138490460611.1140853589612; Wed, 3 Jul 2019 00:21:30 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id E782485A04; Wed, 3 Jul 2019 07:21:25 +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 C357B174A7; Wed, 3 Jul 2019 07:21:24 +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 4DD4B4EBC5; Wed, 3 Jul 2019 07:21:23 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x637JYPK019922 for ; Wed, 3 Jul 2019 03:19:34 -0400 Received: by smtp.corp.redhat.com (Postfix) id 4A47A7840D; Wed, 3 Jul 2019 07:19:34 +0000 (UTC) Received: from localhost.localdomain (ovpn-204-217.brq.redhat.com [10.40.204.217]) by smtp.corp.redhat.com (Postfix) with ESMTP id A40C218EC7 for ; Wed, 3 Jul 2019 07:19:30 +0000 (UTC) From: Michal Privoznik To: libvir-list@redhat.com Date: Wed, 3 Jul 2019 09:19:18 +0200 Message-Id: <62f9779c25af1a0b49fa21098e494d058e096844.1562138162.git.mprivozn@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 1/3] virNetDevOpenvswitchInterfaceStats: Optimize for speed 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: , Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Wed, 03 Jul 2019 07:21:28 +0000 (UTC) Content-Type: text/plain; charset="utf-8" We run 'ovs-vsctl' nine times (first to find if interface is there and then eight times =3D for each stats member separately). This is very inefficient. I've found a way to run it once and with a bit of help from virJSON module we can parse out stats we need. Signed-off-by: Michal Privoznik --- src/util/virnetdevopenvswitch.c | 111 +++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 37 deletions(-) diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitc= h.c index c99ecfbf15..0fe64bedab 100644 --- a/src/util/virnetdevopenvswitch.c +++ b/src/util/virnetdevopenvswitch.c @@ -28,6 +28,7 @@ #include "virmacaddr.h" #include "virstring.h" #include "virlog.h" +#include "virjson.h" =20 #define VIR_FROM_THIS VIR_FROM_NONE =20 @@ -311,58 +312,94 @@ int virNetDevOpenvswitchInterfaceStats(const char *ifname, virDomainInterfaceStatsPtr stats) { - char *tmp; - bool gotStats =3D false; VIR_AUTOPTR(virCommand) cmd =3D NULL; VIR_AUTOFREE(char *) output =3D NULL; + VIR_AUTOPTR(virJSONValue) jsonStats =3D NULL; + virJSONValuePtr jsonMap =3D NULL; + size_t i; =20 - /* Just ensure the interface exists in ovs */ cmd =3D virCommandNew(OVSVSCTL); virNetDevOpenvswitchAddTimeout(cmd); - virCommandAddArgList(cmd, "get", "Interface", ifname, "name", NULL); + virCommandAddArgList(cmd, "--if-exists", "--format=3Dlist", "--data=3D= json", + "--no-headings", "--columns=3Dstatistics", "list", + "Interface", ifname, NULL); virCommandSetOutputBuffer(cmd, &output); =20 - if (virCommandRun(cmd, NULL) < 0) { + /* The above command returns either: + * 1) empty string if @ifname doesn't exist, or + * 2) a JSON array, for instance: + * ["map",[["collisions",0],["rx_bytes",0],["rx_crc_err",0],["rx_dr= opped",0], + * ["rx_errors",0],["rx_frame_err",0],["rx_over_err",0],["rx_packet= s",0], + * ["tx_bytes",12406],["tx_dropped",0],["tx_errors",0],["tx_packets= ",173]]] + */ + + if (virCommandRun(cmd, NULL) < 0 || + STREQ_NULLABLE(output, "")) { /* no ovs-vsctl or interface 'ifname' doesn't exists in ovs */ virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Interface not found")); return -1; } =20 -#define GET_STAT(name, member) \ - do { \ - VIR_FREE(output); \ - virCommandFree(cmd); \ - cmd =3D virCommandNew(OVSVSCTL); \ - virNetDevOpenvswitchAddTimeout(cmd); \ - virCommandAddArgList(cmd, "--if-exists", "get", "Interface", \ - ifname, "statistics:" name, NULL); \ - virCommandSetOutputBuffer(cmd, &output); \ - if (virCommandRun(cmd, NULL) < 0 || !output || !*output || *output= =3D=3D '\n') { \ - stats->member =3D -1; \ - } else { \ - if (virStrToLong_ll(output, &tmp, 10, &stats->member) < 0 || \ - *tmp !=3D '\n') { \ - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", \ - _("Fail to parse ovs-vsctl output")); \ - return -1; \ - } \ - gotStats =3D true; \ - } \ - } while (0) + if (!(jsonStats =3D virJSONValueFromString(output)) || + !virJSONValueIsArray(jsonStats) || + !(jsonMap =3D virJSONValueArrayGet(jsonStats, 1))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Unable to parse ovs-vsctl output")); + return -1; + } =20 - /* The TX/RX fields appear to be swapped here - * because this is the host view. */ - GET_STAT("rx_bytes", tx_bytes); - GET_STAT("rx_packets", tx_packets); - GET_STAT("rx_errors", tx_errs); - GET_STAT("rx_dropped", tx_drop); - GET_STAT("tx_bytes", rx_bytes); - GET_STAT("tx_packets", rx_packets); - GET_STAT("tx_errors", rx_errs); - GET_STAT("tx_dropped", rx_drop); + stats->rx_bytes =3D stats->rx_packets =3D stats->rx_errs =3D stats->rx= _drop =3D -1; + stats->tx_bytes =3D stats->tx_packets =3D stats->tx_errs =3D stats->tx= _drop =3D -1; =20 - if (!gotStats) { + for (i =3D 0; i < virJSONValueArraySize(jsonMap); i++) { + virJSONValuePtr item =3D virJSONValueArrayGet(jsonMap, i); + virJSONValuePtr jsonKey; + virJSONValuePtr jsonVal; + const char *key; + long long val; + + if (!item || + (!(jsonKey =3D virJSONValueArrayGet(item, 0))) || + (!(jsonVal =3D virJSONValueArrayGet(item, 1))) || + (!(key =3D virJSONValueGetString(jsonKey))) || + (virJSONValueGetNumberLong(jsonVal, &val) < 0)) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Malformed ovs-vsctl output")); + return -1; + } + + /* The TX/RX fields appear to be swapped here + * because this is the host view. */ + if (STREQ(key, "rx_bytes")) { + stats->tx_bytes =3D val; + } else if (STREQ(key, "rx_packets")) { + stats->tx_packets =3D val; + } else if (STREQ(key, "rx_errors")) { + stats->tx_errs =3D val; + } else if (STREQ(key, "rx_dropped")) { + stats->tx_drop =3D val; + } else if (STREQ(key, "tx_bytes")) { + stats->rx_bytes =3D val; + } else if (STREQ(key, "tx_packets")) { + stats->rx_packets =3D val; + } else if (STREQ(key, "tx_errors")) { + stats->rx_errs =3D val; + } else if (STREQ(key, "tx_dropped")) { + stats->rx_drop =3D val; + } else { + VIR_DEBUG("Unused ovs-vsctl stat key=3D%s val=3D%lld", key, va= l); + } + } + + if (stats->rx_bytes =3D=3D -1 && + stats->rx_packets =3D=3D -1 && + stats->rx_errs =3D=3D -1 && + stats->rx_drop =3D=3D -1 && + stats->tx_bytes =3D=3D -1 && + stats->tx_packets =3D=3D -1 && + stats->tx_errs =3D=3D -1 && + stats->tx_drop =3D=3D -1) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Interface doesn't have any statistics")); return -1; --=20 2.21.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Sat Feb 7 15:48:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1562138497; cv=none; d=zoho.com; s=zohoarc; b=Gm0R8j5uduoU+uyEn3nGyGC66FmI+SgiW1mpEiw/2PdxihlwQjOGcTBAhbWMuEdyszDIOHD0M06E4UbKgvcwLqMEV5rTnSySJ1dmRXcvkfIvtTEdQMu6y/68xZ/7/EDfdb8HyOXAHCjcebW9fz8bVHw9Y/5tqsXvBLqtos7KhzQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1562138497; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=Dfh3/hsmw6vevqpYkCLPVpsRk7VG99Fr+/slrYv/JII=; b=beUj+lI9hQrX6HSEo3PNwmjMrRSK5YqdBXgtBdMkCa1VkMoVGzihx6ZIPH+b3Abd7LL8Gch2AMRSoZ4RKHEhsJnl/A0NK3pFBOP0qiUv8gQBvQii5WaPPPk2DgNcfoDzPV/sEesLdAnYJEwdrnAq/o+M7Ly/TrIRKMSxRj1G/TQ= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1562138497511151.7144879915562; Wed, 3 Jul 2019 00:21:37 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id D5790859FE; Wed, 3 Jul 2019 07:21:35 +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 A7B8298AC; Wed, 3 Jul 2019 07:21:35 +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 4B02D18184A5; Wed, 3 Jul 2019 07:21:35 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x637JZMC019963 for ; Wed, 3 Jul 2019 03:19:35 -0400 Received: by smtp.corp.redhat.com (Postfix) id A85F47840D; Wed, 3 Jul 2019 07:19:35 +0000 (UTC) Received: from localhost.localdomain (ovpn-204-217.brq.redhat.com [10.40.204.217]) by smtp.corp.redhat.com (Postfix) with ESMTP id AEF2718EC7 for ; Wed, 3 Jul 2019 07:19:34 +0000 (UTC) From: Michal Privoznik To: libvir-list@redhat.com Date: Wed, 3 Jul 2019 09:19:19 +0200 Message-Id: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 2/3] vircommand: Separate mass FD closing into a function 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: , Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.26]); Wed, 03 Jul 2019 07:21:36 +0000 (UTC) Content-Type: text/plain; charset="utf-8" I will optimize this code a bit in the next commit. But for that it is better if the code lives in a separate function. Signed-off-by: Michal Privoznik Reviewed-by: J=C3=A1n Tomko --- src/util/vircommand.c | 52 ++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 18 deletions(-) diff --git a/src/util/vircommand.c b/src/util/vircommand.c index 8695c98d1b..faee36c449 100644 --- a/src/util/vircommand.c +++ b/src/util/vircommand.c @@ -491,6 +491,37 @@ virExecCommon(virCommandPtr cmd, gid_t *groups, int ng= roups) return ret; } =20 +static int +virCommandMassClose(virCommandPtr cmd, + int childin, + int childout, + int childerr) +{ + int openmax =3D sysconf(_SC_OPEN_MAX); + int fd; + int tmpfd; + + if (openmax < 0) { + virReportSystemError(errno, "%s", + _("sysconf(_SC_OPEN_MAX) failed")); + return -1; + } + + for (fd =3D 3; fd < openmax; fd++) { + if (fd =3D=3D childin || fd =3D=3D childout || fd =3D=3D childerr) + continue; + if (!virCommandFDIsSet(cmd, fd)) { + tmpfd =3D fd; + VIR_MASS_CLOSE(tmpfd); + } else if (virSetInherit(fd, true) < 0) { + virReportSystemError(errno, _("failed to preserve fd %d"), fd); + return -1; + } + } + + return 0; +} + /* * virExec: * @cmd virCommandPtr containing all information about the program to @@ -500,13 +531,12 @@ static int virExec(virCommandPtr cmd) { pid_t pid; - int null =3D -1, fd, openmax; + int null =3D -1; int pipeout[2] =3D {-1, -1}; int pipeerr[2] =3D {-1, -1}; int childin =3D cmd->infd; int childout =3D -1; int childerr =3D -1; - int tmpfd; VIR_AUTOFREE(char *) binarystr =3D NULL; const char *binary =3D NULL; int ret; @@ -612,23 +642,9 @@ virExec(virCommandPtr cmd) if (cmd->mask) umask(cmd->mask); ret =3D EXIT_CANCELED; - openmax =3D sysconf(_SC_OPEN_MAX); - if (openmax < 0) { - virReportSystemError(errno, "%s", - _("sysconf(_SC_OPEN_MAX) failed")); + + if (virCommandMassClose(cmd, childin, childout, childerr) < 0) goto fork_error; - } - for (fd =3D 3; fd < openmax; fd++) { - if (fd =3D=3D childin || fd =3D=3D childout || fd =3D=3D childerr) - continue; - if (!virCommandFDIsSet(cmd, fd)) { - tmpfd =3D fd; - VIR_MASS_CLOSE(tmpfd); - } else if (virSetInherit(fd, true) < 0) { - virReportSystemError(errno, _("failed to preserve fd %d"), fd); - goto fork_error; - } - } =20 if (prepareStdFd(childin, STDIN_FILENO) < 0) { virReportSystemError(errno, --=20 2.21.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list From nobody Sat Feb 7 15:48:28 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1562138509; cv=none; d=zoho.com; s=zohoarc; b=VgxAYtZ4wk1RZJarNfSvqQg1EJ3rbSsQm3fN3QjEcbnMah/lhT5e8Mf1CcsQIkKJR7gztKY2gnTjI1CRxLKnn2AKvhXh0sKg/6il3p7zuSEkU7CfSbIxq//Zy7ZogK5QqwzbVwr1vsLi6epbEPUP2p0TpzW7Edb3gkCzJp21xHc= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1562138509; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=+A5kXkDIqwUB6xQqrjjcVcKFwSp/cBK4EK/nkcNultU=; b=RhAaBrt2I6WjXXV1rqP5o6A81jiC+Hvu9pLTRXcwH9YQak9QBtpknDYzuHYSTUrkzF06IY8PEejaHvaWQk1cfo+4qU9bl+h7yodvOZMJgkwOSiIKO/mNl3LBG4gLH11LA6SuWu5cYGbLzlR6KtmEIgNu8mIr6+agbHH8xq0E7bs= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1562138509023706.3220893313489; Wed, 3 Jul 2019 00:21:49 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 18332307CDD5; Wed, 3 Jul 2019 07:21:47 +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 DF53D8509; Wed, 3 Jul 2019 07:21:45 +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 6A9D818184B7; Wed, 3 Jul 2019 07:21:45 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id x637Jd3W020060 for ; Wed, 3 Jul 2019 03:19:39 -0400 Received: by smtp.corp.redhat.com (Postfix) id 9247818EC7; Wed, 3 Jul 2019 07:19:39 +0000 (UTC) Received: from localhost.localdomain (ovpn-204-217.brq.redhat.com [10.40.204.217]) by smtp.corp.redhat.com (Postfix) with ESMTP id 24E1F78423 for ; Wed, 3 Jul 2019 07:19:36 +0000 (UTC) From: Michal Privoznik To: libvir-list@redhat.com Date: Wed, 3 Jul 2019 09:19:20 +0200 Message-Id: <8cf311e297b18b159d3bb6dc201df260585b904c.1562138162.git.mprivozn@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-loop: libvir-list@redhat.com Subject: [libvirt] [PATCH 3/3] virCommand: use procfs to learn opened FDs 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: , Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.49]); Wed, 03 Jul 2019 07:21:47 +0000 (UTC) Content-Type: text/plain; charset="utf-8" When spawning a child process, between fork() and exec() we close all file descriptors and keep only those the caller wants us to pass onto the child. The problem is how we do that. Currently, we get the limit of opened files and then iterate through each one of them and either close() it or make it survive exec(). This approach is suboptimal (although, not that much in default configurations where the limit is pretty low - 1024). We have /proc where we can learn what FDs we hold open and thus we can selectively close only those. Signed-off-by: Michal Privoznik --- src/util/vircommand.c | 78 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 8 deletions(-) diff --git a/src/util/vircommand.c b/src/util/vircommand.c index faee36c449..d154bb81d4 100644 --- a/src/util/vircommand.c +++ b/src/util/vircommand.c @@ -491,27 +491,89 @@ virExecCommon(virCommandPtr cmd, gid_t *groups, int n= groups) return ret; } =20 +# ifdef __linux__ +/* On Linux, we can utilize procfs and read the table of opened + * FDs and selectively close only those FDs we don't want to pass + * onto child process (well, the one we will exec soon since this + * is called from the child). */ +static int +virCommandMassCloseGetFDsLinux(virCommandPtr cmd ATTRIBUTE_UNUSED, + virBitmapPtr fds) +{ + DIR *dp =3D NULL; + struct dirent *entry; + const char *dirName =3D "/proc/self/fd"; + int rc; + int ret =3D -1; + + if (virDirOpen(&dp, dirName) < 0) + return -1; + + while ((rc =3D virDirRead(dp, &entry, dirName)) > 0) { + int fd; + + if (virStrToLong_i(entry->d_name, NULL, 10, &fd) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unable to parse FD: %s"), + entry->d_name); + goto cleanup; + } + + if (virBitmapSetBit(fds, fd) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unable to set FD as open: %d"), + fd); + goto cleanup; + } + } + + if (rc < 0) + goto cleanup; + + ret =3D 0; + cleanup: + VIR_DIR_CLOSE(dp); + return ret; +} + +# else /* !__linux__ */ + +static int +virCommandMassCloseGetFDsGeneric(virCommandPtr cmd ATTRIBUTE_UNUSED, + virBitmapPtr fds) +{ + virBitmapSetAll(fds); + return 0; +} +# endif /* !__linux__ */ + static int virCommandMassClose(virCommandPtr cmd, int childin, int childout, int childerr) { + VIR_AUTOPTR(virBitmap) fds =3D NULL; int openmax =3D sysconf(_SC_OPEN_MAX); - int fd; - int tmpfd; + int fd =3D -1; =20 - if (openmax < 0) { - virReportSystemError(errno, "%s", - _("sysconf(_SC_OPEN_MAX) failed")); + if (!(fds =3D virBitmapNew(openmax))) return -1; - } =20 - for (fd =3D 3; fd < openmax; fd++) { +# ifdef __linux__ + if (virCommandMassCloseGetFDsLinux(cmd, fds) < 0) + return -1; +# else + if (virCommandMassCloseGetFDsGeneric(cmd, fds) < 0) + return -1; +# endif + + fd =3D virBitmapNextSetBit(fds, -1); + for (; fd >=3D 0; fd =3D virBitmapNextSetBit(fds, fd)) { if (fd =3D=3D childin || fd =3D=3D childout || fd =3D=3D childerr) continue; if (!virCommandFDIsSet(cmd, fd)) { - tmpfd =3D fd; + int tmpfd =3D fd; VIR_MASS_CLOSE(tmpfd); } else if (virSetInherit(fd, true) < 0) { virReportSystemError(errno, _("failed to preserve fd %d"), fd); --=20 2.21.0 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list