diff options
author | наб <[email protected]> | 2021-04-02 15:10:34 +0200 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2021-04-14 13:19:49 -0700 |
commit | 0a51083e39494b65093ca9f76fc711eae1c08726 (patch) | |
tree | fc63abcc31bac78a14ca698f614abdc926bc864a | |
parent | b73e40a5ad1d0231f73b810732f1dc254869718d (diff) |
zed: implement close_from() in terms of /proc/self/fd, if available
/dev/fd on Darwin
Consider the following strace output:
prlimit64(0, RLIMIT_NOFILE, NULL, {rlim_cur=1024, rlim_max=1024*1024}) = 0
Yes, that is well over a million file descriptors!
This reduces the ZED start-up time from "at least a second" to
"instantaneous", and, under strace, from "don't even try" to "usable"
by simple virtue of doing five syscalls instead of over a million;
in most cases the main loop does nothing
Recent Linuxes (5.8+) have close_range(2) for this, but that's an
overoptimisation (and libcs don't have wrappers for it yet)
This is also run by the ZEDLET pre-exec. Compare:
Finished "all-syslog.sh" eid=13 pid=6717 time=1.027100s exit=0
Finished "history_event-zfs-list-cacher.sh" eid=13 pid=6718 time=1.046923s exit=0
to
Finished "all-syslog.sh" eid=12 pid=4834 time=0.001836s exit=0
Finished "history_event-zfs-list-cacher.sh" eid=12 pid=4835 time=0.001346s exit=0
lol
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Ahelenia Ziemiańska <[email protected]>
Closes #11834
-rw-r--r-- | cmd/zed/zed_file.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/cmd/zed/zed_file.c b/cmd/zed/zed_file.c index 4437892e9..c7b0d00b6 100644 --- a/cmd/zed/zed_file.c +++ b/cmd/zed/zed_file.c @@ -12,6 +12,7 @@ * You may not use this file except in compliance with the license. */ +#include <dirent.h> #include <errno.h> #include <fcntl.h> #include <limits.h> @@ -160,6 +161,13 @@ zed_file_is_locked(int fd) return (lock.l_pid); } + +#if __APPLE__ +#define PROC_SELF_FD "/dev/fd" +#else /* Linux-compatible layout */ +#define PROC_SELF_FD "/proc/self/fd" +#endif + /* * Close all open file descriptors greater than or equal to [lowfd]. * Any errors encountered while closing file descriptors are ignored. @@ -167,17 +175,23 @@ zed_file_is_locked(int fd) void zed_file_close_from(int lowfd) { - const int maxfd_def = 256; - int errno_bak; + static const int maxfd_def = 256; + int errno_bak = errno; struct rlimit rl; - int maxfd; + int maxfd = 0; int fd; - - errno_bak = errno; - - if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { - maxfd = maxfd_def; - } else if (rl.rlim_max == RLIM_INFINITY) { + DIR *fddir; + struct dirent *fdent; + + if ((fddir = opendir(PROC_SELF_FD)) != NULL) { + while ((fdent = readdir(fddir)) != NULL) { + fd = atoi(fdent->d_name); + if (fd > maxfd && fd != dirfd(fddir)) + maxfd = fd; + } + (void) closedir(fddir); + } else if (getrlimit(RLIMIT_NOFILE, &rl) < 0 || + rl.rlim_max == RLIM_INFINITY) { maxfd = maxfd_def; } else { maxfd = rl.rlim_max; |