From nobody Fri Apr 19 10:19:33 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) client-ip=207.211.31.81; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 207.211.31.81 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from us-smtp-delivery-1.mimecast.com (us-smtp-1.mimecast.com [207.211.31.81]) by mx.zohomail.com with SMTPS id 1581091450993390.7955635141433; Fri, 7 Feb 2020 08:04:10 -0800 (PST) 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-419-W8UBK6k1PbOYyUgXppjWFw-1; Fri, 07 Feb 2020 11:04:06 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 84F7D802B9D; Fri, 7 Feb 2020 16:03:59 +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 AEC508EA1D; Fri, 7 Feb 2020 16:03:58 +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 A55BE866A8; Fri, 7 Feb 2020 16:03:56 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 017G3tDZ007900 for ; Fri, 7 Feb 2020 11:03:55 -0500 Received: by smtp.corp.redhat.com (Postfix) id E8E7C1001281; Fri, 7 Feb 2020 16:03:55 +0000 (UTC) Received: from domokun.gsslab.fab.redhat.com (unknown [10.33.8.110]) by smtp.corp.redhat.com (Postfix) with ESMTP id 58405101D481; Fri, 7 Feb 2020 16:03:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1581091449; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=R3Ofm7vME3eSQ7+AtQUBQX5EBELJN2+wcs95c762Nvw=; b=K0a+Y9O3UcBwq2rpLE7z6Is5jQWi5BNNe3XIiJO9ycgA/TP6kTntL2C5S6IrZM1VZRu3Yk Mr9GPsmFfX+uIJcnPsO+mbufoi8cJz1zIvgv8r8soQQGm6ulSahRgh7RDeNHyWYf2ALoRC K4SQgSxCgYMWikQuzGqtkwQG5mKM8Eo= From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Subject: [libvirt PATCH] src: use closefrom() for mass closing of FDs Date: Fri, 7 Feb 2020 16:03:51 +0000 Message-Id: <20200207160351.2832800-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.84 on 10.5.11.22 X-loop: libvir-list@redhat.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.13 X-MC-Unique: W8UBK6k1PbOYyUgXppjWFw-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" On FreeBSD 12 the default ulimit settings allow for 100,000 open file descriptors. As a result spawning processes in libvirt is abominably slow. Fortunately FreeBSD has long since provided a good solution in the form of closefrom(), which closes all FDs equal to or larger than the specified parameter. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: J=C3=A1n Tomko --- src/util/vircommand.c | 60 ++++++++++++++++++++++++++++++++++++++++--- tests/testutils.c | 9 +++++++ 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/util/vircommand.c b/src/util/vircommand.c index 904a3023c5..764fb2fe43 100644 --- a/src/util/vircommand.c +++ b/src/util/vircommand.c @@ -494,6 +494,59 @@ virCommandMassCloseGetFDsGeneric(virCommandPtr cmd G_G= NUC_UNUSED, } # endif /* !__linux__ */ =20 +# ifdef __FreeBSD__ + +static int +virCommandMassClose(virCommandPtr cmd, + int childin, + int childout, + int childerr) +{ + int lastfd =3D -1; + int fd =3D -1; + + /* + * Two phases of closing. + * + * The first (inefficient) phase iterates over FDs, + * preserving certain FDs we need to pass down, and + * closing others. The number of iterations is bounded + * to the number of the biggest FD we need to preserve. + * + * The second (speedy) phase uses closefrom() to cull + * all remaining FDs in the process. + * + * Usually the first phase will be fairly quick only + * processing a handful of low FD numbers, and thus using + * closefrom() is a massive win for high ulimit() NFILES + * values. + */ + lastfd =3D MAX(lastfd, childin); + lastfd =3D MAX(lastfd, childout); + lastfd =3D MAX(lastfd, childerr); + + while (fd < cmd->npassfd) + lastfd =3D MAX(lastfd, cmd->passfd[fd].fd); + + for (fd =3D 0; fd <=3D lastfd; fd++) { + if (fd =3D=3D childin || fd =3D=3D childout || fd =3D=3D childerr) + continue; + if (!virCommandFDIsSet(cmd, fd)) { + int tmpfd =3D fd; + VIR_MASS_CLOSE(tmpfd); + } else if (virSetInherit(fd, true) < 0) { + virReportSystemError(errno, _("failed to preserve fd %d"), fd); + return -1; + } + } + + closefrom(lastfd + 1); + + return 0; +} + +# else /* ! __FreeBSD__ */ + static int virCommandMassClose(virCommandPtr cmd, int childin, @@ -520,13 +573,13 @@ virCommandMassClose(virCommandPtr cmd, if (!(fds =3D virBitmapNew(openmax))) return -1; =20 -# ifdef __linux__ +# ifdef __linux__ if (virCommandMassCloseGetFDsLinux(cmd, fds) < 0) return -1; -# else +# else if (virCommandMassCloseGetFDsGeneric(cmd, fds) < 0) return -1; -# endif +# endif =20 fd =3D virBitmapNextSetBit(fds, 2); for (; fd >=3D 0; fd =3D virBitmapNextSetBit(fds, fd)) { @@ -544,6 +597,7 @@ virCommandMassClose(virCommandPtr cmd, return 0; } =20 +# endif /* ! __FreeBSD__ */ =20 /* * virExec: diff --git a/tests/testutils.c b/tests/testutils.c index 7b9a5ea05b..662203d707 100644 --- a/tests/testutils.c +++ b/tests/testutils.c @@ -333,8 +333,10 @@ static void virTestCaptureProgramExecChild(const char *const argv[], int pipefd) { +# ifndef __FreeBSD__ size_t i; int open_max; +# endif /* ! __FreeBSD__ */ int stdinfd =3D -1; const char *const env[] =3D { "LANG=3DC", @@ -344,6 +346,7 @@ void virTestCaptureProgramExecChild(const char *const a= rgv[], if ((stdinfd =3D open("/dev/null", O_RDONLY)) < 0) goto cleanup; =20 +# ifndef __FreeBSD__ open_max =3D sysconf(_SC_OPEN_MAX); if (open_max < 0) goto cleanup; @@ -356,6 +359,7 @@ void virTestCaptureProgramExecChild(const char *const a= rgv[], VIR_FORCE_CLOSE(tmpfd); } } +# endif /* __FreeBSD__ */ =20 if (dup2(stdinfd, STDIN_FILENO) !=3D STDIN_FILENO) goto cleanup; @@ -364,6 +368,11 @@ void virTestCaptureProgramExecChild(const char *const = argv[], if (dup2(pipefd, STDERR_FILENO) !=3D STDERR_FILENO) goto cleanup; =20 +# ifdef __FreeBSD__ + closefrom(STDERR_FILENO); + stdinfd =3D pipefd =3D -1; +# endif + /* SUS is crazy here, hence the cast */ execve(argv[0], (char *const*)argv, (char *const*)env); =20 --=20 2.24.1