qemu/osdep: Add excluded fd parameter to qemu_close_all_open_fd()
In order for this function to be usable by tap.c code, add a list of file descriptors that should not be closed. Signed-off-by: Clément Léger <cleger@rivosinc.com> Message-ID: <20240802145423.3232974-5-cleger@rivosinc.com> [rth: Use max_fd in qemu_close_all_open_fd_close_range] Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
a9b5d6e536
commit
7532ca570a
@ -760,9 +760,13 @@ int qemu_fdatasync(int fd);
|
||||
/**
|
||||
* qemu_close_all_open_fd:
|
||||
*
|
||||
* Close all open file descriptors
|
||||
* Close all open file descriptors except the ones supplied in the @skip array
|
||||
*
|
||||
* @skip: ordered array of distinct file descriptors that should not be closed
|
||||
* if any, or NULL.
|
||||
* @nskip: number of entries in the @skip array or 0 if @skip is NULL.
|
||||
*/
|
||||
void qemu_close_all_open_fd(void);
|
||||
void qemu_close_all_open_fd(const int *skip, unsigned int nskip);
|
||||
|
||||
/**
|
||||
* Sync changes made to the memory mapped file back to the backing
|
||||
|
@ -52,7 +52,7 @@ static int async_teardown_fn(void *arg)
|
||||
* Close all file descriptors that might have been inherited from the
|
||||
* main qemu process when doing clone, needed to make libvirt happy.
|
||||
*/
|
||||
qemu_close_all_open_fd();
|
||||
qemu_close_all_open_fd(NULL, 0);
|
||||
|
||||
/* Set up a handler for SIGHUP and unblock SIGHUP. */
|
||||
sigaction(SIGHUP, &sa, NULL);
|
||||
|
@ -808,11 +808,12 @@ int qemu_msync(void *addr, size_t length, int fd)
|
||||
return msync(addr, length, MS_SYNC);
|
||||
}
|
||||
|
||||
static bool qemu_close_all_open_fd_proc(void)
|
||||
static bool qemu_close_all_open_fd_proc(const int *skip, unsigned int nskip)
|
||||
{
|
||||
struct dirent *de;
|
||||
int fd, dfd;
|
||||
DIR *dir;
|
||||
unsigned int skip_start = 0, skip_end = nskip;
|
||||
|
||||
dir = opendir("/proc/self/fd");
|
||||
if (!dir) {
|
||||
@ -823,8 +824,33 @@ static bool qemu_close_all_open_fd_proc(void)
|
||||
dfd = dirfd(dir);
|
||||
|
||||
for (de = readdir(dir); de; de = readdir(dir)) {
|
||||
bool close_fd = true;
|
||||
|
||||
if (de->d_name[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
fd = atoi(de->d_name);
|
||||
if (fd != dfd) {
|
||||
if (fd == dfd) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (unsigned int i = skip_start; i < skip_end; i++) {
|
||||
if (fd < skip[i]) {
|
||||
/* We are below the next skipped fd, break */
|
||||
break;
|
||||
} else if (fd == skip[i]) {
|
||||
close_fd = false;
|
||||
/* Restrict the range as we found fds matching start/end */
|
||||
if (i == skip_start) {
|
||||
skip_start++;
|
||||
} else if (i == skip_end) {
|
||||
skip_end--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (close_fd) {
|
||||
close(fd);
|
||||
}
|
||||
}
|
||||
@ -833,24 +859,60 @@ static bool qemu_close_all_open_fd_proc(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool qemu_close_all_open_fd_close_range(void)
|
||||
static bool qemu_close_all_open_fd_close_range(const int *skip,
|
||||
unsigned int nskip,
|
||||
int open_max)
|
||||
{
|
||||
#ifdef CONFIG_CLOSE_RANGE
|
||||
int r = close_range(0, ~0U, 0);
|
||||
if (!r) {
|
||||
/* Success, no need to try other ways. */
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
int max_fd = open_max - 1;
|
||||
int first = 0, last;
|
||||
unsigned int cur_skip = 0;
|
||||
int ret;
|
||||
|
||||
do {
|
||||
/* Find the start boundary of the range to close */
|
||||
while (cur_skip < nskip && first == skip[cur_skip]) {
|
||||
cur_skip++;
|
||||
first++;
|
||||
}
|
||||
|
||||
/* Find the upper boundary of the range to close */
|
||||
last = max_fd;
|
||||
if (cur_skip < nskip) {
|
||||
last = skip[cur_skip] - 1;
|
||||
last = MIN(last, max_fd);
|
||||
}
|
||||
|
||||
/* With the adjustments to the range, we might be done. */
|
||||
if (first > last) {
|
||||
break;
|
||||
}
|
||||
|
||||
ret = close_range(first, last, 0);
|
||||
if (ret < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
first = last + 1;
|
||||
} while (last < max_fd);
|
||||
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void qemu_close_all_open_fd_fallback(void)
|
||||
static void qemu_close_all_open_fd_fallback(const int *skip, unsigned int nskip,
|
||||
int open_max)
|
||||
{
|
||||
int open_max = sysconf(_SC_OPEN_MAX), i;
|
||||
unsigned int cur_skip = 0;
|
||||
|
||||
/* Fallback */
|
||||
for (i = 0; i < open_max; i++) {
|
||||
for (int i = 0; i < open_max; i++) {
|
||||
if (cur_skip < nskip && i == skip[cur_skip]) {
|
||||
cur_skip++;
|
||||
continue;
|
||||
}
|
||||
close(i);
|
||||
}
|
||||
}
|
||||
@ -858,10 +920,14 @@ static void qemu_close_all_open_fd_fallback(void)
|
||||
/*
|
||||
* Close all open file descriptors.
|
||||
*/
|
||||
void qemu_close_all_open_fd(void)
|
||||
void qemu_close_all_open_fd(const int *skip, unsigned int nskip)
|
||||
{
|
||||
if (!qemu_close_all_open_fd_close_range() &&
|
||||
!qemu_close_all_open_fd_proc()) {
|
||||
qemu_close_all_open_fd_fallback();
|
||||
int open_max = sysconf(_SC_OPEN_MAX);
|
||||
|
||||
assert(skip != NULL || nskip == 0);
|
||||
|
||||
if (!qemu_close_all_open_fd_close_range(skip, nskip, open_max) &&
|
||||
!qemu_close_all_open_fd_proc(skip, nskip)) {
|
||||
qemu_close_all_open_fd_fallback(skip, nskip, open_max);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user