Commit 7f9ef9c0 authored by Ramon Nou's avatar Ramon Nou
Browse files

Support for : rename symlinks, and fstat (fd) of renamed files

parent 4127b332
Loading
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -66,7 +66,8 @@ gkfs_access(const std::string& path, int mask, bool follow_links = true);
// Implementation of stat,
// Follow links is true by default
int
gkfs_stat(const std::string& path, struct stat* buf, bool follow_links = true);
gkfs_stat(const std::string& path, struct stat* buf, bool follow_links = true,
          bool bypass_rename = false);

// Implementation of statx, it uses the normal stat and maps the information to
// the statx structure Follow links is true by default
+2 −1
Original line number Diff line number Diff line
@@ -99,7 +99,8 @@ ssize_t
gkfs_pwritev(int fd, const struct iovec* iov, int iovcnt, off_t offset);

int
gkfs_stat(const std::string& path, struct stat* buf, bool follow_links = true);
gkfs_stat(const std::string& path, struct stat* buf, bool follow_links = true,
          bool bypass_rename = false);

int
gkfs_statx(int dirfs, const std::string& path, int flags, unsigned int mask,
+31 −11
Original line number Diff line number Diff line
@@ -475,24 +475,36 @@ gkfs_rename(const string& old_path, const string& new_path) {
        return -1;
    } else {


        if(!md_old.value().target_path().empty()) {


            // the file is a renamed one, we need to get the metadata of the
            // original file. (There will be only one level)
            original_path = md_old.value().target_path();

            original_path = md_old.value().target_path();
            if(!S_ISLNK(md_old->mode())) {
                md_old = gkfs::utils::get_metadata(original_path, false);

                if(!md_old) {
                    return -1;
                }
            }

            auto is_dir = false;
            if(S_ISDIR(md_old->mode()))
                is_dir = true;
            // Remove intermediate file
            gkfs::rpc::forward_remove(old_path, is_dir, CTX->get_replicas());
        }
        auto err = gkfs::rpc::forward_rename(original_path, new_path,
        int err = 0;
        if(!S_ISLNK(md_old->mode())) {
            err = gkfs::rpc::forward_rename(original_path, new_path,
                                            md_old.value());
        } else {
            // Was a link so do a forward symlink to regenerate it
            err = gkfs_mk_symlink(new_path, original_path);
        }
        if(err) {
            errno = err;
            return -1;
@@ -512,20 +524,27 @@ gkfs_rename(const string& old_path, const string& new_path) {
 * @return 0 on success, -1 on failure
 */
int
gkfs_stat(const string& path, struct stat* buf, bool follow_links) {
gkfs_stat(const string& path, struct stat* buf, bool follow_links,
          bool bypass_rename) {
    auto md = gkfs::utils::get_metadata(path, follow_links);
    if(!md) {
        return -1;
    }

    std::string new_path = path;
#ifdef HAS_RENAME
    if(md->is_link() == false) {
        if(md.value().blocks() == -1) {
            // This may not be correct in the case of fstat,
            // then we will check bypass_rename
            if(!bypass_rename) {
                errno = ENOENT;
                return -1;
            }
        } else {
            while(!md.value().target_path().empty() and
                  md.value().blocks() != -1) {
                new_path = md.value().target_path();
                md = gkfs::utils::get_metadata(md.value().target_path(), false);

                if(!md) {
@@ -537,8 +556,9 @@ gkfs_stat(const string& path, struct stat* buf, bool follow_links) {
        }
    }
#endif

    gkfs::utils::metadata_to_stat(path, *md, *buf);
    // Stat should use new_path in order that the inode of a renamed file is
    // equal to the original
    gkfs::utils::metadata_to_stat(new_path, *md, *buf);
    return 0;
}

+11 −7
Original line number Diff line number Diff line
@@ -1029,7 +1029,8 @@ __fxstat(int ver, int fd, struct stat* buf) {
    initializeGekko();
    if(is_gkfs_fd(fd)) {
        DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path());
        return gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), buf);
        return gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), buf,
                                        true, true);
    }
    GKFS_FALLBACK(__fxstat, ver, fd, buf);
}
@@ -1048,8 +1049,8 @@ __fxstat64(int ver, int fd, struct stat64* buf) {
    if(is_gkfs_fd(fd)) {
        struct stat st;
        DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path());
        int res =
                gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), &st);
        int res = gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(),
                                           &st, true, true);
        if(res == 0)
            convert(&st, buf);
        return res;
@@ -1063,8 +1064,8 @@ fstat64(int fd, struct stat64* buf) {
    if(is_gkfs_fd(fd)) {
        struct stat st;
        DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path());
        int res =
                gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), &st);
        int res = gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(),
                                           &st, true, true);
        if(res == 0)
            convert(&st, buf);
        return res;
@@ -1077,8 +1078,11 @@ fstat(int fd, struct stat* buf) {
    initializeGekko();
    if(is_gkfs_fd(fd)) {
        DEBUG_INFO("[GKFS] {}", CTX->file_map()->get(fd)->path());
        int res =
                gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(), buf);

        // The fd could be a renamed file, thus when doing gkfs_stat we will get
        // a is not found.
        int res = gkfs::syscall::gkfs_stat(CTX->file_map()->get(fd)->path(),
                                           buf, true, true);
        return res;
    }
    GKFS_FALLBACK(fstat, fd, buf);
+2 −2
Original line number Diff line number Diff line
@@ -938,10 +938,10 @@ rpc_srv_rename(hg_handle_t handle) {

        md.target_path(in.target_path);
        // We are reverting the rename so we clean up the target_path
        if(strcmp(in.target_path, "") == 0)
        if(strcmp(in.target_path, "") == 0) {
            md.blocks(0);
        }

        //}
        GKFS_DATA->spdlogger()->debug(
                "{}() Updating path '{}' with metadata '{}'", __func__, in.path,
                md.serialize());