mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-26 19:01:56 -04:00
Remove "channels" and embed into session
This commit is contained in:
parent
e55bb93890
commit
15bcc47d6a
12 changed files with 203 additions and 261 deletions
|
|
@ -273,14 +273,16 @@ struct fuse_operations
|
|||
* Create a new FUSE filesystem.
|
||||
*
|
||||
* @param ch the communication channel
|
||||
* @param fd the /dev/fuse file descriptor
|
||||
* @param bufsize the buffer size for FUSE communication
|
||||
* @param args argument vector
|
||||
* @param op the filesystem operations
|
||||
* @param op_size the size of the fuse_operations structure
|
||||
* @return the created FUSE handle
|
||||
*/
|
||||
struct fuse *fuse_new(struct fuse_chan *ch,
|
||||
struct fuse_args *args,
|
||||
const struct fuse_operations *op);
|
||||
struct fuse *fuse_new(int fd,
|
||||
size_t bufsize,
|
||||
struct fuse_args *args,
|
||||
const struct fuse_operations *op);
|
||||
|
||||
/**
|
||||
* Destroy the FUSE handle.
|
||||
|
|
|
|||
|
|
@ -135,25 +135,24 @@ struct fuse_pollhandle_t;
|
|||
typedef struct fuse_pollhandle_t fuse_pollhandle_t;
|
||||
|
||||
/**
|
||||
* Create a FUSE mountpoint
|
||||
* Mount a FUSE filesystem.
|
||||
*
|
||||
* Returns a control file descriptor suitable for passing to
|
||||
* fuse_new()
|
||||
* This function creates a FUSE mount and returns the /dev/fuse file descriptor.
|
||||
* The file descriptor is stored in the session for internal use.
|
||||
*
|
||||
* @param mountpoint the mount point path
|
||||
* @param args argument vector
|
||||
* @return the communication channel on success, NULL on failure
|
||||
* @return the /dev/fuse file descriptor on success, -1 on failure
|
||||
*/
|
||||
struct fuse_chan *fuse_mount(const char *mountpoint,
|
||||
struct fuse_args *args);
|
||||
int fuse_mount(const char *mountpoint, struct fuse_args *args);
|
||||
|
||||
/**
|
||||
* Umount a FUSE mountpoint
|
||||
*
|
||||
* @param mountpoint the mount point path
|
||||
* @param ch the communication channel
|
||||
* @param fd the /dev/fuse file descriptor (or -1 if already closed)
|
||||
*/
|
||||
void fuse_unmount(const char *mountpoint, struct fuse_chan *ch);
|
||||
void fuse_unmount(const char *mountpoint, int fd);
|
||||
|
||||
/**
|
||||
* Parse common options
|
||||
|
|
|
|||
|
|
@ -29,13 +29,7 @@ EXTERN_C_BEGIN
|
|||
*/
|
||||
struct fuse_session;
|
||||
|
||||
/**
|
||||
* Channel
|
||||
*
|
||||
* A communication channel, providing hooks for sending and receiving
|
||||
* messages
|
||||
*/
|
||||
struct fuse_chan;
|
||||
|
||||
|
||||
/** Directory entry parameters supplied to fuse_reply_entry() */
|
||||
struct fuse_entry_param
|
||||
|
|
@ -425,14 +419,14 @@ int fuse_lowlevel_notify_poll(fuse_pollhandle_t *ph);
|
|||
/**
|
||||
* Notify to invalidate cache for an inode
|
||||
*
|
||||
* @param ch the channel through which to send the invalidation
|
||||
* @param se the session through which to send the invalidation
|
||||
* @param ino the inode number
|
||||
* @param off the offset in the inode where to start invalidating
|
||||
* or negative to invalidate attributes only
|
||||
* @param len the amount of cache to invalidate or 0 for all
|
||||
* @return zero for success, -errno for failure
|
||||
*/
|
||||
int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, uint64_t ino,
|
||||
int fuse_lowlevel_notify_inval_inode(struct fuse_session *se, uint64_t ino,
|
||||
off_t off, off_t len);
|
||||
|
||||
/**
|
||||
|
|
@ -443,13 +437,13 @@ int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, uint64_t ino,
|
|||
* don't call it with a lock held that can also be held by a filesystem
|
||||
* operation.
|
||||
*
|
||||
* @param ch the channel through which to send the invalidation
|
||||
* @param se the session through which to send the invalidation
|
||||
* @param parent inode number
|
||||
* @param name file name
|
||||
* @param namelen strlen() of file name
|
||||
* @return zero for success, -errno for failure
|
||||
*/
|
||||
int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, uint64_t parent,
|
||||
int fuse_lowlevel_notify_inval_entry(struct fuse_session *se, uint64_t parent,
|
||||
const char *name, size_t namelen);
|
||||
|
||||
/**
|
||||
|
|
@ -461,14 +455,14 @@ int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, uint64_t parent,
|
|||
* don't call it with a lock held that can also be held by a filesystem
|
||||
* operation.
|
||||
*
|
||||
* @param ch the channel through which to send the notification
|
||||
* @param se the session through which to send the notification
|
||||
* @param parent inode number
|
||||
* @param child inode number
|
||||
* @param name file name
|
||||
* @param namelen strlen() of file name
|
||||
* @return zero for success, -errno for failure
|
||||
*/
|
||||
int fuse_lowlevel_notify_delete(struct fuse_chan *ch,
|
||||
int fuse_lowlevel_notify_delete(struct fuse_session *se,
|
||||
uint64_t parent, uint64_t child,
|
||||
const char *name, size_t namelen);
|
||||
|
||||
|
|
@ -490,14 +484,14 @@ int fuse_lowlevel_notify_delete(struct fuse_chan *ch,
|
|||
* buffer. For dirty pages the write() method will be called
|
||||
* regardless of having been retrieved previously.
|
||||
*
|
||||
* @param ch the channel through which to send the invalidation
|
||||
* @param se the session through which to send the invalidation
|
||||
* @param ino the inode number
|
||||
* @param size the number of bytes to retrieve
|
||||
* @param offset the starting offset into the file to retrieve from
|
||||
* @param cookie user data to supply to the reply callback
|
||||
* @return zero for success, -errno for failure
|
||||
*/
|
||||
int fuse_lowlevel_notify_retrieve(struct fuse_chan *ch, uint64_t ino,
|
||||
int fuse_lowlevel_notify_retrieve(struct fuse_session *se, uint64_t ino,
|
||||
size_t size, off_t offset, void *cookie);
|
||||
|
||||
|
||||
|
|
@ -554,8 +548,6 @@ struct fuse_session *fuse_session_new(void *data,
|
|||
void *receive_buf,
|
||||
void *process_buf,
|
||||
void *destroy);
|
||||
void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch);
|
||||
void fuse_session_remove_chan(struct fuse_chan *ch);
|
||||
void fuse_session_destroy(struct fuse_session *se);
|
||||
void fuse_session_exit(struct fuse_session *se);
|
||||
int fuse_session_exited(struct fuse_session *se);
|
||||
|
|
@ -573,44 +565,12 @@ int fuse_session_loop_mt(struct fuse_session *se,
|
|||
const int process_thread_queue_depth,
|
||||
const char *pin_threads_type);
|
||||
|
||||
/* ----------------------------------------------------------- *
|
||||
* Channel interface *
|
||||
* ----------------------------------------------------------- */
|
||||
|
||||
struct fuse_chan *fuse_chan_new(int fd, size_t bufsize);
|
||||
|
||||
/**
|
||||
* Query the file descriptor of the channel
|
||||
*
|
||||
* @param ch the channel
|
||||
* @return the file descriptor passed to fuse_chan_new()
|
||||
*/
|
||||
int fuse_chan_fd(struct fuse_chan *ch);
|
||||
|
||||
/**
|
||||
* Query the minimal receive buffer size
|
||||
*
|
||||
* @param ch the channel
|
||||
* @return the buffer size passed to fuse_chan_new()
|
||||
*/
|
||||
size_t fuse_chan_bufsize(struct fuse_chan *ch);
|
||||
|
||||
/**
|
||||
* Query the user data
|
||||
*
|
||||
* @param ch the channel
|
||||
* @return the user data passed to fuse_chan_new()
|
||||
*/
|
||||
void *fuse_chan_data(struct fuse_chan *ch);
|
||||
|
||||
/**
|
||||
* Query the session to which this channel is assigned
|
||||
*
|
||||
* @param ch the channel
|
||||
* @return the session, or NULL if the channel is not assigned
|
||||
*/
|
||||
struct fuse_session *fuse_chan_session(struct fuse_chan *ch);
|
||||
|
||||
void fuse_chan_destroy(struct fuse_chan *ch);
|
||||
/* Direct file descriptor and buffer size accessors
|
||||
* (channel fields inlined into session for single-mount simplicity) */
|
||||
int fuse_session_fd(struct fuse_session *se);
|
||||
size_t fuse_session_bufsize(struct fuse_session *se);
|
||||
int fuse_session_clearfd(struct fuse_session *se);
|
||||
void fuse_session_setfd(struct fuse_session *se, int fd);
|
||||
void fuse_session_setbufsize(struct fuse_session *se, size_t bufsize);
|
||||
|
||||
EXTERN_C_END
|
||||
|
|
|
|||
|
|
@ -21,16 +21,16 @@
|
|||
#include "base_types.h"
|
||||
#include "fuse_msgbuf_t.h"
|
||||
|
||||
u32 msgbuf_get_pagesize();
|
||||
void msgbuf_set_bufsize(const uint32_t size);
|
||||
uint64_t msgbuf_get_bufsize();
|
||||
u32 msgbuf_get_pagesize();
|
||||
void msgbuf_set_bufsize(const u64 size);
|
||||
u64 msgbuf_get_bufsize();
|
||||
|
||||
fuse_msgbuf_t *msgbuf_alloc();
|
||||
fuse_msgbuf_t *msgbuf_alloc_page_aligned();
|
||||
void msgbuf_free(fuse_msgbuf_t *msgbuf);
|
||||
|
||||
void msgbuf_gc();
|
||||
void msgbuf_gc_10percent();
|
||||
void msgbuf_gc();
|
||||
void msgbuf_gc_10percent();
|
||||
|
||||
uint64_t msgbuf_alloc_count();
|
||||
uint64_t msgbuf_avail_count();
|
||||
u64 msgbuf_alloc_count();
|
||||
u64 msgbuf_avail_count();
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
struct fuse_chan;
|
||||
struct fuse_session;
|
||||
|
||||
typedef struct fuse_pollhandle_t fuse_pollhandle_t;
|
||||
struct fuse_pollhandle_t
|
||||
{
|
||||
uint64_t kh;
|
||||
struct fuse_chan *ch;
|
||||
struct fuse_session *se;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,13 +3,13 @@
|
|||
#include "fuse_req_ctx.h"
|
||||
#include "fuse_conn_info.hpp"
|
||||
|
||||
struct fuse_chan;
|
||||
struct fuse_session;
|
||||
|
||||
typedef struct fuse_req_t fuse_req_t;
|
||||
struct fuse_req_t
|
||||
{
|
||||
fuse_req_ctx_t ctx;
|
||||
struct fuse_chan *ch;
|
||||
struct fuse_session *se;
|
||||
fuse_conn_info_t conn;
|
||||
unsigned int ioctl_64bit : 1;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3313,7 +3313,7 @@ fuse_lib_poll(fuse_req_t *req_,
|
|||
}
|
||||
|
||||
ph->kh = arg->kh;
|
||||
ph->ch = req_->ch;
|
||||
ph->se = req_->se;
|
||||
}
|
||||
|
||||
err = f.ops.poll(&req_->ctx,
|
||||
|
|
@ -3708,7 +3708,7 @@ fuse_invalidate_all_nodes()
|
|||
names.size());
|
||||
for(auto &name : names)
|
||||
{
|
||||
fuse_lowlevel_notify_inval_entry(f.se->ch,
|
||||
fuse_lowlevel_notify_inval_entry(f.se,
|
||||
FUSE_ROOT_ID,
|
||||
name.c_str(),
|
||||
name.size());
|
||||
|
|
@ -3756,7 +3756,8 @@ fuse_populate_maintenance_thread(struct fuse *f_)
|
|||
}
|
||||
|
||||
struct fuse*
|
||||
fuse_new(struct fuse_chan *ch,
|
||||
fuse_new(int fd_,
|
||||
size_t bufsize_,
|
||||
struct fuse_args *args,
|
||||
const struct fuse_operations *ops_)
|
||||
{
|
||||
|
|
@ -3779,7 +3780,9 @@ fuse_new(struct fuse_chan *ch,
|
|||
if(f.se == NULL)
|
||||
goto out_free_fs;
|
||||
|
||||
fuse_session_add_chan(f.se,ch);
|
||||
/* Inlined channel fields - direct assignment */
|
||||
f.se->fd = fd_;
|
||||
f.se->bufsize = bufsize_;
|
||||
|
||||
/* Trace topmost layer by default */
|
||||
srand(time(NULL));
|
||||
|
|
@ -3857,7 +3860,7 @@ fuse_passthrough_open(const int fd_)
|
|||
int dev_fuse_fd;
|
||||
struct fuse_backing_map bm = {};
|
||||
|
||||
dev_fuse_fd = fuse_chan_fd(f.se->ch);
|
||||
dev_fuse_fd = f.se->fd;
|
||||
bm.fd = fd_;
|
||||
|
||||
rv = ::ioctl(dev_fuse_fd,FUSE_DEV_IOC_BACKING_OPEN,&bm);
|
||||
|
|
@ -3870,7 +3873,7 @@ fuse_passthrough_close(const int backing_id_)
|
|||
{
|
||||
int dev_fuse_fd;
|
||||
|
||||
dev_fuse_fd = fuse_chan_fd(f.se->ch);
|
||||
dev_fuse_fd = f.se->fd;
|
||||
|
||||
return ::ioctl(dev_fuse_fd,FUSE_DEV_IOC_BACKING_CLOSE,&backing_id_);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,9 +14,13 @@
|
|||
|
||||
#include "extern_c.h"
|
||||
|
||||
struct fuse_chan;
|
||||
struct fuse_ll;
|
||||
|
||||
/* Simplified fuse_session - fields inlined from former fuse_chan
|
||||
* Since mergerfs only supports one mount, we collapse the hierarchy:
|
||||
* fuse_session -> fuse_chan -> fd
|
||||
* into a single structure with direct fields.
|
||||
*/
|
||||
struct fuse_session
|
||||
{
|
||||
int (*receive_buf)(struct fuse_session *se,
|
||||
|
|
@ -29,7 +33,10 @@ struct fuse_session
|
|||
|
||||
struct fuse_ll *f;
|
||||
volatile int exited;
|
||||
struct fuse_chan *ch;
|
||||
|
||||
/* Formerly in fuse_chan - inlined for single-mount simplicity */
|
||||
int fd; /* /dev/fuse file descriptor */
|
||||
size_t bufsize; /* Buffer size for I/O operations */
|
||||
};
|
||||
|
||||
struct fuse_notify_req
|
||||
|
|
@ -43,26 +50,22 @@ struct fuse_notify_req
|
|||
struct fuse_notify_req *prev;
|
||||
};
|
||||
|
||||
struct fuse_cmd
|
||||
{
|
||||
char *buf;
|
||||
size_t buflen;
|
||||
struct fuse_chan *ch;
|
||||
};
|
||||
|
||||
|
||||
EXTERN_C_BEGIN
|
||||
|
||||
struct fuse *fuse_new_common(struct fuse_chan *ch,
|
||||
struct fuse_args *args,
|
||||
struct fuse *fuse_new_common(int fd,
|
||||
size_t bufsize,
|
||||
struct fuse_args *args,
|
||||
const struct fuse_operations *op);
|
||||
|
||||
struct fuse_chan *fuse_kern_chan_new(int fd);
|
||||
|
||||
|
||||
struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
|
||||
const struct fuse_lowlevel_ops *op,
|
||||
size_t op_size, void *userdata);
|
||||
|
||||
int fuse_chan_clearfd(struct fuse_chan *ch);
|
||||
|
||||
|
||||
void fuse_kern_unmount(const char *mountpoint, int fd);
|
||||
int fuse_kern_mount(const char *mountpoint, struct fuse_args *args);
|
||||
|
|
|
|||
|
|
@ -102,16 +102,16 @@ iov_length(const struct iovec *iov,
|
|||
|
||||
static
|
||||
int
|
||||
fuse_send_msg(struct fuse_chan *ch,
|
||||
struct iovec *iov,
|
||||
int count)
|
||||
fuse_send_msg(struct fuse_session *se,
|
||||
struct iovec *iov,
|
||||
int count)
|
||||
{
|
||||
int rv;
|
||||
struct fuse_out_header *out = (fuse_out_header*)iov[0].iov_base;
|
||||
|
||||
out->len = iov_length(iov, count);
|
||||
|
||||
rv = writev(fuse_chan_fd(ch),iov,count);
|
||||
rv = writev(se->fd,iov,count);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
|
|
@ -143,7 +143,7 @@ fuse_send_reply_iov_nofree(fuse_req_t *req,
|
|||
iov[0].iov_base = &out;
|
||||
iov[0].iov_len = sizeof(struct fuse_out_header);
|
||||
|
||||
return fuse_send_msg(req->ch, iov, count);
|
||||
return fuse_send_msg(req->se, iov, count);
|
||||
}
|
||||
|
||||
static
|
||||
|
|
@ -424,7 +424,7 @@ fuse_reply_data(fuse_req_t *req,
|
|||
if(fuse_cfg.debug)
|
||||
fuse_debug_data_out(req->ctx.unique,bufsize_);
|
||||
|
||||
res = fuse_send_msg(req->ch,iov,2);
|
||||
res = fuse_send_msg(req->se,iov,2);
|
||||
if(res <= 0)
|
||||
{
|
||||
fuse_req_free(req);
|
||||
|
|
@ -1077,7 +1077,7 @@ do_init(fuse_req_t *req,
|
|||
|
||||
max_write = UINT_MAX;
|
||||
max_readahead = UINT_MAX;
|
||||
bufsize = fuse_chan_bufsize(req->ch);
|
||||
bufsize = req->se->bufsize;
|
||||
|
||||
inargflags = 0;
|
||||
outargflags = 0;
|
||||
|
|
@ -1421,10 +1421,10 @@ do_lseek(fuse_req_t *req_,
|
|||
|
||||
static
|
||||
int
|
||||
send_notify_iov(struct fuse_chan *ch,
|
||||
int notify_code,
|
||||
struct iovec *iov,
|
||||
int count)
|
||||
send_notify_iov(struct fuse_session *se,
|
||||
int notify_code,
|
||||
struct iovec *iov,
|
||||
int count)
|
||||
{
|
||||
struct fuse_out_header out;
|
||||
|
||||
|
|
@ -1436,7 +1436,7 @@ send_notify_iov(struct fuse_chan *ch,
|
|||
iov[0].iov_base = &out;
|
||||
iov[0].iov_len = sizeof(struct fuse_out_header);
|
||||
|
||||
return fuse_send_msg(ch, iov, count);
|
||||
return fuse_send_msg(se, iov, count);
|
||||
}
|
||||
|
||||
int
|
||||
|
|
@ -1452,7 +1452,7 @@ fuse_lowlevel_notify_poll(fuse_pollhandle_t *ph)
|
|||
iov[1].iov_base = &outarg;
|
||||
iov[1].iov_len = sizeof(outarg);
|
||||
|
||||
return send_notify_iov(ph->ch, FUSE_NOTIFY_POLL, iov, 2);
|
||||
return send_notify_iov(ph->se, FUSE_NOTIFY_POLL, iov, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1461,15 +1461,15 @@ fuse_lowlevel_notify_poll(fuse_pollhandle_t *ph)
|
|||
}
|
||||
|
||||
int
|
||||
fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch,
|
||||
uint64_t ino,
|
||||
off_t off,
|
||||
off_t len)
|
||||
fuse_lowlevel_notify_inval_inode(struct fuse_session *se,
|
||||
uint64_t ino,
|
||||
off_t off,
|
||||
off_t len)
|
||||
{
|
||||
struct fuse_notify_inval_inode_out outarg;
|
||||
struct iovec iov[2];
|
||||
|
||||
if(!ch)
|
||||
if(!se)
|
||||
return -EINVAL;
|
||||
|
||||
outarg.ino = ino;
|
||||
|
|
@ -1479,19 +1479,19 @@ fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch,
|
|||
iov[1].iov_base = &outarg;
|
||||
iov[1].iov_len = sizeof(outarg);
|
||||
|
||||
return send_notify_iov(ch, FUSE_NOTIFY_INVAL_INODE, iov, 2);
|
||||
return send_notify_iov(se, FUSE_NOTIFY_INVAL_INODE, iov, 2);
|
||||
}
|
||||
|
||||
int
|
||||
fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch,
|
||||
uint64_t parent,
|
||||
const char *name,
|
||||
size_t namelen)
|
||||
fuse_lowlevel_notify_inval_entry(struct fuse_session *se,
|
||||
uint64_t parent,
|
||||
const char *name,
|
||||
size_t namelen)
|
||||
{
|
||||
struct fuse_notify_inval_entry_out outarg;
|
||||
struct iovec iov[3];
|
||||
|
||||
if(!ch)
|
||||
if(!se)
|
||||
return -EINVAL;
|
||||
|
||||
outarg.parent = parent;
|
||||
|
|
@ -1504,20 +1504,20 @@ fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch,
|
|||
iov[2].iov_base = (void *)name;
|
||||
iov[2].iov_len = namelen + 1;
|
||||
|
||||
return send_notify_iov(ch, FUSE_NOTIFY_INVAL_ENTRY, iov, 3);
|
||||
return send_notify_iov(se, FUSE_NOTIFY_INVAL_ENTRY, iov, 3);
|
||||
}
|
||||
|
||||
int
|
||||
fuse_lowlevel_notify_delete(struct fuse_chan *ch,
|
||||
uint64_t parent,
|
||||
uint64_t child,
|
||||
const char *name,
|
||||
size_t namelen)
|
||||
fuse_lowlevel_notify_delete(struct fuse_session *se,
|
||||
uint64_t parent,
|
||||
uint64_t child,
|
||||
const char *name,
|
||||
size_t namelen)
|
||||
{
|
||||
struct fuse_notify_delete_out outarg;
|
||||
struct iovec iov[3];
|
||||
|
||||
if(!ch)
|
||||
if(!se)
|
||||
return -EINVAL;
|
||||
|
||||
if(f.conn.proto_minor < 18)
|
||||
|
|
@ -1533,7 +1533,7 @@ fuse_lowlevel_notify_delete(struct fuse_chan *ch,
|
|||
iov[2].iov_base = (void *)name;
|
||||
iov[2].iov_len = namelen + 1;
|
||||
|
||||
return send_notify_iov(ch, FUSE_NOTIFY_DELETE, iov, 3);
|
||||
return send_notify_iov(se, FUSE_NOTIFY_DELETE, iov, 3);
|
||||
}
|
||||
|
||||
struct fuse_retrieve_req
|
||||
|
|
@ -1558,18 +1558,18 @@ fuse_ll_retrieve_reply(struct fuse_notify_req *nreq,
|
|||
}
|
||||
|
||||
int
|
||||
fuse_lowlevel_notify_retrieve(struct fuse_chan *ch,
|
||||
uint64_t ino,
|
||||
size_t size,
|
||||
off_t offset,
|
||||
void *cookie)
|
||||
fuse_lowlevel_notify_retrieve(struct fuse_session *se,
|
||||
uint64_t ino,
|
||||
size_t size,
|
||||
off_t offset,
|
||||
void *cookie)
|
||||
{
|
||||
struct fuse_notify_retrieve_out outarg;
|
||||
struct iovec iov[2];
|
||||
struct fuse_retrieve_req *rreq;
|
||||
int err;
|
||||
|
||||
if(!ch)
|
||||
if(!se)
|
||||
return -EINVAL;
|
||||
|
||||
if(f.conn.proto_minor < 15)
|
||||
|
|
@ -1594,7 +1594,7 @@ fuse_lowlevel_notify_retrieve(struct fuse_chan *ch,
|
|||
iov[1].iov_base = &outarg;
|
||||
iov[1].iov_len = sizeof(outarg);
|
||||
|
||||
err = send_notify_iov(ch, FUSE_NOTIFY_RETRIEVE, iov, 2);
|
||||
err = send_notify_iov(se, FUSE_NOTIFY_RETRIEVE, iov, 2);
|
||||
if(err)
|
||||
{
|
||||
mutex_lock(&f.lock);
|
||||
|
|
@ -1685,9 +1685,9 @@ fuse_ll_destroy(void *data)
|
|||
|
||||
static
|
||||
void
|
||||
fuse_send_errno(struct fuse_chan *ch_,
|
||||
const int errno_,
|
||||
const uint64_t unique_id_)
|
||||
fuse_send_errno(struct fuse_session *se_,
|
||||
const int errno_,
|
||||
const uint64_t unique_id_)
|
||||
{
|
||||
struct fuse_out_header out = {};
|
||||
struct iovec iov = {};
|
||||
|
|
@ -1701,15 +1701,15 @@ fuse_send_errno(struct fuse_chan *ch_,
|
|||
if(fuse_cfg.debug)
|
||||
fuse_debug_out_header(&out);
|
||||
|
||||
fuse_send_msg(ch_,&iov,1);
|
||||
fuse_send_msg(se_,&iov,1);
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
fuse_send_enomem(struct fuse_chan *ch_,
|
||||
const uint64_t unique_id_)
|
||||
fuse_send_enomem(struct fuse_session *se_,
|
||||
const uint64_t unique_id_)
|
||||
{
|
||||
fuse_send_errno(ch_,ENOMEM,unique_id_);
|
||||
fuse_send_errno(se_,ENOMEM,unique_id_);
|
||||
}
|
||||
|
||||
// static
|
||||
|
|
@ -1728,7 +1728,7 @@ fuse_ll_buf_receive_read(struct fuse_session *se_,
|
|||
{
|
||||
int rv;
|
||||
|
||||
rv = read(fuse_chan_fd(se_->ch),msgbuf_->mem,msgbuf_->size);
|
||||
rv = read(se_->fd,msgbuf_->mem,msgbuf_->size);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
|
|
@ -1757,7 +1757,7 @@ fuse_ll_buf_process_read(struct fuse_session *se_,
|
|||
|
||||
req = fuse_req_alloc();
|
||||
if(req == NULL)
|
||||
return fuse_send_enomem(se_->ch,in->unique);
|
||||
return fuse_send_enomem(se_,in->unique);
|
||||
|
||||
req->ctx.len = in->len;
|
||||
req->ctx.opcode = in->opcode;
|
||||
|
|
@ -1768,7 +1768,7 @@ fuse_ll_buf_process_read(struct fuse_session *se_,
|
|||
req->ctx.pid = in->pid;
|
||||
req->ctx.umask = 0;
|
||||
req->conn = f.conn;
|
||||
req->ch = se_->ch;
|
||||
req->se = se_;
|
||||
|
||||
err = ENOSYS;
|
||||
if(in->opcode >= FUSE_MAXOPS)
|
||||
|
|
@ -1801,7 +1801,7 @@ fuse_ll_buf_process_read_init(struct fuse_session *se_,
|
|||
|
||||
req = fuse_req_alloc();
|
||||
if(req == NULL)
|
||||
return fuse_send_enomem(se_->ch,in->unique);
|
||||
return fuse_send_enomem(se_,in->unique);
|
||||
|
||||
req->ctx.len = in->len;
|
||||
req->ctx.opcode = in->opcode;
|
||||
|
|
@ -1811,7 +1811,7 @@ fuse_ll_buf_process_read_init(struct fuse_session *se_,
|
|||
req->ctx.gid = in->gid;
|
||||
req->ctx.pid = in->pid;
|
||||
req->ctx.umask = 0;
|
||||
req->ch = se_->ch;
|
||||
req->se = se_;
|
||||
|
||||
err = EIO;
|
||||
if(in->opcode != FUSE_INIT)
|
||||
|
|
|
|||
|
|
@ -22,22 +22,22 @@
|
|||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <atomic>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
|
||||
static std::uint32_t g_PAGESIZE = 0;
|
||||
static std::uint32_t g_BUFSIZE = 0;
|
||||
static u32 g_PAGESIZE = 0;
|
||||
static u64 g_BUFSIZE = 0;
|
||||
|
||||
static std::atomic<std::uint_fast64_t> g_MSGBUF_ALLOC_COUNT;
|
||||
static std::atomic<std::uint_fast64_t> g_MSGBUF_ALLOC_COUNT = 0;
|
||||
|
||||
static std::mutex g_MUTEX;
|
||||
static std::vector<fuse_msgbuf_t*> g_MSGBUF_STACK;
|
||||
|
||||
uint64_t
|
||||
u64
|
||||
msgbuf_get_bufsize()
|
||||
{
|
||||
return g_BUFSIZE;
|
||||
|
|
@ -54,7 +54,7 @@ msgbuf_get_pagesize()
|
|||
// aligned. +1 again for fuse header as the max_pages value is for the
|
||||
// body.
|
||||
void
|
||||
msgbuf_set_bufsize(const uint32_t size_in_pages_)
|
||||
msgbuf_set_bufsize(const u64 size_in_pages_)
|
||||
{
|
||||
g_BUFSIZE = ((size_in_pages_ + 2) * g_PAGESIZE);
|
||||
}
|
||||
|
|
@ -84,7 +84,14 @@ __attribute__((constructor))
|
|||
void
|
||||
_msgbuf_constructor()
|
||||
{
|
||||
g_PAGESIZE = sysconf(_SC_PAGESIZE);
|
||||
long pagesize = sysconf(_SC_PAGESIZE);
|
||||
|
||||
assert(pagesize > 0);
|
||||
g_PAGESIZE = pagesize;
|
||||
|
||||
// Ensure fuse headers fit within a single page for O_DIRECT alignment
|
||||
assert((sizeof(struct fuse_in_header) + sizeof(struct fuse_write_in))
|
||||
< g_PAGESIZE);
|
||||
|
||||
msgbuf_set_bufsize(FUSE_DEFAULT_MAX_MAX_PAGES);
|
||||
}
|
||||
|
|
@ -94,17 +101,17 @@ __attribute__((destructor))
|
|||
void
|
||||
_msgbuf_destructor()
|
||||
{
|
||||
|
||||
msgbuf_gc();
|
||||
}
|
||||
|
||||
static
|
||||
void*
|
||||
_page_aligned_malloc(const uint64_t size_)
|
||||
_page_aligned_malloc(const u64 size_in_bytes_)
|
||||
{
|
||||
int rv;
|
||||
void *buf = NULL;
|
||||
|
||||
rv = posix_memalign(&buf,g_PAGESIZE,size_);
|
||||
rv = posix_memalign(&buf,g_PAGESIZE,size_in_bytes_);
|
||||
if(rv != 0)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -167,26 +174,30 @@ msgbuf_destroy(fuse_msgbuf_t *msgbuf_)
|
|||
void
|
||||
msgbuf_free(fuse_msgbuf_t *msgbuf_)
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(g_MUTEX);
|
||||
bool destroy;
|
||||
|
||||
if(msgbuf_->size != (g_BUFSIZE - g_PAGESIZE))
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(g_MUTEX);
|
||||
|
||||
destroy = (msgbuf_->size != (g_BUFSIZE - g_PAGESIZE));
|
||||
if(!destroy)
|
||||
g_MSGBUF_STACK.emplace_back(msgbuf_);
|
||||
}
|
||||
|
||||
if(destroy)
|
||||
{
|
||||
msgbuf_destroy(msgbuf_);
|
||||
g_MSGBUF_ALLOC_COUNT.fetch_sub(1,std::memory_order_relaxed);
|
||||
return;
|
||||
}
|
||||
|
||||
g_MSGBUF_STACK.emplace_back(msgbuf_);
|
||||
|
||||
}
|
||||
|
||||
uint64_t
|
||||
u64
|
||||
msgbuf_alloc_count()
|
||||
{
|
||||
return g_MSGBUF_ALLOC_COUNT;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
u64
|
||||
msgbuf_avail_count()
|
||||
{
|
||||
std::lock_guard<std::mutex> lck(g_MUTEX);
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
This program can be distributed under the terms of the GNU LGPLv2.
|
||||
See the file COPYING.LIB
|
||||
*/
|
||||
*/
|
||||
|
||||
#include "fuse_i.h"
|
||||
#include "fuse_kernel.h"
|
||||
|
|
@ -17,15 +17,14 @@
|
|||
#include <unistd.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
/*
|
||||
* Simplified session management for single-mount filesystems.
|
||||
* The fuse_chan structure has been removed and its fields inlined
|
||||
* into fuse_session (fd, bufsize) since mergerfs only supports
|
||||
* one mount point per process.
|
||||
*/
|
||||
|
||||
struct fuse_chan
|
||||
{
|
||||
struct fuse_session *se;
|
||||
int fd;
|
||||
size_t bufsize;
|
||||
};
|
||||
|
||||
struct fuse_session *
|
||||
struct fuse_session*
|
||||
fuse_session_new(void *data,
|
||||
void *receive_buf,
|
||||
void *process_buf,
|
||||
|
|
@ -42,38 +41,25 @@ fuse_session_new(void *data,
|
|||
se->receive_buf = receive_buf;
|
||||
se->process_buf = process_buf;
|
||||
se->destroy = destroy;
|
||||
se->fd = -1; /* Not yet mounted */
|
||||
se->bufsize = 0;
|
||||
|
||||
return se;
|
||||
}
|
||||
|
||||
void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch)
|
||||
{
|
||||
assert(se->ch == NULL);
|
||||
assert(ch->se == NULL);
|
||||
se->ch = ch;
|
||||
ch->se = se;
|
||||
}
|
||||
|
||||
void fuse_session_remove_chan(struct fuse_chan *ch)
|
||||
{
|
||||
struct fuse_session *se = ch->se;
|
||||
if (se) {
|
||||
assert(se->ch == ch);
|
||||
se->ch = NULL;
|
||||
ch->se = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
fuse_session_destroy(struct fuse_session *se)
|
||||
{
|
||||
se->destroy(se->f);
|
||||
if(se->ch != NULL)
|
||||
fuse_chan_destroy(se->ch);
|
||||
if(se->fd != -1) {
|
||||
close(se->fd);
|
||||
se->fd = -1;
|
||||
}
|
||||
free(se);
|
||||
}
|
||||
|
||||
void fuse_session_reset(struct fuse_session *se)
|
||||
void
|
||||
fuse_session_reset(struct fuse_session *se)
|
||||
{
|
||||
se->exited = 0;
|
||||
}
|
||||
|
|
@ -96,59 +82,37 @@ fuse_session_data(struct fuse_session *se)
|
|||
return se->f;
|
||||
}
|
||||
|
||||
struct fuse_chan *
|
||||
fuse_chan_new(int fd,
|
||||
size_t bufsize)
|
||||
/* Direct accessors for inlined channel fields */
|
||||
int
|
||||
fuse_session_fd(struct fuse_session *se)
|
||||
{
|
||||
struct fuse_chan *ch;
|
||||
|
||||
ch = (struct fuse_chan*)malloc(sizeof(*ch));
|
||||
if(ch == NULL)
|
||||
{
|
||||
fprintf(stderr, "fuse: failed to allocate channel\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(ch, 0, sizeof(*ch));
|
||||
|
||||
ch->fd = fd;
|
||||
ch->bufsize = bufsize;
|
||||
|
||||
return ch;
|
||||
return se->fd;
|
||||
}
|
||||
|
||||
int fuse_chan_fd(struct fuse_chan *ch)
|
||||
size_t
|
||||
fuse_session_bufsize(struct fuse_session *se)
|
||||
{
|
||||
return ch->fd;
|
||||
return se->bufsize;
|
||||
}
|
||||
|
||||
int fuse_chan_clearfd(struct fuse_chan *ch)
|
||||
int
|
||||
fuse_session_clearfd(struct fuse_session *se)
|
||||
{
|
||||
int fd = ch->fd;
|
||||
ch->fd = -1;
|
||||
int fd = se->fd;
|
||||
se->fd = -1;
|
||||
return fd;
|
||||
}
|
||||
|
||||
size_t fuse_chan_bufsize(struct fuse_chan *ch)
|
||||
void
|
||||
fuse_session_setfd(struct fuse_session *se,
|
||||
int fd)
|
||||
{
|
||||
return ch->bufsize;
|
||||
}
|
||||
|
||||
struct fuse_session *fuse_chan_session(struct fuse_chan *ch)
|
||||
{
|
||||
return ch->se;
|
||||
se->fd = fd;
|
||||
}
|
||||
|
||||
void
|
||||
fuse_chan_destroy(struct fuse_chan *ch)
|
||||
fuse_session_setbufsize(struct fuse_session *se,
|
||||
size_t bufsize)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fuse_session_remove_chan(ch);
|
||||
|
||||
fd = fuse_chan_fd(ch);
|
||||
if(fd != -1)
|
||||
close(fd);
|
||||
|
||||
free(ch);
|
||||
se->bufsize = bufsize;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -194,14 +194,14 @@ int fuse_daemonize(int foreground)
|
|||
}
|
||||
|
||||
static
|
||||
struct fuse_chan *
|
||||
int
|
||||
fuse_mount_common(const char *mountpoint_,
|
||||
struct fuse_args *args_)
|
||||
struct fuse_args *args_,
|
||||
size_t *bufsize_)
|
||||
{
|
||||
int fd;
|
||||
long bufsize;
|
||||
long pagesize;
|
||||
struct fuse_chan *ch;
|
||||
|
||||
/*
|
||||
* Make sure file descriptors 0, 1 and 2 are open, otherwise chaos
|
||||
|
|
@ -216,38 +216,34 @@ fuse_mount_common(const char *mountpoint_,
|
|||
|
||||
fd = fuse_kern_mount(mountpoint_,args_);
|
||||
if(fd == -1)
|
||||
return NULL;
|
||||
return -1;
|
||||
|
||||
pagesize = sysconf(_SC_PAGESIZE);
|
||||
bufsize = ((FUSE_DEFAULT_MAX_MAX_PAGES + 1) * pagesize);
|
||||
|
||||
ch = fuse_chan_new(fd,bufsize);
|
||||
if(!ch)
|
||||
fuse_kern_unmount(mountpoint_, fd);
|
||||
if (bufsize_)
|
||||
*bufsize_ = bufsize;
|
||||
|
||||
return ch;
|
||||
return fd;
|
||||
}
|
||||
|
||||
struct fuse_chan *
|
||||
int
|
||||
fuse_mount(const char *mountpoint_,
|
||||
struct fuse_args *args_)
|
||||
{
|
||||
return fuse_mount_common(mountpoint_,args_);
|
||||
return fuse_mount_common(mountpoint_,args_,NULL);
|
||||
}
|
||||
|
||||
static void fuse_unmount_common(const char *mountpoint, struct fuse_chan *ch)
|
||||
static void fuse_unmount_common(const char *mountpoint, int fd)
|
||||
{
|
||||
if (mountpoint) {
|
||||
int fd = ch ? fuse_chan_clearfd(ch) : -1;
|
||||
if (mountpoint && fd != -1) {
|
||||
fuse_kern_unmount(mountpoint, fd);
|
||||
if (ch)
|
||||
fuse_chan_destroy(ch);
|
||||
}
|
||||
}
|
||||
|
||||
void fuse_unmount(const char *mountpoint, struct fuse_chan *ch)
|
||||
void fuse_unmount(const char *mountpoint, int fd)
|
||||
{
|
||||
fuse_unmount_common(mountpoint, ch);
|
||||
fuse_unmount_common(mountpoint, fd);
|
||||
}
|
||||
|
||||
struct fuse*
|
||||
|
|
@ -258,7 +254,8 @@ fuse_setup_common(int argc,
|
|||
int *fd)
|
||||
{
|
||||
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
||||
struct fuse_chan *ch;
|
||||
int fuse_fd;
|
||||
size_t bufsize;
|
||||
struct fuse *fuse;
|
||||
int foreground;
|
||||
int res;
|
||||
|
|
@ -267,13 +264,13 @@ fuse_setup_common(int argc,
|
|||
if (res == -1)
|
||||
return NULL;
|
||||
|
||||
ch = fuse_mount_common(*mountpoint, &args);
|
||||
if (!ch) {
|
||||
fuse_fd = fuse_mount_common(*mountpoint, &args, &bufsize);
|
||||
if (fuse_fd == -1) {
|
||||
fuse_opt_free_args(&args);
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
fuse = fuse_new(ch, &args, op);
|
||||
fuse = fuse_new(fuse_fd, bufsize, &args, op);
|
||||
fuse_opt_free_args(&args);
|
||||
if (fuse == NULL)
|
||||
goto err_unmount;
|
||||
|
|
@ -287,12 +284,12 @@ fuse_setup_common(int argc,
|
|||
goto err_unmount;
|
||||
|
||||
if (fd)
|
||||
*fd = fuse_chan_fd(ch);
|
||||
*fd = fuse_fd;
|
||||
|
||||
return fuse;
|
||||
|
||||
err_unmount:
|
||||
fuse_unmount_common(*mountpoint, ch);
|
||||
fuse_unmount_common(*mountpoint, fuse_fd);
|
||||
err_free:
|
||||
free(*mountpoint);
|
||||
return NULL;
|
||||
|
|
@ -313,9 +310,12 @@ struct fuse *fuse_setup(int argc,
|
|||
static void fuse_teardown_common(char *mountpoint)
|
||||
{
|
||||
struct fuse_session *se = fuse_get_session();
|
||||
struct fuse_chan *ch = se->ch;
|
||||
int fd = se ? se->fd : -1;
|
||||
fuse_remove_signal_handlers(se);
|
||||
fuse_unmount_common(mountpoint, ch);
|
||||
if (mountpoint && fd != -1) {
|
||||
se->fd = -1;
|
||||
fuse_kern_unmount(mountpoint, fd);
|
||||
}
|
||||
free(mountpoint);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue