Loading src/client/fuse/fuse_client.cpp +81 −25 Original line number Diff line number Diff line Loading @@ -218,33 +218,34 @@ getattr_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { static void setattr_handler(fuse_req_t req, fuse_ino_t ino, struct stat* attr, int to_set, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "setattr handler \n"); fuse_log(FUSE_LOG_DEBUG, "setattr handler ino %u\n", ino); auto* inode = get_inode(ino); if(!inode) { fuse_reply_err(req, ENOENT); return; } // TODO how to change attr? int rc = 0; if(rc) { fuse_reply_err(req, rc); if(to_set & FUSE_SET_ATTR_SIZE) { off_t new_size = attr->st_size; int res = gkfs::syscall::gkfs_truncate(inode->path, new_size); if(res < 0) { fuse_log(FUSE_LOG_DEBUG, "setattr truncate failed on %s\n", inode->path.c_str()); fuse_reply_err(req, EIO); return; } // TODO thats not in gkfs!!! // Update cached stat so users see the new size inode->st.st_size = new_size; } if(to_set & FUSE_SET_ATTR_ATIME) inode->st.st_atim = attr->st_atim; inode->st.st_blksize = attr->st_blksize; inode->st.st_blocks = attr->st_blocks; inode->st.st_ctim = attr->st_ctim; inode->st.st_dev = attr->st_dev; inode->st.st_gid = attr->st_gid; inode->st.st_ino = attr->st_ino; inode->st.st_mode = attr->st_mode; if(to_set & FUSE_SET_ATTR_MTIME) inode->st.st_mtim = attr->st_mtim; inode->st.st_nlink = attr->st_nlink; inode->st.st_rdev = attr->st_rdev; inode->st.st_size = attr->st_size; inode->st.st_uid = attr->st_uid; // TODO because we cannot save the attributes in gekko, we just return the // buffered results of stat fuse_reply_attr(req, &inode->st, 1.0); return; } static void Loading Loading @@ -346,6 +347,7 @@ create_handler(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, return; } fuse_ino_t ino = alloc_inode(path); fuse_log(FUSE_LOG_DEBUG, "create new inode ino %i\n", ino); ino_map[ino].st = st; fuse_entry_param e = {}; e.ino = ino; Loading Loading @@ -458,15 +460,69 @@ readdir_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, static void init_handler(void* userdata, struct fuse_conn_info* conn) { fuse_log(FUSE_LOG_DEBUG, "init handler \n"); // userdata is GekkoFuse* if passed // optional: adjust conn->max_write, enable writeback etc. } static void destroy_handler(void* userdata) { fuse_log(FUSE_LOG_DEBUG, "destroy handler \n"); // userdata is GekkoFuse* if passed // optional: adjust conn->max_write, enable writeback etc. } static void release_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { // TODO decrease inode count fuse_log(FUSE_LOG_DEBUG, "release handler \n"); auto* inode = get_inode(ino); if(!inode) { fuse_log(FUSE_LOG_DEBUG, "release here \n"); fuse_reply_err(req, ENOENT); return; } int lc = gkfs::syscall::gkfs_close(fi->fh); if(lc < 0) { fuse_log(FUSE_LOG_DEBUG, "release there \n"); fuse_reply_err(req, 1); return; } fuse_log(FUSE_LOG_DEBUG, "release success \n"); fuse_reply_err(req, 0); } static void forget_handler(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup) { // TODO remove inode at some point if count == 0 fuse_log(FUSE_LOG_DEBUG, "forget handler \n"); fuse_reply_err(req, 0); } static void 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 const struct fuse_lowlevel_ops lo_oper = { .init = init_handler, // lo_init, //.destroy = lo_destroy, .init = init_handler, .destroy = destroy_handler, .lookup = lookup_handler, //.forget = lo_forget, .forget = forget_handler, .getattr = getattr_handler, .setattr = setattr_handler, //.readlink = lo_readlink, Loading @@ -480,8 +536,8 @@ static const struct fuse_lowlevel_ops lo_oper = { .open = open_handler, .read = read_handler, .write = write_handler, //.flush = lo_flush, //.release = lo_release, .flush = flush_handler, .release = release_handler, //.fsync = lo_fsync, .opendir = opendir_handler, .readdir = readdir_handler, Loading tests/integration/fuse/test_basic_operations.py +2 −0 Original line number Diff line number Diff line Loading @@ -43,7 +43,9 @@ nonexisting = "nonexisting" def test_read(gkfs_daemon, fuse_client): file = gkfs_daemon.mountdir / "file" file2 = gkfs_daemon.mountdir / "file2" sh.bash("-c", "echo baum > " + str(file)) assert sh.ls(fuse_client.mountdir) == "file\n" assert sh.cat(file) == "baum\n" sh.touch(str(file2)) tests/integration/harness/gkfs.py +3 −5 Original line number Diff line number Diff line Loading @@ -1669,9 +1669,10 @@ class FuseClient: self._proc = self._cmd( args, _env=self._env, # _out=sys.stdout, # _err=sys.stderr, _out='/dev/null', _err='/dev/null', _bg=True, _ok_code=list(range(0, 256)) ) print(f"fuse client process spawned (PID={self._proc.pid})") Loading @@ -1680,9 +1681,6 @@ class FuseClient: return self def shutdown(self): print(f"terminating fuse client and unmounting") sh.fusermount("-u", self._workspace.mountdir) try: self._proc.terminate() err = self._proc.wait() Loading Loading
src/client/fuse/fuse_client.cpp +81 −25 Original line number Diff line number Diff line Loading @@ -218,33 +218,34 @@ getattr_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { static void setattr_handler(fuse_req_t req, fuse_ino_t ino, struct stat* attr, int to_set, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "setattr handler \n"); fuse_log(FUSE_LOG_DEBUG, "setattr handler ino %u\n", ino); auto* inode = get_inode(ino); if(!inode) { fuse_reply_err(req, ENOENT); return; } // TODO how to change attr? int rc = 0; if(rc) { fuse_reply_err(req, rc); if(to_set & FUSE_SET_ATTR_SIZE) { off_t new_size = attr->st_size; int res = gkfs::syscall::gkfs_truncate(inode->path, new_size); if(res < 0) { fuse_log(FUSE_LOG_DEBUG, "setattr truncate failed on %s\n", inode->path.c_str()); fuse_reply_err(req, EIO); return; } // TODO thats not in gkfs!!! // Update cached stat so users see the new size inode->st.st_size = new_size; } if(to_set & FUSE_SET_ATTR_ATIME) inode->st.st_atim = attr->st_atim; inode->st.st_blksize = attr->st_blksize; inode->st.st_blocks = attr->st_blocks; inode->st.st_ctim = attr->st_ctim; inode->st.st_dev = attr->st_dev; inode->st.st_gid = attr->st_gid; inode->st.st_ino = attr->st_ino; inode->st.st_mode = attr->st_mode; if(to_set & FUSE_SET_ATTR_MTIME) inode->st.st_mtim = attr->st_mtim; inode->st.st_nlink = attr->st_nlink; inode->st.st_rdev = attr->st_rdev; inode->st.st_size = attr->st_size; inode->st.st_uid = attr->st_uid; // TODO because we cannot save the attributes in gekko, we just return the // buffered results of stat fuse_reply_attr(req, &inode->st, 1.0); return; } static void Loading Loading @@ -346,6 +347,7 @@ create_handler(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, return; } fuse_ino_t ino = alloc_inode(path); fuse_log(FUSE_LOG_DEBUG, "create new inode ino %i\n", ino); ino_map[ino].st = st; fuse_entry_param e = {}; e.ino = ino; Loading Loading @@ -458,15 +460,69 @@ readdir_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, static void init_handler(void* userdata, struct fuse_conn_info* conn) { fuse_log(FUSE_LOG_DEBUG, "init handler \n"); // userdata is GekkoFuse* if passed // optional: adjust conn->max_write, enable writeback etc. } static void destroy_handler(void* userdata) { fuse_log(FUSE_LOG_DEBUG, "destroy handler \n"); // userdata is GekkoFuse* if passed // optional: adjust conn->max_write, enable writeback etc. } static void release_handler(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { // TODO decrease inode count fuse_log(FUSE_LOG_DEBUG, "release handler \n"); auto* inode = get_inode(ino); if(!inode) { fuse_log(FUSE_LOG_DEBUG, "release here \n"); fuse_reply_err(req, ENOENT); return; } int lc = gkfs::syscall::gkfs_close(fi->fh); if(lc < 0) { fuse_log(FUSE_LOG_DEBUG, "release there \n"); fuse_reply_err(req, 1); return; } fuse_log(FUSE_LOG_DEBUG, "release success \n"); fuse_reply_err(req, 0); } static void forget_handler(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup) { // TODO remove inode at some point if count == 0 fuse_log(FUSE_LOG_DEBUG, "forget handler \n"); fuse_reply_err(req, 0); } static void 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 const struct fuse_lowlevel_ops lo_oper = { .init = init_handler, // lo_init, //.destroy = lo_destroy, .init = init_handler, .destroy = destroy_handler, .lookup = lookup_handler, //.forget = lo_forget, .forget = forget_handler, .getattr = getattr_handler, .setattr = setattr_handler, //.readlink = lo_readlink, Loading @@ -480,8 +536,8 @@ static const struct fuse_lowlevel_ops lo_oper = { .open = open_handler, .read = read_handler, .write = write_handler, //.flush = lo_flush, //.release = lo_release, .flush = flush_handler, .release = release_handler, //.fsync = lo_fsync, .opendir = opendir_handler, .readdir = readdir_handler, Loading
tests/integration/fuse/test_basic_operations.py +2 −0 Original line number Diff line number Diff line Loading @@ -43,7 +43,9 @@ nonexisting = "nonexisting" def test_read(gkfs_daemon, fuse_client): file = gkfs_daemon.mountdir / "file" file2 = gkfs_daemon.mountdir / "file2" sh.bash("-c", "echo baum > " + str(file)) assert sh.ls(fuse_client.mountdir) == "file\n" assert sh.cat(file) == "baum\n" sh.touch(str(file2))
tests/integration/harness/gkfs.py +3 −5 Original line number Diff line number Diff line Loading @@ -1669,9 +1669,10 @@ class FuseClient: self._proc = self._cmd( args, _env=self._env, # _out=sys.stdout, # _err=sys.stderr, _out='/dev/null', _err='/dev/null', _bg=True, _ok_code=list(range(0, 256)) ) print(f"fuse client process spawned (PID={self._proc.pid})") Loading @@ -1680,9 +1681,6 @@ class FuseClient: return self def shutdown(self): print(f"terminating fuse client and unmounting") sh.fusermount("-u", self._workspace.mountdir) try: self._proc.terminate() err = self._proc.wait() Loading