Loading include/client/fuse/fuse_client.hpp +41 −25 Original line number Diff line number Diff line /* Copyright 2018-2025, Barcelona Supercomputing Center (BSC), Spain Copyright 2015-2025, Johannes Gutenberg Universitaet Mainz, Germany This software was partially supported by the EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu). This software was partially supported by the ADA-FS project under the SPPEXA project funded by the DFG. This software was partially supported by the the European Union’s Horizon 2020 JTI-EuroHPC research and innovation programme, by the project ADMIRE (Project ID: 956748, admire-eurohpc.eu) This project was partially promoted by the Ministry for Digital Transformation and the Civil Service, within the framework of the Recovery, Transformation and Resilience Plan - Funded by the European Union -NextGenerationEU. This file is part of GekkoFS' POSIX interface. GekkoFS' POSIX interface is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GekkoFS' POSIX interface is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with GekkoFS' POSIX interface. If not, see <https://www.gnu.org/licenses/>. SPDX-License-Identifier: LGPL-3.0-or-later */ #ifndef GKFS_CLIENT_FUSE_CONTEXT_HPP #define GKFS_CLIENT_FUSE_CONTEXT_HPP Loading Loading @@ -37,31 +76,6 @@ struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct { }; #endif /* * FUSE: Filesystem in Userspace * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE */ #include <errno.h> #include <fcntl.h> #include <string.h> Loading @@ -73,6 +87,8 @@ struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct { #include <sys/un.h> #endif #include <client/user_functions.hpp> static inline int do_fallocate(int fd, int mode, off_t offset, off_t length) { #ifdef HAVE_FALLOCATE Loading src/client/fuse/fuse_client.cpp +111 −1 Original line number Diff line number Diff line /* Copyright 2018-2025, Barcelona Supercomputing Center (BSC), Spain Copyright 2015-2025, Johannes Gutenberg Universitaet Mainz, Germany This software was partially supported by the EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu). This software was partially supported by the ADA-FS project under the SPPEXA project funded by the DFG. This software was partially supported by the the European Union’s Horizon 2020 JTI-EuroHPC research and innovation programme, by the project ADMIRE (Project ID: 956748, admire-eurohpc.eu) This project was partially promoted by the Ministry for Digital Transformation and the Civil Service, within the framework of the Recovery, Transformation and Resilience Plan - Funded by the European Union -NextGenerationEU. This file is part of GekkoFS' POSIX interface. GekkoFS' POSIX interface is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GekkoFS' POSIX interface is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with GekkoFS' POSIX interface. If not, see <https://www.gnu.org/licenses/>. SPDX-License-Identifier: LGPL-3.0-or-later */ #include "client/env.hpp" #include "common/env_util.hpp" #include <client/fuse/fuse_client.hpp> #include <cstdlib> #include <iostream> struct lo_inode { struct lo_inode* next; /* protected by lo->mutex */ Loading Loading @@ -85,6 +128,7 @@ lo_debug(fuse_req_t req) { static void lo_init(void* userdata, struct fuse_conn_info* conn) { // TODO init gkfs struct lo_data* lo = (struct lo_data*) userdata; bool has_flag; Loading @@ -103,8 +147,11 @@ lo_init(void* userdata, struct fuse_conn_info* conn) { conn->no_interrupt = 1; } // cleanup of the fs // delete all inodes static void lo_destroy(void* userdata) { fuse_log(FUSE_LOG_DEBUG, "lo_destroy\n"); struct lo_data* lo = (struct lo_data*) userdata; while(lo->root.next != &lo->root) { Loading @@ -115,8 +162,11 @@ lo_destroy(void* userdata) { } } // This is similar to stat(). The st_dev and st_blksize fields are ignored. The // st_ino field is ignored unless the use_ino mount option is given. static void lo_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_getattr\n"); int res; struct stat buf; struct lo_data* lo = lo_data(req); Loading @@ -134,6 +184,7 @@ lo_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat* attr, int valid, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_setattr\n"); int saverr; char procname[64]; struct lo_inode* inode = lo_inode(req, ino); Loading Loading @@ -203,8 +254,10 @@ out_err: fuse_reply_err(req, saverr); } // traverse double linked list to find inode on device id and original ino static struct lo_inode* lo_find(struct lo_data* lo, struct stat* st) { fuse_log(FUSE_LOG_DEBUG, "lo_find\n"); struct lo_inode* p; struct lo_inode* ret = NULL; Loading @@ -224,6 +277,7 @@ lo_find(struct lo_data* lo, struct stat* st) { static struct lo_inode* create_new_inode(int fd, struct fuse_entry_param* e, struct lo_data* lo) { fuse_log(FUSE_LOG_DEBUG, "create new inode\n"); struct lo_inode* inode = NULL; struct lo_inode *prev, *next; Loading @@ -236,6 +290,8 @@ create_new_inode(int fd, struct fuse_entry_param* e, struct lo_data* lo) { inode->ino = e->attr.st_ino; inode->dev = e->attr.st_dev; // this places the new inode directly after root and before the otheres // doubled linked inode list... pthread_mutex_lock(&lo->mutex); prev = &lo->root; next = prev->next; Loading @@ -250,6 +306,7 @@ create_new_inode(int fd, struct fuse_entry_param* e, struct lo_data* lo) { static int fill_entry_param_new_inode(fuse_req_t req, fuse_ino_t parent, int fd, struct fuse_entry_param* e) { fuse_log(FUSE_LOG_DEBUG, "fill entry param new inode\n"); int res; struct lo_data* lo = lo_data(req); Loading @@ -261,6 +318,7 @@ fill_entry_param_new_inode(fuse_req_t req, fuse_ino_t parent, int fd, if(res == -1) return errno; // pointer trick, set ino to lo_inode address e->ino = (uintptr_t) create_new_inode(dup(fd), e, lo); if(lo_debug(req)) Loading @@ -273,13 +331,14 @@ fill_entry_param_new_inode(fuse_req_t req, fuse_ino_t parent, int fd, static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char* name, struct fuse_entry_param* e) { fuse_log(FUSE_LOG_DEBUG, "lo_do_lookup\n"); int newfd; int res; int saverr; struct lo_data* lo = lo_data(req); struct lo_inode* inode; memset(e, 0, sizeof(*e)); memset(e, 0, sizeof(*e)); // zero init bc e is our result thing from lo_lookup e->attr_timeout = lo->timeout; e->entry_timeout = lo->timeout; Loading @@ -300,6 +359,7 @@ lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char* name, if(!inode) goto out_err; } // pointer trick, set ino to lo_inode address e->ino = (uintptr_t) inode; if(lo_debug(req)) Loading @@ -318,6 +378,7 @@ out_err: static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_lookup\n"); struct fuse_entry_param e; int err; Loading @@ -335,6 +396,7 @@ lo_lookup(fuse_req_t req, fuse_ino_t parent, const char* name) { static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, dev_t rdev, const char* link) { fuse_log(FUSE_LOG_DEBUG, "lo_mknod_symlink\n"); int res; int saverr; struct lo_inode* dir = lo_inode(req, parent); Loading Loading @@ -364,22 +426,26 @@ out: static void lo_mknod(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, dev_t rdev) { fuse_log(FUSE_LOG_DEBUG, "lo_mknod\n"); lo_mknod_symlink(req, parent, name, mode, rdev, NULL); } static void lo_mkdir(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode) { fuse_log(FUSE_LOG_DEBUG, "lo_mkdir\n"); lo_mknod_symlink(req, parent, name, S_IFDIR | mode, 0, NULL); } static void lo_symlink(fuse_req_t req, const char* link, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_symlink\n"); lo_mknod_symlink(req, parent, name, S_IFLNK, 0, link); } static void lo_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_link\n"); int res; struct lo_data* lo = lo_data(req); struct lo_inode* inode = lo_inode(req, ino); Loading Loading @@ -420,6 +486,7 @@ out_err: static void lo_rmdir(fuse_req_t req, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_rmdir\n"); int res; res = unlinkat(lo_fd(req, parent), name, AT_REMOVEDIR); Loading @@ -430,6 +497,7 @@ lo_rmdir(fuse_req_t req, fuse_ino_t parent, const char* name) { static void lo_rename(fuse_req_t req, fuse_ino_t parent, const char* name, fuse_ino_t newparent, const char* newname, unsigned int flags) { fuse_log(FUSE_LOG_DEBUG, "lo_rename\n"); int res; if(flags) { Loading @@ -444,6 +512,7 @@ lo_rename(fuse_req_t req, fuse_ino_t parent, const char* name, static void lo_unlink(fuse_req_t req, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_unlink\n"); int res; res = unlinkat(lo_fd(req, parent), name, 0); Loading @@ -453,6 +522,7 @@ lo_unlink(fuse_req_t req, fuse_ino_t parent, const char* name) { static void unref_inode(struct lo_data* lo, struct lo_inode* inode, uint64_t n) { fuse_log(FUSE_LOG_DEBUG, "unref inode\n"); if(!inode) return; Loading @@ -478,6 +548,7 @@ unref_inode(struct lo_data* lo, struct lo_inode* inode, uint64_t n) { static void lo_forget_one(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup) { fuse_log(FUSE_LOG_DEBUG, "lo_forget_one\n"); struct lo_data* lo = lo_data(req); struct lo_inode* inode = lo_inode(req, ino); Loading @@ -492,6 +563,7 @@ lo_forget_one(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup) { static void lo_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup) { fuse_log(FUSE_LOG_DEBUG, "lo_forget\n"); lo_forget_one(req, ino, nlookup); fuse_reply_none(req); } Loading @@ -499,6 +571,7 @@ lo_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup) { static void lo_forget_multi(fuse_req_t req, size_t count, struct fuse_forget_data* forgets) { fuse_log(FUSE_LOG_DEBUG, "lo_forget_multi\n"); int i; for(i = 0; i < count; i++) Loading @@ -508,6 +581,7 @@ lo_forget_multi(fuse_req_t req, size_t count, static void lo_readlink(fuse_req_t req, fuse_ino_t ino) { fuse_log(FUSE_LOG_DEBUG, "lo_readlink\n"); char buf[PATH_MAX + 1]; int res; Loading @@ -531,11 +605,13 @@ struct lo_dirp { static struct lo_dirp* lo_dirp(struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_dirp\n"); return (struct lo_dirp*) (uintptr_t) fi->fh; } static void lo_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_opendir\n"); int error = ENOMEM; struct lo_data* lo = lo_data(req); struct lo_dirp* d; Loading Loading @@ -577,6 +653,7 @@ out_err: static int is_dot_or_dotdot(const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_dot_or_dotdot\n"); return name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')); } Loading @@ -584,6 +661,7 @@ is_dot_or_dotdot(const char* name) { static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info* fi, int plus) { fuse_log(FUSE_LOG_DEBUG, "lo_do_readdir\n"); struct lo_dirp* d = lo_dirp(fi); char* buf; char* p; Loading Loading @@ -674,17 +752,20 @@ error: static void lo_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_readdir\n"); lo_do_readdir(req, ino, size, offset, fi, 0); } static void lo_readdirplus(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_readdirplus\n"); lo_do_readdir(req, ino, size, offset, fi, 1); } static void lo_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_releasedir\n"); struct lo_dirp* d = lo_dirp(fi); (void) ino; closedir(d->dp); Loading @@ -695,6 +776,7 @@ lo_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { static void lo_tmpfile(fuse_req_t req, fuse_ino_t parent, mode_t mode, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_tmpfile\n"); int fd; struct lo_data* lo = lo_data(req); struct fuse_entry_param e; Loading Loading @@ -729,6 +811,7 @@ lo_tmpfile(fuse_req_t req, fuse_ino_t parent, mode_t mode, static void lo_create(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_create\n"); int fd; struct lo_data* lo = lo_data(req); struct fuse_entry_param e; Loading Loading @@ -764,6 +847,7 @@ lo_create(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, static void lo_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_fsyncdir\n"); int res; int fd = dirfd(lo_dirp(fi)->dp); (void) ino; Loading @@ -776,6 +860,7 @@ lo_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync, static void lo_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_open\n"); int fd; char buf[64]; struct lo_data* lo = lo_data(req); Loading Loading @@ -827,6 +912,7 @@ for writes to the same file in the kernel). */ static void lo_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_release\n"); (void) ino; close(fi->fh); Loading @@ -835,6 +921,7 @@ lo_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { static void lo_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_flush\n"); int res; (void) ino; res = close(dup(fi->fh)); Loading @@ -844,6 +931,7 @@ lo_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { static void lo_fsync(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_fsync\n"); int res; (void) ino; if(datasync) Loading @@ -856,6 +944,7 @@ lo_fsync(fuse_req_t req, fuse_ino_t ino, int datasync, static void lo_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_read\n"); struct fuse_bufvec buf = FUSE_BUFVEC_INIT(size); if(lo_debug(req)) Loading @@ -874,6 +963,7 @@ lo_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, static void lo_write_buf(fuse_req_t req, fuse_ino_t ino, struct fuse_bufvec* in_buf, off_t off, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_write_buf\n"); (void) ino; ssize_t res; struct fuse_bufvec out_buf = FUSE_BUFVEC_INIT(fuse_buf_size(in_buf)); Loading @@ -898,6 +988,7 @@ lo_write_buf(fuse_req_t req, fuse_ino_t ino, struct fuse_bufvec* in_buf, static void lo_statfs(fuse_req_t req, fuse_ino_t ino) { fuse_log(FUSE_LOG_DEBUG, "lo_statfs\n"); int res; struct statvfs stbuf; Loading @@ -911,6 +1002,7 @@ lo_statfs(fuse_req_t req, fuse_ino_t ino) { static void lo_fallocate(fuse_req_t req, fuse_ino_t ino, int mode, off_t offset, off_t length, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_fallocate\n"); int err; (void) ino; Loading @@ -921,6 +1013,7 @@ lo_fallocate(fuse_req_t req, fuse_ino_t ino, int mode, off_t offset, static void lo_flock(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi, int op) { fuse_log(FUSE_LOG_DEBUG, "lo_flock\n"); int res; (void) ino; Loading @@ -931,6 +1024,7 @@ lo_flock(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi, int op) { static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char* name, size_t size) { fuse_log(FUSE_LOG_DEBUG, "lo_getxattr\n"); char* value = NULL; char procname[64]; struct lo_inode* inode = lo_inode(req, ino); Loading Loading @@ -982,6 +1076,7 @@ out: static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) { fuse_log(FUSE_LOG_DEBUG, "lo_listxattr\n"); char* value = NULL; char procname[64]; struct lo_inode* inode = lo_inode(req, ino); Loading Loading @@ -1033,6 +1128,7 @@ out: static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char* name, const char* value, size_t size, int flags) { fuse_log(FUSE_LOG_DEBUG, "lo_setxattr\n"); char procname[64]; struct lo_inode* inode = lo_inode(req, ino); ssize_t ret; Loading @@ -1059,6 +1155,7 @@ out: static void lo_removexattr(fuse_req_t req, fuse_ino_t ino, const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_removexattr\n"); char procname[64]; struct lo_inode* inode = lo_inode(req, ino); ssize_t ret; Loading Loading @@ -1109,6 +1206,7 @@ lo_copy_file_range(fuse_req_t req, fuse_ino_t ino_in, off_t off_in, static void lo_lseek(fuse_req_t req, fuse_ino_t ino, off_t off, int whence, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_lseek\n"); off_t res; (void) ino; Loading Loading @@ -1212,6 +1310,18 @@ main(int argc, char* argv[]) { lo.root.fd = -1; lo.cache = CACHE_NORMAL; // init gekkofs // TODO how to handle mount point int res = gkfs_init(); if(res != 0) { printf("FUSE client failed to connect to gkfs daemon. Exit."); exit(1); } auto fl = gkfs::syscall::gkfs_get_file_list("/"); for(std::string s : fl) { std::cout << s << std::endl; } if(fuse_parse_cmdline(&args, &opts) != 0) return 1; if(opts.show_help) { Loading src/client/gkfs_functions.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -185,7 +185,7 @@ test_lock_file(const std::string& path) { * @param path * @param mode * @param flags * @return 0 on success, -1 on failure * @return fd on success, -1 on failure */ int gkfs_open(const std::string& path, mode_t mode, int flags) { Loading Loading @@ -1451,7 +1451,7 @@ gkfs_readv(int fd, const struct iovec* iov, int iovcnt) { * wrapper function for opening directories * errno may be set * @param path * @return 0 on success or -1 on error * @return fd on success or -1 on error */ int gkfs_opendir(const std::string& path) { Loading Loading
include/client/fuse/fuse_client.hpp +41 −25 Original line number Diff line number Diff line /* Copyright 2018-2025, Barcelona Supercomputing Center (BSC), Spain Copyright 2015-2025, Johannes Gutenberg Universitaet Mainz, Germany This software was partially supported by the EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu). This software was partially supported by the ADA-FS project under the SPPEXA project funded by the DFG. This software was partially supported by the the European Union’s Horizon 2020 JTI-EuroHPC research and innovation programme, by the project ADMIRE (Project ID: 956748, admire-eurohpc.eu) This project was partially promoted by the Ministry for Digital Transformation and the Civil Service, within the framework of the Recovery, Transformation and Resilience Plan - Funded by the European Union -NextGenerationEU. This file is part of GekkoFS' POSIX interface. GekkoFS' POSIX interface is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GekkoFS' POSIX interface is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with GekkoFS' POSIX interface. If not, see <https://www.gnu.org/licenses/>. SPDX-License-Identifier: LGPL-3.0-or-later */ #ifndef GKFS_CLIENT_FUSE_CONTEXT_HPP #define GKFS_CLIENT_FUSE_CONTEXT_HPP Loading Loading @@ -37,31 +76,6 @@ struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct { }; #endif /* * FUSE: Filesystem in Userspace * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE */ #include <errno.h> #include <fcntl.h> #include <string.h> Loading @@ -73,6 +87,8 @@ struct _uintptr_to_must_hold_fuse_ino_t_dummy_struct { #include <sys/un.h> #endif #include <client/user_functions.hpp> static inline int do_fallocate(int fd, int mode, off_t offset, off_t length) { #ifdef HAVE_FALLOCATE Loading
src/client/fuse/fuse_client.cpp +111 −1 Original line number Diff line number Diff line /* Copyright 2018-2025, Barcelona Supercomputing Center (BSC), Spain Copyright 2015-2025, Johannes Gutenberg Universitaet Mainz, Germany This software was partially supported by the EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu). This software was partially supported by the ADA-FS project under the SPPEXA project funded by the DFG. This software was partially supported by the the European Union’s Horizon 2020 JTI-EuroHPC research and innovation programme, by the project ADMIRE (Project ID: 956748, admire-eurohpc.eu) This project was partially promoted by the Ministry for Digital Transformation and the Civil Service, within the framework of the Recovery, Transformation and Resilience Plan - Funded by the European Union -NextGenerationEU. This file is part of GekkoFS' POSIX interface. GekkoFS' POSIX interface is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GekkoFS' POSIX interface is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with GekkoFS' POSIX interface. If not, see <https://www.gnu.org/licenses/>. SPDX-License-Identifier: LGPL-3.0-or-later */ #include "client/env.hpp" #include "common/env_util.hpp" #include <client/fuse/fuse_client.hpp> #include <cstdlib> #include <iostream> struct lo_inode { struct lo_inode* next; /* protected by lo->mutex */ Loading Loading @@ -85,6 +128,7 @@ lo_debug(fuse_req_t req) { static void lo_init(void* userdata, struct fuse_conn_info* conn) { // TODO init gkfs struct lo_data* lo = (struct lo_data*) userdata; bool has_flag; Loading @@ -103,8 +147,11 @@ lo_init(void* userdata, struct fuse_conn_info* conn) { conn->no_interrupt = 1; } // cleanup of the fs // delete all inodes static void lo_destroy(void* userdata) { fuse_log(FUSE_LOG_DEBUG, "lo_destroy\n"); struct lo_data* lo = (struct lo_data*) userdata; while(lo->root.next != &lo->root) { Loading @@ -115,8 +162,11 @@ lo_destroy(void* userdata) { } } // This is similar to stat(). The st_dev and st_blksize fields are ignored. The // st_ino field is ignored unless the use_ino mount option is given. static void lo_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_getattr\n"); int res; struct stat buf; struct lo_data* lo = lo_data(req); Loading @@ -134,6 +184,7 @@ lo_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { static void lo_setattr(fuse_req_t req, fuse_ino_t ino, struct stat* attr, int valid, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_setattr\n"); int saverr; char procname[64]; struct lo_inode* inode = lo_inode(req, ino); Loading Loading @@ -203,8 +254,10 @@ out_err: fuse_reply_err(req, saverr); } // traverse double linked list to find inode on device id and original ino static struct lo_inode* lo_find(struct lo_data* lo, struct stat* st) { fuse_log(FUSE_LOG_DEBUG, "lo_find\n"); struct lo_inode* p; struct lo_inode* ret = NULL; Loading @@ -224,6 +277,7 @@ lo_find(struct lo_data* lo, struct stat* st) { static struct lo_inode* create_new_inode(int fd, struct fuse_entry_param* e, struct lo_data* lo) { fuse_log(FUSE_LOG_DEBUG, "create new inode\n"); struct lo_inode* inode = NULL; struct lo_inode *prev, *next; Loading @@ -236,6 +290,8 @@ create_new_inode(int fd, struct fuse_entry_param* e, struct lo_data* lo) { inode->ino = e->attr.st_ino; inode->dev = e->attr.st_dev; // this places the new inode directly after root and before the otheres // doubled linked inode list... pthread_mutex_lock(&lo->mutex); prev = &lo->root; next = prev->next; Loading @@ -250,6 +306,7 @@ create_new_inode(int fd, struct fuse_entry_param* e, struct lo_data* lo) { static int fill_entry_param_new_inode(fuse_req_t req, fuse_ino_t parent, int fd, struct fuse_entry_param* e) { fuse_log(FUSE_LOG_DEBUG, "fill entry param new inode\n"); int res; struct lo_data* lo = lo_data(req); Loading @@ -261,6 +318,7 @@ fill_entry_param_new_inode(fuse_req_t req, fuse_ino_t parent, int fd, if(res == -1) return errno; // pointer trick, set ino to lo_inode address e->ino = (uintptr_t) create_new_inode(dup(fd), e, lo); if(lo_debug(req)) Loading @@ -273,13 +331,14 @@ fill_entry_param_new_inode(fuse_req_t req, fuse_ino_t parent, int fd, static int lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char* name, struct fuse_entry_param* e) { fuse_log(FUSE_LOG_DEBUG, "lo_do_lookup\n"); int newfd; int res; int saverr; struct lo_data* lo = lo_data(req); struct lo_inode* inode; memset(e, 0, sizeof(*e)); memset(e, 0, sizeof(*e)); // zero init bc e is our result thing from lo_lookup e->attr_timeout = lo->timeout; e->entry_timeout = lo->timeout; Loading @@ -300,6 +359,7 @@ lo_do_lookup(fuse_req_t req, fuse_ino_t parent, const char* name, if(!inode) goto out_err; } // pointer trick, set ino to lo_inode address e->ino = (uintptr_t) inode; if(lo_debug(req)) Loading @@ -318,6 +378,7 @@ out_err: static void lo_lookup(fuse_req_t req, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_lookup\n"); struct fuse_entry_param e; int err; Loading @@ -335,6 +396,7 @@ lo_lookup(fuse_req_t req, fuse_ino_t parent, const char* name) { static void lo_mknod_symlink(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, dev_t rdev, const char* link) { fuse_log(FUSE_LOG_DEBUG, "lo_mknod_symlink\n"); int res; int saverr; struct lo_inode* dir = lo_inode(req, parent); Loading Loading @@ -364,22 +426,26 @@ out: static void lo_mknod(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, dev_t rdev) { fuse_log(FUSE_LOG_DEBUG, "lo_mknod\n"); lo_mknod_symlink(req, parent, name, mode, rdev, NULL); } static void lo_mkdir(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode) { fuse_log(FUSE_LOG_DEBUG, "lo_mkdir\n"); lo_mknod_symlink(req, parent, name, S_IFDIR | mode, 0, NULL); } static void lo_symlink(fuse_req_t req, const char* link, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_symlink\n"); lo_mknod_symlink(req, parent, name, S_IFLNK, 0, link); } static void lo_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_link\n"); int res; struct lo_data* lo = lo_data(req); struct lo_inode* inode = lo_inode(req, ino); Loading Loading @@ -420,6 +486,7 @@ out_err: static void lo_rmdir(fuse_req_t req, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_rmdir\n"); int res; res = unlinkat(lo_fd(req, parent), name, AT_REMOVEDIR); Loading @@ -430,6 +497,7 @@ lo_rmdir(fuse_req_t req, fuse_ino_t parent, const char* name) { static void lo_rename(fuse_req_t req, fuse_ino_t parent, const char* name, fuse_ino_t newparent, const char* newname, unsigned int flags) { fuse_log(FUSE_LOG_DEBUG, "lo_rename\n"); int res; if(flags) { Loading @@ -444,6 +512,7 @@ lo_rename(fuse_req_t req, fuse_ino_t parent, const char* name, static void lo_unlink(fuse_req_t req, fuse_ino_t parent, const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_unlink\n"); int res; res = unlinkat(lo_fd(req, parent), name, 0); Loading @@ -453,6 +522,7 @@ lo_unlink(fuse_req_t req, fuse_ino_t parent, const char* name) { static void unref_inode(struct lo_data* lo, struct lo_inode* inode, uint64_t n) { fuse_log(FUSE_LOG_DEBUG, "unref inode\n"); if(!inode) return; Loading @@ -478,6 +548,7 @@ unref_inode(struct lo_data* lo, struct lo_inode* inode, uint64_t n) { static void lo_forget_one(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup) { fuse_log(FUSE_LOG_DEBUG, "lo_forget_one\n"); struct lo_data* lo = lo_data(req); struct lo_inode* inode = lo_inode(req, ino); Loading @@ -492,6 +563,7 @@ lo_forget_one(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup) { static void lo_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup) { fuse_log(FUSE_LOG_DEBUG, "lo_forget\n"); lo_forget_one(req, ino, nlookup); fuse_reply_none(req); } Loading @@ -499,6 +571,7 @@ lo_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup) { static void lo_forget_multi(fuse_req_t req, size_t count, struct fuse_forget_data* forgets) { fuse_log(FUSE_LOG_DEBUG, "lo_forget_multi\n"); int i; for(i = 0; i < count; i++) Loading @@ -508,6 +581,7 @@ lo_forget_multi(fuse_req_t req, size_t count, static void lo_readlink(fuse_req_t req, fuse_ino_t ino) { fuse_log(FUSE_LOG_DEBUG, "lo_readlink\n"); char buf[PATH_MAX + 1]; int res; Loading @@ -531,11 +605,13 @@ struct lo_dirp { static struct lo_dirp* lo_dirp(struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_dirp\n"); return (struct lo_dirp*) (uintptr_t) fi->fh; } static void lo_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_opendir\n"); int error = ENOMEM; struct lo_data* lo = lo_data(req); struct lo_dirp* d; Loading Loading @@ -577,6 +653,7 @@ out_err: static int is_dot_or_dotdot(const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_dot_or_dotdot\n"); return name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0')); } Loading @@ -584,6 +661,7 @@ is_dot_or_dotdot(const char* name) { static void lo_do_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info* fi, int plus) { fuse_log(FUSE_LOG_DEBUG, "lo_do_readdir\n"); struct lo_dirp* d = lo_dirp(fi); char* buf; char* p; Loading Loading @@ -674,17 +752,20 @@ error: static void lo_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_readdir\n"); lo_do_readdir(req, ino, size, offset, fi, 0); } static void lo_readdirplus(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_readdirplus\n"); lo_do_readdir(req, ino, size, offset, fi, 1); } static void lo_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_releasedir\n"); struct lo_dirp* d = lo_dirp(fi); (void) ino; closedir(d->dp); Loading @@ -695,6 +776,7 @@ lo_releasedir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { static void lo_tmpfile(fuse_req_t req, fuse_ino_t parent, mode_t mode, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_tmpfile\n"); int fd; struct lo_data* lo = lo_data(req); struct fuse_entry_param e; Loading Loading @@ -729,6 +811,7 @@ lo_tmpfile(fuse_req_t req, fuse_ino_t parent, mode_t mode, static void lo_create(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_create\n"); int fd; struct lo_data* lo = lo_data(req); struct fuse_entry_param e; Loading Loading @@ -764,6 +847,7 @@ lo_create(fuse_req_t req, fuse_ino_t parent, const char* name, mode_t mode, static void lo_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_fsyncdir\n"); int res; int fd = dirfd(lo_dirp(fi)->dp); (void) ino; Loading @@ -776,6 +860,7 @@ lo_fsyncdir(fuse_req_t req, fuse_ino_t ino, int datasync, static void lo_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_open\n"); int fd; char buf[64]; struct lo_data* lo = lo_data(req); Loading Loading @@ -827,6 +912,7 @@ for writes to the same file in the kernel). */ static void lo_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_release\n"); (void) ino; close(fi->fh); Loading @@ -835,6 +921,7 @@ lo_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { static void lo_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_flush\n"); int res; (void) ino; res = close(dup(fi->fh)); Loading @@ -844,6 +931,7 @@ lo_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi) { static void lo_fsync(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_fsync\n"); int res; (void) ino; if(datasync) Loading @@ -856,6 +944,7 @@ lo_fsync(fuse_req_t req, fuse_ino_t ino, int datasync, static void lo_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_read\n"); struct fuse_bufvec buf = FUSE_BUFVEC_INIT(size); if(lo_debug(req)) Loading @@ -874,6 +963,7 @@ lo_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t offset, static void lo_write_buf(fuse_req_t req, fuse_ino_t ino, struct fuse_bufvec* in_buf, off_t off, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_write_buf\n"); (void) ino; ssize_t res; struct fuse_bufvec out_buf = FUSE_BUFVEC_INIT(fuse_buf_size(in_buf)); Loading @@ -898,6 +988,7 @@ lo_write_buf(fuse_req_t req, fuse_ino_t ino, struct fuse_bufvec* in_buf, static void lo_statfs(fuse_req_t req, fuse_ino_t ino) { fuse_log(FUSE_LOG_DEBUG, "lo_statfs\n"); int res; struct statvfs stbuf; Loading @@ -911,6 +1002,7 @@ lo_statfs(fuse_req_t req, fuse_ino_t ino) { static void lo_fallocate(fuse_req_t req, fuse_ino_t ino, int mode, off_t offset, off_t length, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_fallocate\n"); int err; (void) ino; Loading @@ -921,6 +1013,7 @@ lo_fallocate(fuse_req_t req, fuse_ino_t ino, int mode, off_t offset, static void lo_flock(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi, int op) { fuse_log(FUSE_LOG_DEBUG, "lo_flock\n"); int res; (void) ino; Loading @@ -931,6 +1024,7 @@ lo_flock(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info* fi, int op) { static void lo_getxattr(fuse_req_t req, fuse_ino_t ino, const char* name, size_t size) { fuse_log(FUSE_LOG_DEBUG, "lo_getxattr\n"); char* value = NULL; char procname[64]; struct lo_inode* inode = lo_inode(req, ino); Loading Loading @@ -982,6 +1076,7 @@ out: static void lo_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size) { fuse_log(FUSE_LOG_DEBUG, "lo_listxattr\n"); char* value = NULL; char procname[64]; struct lo_inode* inode = lo_inode(req, ino); Loading Loading @@ -1033,6 +1128,7 @@ out: static void lo_setxattr(fuse_req_t req, fuse_ino_t ino, const char* name, const char* value, size_t size, int flags) { fuse_log(FUSE_LOG_DEBUG, "lo_setxattr\n"); char procname[64]; struct lo_inode* inode = lo_inode(req, ino); ssize_t ret; Loading @@ -1059,6 +1155,7 @@ out: static void lo_removexattr(fuse_req_t req, fuse_ino_t ino, const char* name) { fuse_log(FUSE_LOG_DEBUG, "lo_removexattr\n"); char procname[64]; struct lo_inode* inode = lo_inode(req, ino); ssize_t ret; Loading Loading @@ -1109,6 +1206,7 @@ lo_copy_file_range(fuse_req_t req, fuse_ino_t ino_in, off_t off_in, static void lo_lseek(fuse_req_t req, fuse_ino_t ino, off_t off, int whence, struct fuse_file_info* fi) { fuse_log(FUSE_LOG_DEBUG, "lo_lseek\n"); off_t res; (void) ino; Loading Loading @@ -1212,6 +1310,18 @@ main(int argc, char* argv[]) { lo.root.fd = -1; lo.cache = CACHE_NORMAL; // init gekkofs // TODO how to handle mount point int res = gkfs_init(); if(res != 0) { printf("FUSE client failed to connect to gkfs daemon. Exit."); exit(1); } auto fl = gkfs::syscall::gkfs_get_file_list("/"); for(std::string s : fl) { std::cout << s << std::endl; } if(fuse_parse_cmdline(&args, &opts) != 0) return 1; if(opts.show_help) { Loading
src/client/gkfs_functions.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -185,7 +185,7 @@ test_lock_file(const std::string& path) { * @param path * @param mode * @param flags * @return 0 on success, -1 on failure * @return fd on success, -1 on failure */ int gkfs_open(const std::string& path, mode_t mode, int flags) { Loading Loading @@ -1451,7 +1451,7 @@ gkfs_readv(int fd, const struct iovec* iov, int iovcnt) { * wrapper function for opening directories * errno may be set * @param path * @return 0 on success or -1 on error * @return fd on success or -1 on error */ int gkfs_opendir(const std::string& path) { Loading