diff --git a/libfuse/include/fuse.h b/libfuse/include/fuse.h index 59354680..567b0eec 100644 --- a/libfuse/include/fuse.h +++ b/libfuse/include/fuse.h @@ -482,10 +482,10 @@ struct fuse_operations * * Introduced in version 2.9 */ - int (*read_buf) (const fuse_file_info_t *ffi, - struct fuse_bufvec **bufp, - size_t size, - off_t off); + int (*read)(const fuse_file_info_t *ffi, + char *buf, + size_t size, + off_t off); /** * Perform BSD file locking operation * diff --git a/libfuse/include/fuse_lowlevel.h b/libfuse/include/fuse_lowlevel.h index b427638e..25670657 100644 --- a/libfuse/include/fuse_lowlevel.h +++ b/libfuse/include/fuse_lowlevel.h @@ -1137,19 +1137,9 @@ int fuse_reply_write(fuse_req_t req, size_t count); */ int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size); -/** - * Reply with data copied/moved from buffer(s) - * - * Possible requests: - * read, readdir, getxattr, listxattr - * - * @param req request handle - * @param bufv buffer vector - * @param flags flags controlling the copy - * @return zero for success, -errno for failure to send reply - */ -int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv, - enum fuse_buf_copy_flags flags); +int fuse_reply_data(fuse_req_t req, + char *buf, + size_t bufsize); /** * Reply with data vector diff --git a/libfuse/lib/fuse.c b/libfuse/lib/fuse.c index d3acce55..af8d149e 100644 --- a/libfuse/lib/fuse.c +++ b/libfuse/lib/fuse.c @@ -23,6 +23,7 @@ #include "fuse_misc.h" #include "fuse_opt.h" #include "fuse_pollhandle.h" +#include "fuse_msgbuf.hpp" #include #include @@ -1379,20 +1380,6 @@ req_fuse(fuse_req_t req) return (struct fuse*)fuse_req_userdata(req); } -static -void -fuse_free_buf(struct fuse_bufvec *buf) -{ - if(buf != NULL) - { - size_t i; - - for(i = 0; i < buf->count; i++) - free(buf->buf[i].mem); - free(buf); - } -} - static int node_open(const struct node *node_) @@ -1545,16 +1532,6 @@ req_fuse_prepare(fuse_req_t req) return c->ctx.fuse; } -static -inline -void -reply_err(fuse_req_t req, - int err) -{ - /* fuse_reply_err() uses non-negated errno values */ - fuse_reply_err(req,-err); -} - static void reply_entry(fuse_req_t req, @@ -1573,7 +1550,7 @@ reply_entry(fuse_req_t req, } else { - reply_err(req,err); + fuse_reply_err(req,err); } } @@ -1770,7 +1747,7 @@ fuse_lib_getattr(fuse_req_t req, } else { - reply_err(req,err); + fuse_reply_err(req,err); } } @@ -1893,7 +1870,7 @@ fuse_lib_setattr(fuse_req_t req, } else { - reply_err(req,err); + fuse_reply_err(req,err); } } @@ -1918,7 +1895,7 @@ fuse_lib_access(fuse_req_t req, free_path(f,hdr_->nodeid,path); } - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -1947,7 +1924,7 @@ fuse_lib_readlink(fuse_req_t req, } else { - reply_err(req,err); + fuse_reply_err(req,err); } } @@ -2068,7 +2045,7 @@ fuse_lib_unlink(fuse_req_t req, free_path_wrlock(f,hdr_->nodeid,wnode,path); } - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -2095,7 +2072,7 @@ fuse_lib_rmdir(fuse_req_t req, free_path_wrlock(f,hdr_->nodeid,wnode,path); } - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -2168,7 +2145,7 @@ fuse_lib_rename(fuse_req_t req, free_path2(f,hdr_->nodeid,arg->newdir,wnode1,wnode2,oldpath,newpath); } - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -2295,7 +2272,7 @@ fuse_lib_create(fuse_req_t req, } else { - reply_err(req,err); + fuse_reply_err(req,err); } free_path(f,hdr_->nodeid,path); @@ -2376,7 +2353,7 @@ fuse_lib_open(fuse_req_t req, } else { - reply_err(req,err); + fuse_reply_err(req,err); } free_path(f,hdr_->nodeid,path); @@ -2390,8 +2367,8 @@ fuse_lib_read(fuse_req_t req, int res; struct fuse *f; fuse_file_info_t ffi = {0}; - struct fuse_bufvec *buf = NULL; struct fuse_read_in *arg; + fuse_msgbuf_t *msgbuf; arg = fuse_hdr_arg(hdr_); ffi.fh = arg->fh; @@ -2403,14 +2380,16 @@ fuse_lib_read(fuse_req_t req, f = req_fuse_prepare(req); - res = f->fs->op.read_buf(&ffi,&buf,arg->size,arg->offset); + msgbuf = msgbuf_alloc(); + + res = f->fs->op.read(&ffi,msgbuf->mem,arg->size,arg->offset); if(res >= 0) - fuse_reply_data(req,buf,FUSE_BUF_SPLICE_MOVE); + fuse_reply_data(req,msgbuf->mem,res); else - reply_err(req,res); + fuse_reply_err(req,res); - fuse_free_buf(buf); + msgbuf_free(msgbuf); } static @@ -2446,7 +2425,7 @@ fuse_lib_write(fuse_req_t req, if(res >= 0) fuse_reply_write(req,res); else - reply_err(req,res); + fuse_reply_err(req,res); } static @@ -2467,7 +2446,7 @@ fuse_lib_fsync(fuse_req_t req, err = f->fs->op.fsync(&ffi, !!(arg->fsync_flags & 1)); - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -2502,7 +2481,7 @@ fuse_lib_opendir(fuse_req_t req, dh = (struct fuse_dh *)calloc(1,sizeof(struct fuse_dh)); if(dh == NULL) { - reply_err(req,-ENOMEM); + fuse_reply_err(req,ENOMEM); return; } @@ -2534,7 +2513,7 @@ fuse_lib_opendir(fuse_req_t req, } else { - reply_err(req,err); + fuse_reply_err(req,err); pthread_mutex_destroy(&dh->lock); free(dh); } @@ -2597,7 +2576,7 @@ fuse_lib_readdir(fuse_req_t req_, if(rv) { - reply_err(req_,rv); + fuse_reply_err(req_,rv); goto out; } @@ -2641,7 +2620,7 @@ fuse_lib_readdir_plus(fuse_req_t req_, if(rv) { - reply_err(req_,rv); + fuse_reply_err(req_,rv); goto out; } @@ -2681,7 +2660,7 @@ fuse_lib_releasedir(fuse_req_t req_, pthread_mutex_destroy(&dh->lock); fuse_dirents_free(&dh->d); free(dh); - reply_err(req_,0); + fuse_reply_err(req_,0); } static @@ -2705,7 +2684,7 @@ fuse_lib_fsyncdir(fuse_req_t req, err = f->fs->op.fsyncdir(&ffi, !!(arg->fsync_flags & FUSE_FSYNC_FDATASYNC)); - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -2732,7 +2711,7 @@ fuse_lib_statfs(fuse_req_t req, if(!err) fuse_reply_statfs(req,&buf); else - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -2764,7 +2743,7 @@ fuse_lib_setxattr(fuse_req_t req, free_path(f,hdr_->nodeid,path); } - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -2810,7 +2789,7 @@ fuse_lib_getxattr(fuse_req_t req, char *value = (char*)malloc(arg->size); if(value == NULL) { - reply_err(req,-ENOMEM); + fuse_reply_err(req,ENOMEM); return; } @@ -2818,7 +2797,7 @@ fuse_lib_getxattr(fuse_req_t req, if(res > 0) fuse_reply_buf(req,value,res); else - reply_err(req,res); + fuse_reply_err(req,res); free(value); } else @@ -2827,7 +2806,7 @@ fuse_lib_getxattr(fuse_req_t req, if(res >= 0) fuse_reply_xattr(req,res); else - reply_err(req,res); + fuse_reply_err(req,res); } } @@ -2870,7 +2849,7 @@ fuse_lib_listxattr(fuse_req_t req, char *list = (char*)malloc(arg->size); if(list == NULL) { - reply_err(req,-ENOMEM); + fuse_reply_err(req,ENOMEM); return; } @@ -2878,7 +2857,7 @@ fuse_lib_listxattr(fuse_req_t req, if(res > 0) fuse_reply_buf(req,list,res); else - reply_err(req,res); + fuse_reply_err(req,res); free(list); } else @@ -2887,7 +2866,7 @@ fuse_lib_listxattr(fuse_req_t req, if(res >= 0) fuse_reply_xattr(req,res); else - reply_err(req,res); + fuse_reply_err(req,res); } } @@ -2912,7 +2891,7 @@ fuse_lib_removexattr(fuse_req_t req, free_path(f,hdr_->nodeid,path); } - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -2942,7 +2921,7 @@ fuse_lib_copy_file_range(fuse_req_t req_, if(rv >= 0) fuse_reply_write(req_,rv); else - reply_err(req_,rv); + fuse_reply_err(req_,rv); } static @@ -3157,7 +3136,7 @@ fuse_lib_release(fuse_req_t req, fuse_do_release(f,hdr_->nodeid,&ffi); - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -3181,7 +3160,7 @@ fuse_lib_flush(fuse_req_t req, err = fuse_flush_common(f,req,hdr_->nodeid,&ffi); - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -3252,7 +3231,7 @@ fuse_lib_getlk(fuse_req_t req, if(!err) fuse_reply_lock(req,&flk); else - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -3276,7 +3255,7 @@ fuse_lib_setlk(fuse_req_t req, pthread_mutex_unlock(&f->lock); } - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -3291,7 +3270,7 @@ fuse_lib_flock(fuse_req_t req, err = f->fs->op.flock(fi,op); - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -3320,7 +3299,7 @@ fuse_lib_bmap(fuse_req_t req, if(!err) fuse_reply_bmap(req,block); else - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -3388,7 +3367,7 @@ fuse_lib_ioctl(fuse_req_t req, fuse_reply_ioctl(req,err,out_buf,out_size); goto out; err: - reply_err(req,err); + fuse_reply_err(req,err); out: free(out_buf); } @@ -3427,7 +3406,7 @@ fuse_lib_poll(fuse_req_t req, if(!err) fuse_reply_poll(req,revents); else - reply_err(req,err); + fuse_reply_err(req,err); } static @@ -3450,7 +3429,7 @@ fuse_lib_fallocate(fuse_req_t req, arg->offset, arg->length); - reply_err(req,err); + fuse_reply_err(req,err); } static diff --git a/libfuse/lib/fuse_lowlevel.c b/libfuse/lib/fuse_lowlevel.c index 2d0220ba..fa8a8535 100644 --- a/libfuse/lib/fuse_lowlevel.c +++ b/libfuse/lib/fuse_lowlevel.c @@ -146,6 +146,8 @@ fuse_send_msg(struct fuse_ll *f, return 0; } +#define MAX_ERRNO 4095 + int fuse_send_reply_iov_nofree(fuse_req_t req, int error, @@ -154,17 +156,20 @@ fuse_send_reply_iov_nofree(fuse_req_t req, { struct fuse_out_header out; - if(error <= -1000 || error > 0) + if(error > 0) + error = -error; + + if(error <= -MAX_ERRNO) { - fprintf(stderr, "fuse: bad error value: %i\n",error); + fprintf(stderr,"fuse: bad error value: %i\n",error); error = -ERANGE; } out.unique = req->unique; - out.error = error; + out.error = error; iov[0].iov_base = &out; - iov[0].iov_len = sizeof(struct fuse_out_header); + iov[0].iov_len = sizeof(struct fuse_out_header); return fuse_send_msg(req->f, req->ch, iov, count); } @@ -231,7 +236,7 @@ int fuse_reply_err(fuse_req_t req_, int err_) { - return send_reply(req_,-err_,NULL,0); + return send_reply(req_,err_,NULL,0); } void @@ -445,21 +450,23 @@ fuse_send_data_iov(struct fuse_ll *f, } int -fuse_reply_data(fuse_req_t req, - struct fuse_bufvec *bufv, - enum fuse_buf_copy_flags flags) +fuse_reply_data(fuse_req_t req, + char *buf_, + const size_t bufsize_) { + int res; struct iovec iov[2]; struct fuse_out_header out; - int res; iov[0].iov_base = &out; - iov[0].iov_len = sizeof(struct fuse_out_header); + iov[0].iov_len = sizeof(struct fuse_out_header); + iov[1].iov_base = buf_; + iov[1].iov_len = bufsize_; out.unique = req->unique; out.error = 0; - res = fuse_send_data_iov(req->f, req->ch, iov, 1, bufv, flags); + res = fuse_send_msg(req->f,req->ch,iov,2); if(res <= 0) { destroy_req(req); diff --git a/src/fs_pread.hpp b/src/fs_pread.hpp new file mode 100644 index 00000000..b3258688 --- /dev/null +++ b/src/fs_pread.hpp @@ -0,0 +1,38 @@ +/* + ISC License + + Copyright (c) 2023, Antonio SJ Musumeci + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#pragma once + +#include + +namespace fs +{ + static + int + pread(const int fd_, + void *buf_, + const size_t count_, + const off_t offset_) + { + int rv; + + rv = ::pread(fd_,buf_,count_,offset_); + + return ((rv == -1) ? -errno : rv); + } +} diff --git a/src/fuse_read.cpp b/src/fuse_read.cpp new file mode 100644 index 00000000..e3d29de5 --- /dev/null +++ b/src/fuse_read.cpp @@ -0,0 +1,70 @@ +/* + Copyright (c) 2016, Antonio SJ Musumeci + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include "errno.hpp" +#include "fileinfo.hpp" +#include "fs_pread.hpp" + +#include "fuse.h" + +#include +#include + +typedef struct fuse_bufvec fuse_bufvec; + + +namespace l +{ + static + int + read(const int fd_, + char *buf_, + const size_t size_, + const off_t offset_) + { + int rv; + + rv = fs::pread(fd_,buf_,size_,offset_); + + return rv; + } +} + +namespace FUSE +{ + int + read(const fuse_file_info_t *ffi_, + char *buf_, + size_t size_, + off_t offset_) + { + FileInfo *fi = reinterpret_cast(ffi_->fh); + + return l::read(fi->fd, + buf_, + size_, + offset_); + } + + int + read_null(const fuse_file_info_t *ffi_, + char *buf_, + size_t size_, + off_t offset_) + { + return size_; + } +} diff --git a/src/fuse_read_buf.hpp b/src/fuse_read.hpp similarity index 71% rename from src/fuse_read_buf.hpp rename to src/fuse_read.hpp index cbd07cb4..8e641f6d 100644 --- a/src/fuse_read_buf.hpp +++ b/src/fuse_read.hpp @@ -24,14 +24,14 @@ namespace FUSE { int - read_buf(const fuse_file_info_t *ffi, - struct fuse_bufvec **buf, - size_t size, - off_t offset); + read(const fuse_file_info_t *ffi, + char *buf, + size_t size, + off_t offset); int - read_buf_null(const fuse_file_info_t *ffi, - struct fuse_bufvec **buf, - size_t size, - off_t offset); + read_null(const fuse_file_info_t *ffi, + char *buf, + size_t size, + off_t offset); } diff --git a/src/fuse_read_buf.cpp b/src/fuse_read_buf.cpp deleted file mode 100644 index 08a781b8..00000000 --- a/src/fuse_read_buf.cpp +++ /dev/null @@ -1,98 +0,0 @@ -/* - Copyright (c) 2016, Antonio SJ Musumeci - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -*/ - -#include "errno.hpp" -#include "fileinfo.hpp" - -#include "fuse.h" - -#include -#include - -typedef struct fuse_bufvec fuse_bufvec; - - -namespace l -{ - static - int - read_buf(const int fd_, - fuse_bufvec **bufp_, - const size_t size_, - const off_t offset_) - { - fuse_bufvec *src; - - src = (fuse_bufvec*)malloc(sizeof(fuse_bufvec)); - if(src == NULL) - return -ENOMEM; - - *src = FUSE_BUFVEC_INIT(size_); - - src->buf->flags = (fuse_buf_flags)(FUSE_BUF_IS_FD|FUSE_BUF_FD_SEEK|FUSE_BUF_FD_RETRY); - src->buf->fd = fd_; - src->buf->pos = offset_; - - *bufp_ = src; - - return 0; - } -} - -namespace FUSE -{ - int - read_buf(const fuse_file_info_t *ffi_, - fuse_bufvec **bufp_, - size_t size_, - off_t offset_) - { - FileInfo *fi = reinterpret_cast(ffi_->fh); - - return l::read_buf(fi->fd, - bufp_, - size_, - offset_); - } - - int - read_buf_null(const fuse_file_info_t *ffi_, - fuse_bufvec **bufp_, - size_t size_, - off_t offset_) - { - void *mem; - struct fuse_bufvec *buf; - - buf = (struct fuse_bufvec*)malloc(sizeof(struct fuse_bufvec)); - if(buf == NULL) - return -ENOMEM; - - mem = (void*)calloc(1,size_); - if(mem == NULL) - { - free(buf); - return -ENOMEM; - } - - *buf = FUSE_BUFVEC_INIT(size_); - buf->buf[0].mem = mem; - - *bufp_ = buf; - - return 0; - } -} diff --git a/src/mergerfs.cpp b/src/mergerfs.cpp index b6fde30b..248f7c51 100644 --- a/src/mergerfs.cpp +++ b/src/mergerfs.cpp @@ -56,7 +56,7 @@ #include "fuse_opendir.hpp" #include "fuse_poll.hpp" #include "fuse_prepare_hide.hpp" -#include "fuse_read_buf.hpp" +#include "fuse_read.hpp" #include "fuse_readdir.hpp" #include "fuse_readdir_plus.hpp" #include "fuse_readlink.hpp" @@ -119,7 +119,7 @@ namespace l ops_.opendir = FUSE::opendir; ops_.poll = FUSE::poll;; ops_.prepare_hide = FUSE::prepare_hide; - ops_.read_buf = (nullrw_ ? FUSE::read_buf_null : FUSE::read_buf); + ops_.read = (nullrw_ ? FUSE::read_null : FUSE::read); ops_.readdir = FUSE::readdir; ops_.readdir_plus = FUSE::readdir_plus; ops_.readlink = FUSE::readlink;