Commit 10c7999c authored by sevenuz's avatar sevenuz
Browse files

instead of stat in open, use flags to identify dirs

parent 51238377
Loading
Loading
Loading
Loading
Loading
+26 −9
Original line number Diff line number Diff line
@@ -210,12 +210,9 @@ hook_openat(int dirfd, const char* cpath, int flags, mode_t mode) {
            return -ENOTDIR;

        case gkfs::preload::RelativizeStatus::internal: {
            auto md_ = gkfs::utils::get_metadata(resolved);
            if(md_ && S_ISDIR(md_->mode())) {
                // if its a directory, it is handled without fuse
                // TODO this could cause problems in the filemap if a dir fd and
                // a file fd are overwriting each other
                // return gkfs::syscall::gkfs_opendir(resolved);
            if(flags & O_DIRECTORY) {
                // Caller explicitly requests a directory: route via FUSE.
                // No metadata RPC needed — flag is authoritative.
                int fd = gsl::narrow_cast<int>(syscall_no_intercept_wrapper(
                        SYS_openat, dirfd, cpath, flags, mode));
                if(fd < 0) {
@@ -225,10 +222,30 @@ hook_openat(int dirfd, const char* cpath, int flags, mode_t mode) {
                        fd, std::make_shared<gkfs::filemap::OpenFile>(resolved,
                                                                      flags));
                return fd;
            } else {
            }
            if(flags & (O_WRONLY | O_RDWR | O_CREAT)) {
                // Write or create flags imply a regular file: intercept directly.
                return with_errno(
                        gkfs::syscall::gkfs_open(resolved, mode, flags));
            }
            // O_RDONLY without O_DIRECTORY: ambiguous (could be a regular file
            // or a dir/FUSE-only entry created by a non-intercepted process).
            // Try intercept first; on ENOENT fall back to FUSE — no upfront stat.
            {
                int ret = gkfs::syscall::gkfs_open(resolved, mode, flags);
                if(ret >= 0) {
                    return ret;
                }
                int saved_errno = errno;
                if(saved_errno != ENOENT) {
                    return -saved_errno;
                }
                // Not in intercept namespace: let FUSE handle it (dir or
                // entry created outside intercept). Do not register in
                // file_map so that subsequent ops (fstat, read) go to kernel.
                return gsl::narrow_cast<int>(syscall_no_intercept_wrapper(
                        SYS_openat, dirfd, cpath, flags, mode));
            }
        }

        default:
@@ -254,8 +271,8 @@ hook_close(int fd) {

    LOG(DEBUG, "{}() called with fd: {}", __func__, fd);

    auto f = CTX->file_map()->get(fd);
    if(f != nullptr && f->type() == filemap::FileType::directory) {
    auto f = CTX->file_map()->get_dir(fd);
    if(f != nullptr) {
        CTX->file_map()->remove(fd);
        return gsl::narrow_cast<int>(
                syscall_no_intercept_wrapper(SYS_close, fd));