From: Markus Armbruster <armbru@redhat.com>
To: Bin Meng <bmeng@tinylab.org>
Cc: qemu-devel@nongnu.org, "Zhangjin Wu" <falcon@tinylab.org>,
"Alberto Faria" <afaria@redhat.com>,
"Kevin Wolf" <kwolf@redhat.com>,
"Marc-André Lureau" <marcandre.lureau@redhat.com>,
"Nikita Ivanov" <nivanov@cloudlinux.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Thomas Huth" <thuth@redhat.com>,
"Xuzhou Cheng" <xuzhou.cheng@windriver.com>
Subject: Re: [PATCH v3 4/6] util/osdep: Introduce qemu_close_range()
Date: Mon, 19 Jun 2023 11:22:53 +0200 [thread overview]
Message-ID: <87a5wv24cy.fsf@pond.sub.org> (raw)
In-Reply-To: <20230617053621.50359-5-bmeng@tinylab.org> (Bin Meng's message of "Sat, 17 Jun 2023 13:36:19 +0800")
Bin Meng <bmeng@tinylab.org> writes:
> This introduces a new QEMU API qemu_close_range() that closes all
> open file descriptors from first to last (included).
>
> This API will try a more efficient call to close_range(), or walk
> through of /proc/self/fd whenever these are possible, otherwise it
> falls back to a plain close loop.
>
> Co-developed-by: Zhangjin Wu <falcon@tinylab.org>
> Signed-off-by: Bin Meng <bmeng@tinylab.org>
>
> ---
>
> Changes in v3:
> - fix win32 build failure
>
> Changes in v2:
> - new patch: "util/osdep: Introduce qemu_close_range()"
>
> include/qemu/osdep.h | 1 +
> util/osdep.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 49 insertions(+)
>
> diff --git a/include/qemu/osdep.h b/include/qemu/osdep.h
> index cc61b00ba9..e22434ce10 100644
> --- a/include/qemu/osdep.h
> +++ b/include/qemu/osdep.h
> @@ -560,6 +560,7 @@ int qemu_open_old(const char *name, int flags, ...);
> int qemu_open(const char *name, int flags, Error **errp);
> int qemu_create(const char *name, int flags, mode_t mode, Error **errp);
> int qemu_close(int fd);
> +int qemu_close_range(unsigned int first, unsigned int last);
> int qemu_unlink(const char *name);
> #ifndef _WIN32
> int qemu_dup_flags(int fd, int flags);
> diff --git a/util/osdep.c b/util/osdep.c
> index e996c4744a..91275e70f8 100644
> --- a/util/osdep.c
> +++ b/util/osdep.c
> @@ -30,6 +30,7 @@
> #include "qemu/mprotect.h"
> #include "qemu/hw-version.h"
> #include "monitor/monitor.h"
> +#include <dirent.h>
>
> static const char *hw_version = QEMU_HW_VERSION;
>
> @@ -411,6 +412,53 @@ int qemu_close(int fd)
> return close(fd);
> }
>
> +int qemu_close_range(unsigned int first, unsigned int last)
> +{
> + DIR *dir = NULL;
> +
> +#ifdef CONFIG_CLOSE_RANGE
> + int r = close_range(first, last, 0);
close_range(2) explains flag
CLOSE_RANGE_UNSHARE
Unshare the specified file descriptors from any other processes
before closing them, avoiding races with other threads sharing
the file descriptor table.
Can anybody explain the races this avoids?
> + if (!r) {
> + /* Success, no need to try other ways. */
> + return 0;
> + }
What are the failure modes of close_range() where the other ways are
worth trying?
> +#endif
> +
> +#ifdef __linux__
> + dir = opendir("/proc/self/fd");
> +#endif
> + if (!dir) {
> + /*
> + * If /proc is not mounted or /proc/self/fd is not supported,
> + * try close() from first to last.
> + */
> + for (int i = first; i <= last; i++) {
> + close(i);
> + }
> +
> + return 0;
> + }
> +
> +#ifndef _WIN32
> + /* Avoid closing the directory */
> + int dfd = dirfd(dir);
This directory contains "." "..", "0", "1", ...
> +
> + for (struct dirent *de = readdir(dir); de; de = readdir(dir)) {
> + int fd = atoi(de->d_name);
Maps "." and ".." to 0. Unclean.
Please use qemu_strtoi(de->d_name, NULL, 10, &fd), and skip entries
where it fails.
> + if (fd < first || fd > last) {
> + /* Exclude the fds outside the target range */
> + continue;
> + }
> + if (fd != dfd) {
> + close(fd);
> + }
> + }
> + closedir(dir);
> +#endif /* _WIN32 */
> +
> + return 0;
> +}
I'd prefer to order this from most to least preferred:
close_range()
iterate over /proc/self/fd
iterate from first to last
Unlike close_range(), qemu_close_range() returns 0 when last < first.
If we want to deviate from close_range(), we better document the
differences.
This is a generalized version of async-teardown.c's close_all_open_fd().
I'd mention this in the commit message. Suggestion, not demand.
> +
> /*
> * Delete a file from the filesystem, unless the filename is /dev/fdset/...
> *
next prev parent reply other threads:[~2023-06-19 9:23 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-06-17 5:36 [PATCH v3 0/6] net/tap: Fix QEMU frozen issue when the maximum number of file descriptors is very large Bin Meng
2023-06-17 5:36 ` [PATCH v3 1/6] tests/tcg/cris: Fix the coding style Bin Meng
2023-06-17 22:52 ` Philippe Mathieu-Daudé
2023-06-17 5:36 ` [PATCH v3 2/6] tests/tcg/cris: Correct the off-by-one error Bin Meng
2023-06-17 22:52 ` Philippe Mathieu-Daudé
2023-06-17 5:36 ` [PATCH v3 3/6] util/async-teardown: Fall back to close fds one by one Bin Meng
2023-06-19 9:18 ` Claudio Imbrenda
2023-06-25 15:17 ` Bin Meng
2023-06-17 5:36 ` [PATCH v3 4/6] util/osdep: Introduce qemu_close_range() Bin Meng
2023-06-19 9:18 ` Claudio Imbrenda
2023-06-28 15:12 ` Bin Meng
2023-06-19 9:22 ` Markus Armbruster [this message]
2023-06-28 15:40 ` Bin Meng
2023-06-17 5:36 ` [PATCH v3 5/6] util/async-teardown: Use qemu_close_range() to close fds Bin Meng
2023-06-19 9:19 ` Claudio Imbrenda
2023-06-17 5:36 ` [PATCH v3 6/6] net: tap: " Bin Meng
2023-06-19 9:23 ` Claudio Imbrenda
2023-06-19 7:13 ` [PATCH v3 0/6] net/tap: Fix QEMU frozen issue when the maximum number of file descriptors is very large Richard Henderson
2023-06-28 17:13 ` Michael Tokarev
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87a5wv24cy.fsf@pond.sub.org \
--to=armbru@redhat.com \
--cc=afaria@redhat.com \
--cc=bmeng@tinylab.org \
--cc=falcon@tinylab.org \
--cc=kwolf@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=nivanov@cloudlinux.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=thuth@redhat.com \
--cc=xuzhou.cheng@windriver.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.