Rework fuse read to use same buffers as messages

This commit is contained in:
Antonio SJ Musumeci 2023-02-26 15:16:18 -05:00
parent 4a647beec1
commit 373d331f39
9 changed files with 188 additions and 202 deletions

View File

@ -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
*

View File

@ -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

View File

@ -23,6 +23,7 @@
#include "fuse_misc.h"
#include "fuse_opt.h"
#include "fuse_pollhandle.h"
#include "fuse_msgbuf.hpp"
#include <assert.h>
#include <dlfcn.h>
@ -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

View File

@ -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);

38
src/fs_pread.hpp Normal file
View File

@ -0,0 +1,38 @@
/*
ISC License
Copyright (c) 2023, Antonio SJ Musumeci <trapexit@spawn.link>
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 <unistd.h>
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);
}
}

70
src/fuse_read.cpp Normal file
View File

@ -0,0 +1,70 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
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 <stdlib.h>
#include <string.h>
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<FileInfo*>(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_;
}
}

View File

@ -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);
}

View File

@ -1,98 +0,0 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
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 <stdlib.h>
#include <string.h>
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<FileInfo*>(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;
}
}

View File

@ -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;