summaryrefslogtreecommitdiffstats
path: root/src/stat.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2024-05-07 12:48:30 -0400
committerTavian Barnes <tavianator@tavianator.com>2024-05-07 12:48:30 -0400
commit7129ed0ff069fde418773be313442beb0dacfaaf (patch)
tree89f1c19826a2a899a56da89fde9bf053a106e3a3 /src/stat.c
parent781b9eb78070872734c4e8303b3d02ae9e9c0f37 (diff)
downloadbfs-7129ed0ff069fde418773be313442beb0dacfaaf.tar.xz
stat: Prefer fstat(fd) to fstatat(fd, "", AT_EMPTY_PATH)
This lets us get rid of the runtime probe for AT_EMPTY_PATH support, and should be more efficient anyway. We still use statx(fd, "", AT_EMPTY_PATH) if available. Link: https://lore.kernel.org/linux-fsdevel/CAHk-=wiYnnv7Kw7v+Cp2xU6_Fd-qxQMZuuxZ61LgA2=Gtftw-A@mail.gmail.com/
Diffstat (limited to 'src/stat.c')
-rw-r--r--src/stat.c32
1 files changed, 13 insertions, 19 deletions
diff --git a/src/stat.c b/src/stat.c
index f5cf3fe..db1f99a 100644
--- a/src/stat.c
+++ b/src/stat.c
@@ -297,27 +297,21 @@ int bfs_stat(int at_fd, const char *at_path, enum bfs_stat_flags flags, struct b
return bfs_stat_tryfollow(at_fd, at_path, at_flags, flags, buf);
}
- // Check __GNU__ to work around https://lists.gnu.org/archive/html/bug-hurd/2021-12/msg00001.html
-#if defined(AT_EMPTY_PATH) && !__GNU__
- static atomic bool has_at_ep = true;
- if (load(&has_at_ep, relaxed)) {
- at_flags |= AT_EMPTY_PATH;
- int ret = bfs_stat_explicit(at_fd, "", at_flags, buf);
- if (ret != 0 && errno == EINVAL) {
- store(&has_at_ep, false, relaxed);
- } else {
- return ret;
- }
- }
-#endif
-
- struct stat statbuf;
- if (fstat(at_fd, &statbuf) == 0) {
- bfs_stat_convert(buf, &statbuf);
- return 0;
- } else {
+#if BFS_USE_STATX
+ // If we have statx(), use it with AT_EMPTY_PATH for its extra features
+ at_flags |= AT_EMPTY_PATH;
+ return bfs_stat_explicit(at_fd, "", at_flags, buf);
+#else
+ // Otherwise, just use fstat() rather than fstatat(at_fd, ""), to save
+ // the kernel the trouble of copying in the empty string
+ struct stat sb;
+ if (fstat(at_fd, &sb) != 0) {
return -1;
}
+
+ bfs_stat_convert(buf, &sb);
+ return 0;
+#endif
}
const struct timespec *bfs_stat_time(const struct bfs_stat *buf, enum bfs_stat_field field) {