Loading src/client/fuse/fuse_client.cpp +86 −8 Original line number Diff line number Diff line Loading @@ -251,6 +251,18 @@ open_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_reply_open(req, fi); } static void lseek_handler(fuse_req_t req, fuse_ino_t ino, off_t off, int whence, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lseek handler \n"); int lc = gkfs::syscall::gkfs_lseek(fi->fh, off, whence); if(lc < 0) { fuse_reply_err(req, 1); return; } fuse_reply_lseek(req, lc); } static void read_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info* fi) { Loading Loading @@ -342,6 +354,25 @@ create_handler(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, fuse_reply_create(req, &e, fi); } /// TODO normally, the file should only be removed if the lookup count is zero, /// problem? static void unlink_handler(fuse_req_t req, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "unlink handler \n"); auto* parent_inode = get_inode(parent); if(!parent_inode) { fuse_reply_err(req, ENOENT); return; } std::string path = get_path(parent_inode, name); int rc = gkfs::syscall::gkfs_remove(path); if(rc == -1) { fuse_reply_err(req, 1); return; } fuse_reply_err(req, 0); } static void opendir_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "opendir handler \n"); Loading Loading @@ -443,6 +474,24 @@ readdir_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, free(buf); } static void releasedir_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "releasedir handler \n"); GkfsDir* dir_ptr = reinterpret_cast<GkfsDir*>(fi->fh); if(CTX->interception_enabled() && CTX->file_map()->exist(dir_ptr->fd)) { int fd = dir_ptr->fd; int ret = gkfs::syscall::gkfs_close(fd); // Close GekkoFS internal FD if(dir_ptr->path) { // Check if path was strdup'd free(dir_ptr->path); } free(dir_ptr); // Free the DIR struct itself fuse_reply_err(req, ret); return; } fuse_reply_err(req, 0); } /// releases file descriptor, not connected to lookup_count static void release_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { Loading Loading @@ -495,17 +544,30 @@ flush_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "flush handler \n"); auto* inode = get_inode(ino); if(!inode) { fuse_log(FUSE_LOG_DEBUG, "flush here \n"); fuse_reply_err(req, ENOENT); return; } int lc = gkfs::syscall::gkfs_fsync(fi->fh); if(lc < 0) { fuse_log(FUSE_LOG_DEBUG, "flush there \n"); fuse_reply_err(req, 1); return; } fuse_log(FUSE_LOG_DEBUG, "flush success \n"); fuse_reply_err(req, 0); } static void access_handler(fuse_req_t req, fuse_ino_t ino, int mask) { fuse_log(FUSE_LOG_DEBUG, "access handler \n"); auto* inode = get_inode(ino); if(!inode) { fuse_reply_err(req, ENOENT); return; } int lc = gkfs::syscall::gkfs_access(inode->path, mask, true); if(lc < 0) { fuse_reply_err(req, 1); return; } fuse_reply_err(req, 0); } Loading Loading @@ -544,6 +606,22 @@ mkdir_handler(fuse_req_t req, fuse_ino_t parent, const char* name, fuse_reply_entry(req, &e); } static void rmdir_handler(fuse_req_t req, fuse_ino_t parent, const char* name) { auto* parent_inode = get_inode(parent); if(!parent_inode) { fuse_reply_err(req, ENOENT); return; } std::string path = get_path(parent_inode, name); int rc = gkfs::syscall::gkfs_rmdir(path); if(rc == -1) { fuse_reply_err(req, 1); return; } fuse_reply_err(req, 0); } static void init_gekkofs() { // TODO how to handle mount point Loading Loading @@ -579,7 +657,7 @@ init_ll_ops(fuse_lowlevel_ops* ops) { ops->setattr = setattr_handler; ops->open = open_handler; ops->create = create_handler; // ops->unlink ops->unlink = unlink_handler; ops->forget = forget_handler; // ops->forget_multi // ops->readlink Loading @@ -591,6 +669,7 @@ init_ll_ops(fuse_lowlevel_ops* ops) { ops->release = release_handler; // ops->fsync // ops->write_buf ops->lseek = lseek_handler; // xattr // ops->setxattr Loading @@ -601,10 +680,10 @@ init_ll_ops(fuse_lowlevel_ops* ops) { // directory ops->lookup = lookup_handler; ops->mkdir = mkdir_handler; // ops->rmdir ops->rmdir = rmdir_handler; ops->readdir = readdir_handler; ops->opendir = opendir_handler; // ops->releasedir ops->releasedir = releasedir_handler; // ops->fsyncdir = nullptr; // ops->readdirplus Loading @@ -613,7 +692,7 @@ init_ll_ops(fuse_lowlevel_ops* ops) { ops->read = read_handler; // permission // ops->access ops->access = access_handler; // misc ops->init = init_handler; Loading @@ -629,7 +708,6 @@ init_ll_ops(fuse_lowlevel_ops* ops) { // ops->retrive_reply // ops->fallocate // ops->copy_file_range // ops->lseek // ops->tmpfile // ops->statx } Loading tests/integration/fuse/test_basic_operations.py +21 −3 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ from harness.logger import logger nonexisting = "nonexisting" # somehow are multiple test causing an error in the fuse client... def test_read(gkfs_daemon, fuse_client): file = gkfs_daemon.mountdir / "file" Loading @@ -58,6 +59,23 @@ def test_read(gkfs_daemon, fuse_client): assert sh.ls(fuse_client.mountdir) == "dir file file2\n" sh.cd(str(dir)) assert sh.pwd() == str(dir) + "\n" sh.mkdir("-p", "fu/bar") assert sh.ls() == "fu\n" sh.cd("fu") sh.mkdir("-p", "foo/bar") assert sh.ls() == "foo\n" sh.cd("foo") sh.rmdir("bar") sh.cd("..") sh.rmdir("foo") sh.rm(str(file2)) assert sh.ls(fuse_client.mountdir) == "dir file\n" # lseek test path = gkfs_daemon.mountdir / "lseek_file" with open(path, "wb") as f: f.write(b"HelloWorld") # 10 bytes fd = os.open(path, os.O_RDONLY) pos = os.lseek(fd, 5, os.SEEK_SET) # absolute seek assert pos == 5 data = os.read(fd, 5) assert data == b"World" os.close(fd) os.remove(path) Loading
src/client/fuse/fuse_client.cpp +86 −8 Original line number Diff line number Diff line Loading @@ -251,6 +251,18 @@ open_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_reply_open(req, fi); } static void lseek_handler(fuse_req_t req, fuse_ino_t ino, off_t off, int whence, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lseek handler \n"); int lc = gkfs::syscall::gkfs_lseek(fi->fh, off, whence); if(lc < 0) { fuse_reply_err(req, 1); return; } fuse_reply_lseek(req, lc); } static void read_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info* fi) { Loading Loading @@ -342,6 +354,25 @@ create_handler(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, fuse_reply_create(req, &e, fi); } /// TODO normally, the file should only be removed if the lookup count is zero, /// problem? static void unlink_handler(fuse_req_t req, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "unlink handler \n"); auto* parent_inode = get_inode(parent); if(!parent_inode) { fuse_reply_err(req, ENOENT); return; } std::string path = get_path(parent_inode, name); int rc = gkfs::syscall::gkfs_remove(path); if(rc == -1) { fuse_reply_err(req, 1); return; } fuse_reply_err(req, 0); } static void opendir_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "opendir handler \n"); Loading Loading @@ -443,6 +474,24 @@ readdir_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, free(buf); } static void releasedir_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "releasedir handler \n"); GkfsDir* dir_ptr = reinterpret_cast<GkfsDir*>(fi->fh); if(CTX->interception_enabled() && CTX->file_map()->exist(dir_ptr->fd)) { int fd = dir_ptr->fd; int ret = gkfs::syscall::gkfs_close(fd); // Close GekkoFS internal FD if(dir_ptr->path) { // Check if path was strdup'd free(dir_ptr->path); } free(dir_ptr); // Free the DIR struct itself fuse_reply_err(req, ret); return; } fuse_reply_err(req, 0); } /// releases file descriptor, not connected to lookup_count static void release_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { Loading Loading @@ -495,17 +544,30 @@ flush_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "flush handler \n"); auto* inode = get_inode(ino); if(!inode) { fuse_log(FUSE_LOG_DEBUG, "flush here \n"); fuse_reply_err(req, ENOENT); return; } int lc = gkfs::syscall::gkfs_fsync(fi->fh); if(lc < 0) { fuse_log(FUSE_LOG_DEBUG, "flush there \n"); fuse_reply_err(req, 1); return; } fuse_log(FUSE_LOG_DEBUG, "flush success \n"); fuse_reply_err(req, 0); } static void access_handler(fuse_req_t req, fuse_ino_t ino, int mask) { fuse_log(FUSE_LOG_DEBUG, "access handler \n"); auto* inode = get_inode(ino); if(!inode) { fuse_reply_err(req, ENOENT); return; } int lc = gkfs::syscall::gkfs_access(inode->path, mask, true); if(lc < 0) { fuse_reply_err(req, 1); return; } fuse_reply_err(req, 0); } Loading Loading @@ -544,6 +606,22 @@ mkdir_handler(fuse_req_t req, fuse_ino_t parent, const char* name, fuse_reply_entry(req, &e); } static void rmdir_handler(fuse_req_t req, fuse_ino_t parent, const char* name) { auto* parent_inode = get_inode(parent); if(!parent_inode) { fuse_reply_err(req, ENOENT); return; } std::string path = get_path(parent_inode, name); int rc = gkfs::syscall::gkfs_rmdir(path); if(rc == -1) { fuse_reply_err(req, 1); return; } fuse_reply_err(req, 0); } static void init_gekkofs() { // TODO how to handle mount point Loading Loading @@ -579,7 +657,7 @@ init_ll_ops(fuse_lowlevel_ops* ops) { ops->setattr = setattr_handler; ops->open = open_handler; ops->create = create_handler; // ops->unlink ops->unlink = unlink_handler; ops->forget = forget_handler; // ops->forget_multi // ops->readlink Loading @@ -591,6 +669,7 @@ init_ll_ops(fuse_lowlevel_ops* ops) { ops->release = release_handler; // ops->fsync // ops->write_buf ops->lseek = lseek_handler; // xattr // ops->setxattr Loading @@ -601,10 +680,10 @@ init_ll_ops(fuse_lowlevel_ops* ops) { // directory ops->lookup = lookup_handler; ops->mkdir = mkdir_handler; // ops->rmdir ops->rmdir = rmdir_handler; ops->readdir = readdir_handler; ops->opendir = opendir_handler; // ops->releasedir ops->releasedir = releasedir_handler; // ops->fsyncdir = nullptr; // ops->readdirplus Loading @@ -613,7 +692,7 @@ init_ll_ops(fuse_lowlevel_ops* ops) { ops->read = read_handler; // permission // ops->access ops->access = access_handler; // misc ops->init = init_handler; Loading @@ -629,7 +708,6 @@ init_ll_ops(fuse_lowlevel_ops* ops) { // ops->retrive_reply // ops->fallocate // ops->copy_file_range // ops->lseek // ops->tmpfile // ops->statx } Loading
tests/integration/fuse/test_basic_operations.py +21 −3 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ from harness.logger import logger nonexisting = "nonexisting" # somehow are multiple test causing an error in the fuse client... def test_read(gkfs_daemon, fuse_client): file = gkfs_daemon.mountdir / "file" Loading @@ -58,6 +59,23 @@ def test_read(gkfs_daemon, fuse_client): assert sh.ls(fuse_client.mountdir) == "dir file file2\n" sh.cd(str(dir)) assert sh.pwd() == str(dir) + "\n" sh.mkdir("-p", "fu/bar") assert sh.ls() == "fu\n" sh.cd("fu") sh.mkdir("-p", "foo/bar") assert sh.ls() == "foo\n" sh.cd("foo") sh.rmdir("bar") sh.cd("..") sh.rmdir("foo") sh.rm(str(file2)) assert sh.ls(fuse_client.mountdir) == "dir file\n" # lseek test path = gkfs_daemon.mountdir / "lseek_file" with open(path, "wb") as f: f.write(b"HelloWorld") # 10 bytes fd = os.open(path, os.O_RDONLY) pos = os.lseek(fd, 5, os.SEEK_SET) # absolute seek assert pos == 5 data = os.read(fd, 5) assert data == b"World" os.close(fd) os.remove(path)