summaryrefslogtreecommitdiffstats
path: root/src/bftw.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2023-07-17 19:05:23 -0400
committerTavian Barnes <tavianator@tavianator.com>2023-07-17 20:03:33 -0400
commit196c36bb13de94c977a3e360dc5fa529efe2c5ca (patch)
treea7093dda8a03535e362e586e27e340e313ad43d2 /src/bftw.c
parent3cc581c0295465fd5dc2fc818aa92f48dd87788e (diff)
downloadbfs-196c36bb13de94c977a3e360dc5fa529efe2c5ca.tar.xz
bftw: Reserve space in the cache before opening files
This fixes a storm of EMFILE retries observed with -j1 on a very large directory tree. Fixes: 7888fbababd22190e9f919fc272957426a27969e
Diffstat (limited to 'src/bftw.c')
-rw-r--r--src/bftw.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/src/bftw.c b/src/bftw.c
index 2262591..9d85966 100644
--- a/src/bftw.c
+++ b/src/bftw.c
@@ -572,7 +572,13 @@ static int bftw_cache_reserve(struct bftw_state *state) {
}
}
- return bftw_cache_pop(cache);
+ if (bftw_cache_pop(cache) != 0) {
+ errno = EMFILE;
+ return -1;
+ }
+
+ bfs_assert(cache->capacity > 0);
+ return 0;
}
/** Open a bftw_file relative to another one. */
@@ -587,8 +593,13 @@ static int bftw_file_openat(struct bftw_state *state, struct bftw_file *file, st
at_fd = base->fd;
}
+ int fd = -1;
+ if (bftw_cache_reserve(state) != 0) {
+ goto unpin;
+ }
+
int flags = O_RDONLY | O_CLOEXEC | O_DIRECTORY;
- int fd = openat(at_fd, at_path, flags);
+ fd = openat(at_fd, at_path, flags);
if (fd < 0 && errno == EMFILE) {
if (bftw_cache_pop(cache) == 0) {
@@ -597,6 +608,7 @@ static int bftw_file_openat(struct bftw_state *state, struct bftw_file *file, st
cache->capacity = 1;
}
+unpin:
if (base) {
bftw_cache_unpin(cache, base);
}
@@ -606,7 +618,7 @@ static int bftw_file_openat(struct bftw_state *state, struct bftw_file *file, st
bftw_cache_add(cache, file);
}
- return file->fd;
+ return fd;
}
/** Open a bftw_file. */