Browse Source

Remove "channels" and embed into session

pull/1502/merge
Antonio SJ Musumeci 3 weeks ago
committed by trapexit
parent
commit
15bcc47d6a
  1. 10
      libfuse/include/fuse.h
  2. 15
      libfuse/include/fuse_common.h
  3. 72
      libfuse/include/fuse_lowlevel.h
  4. 14
      libfuse/include/fuse_msgbuf.hpp
  5. 4
      libfuse/include/fuse_pollhandle.h
  6. 4
      libfuse/include/fuse_req.hpp
  7. 15
      libfuse/lib/fuse.cpp
  8. 27
      libfuse/lib/fuse_i.h
  9. 102
      libfuse/lib/fuse_lowlevel.cpp
  10. 47
      libfuse/lib/fuse_msgbuf.cpp
  11. 104
      libfuse/lib/fuse_session.c
  12. 50
      libfuse/lib/helper.c

10
libfuse/include/fuse.h

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

15
libfuse/include/fuse_common.h

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

72
libfuse/include/fuse_lowlevel.h

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

14
libfuse/include/fuse_msgbuf.hpp

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

4
libfuse/include/fuse_pollhandle.h

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

4
libfuse/include/fuse_req.hpp

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

15
libfuse/lib/fuse.cpp

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

27
libfuse/lib/fuse_i.h

@ -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
libfuse/lib/fuse_lowlevel.cpp

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

47
libfuse/lib/fuse_msgbuf.cpp

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

104
libfuse/lib/fuse_session.c

@ -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)
{
return ch->bufsize;
}
struct fuse_session *fuse_chan_session(struct fuse_chan *ch)
void
fuse_session_setfd(struct fuse_session *se,
int fd)
{
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;
}

50
libfuse/lib/helper.c

@ -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…
Cancel
Save