From nobody Mon Feb 9 06:33:59 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) client-ip=170.10.129.124; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-delivery-124.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.129.124 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=1692711312; cv=none; d=zohomail.com; s=zohoarc; b=YBYcCEbyBK4Hj7ee2m4M1UJvunFR31cyw9oHN6FVsZQTdtDJ38Yy/JKqBGcBwv8MQf2qJ/UywJtjAoF6fpoX5JLuE7YmdBcjhUcKMAn01CGzQKAF/GJ2jzzrQ3j6Xhrtr3/JaJlIbf19JLE+OPW1145jCTAnzxOXc+KsiIiBgEs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1692711312; 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; bh=ZZf67xDzFxXCHcKvPRIbkTRqKMv+4U8bYBXX5esrr+Q=; b=SVPFjmxVgyPqwaAzvbvysRk6jphntzLpJEOf/wGFfJyTVH/vgcRG2E9NRJOalpSbiu3wkrrXtTIjfR6JrcT6vIACc1qq1v0arAm3hWxF1BFJ+VAS81YPIuw8hD+CHL395aTxwdc4K2GEywjwhZV694p3fjcXYxmHOESfDs+biaY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by mx.zohomail.com with SMTPS id 1692711312397184.83997649962885; Tue, 22 Aug 2023 06:35:12 -0700 (PDT) Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-557-rukU1nHcPK-_3ZlTlCFGGg-1; Tue, 22 Aug 2023 09:35:08 -0400 Received: from smtp.corp.redhat.com (int-mx07.intmail.prod.int.rdu2.redhat.com [10.11.54.7]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 053B0823DE3; Tue, 22 Aug 2023 13:34:47 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com [10.30.29.100]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5A181140E922; Tue, 22 Aug 2023 13:34:46 +0000 (UTC) Received: from mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (localhost [IPv6:::1]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 369031946587; Tue, 22 Aug 2023 13:34:46 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) by mm-prod-listman-01.mail-001.prod.us-east-1.aws.redhat.com (Postfix) with ESMTP id 880E51946586 for ; Tue, 22 Aug 2023 13:34:44 +0000 (UTC) Received: by smtp.corp.redhat.com (Postfix) id 7393A2026D33; Tue, 22 Aug 2023 13:34:44 +0000 (UTC) Received: from localhost.localdomain (unknown [10.43.2.56]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1B8852026D38 for ; Tue, 22 Aug 2023 13:34:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1692711311; 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: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=ZZf67xDzFxXCHcKvPRIbkTRqKMv+4U8bYBXX5esrr+Q=; b=KRm+I3pxs1D5/btFO+Fp4cg19AUTAxSyBDPxlWC6d26TXdhbZrevcl1o5xqABhYaCWMyqx 2mQ1oh39UEaUNaOUcsl1/T+DE3ho6ofXryaVfMgPwjSgmgPx6kP5E2iDRak+Ty67EqaavP UohtsQXFSaGoZQugDJO+90i/qN1DdMY= X-MC-Unique: rukU1nHcPK-_3ZlTlCFGGg-1 X-Original-To: libvir-list@listman.corp.redhat.com From: Michal Privoznik To: libvir-list@redhat.com Subject: [PATCH 1/5] virfile: Introduce virCloseRange() Date: Tue, 22 Aug 2023 15:34:37 +0200 Message-ID: In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.4 X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libvir-list-bounces@redhat.com Sender: "libvir-list" X-Scanned-By: MIMEDefang 3.1 on 10.11.54.7 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1692711313443100001 Content-Type: text/plain; charset="utf-8"; x-default="true" Linux gained new close_range() syscall (in v5.9) that allows closing a range of FDs in a single syscall. Ideally, we would use it to close FDs when spawning a process (e.g. via virCommand module). Glibc has close_range() wrapper over the syscall, which falls back to iterative closing of all FDs inside the range if running under older kernel. We don't wan that as in that case we might just close opened FDs (see Linux version of virCommandMassClose()). And musl doesn't have close_range() at all. Therefore, call syscall directly. Now, mass close of FDs happen in a fork()-ed off child. While it could detect whether the kernel does support close_range(), it has no way of passing this info back to the parent and thus each child would need to query it again and again. Since this can't change while we are running we can cache the information - hence virCloseRangeInit(). Signed-off-by: Michal Privoznik Reviewed-by: J=C3=A1n Tomko --- src/libvirt_private.syms | 3 ++ src/util/virfile.c | 89 ++++++++++++++++++++++++++++++++++++++++ src/util/virfile.h | 4 ++ 3 files changed, 96 insertions(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index da60c965dd..3782f7f3c7 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2269,6 +2269,9 @@ saferead; safewrite; safezero; virBuildPathInternal; +virCloseRange; +virCloseRangeInit; +virCloseRangeIsSupported; virDirClose; virDirCreate; virDirIsEmpty; diff --git a/src/util/virfile.c b/src/util/virfile.c index fe456596ae..7696910e00 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -87,6 +87,7 @@ #include "virlog.h" #include "virprocess.h" #include "virstring.h" +#include "virthread.h" #include "virutil.h" #include "virsocket.h" =20 @@ -109,6 +110,9 @@ VIR_LOG_INIT("util.file"); # define O_DIRECT 0 #endif =20 +static virOnceControl virCloseRangeOnce =3D VIR_ONCE_CONTROL_INITIALIZER; +static bool virCloseRangeSupported; + int virFileClose(int *fdptr, virFileCloseFlags flags) { int saved_errno =3D 0; @@ -176,6 +180,91 @@ FILE *virFileFdopen(int *fdptr, const char *mode) } =20 =20 +static int +virCloseRangeImpl(unsigned int first G_GNUC_UNUSED, + unsigned int last G_GNUC_UNUSED) +{ +#if defined(WITH_SYS_SYSCALL_H) && defined(__NR_close_range) + return syscall(__NR_close_range, first, last, 0); +#endif + + errno =3D ENOSYS; + return -1; +} + + +static void +virCloseRangeOnceInit(void) +{ + int fd[2] =3D { -1, -1}; + + if (virPipeQuiet(fd) < 0) + return; + + VIR_FORCE_CLOSE(fd[1]); + if (virCloseRangeImpl(fd[0], fd[0]) < 0) { + VIR_FORCE_CLOSE(fd[0]); + return; + } + + virCloseRangeSupported =3D true; +} + + +/** + * virCloseRange: + * + * Closes all open file descriptors from @first to @last (included). + * + * Returns: 0 on success, + * -1 on failure (with errno set). + */ +int +virCloseRange(unsigned int first, + unsigned int last) +{ + if (virCloseRangeInit() < 0) + return -1; + + if (!virCloseRangeSupported) { + errno =3D ENOSYS; + return -1; + } + + return virCloseRangeImpl(first, last); +} + + +/** + * virCloseRangeInit: + * + * Detects whether close_range() is available and cache the result. + */ +int +virCloseRangeInit(void) +{ + if (virOnce(&virCloseRangeOnce, virCloseRangeOnceInit) < 0) + return -1; + + return 0; +} + + +/** + * virCloseRangeIsSupported: + * + * Returns whether close_range() is supported or not. + */ +bool +virCloseRangeIsSupported(void) +{ + if (virCloseRangeInit() < 0) + return false; + + return virCloseRangeSupported; +} + + /** * virFileDirectFdFlag: * diff --git a/src/util/virfile.h b/src/util/virfile.h index 60bb1d64e7..be0b02fdf0 100644 --- a/src/util/virfile.h +++ b/src/util/virfile.h @@ -61,6 +61,10 @@ static inline void virForceCloseHelper(int *fd) ignore_value(virFileClose(fd, VIR_FILE_CLOSE_PRESERVE_ERRNO)); } =20 +int virCloseRange(unsigned int from, unsigned int to); +int virCloseRangeInit(void); +bool virCloseRangeIsSupported(void); + /* For use on normal paths; caller must check return value, and failure sets errno per close. */ #define VIR_CLOSE(FD) virFileClose(&(FD), 0) --=20 2.41.0