From 1a536d31b0141bef092347b356f26d70126ddf8d Mon Sep 17 00:00:00 2001 From: Chen Chengjun Date: Sat, 29 Nov 2025 16:11:45 +0000 Subject: [PATCH] Fix a bug of caching negative dentry --- kernel/src/fs/path/dentry.rs | 12 ++----- test/src/apps/procfs/dentry_cache.c | 54 +++++++++++++++++++++++++++++ test/src/apps/scripts/process.sh | 1 + 3 files changed, 58 insertions(+), 9 deletions(-) create mode 100644 test/src/apps/procfs/dentry_cache.c diff --git a/kernel/src/fs/path/dentry.rs b/kernel/src/fs/path/dentry.rs index e71878746..b3b2c004e 100644 --- a/kernel/src/fs/path/dentry.rs +++ b/kernel/src/fs/path/dentry.rs @@ -175,15 +175,8 @@ impl Dentry { pub(super) fn lookup_via_fs(&self, name: &str) -> Result> { let children = self.children.upread(); - let inode = match self.inode.lookup(name) { - Ok(inode) => inode, - Err(e) => { - if e.error() == Errno::ENOENT && self.is_dentry_cacheable() { - children.upgrade().insert_negative(String::from(name)); - } - return Err(e); - } - }; + // TODO: Add a right implementation to cache negative dentry. + let inode = self.inode.lookup(name)?; let name = String::from(name); let target = Self::new(inode, DentryOptions::Leaf((name.clone(), self.this()))); @@ -446,6 +439,7 @@ impl DentryChildren { } /// Inserts a negative dentry. + #[expect(dead_code)] fn insert_negative(&mut self, name: String) { let _ = self.dentries.insert(name, None); } diff --git a/test/src/apps/procfs/dentry_cache.c b/test/src/apps/procfs/dentry_cache.c new file mode 100644 index 000000000..752472366 --- /dev/null +++ b/test/src/apps/procfs/dentry_cache.c @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: MPL-2.0 + +#define _GNU_SOURCE + +#include +#include +#include + +#include "../test.h" + +FN_TEST(negative_cache_pid) +{ + pid_t pid, pid2; + char path[20]; + int i, status; + + pid = TEST_SUCC(getpid()); + + // These paths may not yet exist, but we cannot cache negative results here. + for (i = 0; i < 100; ++i) { + snprintf(path, sizeof(path), "/proc/%d", pid + i); + (void)!access(path, F_OK); + } + + pid2 = TEST_SUCC(fork()); + if (pid2 == 0) { + CHECK(access("/proc/self/", F_OK)); + + usleep(200 * 1000); + exit(EXIT_SUCCESS); + } + + snprintf(path, sizeof(path), "/proc/%d", pid2); + TEST_SUCC(access(path, F_OK)); + + TEST_RES(wait(&status), _ret == pid2 && WIFEXITED(status) && + WEXITSTATUS(status) == EXIT_SUCCESS); + + snprintf(path, sizeof(path), "/proc/%d", pid2); + TEST_ERRNO(access(path, F_OK), ENOENT); +} +END_TEST() + +FN_TEST(negative_cache_fd) +{ + TEST_ERRNO(access("/proc/self/fdinfo/100", F_OK), ENOENT); + + TEST_SUCC(dup2(0, 100)); + TEST_SUCC(access("/proc/self/fdinfo/100", F_OK)); + + TEST_SUCC(close(100)); + TEST_ERRNO(access("/proc/self/fdinfo/100", F_OK), ENOENT); +} +END_TEST() diff --git a/test/src/apps/scripts/process.sh b/test/src/apps/scripts/process.sh index 7f7949451..7fd920366 100755 --- a/test/src/apps/scripts/process.sh +++ b/test/src/apps/scripts/process.sh @@ -44,6 +44,7 @@ process/group_session process/job_control process/pidfd process/wait4 +procfs/dentry_cache procfs/pid_mem pseudofs/pseudo_inode pseudofs/memfd_access_err