Commit 9ab31c2d authored by Ramon Nou's avatar Ramon Nou
Browse files

Update RISC-V profile with syscall interception runtime fixes

parent 14bdda95
Loading
Loading
Loading
Loading
+12 −0
Changes for include/client/gkfs_libc.hpp: 12 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -76,6 +76,14 @@ open(const char* path, int flags, ...);
int
open64(const char* path, int flags, ...);
int
__open_2(const char* path, int flags);
int
__open64_2(const char* path, int flags);
int
__openat_2(int dirfd, const char* path, int flags);
int
__openat64_2(int dirfd, const char* path, int flags);
int
openat(int dirfd, const char* path, int flags, ...);
int
openat64(int dirfd, const char* path, int flags,
@@ -117,6 +125,8 @@ lseek64(int fd, off64_t offset, int whence);
int
ftruncate(int fd, off_t length);
int
ftruncate64(int fd, off64_t length);
int
fsync(int fd);
int
flock(int fd, int operation);
@@ -249,6 +259,8 @@ fchmod(int fd, mode_t mode) throw();
int
fchmodat(int dfd, const char* path, mode_t mode, int flags) throw();
int
__fchmodat(int dfd, const char* path, mode_t mode, int flags) throw();
int
chown(const char* path, uid_t owner, gid_t group) throw();
int
fchown(int fd, uid_t owner, gid_t group) throw();
+33 −1
Changes for include/client/rpc/utils.hpp: 33 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -59,9 +59,41 @@
#include <cstring>
#include <type_traits>
#include <limits>
#include <mutex>

namespace gkfs::rpc {

inline thallium::remote_procedure
define_rpc(const std::shared_ptr<thallium::engine>& engine,
           const std::string& tag) {
    // Thallium's lookup-then-register sequence is not atomic. Concurrent
    // first use can register the same RPC twice and corrupt Margo metadata.
    // Share this mutex across call sites, not once per forward_call template.
    static std::mutex registration_mutex;
    const std::lock_guard<std::mutex> lock(registration_mutex);
    auto rpc = engine->define(tag);
    // define() registers MARGO_DEFAULT_PROVIDER_ID, but on(endpoint) sends
    // to provider 0. Prepare that ID here too: otherwise Margo lazily
    // registers it during forward(), outside this registration lock.
    const auto mid = engine->get_margo_instance();
    hg_id_t id;
    hg_bool_t registered;
    if(margo_provider_registered_name(mid, tag.c_str(), 0, &id, &registered) !=
       HG_SUCCESS) {
        throw std::runtime_error("Failed to look up RPC provider: " + tag);
    }
    if(!registered) {
        id = margo_provider_register_name(mid, tag.c_str(),
                                          thallium::hg_proc_meta_serialization,
                                          thallium::hg_proc_meta_serialization,
                                          nullptr, 0, ABT_POOL_NULL);
        if(id == 0) {
            throw std::runtime_error("Failed to register RPC provider: " + tag);
        }
    }
    return rpc;
}

template <typename Rpc, typename Input>
auto
forward_with_timeout(Rpc& rpc, const thallium::endpoint& endp,
@@ -232,7 +264,7 @@ forward_call(const std::shared_ptr<thallium::engine>& engine,
                in.trace_id, tag);
        }

        auto rpc = engine->define(tag);
        auto rpc = define_rpc(engine, tag);
        Output out = forward_with_timeout(rpc, endp, in);

        // Some output structs might not have .err, but most do.
+2 −1
Changes for scripts/profiles/0.9.6-dev/riscv.specs: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -52,7 +52,8 @@ clonedeps=(
    ["mercury"]="v2.4.1"
    ["margo"]="v0.21.0"
    ["thallium"]="v0.15.1"
    ["syscall_intercept"]="f2a644ab5e9742f3d55dcc23ae6d0d0a153da491"
    # RISC-V patching/relocation fixes; threaded futex failures remain unresolved.
    ["syscall_intercept"]="8db291aa6b9cf8b02303de3c15f2d96e4d9d45d5"
)

# Extra arguments for git clone
+158 −32
Changes for src/client/gkfs_libc.cpp: 158 added lines, 32 removed lines.
Original line number Diff line number Diff line
@@ -377,8 +377,9 @@ resolve_gkfs_path(int dirfd, const char* path, std::string& resolved,
            errno = ENOTDIR;
            return PathStatus::Error;
        case gkfs::preload::RelativizeStatus::fd_unknown:
            errno = EBADF;
            return PathStatus::Error;
            // Not in the virtual descriptor map: let libc validate the
            // host descriptor and resolve relative paths (e.g. sysfs).
            return PathStatus::External;
        default: // Assuming other statuses mean external or not applicable
            return PathStatus::External;
    }
@@ -542,6 +543,14 @@ get_result(const struct aiocb* aiocbp) {
// functions.

// File Operations
DLSYM_WRAPPER(int, __open_2, (const char* path, int flags), (path, flags),
              "__open_2")
DLSYM_WRAPPER(int, __open64_2, (const char* path, int flags), (path, flags),
              "__open64_2")
DLSYM_WRAPPER(int, __openat_2, (int dirfd, const char* path, int flags),
              (dirfd, path, flags), "__openat_2")
DLSYM_WRAPPER(int, __openat64_2, (int dirfd, const char* path, int flags),
              (dirfd, path, flags), "__openat64_2")
DLSYM_WRAPPER(int, open2, (const char* path, int flags, mode_t mode),
              (path, flags, mode), "open")
DLSYM_WRAPPER(int, open64, (const char* path, int flags, mode_t mode),
@@ -608,6 +617,8 @@ DLSYM_WRAPPER(int, truncate, (const char* path, off_t length), (path, length),
DLSYM_WRAPPER(int, truncate64, (const char* path, off64_t length),
              (path, length), "truncate64")
DLSYM_WRAPPER(int, ftruncate, (int fd, off_t length), (fd, length), "ftruncate")
DLSYM_WRAPPER(int, ftruncate64, (int fd, off64_t length), (fd, length),
              "ftruncate64")
DLSYM_WRAPPER(int, fsync, (int fd), (fd), "fsync")
DLSYM_WRAPPER(int, flock, (int fd, int operation), (fd, operation), "flock")

@@ -646,6 +657,14 @@ DLSYM_WRAPPER(int, fxstatat,
              (ver, dfd, path, buf, flags), "__fxstatat")

// Filesystem status Operations
DLSYM_WRAPPER(int, statvfs, (const char* path, struct statvfs* buf),
              (path, buf), "statvfs")
DLSYM_WRAPPER(int, fstatvfs, (int fd, struct statvfs* buf), (fd, buf),
              "fstatvfs")
DLSYM_WRAPPER(int, statvfs64, (const char* path, struct statvfs64* buf),
              (path, buf), "statvfs64")
DLSYM_WRAPPER(int, fstatvfs64, (int fd, struct statvfs64* buf), (fd, buf),
              "fstatvfs64")
DLSYM_WRAPPER(int, statfs, (const char* path, struct statfs* buf), (path, buf),
              "statfs")
DLSYM_WRAPPER(int, fstatfs, (int fd, struct statfs* buf), (fd, buf), "fstatfs")
@@ -837,53 +856,49 @@ get_open_fds() {

//------------------------- File I/O Operations ------------------------------//

namespace {
bool
open_needs_mode(int flags) {
    return (flags & O_CREAT) || (flags & O_TMPFILE) == O_TMPFILE;
}
} // namespace

int
open(const char* path, int flags, ...) {
    mode_t mode = 0;
    if(open_needs_mode(flags)) {
        va_list ap;
        va_start(ap, flags);
    mode_t mode = va_arg(ap, mode_t);
        mode = va_arg(ap, mode_t);
        va_end(ap);
    }
    gkfs_init_routine_placeholder();
    GKFS_PATH_OPERATION(open, AT_FDCWD, path, mode, flags)
    GKFS_FALLBACK(open2, path, flags,
                  mode) // Use open2 as it's defined with mode_t
    GKFS_FALLBACK(open2, path, flags, mode)
}

int
open64(const char* path, int flags, ...) {
    mode_t mode = 0;
    if(open_needs_mode(flags)) {
        va_list ap;
        va_start(ap, flags);
    mode_t mode = va_arg(ap, mode_t);
        mode = va_arg(ap, mode_t);
        va_end(ap);
    gkfs_init_routine_placeholder();
    GKFS_PATH_OPERATION(open, AT_FDCWD, path, mode,
                        flags) // GekkoFS uses its 'open' for open64 too
    GKFS_FALLBACK(open64, path, flags, mode)
    }

#ifdef GKFS_ENABLE_UNUSED_FUNCTIONS
// This version of open64 seems redundant if the variadic one exists and is
// standard. Keeping it under the flag as per original structure.
int
open64(const char* path, int flags, mode_t mode) {
    gkfs_init_routine_placeholder();
    GKFS_PATH_OPERATION(open, AT_FDCWD, path, mode, flags)
    GKFS_FALLBACK(open64, path, flags, mode)
}
#endif

int
openat(int dirfd, const char* path, int flags, ...) {
    mode_t mode = 0;
    if(open_needs_mode(flags)) {
        va_list ap;
    mode_t mode = 0; // Default mode if not O_CREAT or O_TMPFILE
    if(flags & (O_CREAT | O_TMPFILE)) {
        va_start(ap, flags);
        mode = va_arg(ap, mode_t);
        va_end(ap);
    } else {
        va_start(ap, flags);
        mode = va_arg(ap, mode_t); // Read for stack balance
        va_end(ap);
    }
    gkfs_init_routine_placeholder();
    GKFS_PATH_OPERATION(open, dirfd, path, mode, flags)
@@ -892,20 +907,49 @@ openat(int dirfd, const char* path, int flags, ...) {

int
openat64(int dirfd, const char* path, int flags, ...) {
    va_list ap;
    mode_t mode = 0;
    if(flags & (O_CREAT | O_TMPFILE)) {
    if(open_needs_mode(flags)) {
        va_list ap;
        va_start(ap, flags);
        mode = va_arg(ap, mode_t);
        va_end(ap);
    } else {
        va_start(ap, flags);
        mode = va_arg(ap, mode_t); // Read for stack balance
        va_end(ap);
    }
    return openat(dirfd, path, flags, mode);
}

int
__open_2(const char* path, int flags) {
    // Retain glibc's fortify failure for calls missing a required mode.
    if(open_needs_mode(flags)) {
        return dlsym___open_2(path, flags);
    }
    return open(path, flags);
}

int
__open64_2(const char* path, int flags) {
    if(open_needs_mode(flags)) {
        return dlsym___open64_2(path, flags);
    }
    return open64(path, flags);
}

int
__openat_2(int dirfd, const char* path, int flags) {
    if(open_needs_mode(flags)) {
        return dlsym___openat_2(dirfd, path, flags);
    }
    return openat(dirfd, path, flags);
}

int
__openat64_2(int dirfd, const char* path, int flags) {
    if(open_needs_mode(flags)) {
        return dlsym___openat64_2(dirfd, path, flags);
    }
    return openat64(dirfd, path, flags);
}

int
creat(const char* path, mode_t mode) {
    gkfs_init_routine_placeholder();
@@ -945,6 +989,79 @@ close_range(unsigned int low, unsigned int high, int flags) {
    return dlsym_close_range(low, high, flags);
}

namespace {
template <typename Statvfs>
int
fill_statvfs(Statvfs* buf) {
    struct statfs stfs{};
    if(gkfs::syscall::gkfs_statfs(&stfs) != 0) {
        return -1;
    }
    *buf = {};
    buf->f_bsize = stfs.f_bsize;
    buf->f_frsize = stfs.f_frsize ? stfs.f_frsize : stfs.f_bsize;
    buf->f_blocks = stfs.f_blocks;
    buf->f_bfree = stfs.f_bfree;
    buf->f_bavail = stfs.f_bavail;
    buf->f_files = stfs.f_files;
    buf->f_ffree = stfs.f_ffree;
    buf->f_favail = stfs.f_ffree;
    buf->f_flag = stfs.f_flags;
    buf->f_namemax = stfs.f_namelen;
    return 0;
}
} // namespace

int
statvfs(const char* path, struct statvfs* buf) {
    gkfs_init_routine_placeholder();
    if(GKFS_INTERCEPTION_ENABLED()) {
        std::string resolved;
        const auto status = resolve_gkfs_path(AT_FDCWD, path, resolved);
        if(status == PathStatus::Internal) {
            return fill_statvfs(buf);
        }
        if(status == PathStatus::Error) {
            return -1;
        }
    }
    GKFS_FALLBACK(statvfs, path, buf)
}

int
statvfs64(const char* path, struct statvfs64* buf) {
    gkfs_init_routine_placeholder();
    if(GKFS_INTERCEPTION_ENABLED()) {
        std::string resolved;
        const auto status = resolve_gkfs_path(AT_FDCWD, path, resolved);
        if(status == PathStatus::Internal) {
            return fill_statvfs(buf);
        }
        if(status == PathStatus::Error) {
            return -1;
        }
    }
    GKFS_FALLBACK(statvfs64, path, buf)
}

int
fstatvfs(int fd, struct statvfs* buf) {
    gkfs_init_routine_placeholder();
    if(GKFS_INTERCEPTION_ENABLED() && is_gkfs_fd(fd)) {
        return fill_statvfs(buf);
    }
    GKFS_FALLBACK(fstatvfs, fd, buf)
}

int
fstatvfs64(int fd, struct statvfs64* buf) {
    gkfs_init_routine_placeholder();
    if(GKFS_INTERCEPTION_ENABLED() && is_gkfs_fd(fd)) {
        return fill_statvfs(buf);
    }
    GKFS_FALLBACK(fstatvfs64, fd, buf)
}

int
statfs(const char* path, struct statfs* buf) {
    gkfs_init_routine_placeholder();
@@ -1255,6 +1372,15 @@ ftruncate(int fd, off_t length) {
    GKFS_FALLBACK(ftruncate, fd, length);
}

int
ftruncate64(int fd, off64_t length) {
    gkfs_init_routine_placeholder();
    if(GKFS_INTERCEPTION_ENABLED() && is_gkfs_fd(fd)) {
        return ftruncate(fd, length);
    }
    GKFS_FALLBACK(ftruncate64, fd, length);
}

int
fsync(int fd) {
    gkfs_init_routine_placeholder();
@@ -2873,8 +2999,8 @@ fopen(const char* path, const char* mode) {
    gkfs_init_routine_placeholder();
    if(GKFS_INTERCEPTION_ENABLED()) {
        std::string resolved;
        if(resolve_gkfs_path(AT_FDCWD, path, resolved) ==
           PathStatus::Internal) {
        const auto status = resolve_gkfs_path(AT_FDCWD, path, resolved);
        if(status == PathStatus::Internal) {
            DEBUG_INFO("[GKFS] fopen(path='{}', mode='{}')", resolved, mode);
            int flags = 0;
            mode_t open_mode = 0666; // Default mode for creation
@@ -2908,7 +3034,7 @@ fopen(const char* path, const char* mode) {
                return nullptr;      // errno set by gkfs_open
            return fdopen(fd, mode); // Call our hooked fdopen
        }
        if(errno != 0 && (errno == ENOTDIR || errno == EBADF))
        if(status == PathStatus::Error)
            return nullptr;
    }
    GKFS_FALLBACK(fopen, path, mode);
+4 −3
Changes for src/client/gkfs_metadata.cpp: 4 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -1249,7 +1249,8 @@ gkfs_opendir(const std::string& path) {
        };

        if(use_proxy_dirents) {
            auto proxy_rpc = CTX->ipc_engine()->define(
            auto proxy_rpc = gkfs::rpc::define_rpc(
                    CTX->ipc_engine(),
                    gkfs::rpc::tag::client_proxy_get_dirents_extended);

            for(uint64_t i = 0; i < target_count; ++i) {
@@ -1275,8 +1276,8 @@ gkfs_opendir(const std::string& path) {
                }
            }
        } else {
            auto get_dirents_rpc = CTX->rpc_engine()->define(
                    gkfs::rpc::tag::get_dirents_extended);
            auto get_dirents_rpc = gkfs::rpc::define_rpc(
                    CTX->rpc_engine(), gkfs::rpc::tag::get_dirents_extended);
            std::string root_path = path;
            if(root_path.length() > 1 && root_path.back() != '/') {
                root_path += '/';
Loading