Fix a bug of caching negative dentry

This commit is contained in:
Chen Chengjun 2025-11-29 16:11:45 +00:00 committed by Tate, Hongliang Tian
parent cf772b804e
commit 1a536d31b0
3 changed files with 58 additions and 9 deletions

View File

@ -175,15 +175,8 @@ impl Dentry {
pub(super) fn lookup_via_fs(&self, name: &str) -> Result<Arc<Dentry>> {
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);
}

View File

@ -0,0 +1,54 @@
// SPDX-License-Identifier: MPL-2.0
#define _GNU_SOURCE
#include <unistd.h>
#include <fcntl.h>
#include <wait.h>
#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()

View File

@ -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