Commit 3579650e authored by Ramon Nou's avatar Ramon Nou
Browse files

fix(client): revalidate dentry cache misses against metadata servers

parent 9a87740e
Loading
Loading
Loading
Loading
Loading
+4 −4
Changes for include/client/gkfs_libc.hpp: 4 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -356,14 +356,14 @@ flistxattr(int fd, char* list, size_t size);
int
posix_spawn(pid_t* __restrict pid, const char* __restrict path,
            const posix_spawn_file_actions_t* __restrict file_actions,
            const posix_spawnattr_t* __restrict attrp,
            char* const argv[], char* const envp[]);
            const posix_spawnattr_t* __restrict attrp, char* const argv[],
            char* const envp[]);

int
posix_spawnp(pid_t* __restrict pid, const char* __restrict file,
             const posix_spawn_file_actions_t* __restrict file_actions,
             const posix_spawnattr_t* __restrict attrp,
             char* const argv[], char* const envp[]);
             const posix_spawnattr_t* __restrict attrp, char* const argv[],
             char* const envp[]);

//========================= C++ ABI Interceptions
//==============================//
+2 −1
Changes for src/client/gkfs_libc.cpp: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -2463,7 +2463,8 @@ chdir(const char* path) throw() {
    if(path != nullptr && CTX && !CTX->mountdir().empty()) {
        std::string p(path);
        if(p.rfind(CTX->mountdir(), 0) == 0 && !GKFS_INTERCEPTION_ENABLED()) {
            long cres = syscall_no_intercept(SYS_chdir, CTX->mountdir().c_str());
            long cres =
                    syscall_no_intercept(SYS_chdir, CTX->mountdir().c_str());
            if(cres < 0) {
                syscall_no_intercept(SYS_chdir, "/");
            }
+3 −2
Changes for src/client/intercept.cpp: 3 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -1553,8 +1553,9 @@ void
stop_interception() {
    LOG(DEBUG, "Disabling syscall interception for client process");

    // Reset callback function pointer to passthrough so that subsequent syscalls
    // (during exit/shutdown/atexit) are forwarded to kernel instead of triggering SIGTRAP.
    // Reset callback function pointer to passthrough so that subsequent
    // syscalls (during exit/shutdown/atexit) are forwarded to kernel instead of
    // triggering SIGTRAP.
    intercept_hook_point = passthrough_hook_wrapper;
    intercept_hook_point_post_kernel = nullptr;
    intercept_hook_point_clone_child = nullptr;
+5 −6
Changes for src/client/preload_util.cpp: 5 added lines, 6 removed lines.
Original line number Diff line number Diff line
@@ -327,12 +327,11 @@ get_metadata(const string& path, bool follow_links, bool include_inline) {
            md.size(cache_entry->size);
            return md;
        }
        if(CTX->dentry_cache()->has_dir(parent)) {
            LOG(DEBUG, "{}(): Negative dentry cache hit for file '{}'", __func__,
                path);
            errno = ENOENT;
            return {};
        }
        // A directory listing is not an authoritative negative lookup:
        // another client can create entries, and the cached directory may
        // contain only a subset of a paginated listing. In particular, '/'
        // has itself as parent but is not an entry in its own listing.
        // Always ask the metadata server on a cache miss.
    }
    if(gkfs::config::proxy::fwd_stat && CTX->use_proxy()) {
        err = gkfs::rpc::forward_stat_proxy(path, attr);
+28 −0
Changes for tests/integration/operations/test_client_cache.py: 28 added lines, 0 removed lines.
Original line number Diff line number Diff line
import pytest
import os
import sys

from harness.gkfs import Client as GKFSClient


def test_dentry_cache_misses_revalidate(gkfs_daemon, gkfs_shell):
    """Cached listings must not hide the root or another client's creates."""
    code = f"""
import os
import subprocess
import sys
root = {str(gkfs_daemon.mountdir)!r}
assert os.listdir(root) == []
os.mkdir(root + '/seed')
assert 'seed' in os.listdir(root)
# Root is not an entry in its own cached listing.
assert os.stat(root).st_mode
assert 'seed' in os.listdir(root)
path = root + '/created-by-peer'
subprocess.run([sys.executable, '-c',
                'import os; os.mkdir(' + repr(path) + ')'], check=True)
assert os.stat(path).st_mode
os.rmdir(path)
os.rmdir(root + '/seed')
"""
    result = gkfs_shell.run(
        sys.executable, "-c", code,
        env={"LIBGKFS_DENTRY_CACHE": "ON",
             "LIBGKFS_DENTRY_CACHE_CLEAR_ON_CLOSE": "OFF"})
    assert result.exit_code == 0, result.stderr.decode()


@pytest.fixture
def gkfs_client_cache(test_workspace, gkfs_daemon, monkeypatch):
    """
+2 −2

File changed.

Contains only whitespace changes.

+2 −2

File changed.

Contains only whitespace changes.