Loading include/client/fuse/fuse_client.hpp +4 −1 Original line number Diff line number Diff line Loading @@ -76,7 +76,9 @@ struct __dirstream { #include <sys/xattr.h> #include <fcntl.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <filesystem> #include <unistd.h> #include <unordered_map> #include <string> Loading Loading @@ -117,7 +119,8 @@ struct u_data { int writeback; int direct_io; int max_readahead; int flock; int fifo; int access; int xattr; char* mountpoint; double timeout; Loading src/client/fuse/fuse_client.cpp +134 −17 Original line number Diff line number Diff line Loading @@ -43,7 +43,9 @@ static struct fuse_lowlevel_ops ll_ops; static std::mutex ino_mutex; static std::unordered_map<fuse_ino_t, Inode> ino_map; static std::unordered_map<std::string, fuse_ino_t> path_map; static std::unordered_map<std::string, struct stat> local_fifos; static fuse_ino_t next_ino = 2; // reserve 1 for root static const std::string fifo_path = "/tmp/gekkofs_fifos/"; static fuse_ino_t alloc_inode(const std::string& path) { Loading Loading @@ -84,8 +86,10 @@ static const struct fuse_opt lo_opts[] = { {"direct_io", offsetof(struct u_data, direct_io), 1}, {"no_direct_io", offsetof(struct u_data, direct_io), 0}, {"max_readahead=%ui", offsetof(struct u_data, max_readahead), 0}, {"flock", offsetof(struct u_data, flock), 1}, {"no_flock", offsetof(struct u_data, flock), 0}, {"fifo", offsetof(struct u_data, fifo), 1}, {"no_fifo", offsetof(struct u_data, fifo), 0}, {"access", offsetof(struct u_data, access), 1}, {"no_access", offsetof(struct u_data, access), 0}, {"xattr", offsetof(struct u_data, xattr), 1}, {"no_xattr", offsetof(struct u_data, xattr), 0}, {"timeout=%lf", offsetof(struct u_data, timeout), 0}, Loading @@ -103,8 +107,10 @@ passthrough_ll_help(void) { " -o direct_io Enables direct io\n" " -o no_direct_io Disable direct io\n" " -o max_readahead=1 Amount of allowed readaheads\n" " -o flock Enable flock\n" " -o no_flock Disable flock\n" " -o fifo Enable fifo, disables GekkoFS access check\n" " -o no_fifo Disable fifo\n" " -o access Enable GekkoFS access check if fifo is deactivated\n" " -o no_access Disable access handler\n" " -o xattr Enable xattr\n" " -o no_xattr Disable xattr\n" " -o timeout=1.0 Caching timeout\n" Loading @@ -117,7 +123,8 @@ passthrough_ll_help(void) { static void init_handler(void* userdata, struct fuse_conn_info* conn) { struct u_data* ud = (struct u_data*) userdata; fuse_log(FUSE_LOG_DEBUG, "init handler readahead %i direct_io %i \n", ud->max_readahead, ud->direct_io); fuse_log(FUSE_LOG_DEBUG, "init handler readahead %i direct_io %i \n", ud->max_readahead, ud->direct_io); // bool has_flag; // TODO check other capabilities e.g. FUSE_CAP_READDIRPLUS Loading Loading @@ -156,6 +163,21 @@ lookup_handler(fuse_req_t req, fuse_ino_t parent, const char* name) { std::string child = get_path(parent_inode, name); fuse_log(FUSE_LOG_DEBUG, "lookup %s\n", child.c_str()); if(ud->fifo) { auto iit = local_fifos.find(child); if(iit != local_fifos.end()) { const struct stat& st = iit->second; fuse_entry_param e{}; e.ino = st.st_ino; e.attr = st; e.attr_timeout = ud->timeout; e.entry_timeout = ud->timeout; fuse_reply_entry(req, &e); return; } } // See if we already have this path auto it = path_map.find(child); Loading Loading @@ -366,12 +388,25 @@ tmpfile_handler(fuse_req_t req, fuse_ino_t parent, mode_t mode, static void unlink_handler(fuse_req_t req, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "unlink handler \n"); auto* ud = udata(req); auto* parent_inode = get_inode(parent); if(!parent_inode) { fuse_reply_err(req, ENOENT); return; } std::string path = get_path(parent_inode, name); if(ud->fifo) { auto it = local_fifos.find(path); if(it != local_fifos.end()) { std::string real = fifo_path + std::string(name); unlink(real.c_str()); local_fifos.erase(it); fuse_reply_err(req, 0); return; } } int rc = gkfs::syscall::gkfs_remove(path); if(rc == -1) { fuse_reply_err(req, 1); Loading Loading @@ -429,6 +464,7 @@ static void readdir_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "readdir handler \n"); auto* ud = udata(req); auto* dir_ptr = reinterpret_cast<GkfsDir*>(fi->fh); if(!dir_ptr) { fuse_reply_err(req, EBADF); Loading Loading @@ -458,7 +494,7 @@ readdir_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, auto de = open_dir->getdent(pos); struct stat st{}; // TODO cannot be right, right? // TODO cannot be right, right? no stat? st.st_ino = std::hash<std::string>()(open_dir->path() + "/" + de.name()); st.st_mode = (de.type() == gkfs::filemap::FileType::regular) ? S_IFREG Loading @@ -475,6 +511,34 @@ readdir_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, pos += 1; } if(ud->fifo) { int i = 0; for(auto const& kv : local_fifos) { if(i < off) { i++; continue; } std::filesystem::path vpath = kv.first; const struct stat& st = kv.second; // check if FIFO belongs to this directory if(vpath.parent_path() != open_dir->path()) continue; std::string fname = vpath.filename(); size_t entry_size = fuse_add_direntry(req, buf + bytes_filled, size - bytes_filled, fname.c_str(), &st, pos + 1); if(entry_size > size - bytes_filled) break; bytes_filled += entry_size; pos += 1; } } open_dir->pos(pos); // update internal position if needed fuse_reply_buf(req, buf, bytes_filled); Loading Loading @@ -572,6 +636,8 @@ fsync_handler(fuse_req_t req, fuse_ino_t ino, int datasync, static void access_handler(fuse_req_t req, fuse_ino_t ino, int mask) { fuse_log(FUSE_LOG_DEBUG, "access handler \n"); auto* ud = udata(req); if(ud->access && !ud->fifo) { auto* inode = get_inode(ino); if(!inode) { fuse_reply_err(req, ENOENT); Loading @@ -583,6 +649,11 @@ access_handler(fuse_req_t req, fuse_ino_t ino, int mask) { return; } fuse_reply_err(req, 0); } else { // deactivates following access requests and it is always treated as // success fuse_reply_err(req, ENOSYS); } } static void Loading Loading @@ -795,6 +866,52 @@ rename_handler(fuse_req_t req, fuse_ino_t old_parent, const char* old_name, #endif } void mknod_handler(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, dev_t rdev) { auto* ud = udata(req); if(!ud->fifo) { fuse_reply_err(req, ENOTSUP); return; } auto* parent_inode = get_inode(parent); if(!parent_inode) { fuse_reply_err(req, ENOENT); return; } mkdir(fifo_path.c_str(), 0700); std::string path = fifo_path + "/" + name; if(!S_ISFIFO(mode)) { fuse_reply_err(req, EINVAL); return; } if(mkfifo(path.c_str(), mode) == -1) { fuse_reply_err(req, errno); return; } struct stat st{}; if(stat(path.c_str(), &st) == -1) { fuse_reply_err(req, errno); return; } // save synthetic entry std::string vpath = get_path(parent_inode, name); // path in mount namespace local_fifos[vpath] = st; fuse_entry_param e{}; e.ino = st.st_ino; e.attr = st; e.attr_timeout = ud->timeout; e.entry_timeout = ud->timeout; fuse_reply_entry(req, &e); } static void init_gekkofs() { // TODO how to handle mount point Loading Loading @@ -834,7 +951,7 @@ init_ll_ops(fuse_lowlevel_ops* ops) { ops->forget = forget_handler; // ops->forget_multi ops->readlink = readlink_handler; // ops->mknod ops->mknod = mknod_handler; ops->symlink = symlink_handler; ops->rename = rename_handler; // ops->link Loading Loading
include/client/fuse/fuse_client.hpp +4 −1 Original line number Diff line number Diff line Loading @@ -76,7 +76,9 @@ struct __dirstream { #include <sys/xattr.h> #include <fcntl.h> #include <string.h> #include <sys/types.h> #include <sys/stat.h> #include <filesystem> #include <unistd.h> #include <unordered_map> #include <string> Loading Loading @@ -117,7 +119,8 @@ struct u_data { int writeback; int direct_io; int max_readahead; int flock; int fifo; int access; int xattr; char* mountpoint; double timeout; Loading
src/client/fuse/fuse_client.cpp +134 −17 Original line number Diff line number Diff line Loading @@ -43,7 +43,9 @@ static struct fuse_lowlevel_ops ll_ops; static std::mutex ino_mutex; static std::unordered_map<fuse_ino_t, Inode> ino_map; static std::unordered_map<std::string, fuse_ino_t> path_map; static std::unordered_map<std::string, struct stat> local_fifos; static fuse_ino_t next_ino = 2; // reserve 1 for root static const std::string fifo_path = "/tmp/gekkofs_fifos/"; static fuse_ino_t alloc_inode(const std::string& path) { Loading Loading @@ -84,8 +86,10 @@ static const struct fuse_opt lo_opts[] = { {"direct_io", offsetof(struct u_data, direct_io), 1}, {"no_direct_io", offsetof(struct u_data, direct_io), 0}, {"max_readahead=%ui", offsetof(struct u_data, max_readahead), 0}, {"flock", offsetof(struct u_data, flock), 1}, {"no_flock", offsetof(struct u_data, flock), 0}, {"fifo", offsetof(struct u_data, fifo), 1}, {"no_fifo", offsetof(struct u_data, fifo), 0}, {"access", offsetof(struct u_data, access), 1}, {"no_access", offsetof(struct u_data, access), 0}, {"xattr", offsetof(struct u_data, xattr), 1}, {"no_xattr", offsetof(struct u_data, xattr), 0}, {"timeout=%lf", offsetof(struct u_data, timeout), 0}, Loading @@ -103,8 +107,10 @@ passthrough_ll_help(void) { " -o direct_io Enables direct io\n" " -o no_direct_io Disable direct io\n" " -o max_readahead=1 Amount of allowed readaheads\n" " -o flock Enable flock\n" " -o no_flock Disable flock\n" " -o fifo Enable fifo, disables GekkoFS access check\n" " -o no_fifo Disable fifo\n" " -o access Enable GekkoFS access check if fifo is deactivated\n" " -o no_access Disable access handler\n" " -o xattr Enable xattr\n" " -o no_xattr Disable xattr\n" " -o timeout=1.0 Caching timeout\n" Loading @@ -117,7 +123,8 @@ passthrough_ll_help(void) { static void init_handler(void* userdata, struct fuse_conn_info* conn) { struct u_data* ud = (struct u_data*) userdata; fuse_log(FUSE_LOG_DEBUG, "init handler readahead %i direct_io %i \n", ud->max_readahead, ud->direct_io); fuse_log(FUSE_LOG_DEBUG, "init handler readahead %i direct_io %i \n", ud->max_readahead, ud->direct_io); // bool has_flag; // TODO check other capabilities e.g. FUSE_CAP_READDIRPLUS Loading Loading @@ -156,6 +163,21 @@ lookup_handler(fuse_req_t req, fuse_ino_t parent, const char* name) { std::string child = get_path(parent_inode, name); fuse_log(FUSE_LOG_DEBUG, "lookup %s\n", child.c_str()); if(ud->fifo) { auto iit = local_fifos.find(child); if(iit != local_fifos.end()) { const struct stat& st = iit->second; fuse_entry_param e{}; e.ino = st.st_ino; e.attr = st; e.attr_timeout = ud->timeout; e.entry_timeout = ud->timeout; fuse_reply_entry(req, &e); return; } } // See if we already have this path auto it = path_map.find(child); Loading Loading @@ -366,12 +388,25 @@ tmpfile_handler(fuse_req_t req, fuse_ino_t parent, mode_t mode, static void unlink_handler(fuse_req_t req, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "unlink handler \n"); auto* ud = udata(req); auto* parent_inode = get_inode(parent); if(!parent_inode) { fuse_reply_err(req, ENOENT); return; } std::string path = get_path(parent_inode, name); if(ud->fifo) { auto it = local_fifos.find(path); if(it != local_fifos.end()) { std::string real = fifo_path + std::string(name); unlink(real.c_str()); local_fifos.erase(it); fuse_reply_err(req, 0); return; } } int rc = gkfs::syscall::gkfs_remove(path); if(rc == -1) { fuse_reply_err(req, 1); Loading Loading @@ -429,6 +464,7 @@ static void readdir_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "readdir handler \n"); auto* ud = udata(req); auto* dir_ptr = reinterpret_cast<GkfsDir*>(fi->fh); if(!dir_ptr) { fuse_reply_err(req, EBADF); Loading Loading @@ -458,7 +494,7 @@ readdir_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, auto de = open_dir->getdent(pos); struct stat st{}; // TODO cannot be right, right? // TODO cannot be right, right? no stat? st.st_ino = std::hash<std::string>()(open_dir->path() + "/" + de.name()); st.st_mode = (de.type() == gkfs::filemap::FileType::regular) ? S_IFREG Loading @@ -475,6 +511,34 @@ readdir_handler(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, pos += 1; } if(ud->fifo) { int i = 0; for(auto const& kv : local_fifos) { if(i < off) { i++; continue; } std::filesystem::path vpath = kv.first; const struct stat& st = kv.second; // check if FIFO belongs to this directory if(vpath.parent_path() != open_dir->path()) continue; std::string fname = vpath.filename(); size_t entry_size = fuse_add_direntry(req, buf + bytes_filled, size - bytes_filled, fname.c_str(), &st, pos + 1); if(entry_size > size - bytes_filled) break; bytes_filled += entry_size; pos += 1; } } open_dir->pos(pos); // update internal position if needed fuse_reply_buf(req, buf, bytes_filled); Loading Loading @@ -572,6 +636,8 @@ fsync_handler(fuse_req_t req, fuse_ino_t ino, int datasync, static void access_handler(fuse_req_t req, fuse_ino_t ino, int mask) { fuse_log(FUSE_LOG_DEBUG, "access handler \n"); auto* ud = udata(req); if(ud->access && !ud->fifo) { auto* inode = get_inode(ino); if(!inode) { fuse_reply_err(req, ENOENT); Loading @@ -583,6 +649,11 @@ access_handler(fuse_req_t req, fuse_ino_t ino, int mask) { return; } fuse_reply_err(req, 0); } else { // deactivates following access requests and it is always treated as // success fuse_reply_err(req, ENOSYS); } } static void Loading Loading @@ -795,6 +866,52 @@ rename_handler(fuse_req_t req, fuse_ino_t old_parent, const char* old_name, #endif } void mknod_handler(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, dev_t rdev) { auto* ud = udata(req); if(!ud->fifo) { fuse_reply_err(req, ENOTSUP); return; } auto* parent_inode = get_inode(parent); if(!parent_inode) { fuse_reply_err(req, ENOENT); return; } mkdir(fifo_path.c_str(), 0700); std::string path = fifo_path + "/" + name; if(!S_ISFIFO(mode)) { fuse_reply_err(req, EINVAL); return; } if(mkfifo(path.c_str(), mode) == -1) { fuse_reply_err(req, errno); return; } struct stat st{}; if(stat(path.c_str(), &st) == -1) { fuse_reply_err(req, errno); return; } // save synthetic entry std::string vpath = get_path(parent_inode, name); // path in mount namespace local_fifos[vpath] = st; fuse_entry_param e{}; e.ino = st.st_ino; e.attr = st; e.attr_timeout = ud->timeout; e.entry_timeout = ud->timeout; fuse_reply_entry(req, &e); } static void init_gekkofs() { // TODO how to handle mount point Loading Loading @@ -834,7 +951,7 @@ init_ll_ops(fuse_lowlevel_ops* ops) { ops->forget = forget_handler; // ops->forget_multi ops->readlink = readlink_handler; // ops->mknod ops->mknod = mknod_handler; ops->symlink = symlink_handler; ops->rename = rename_handler; // ops->link Loading