mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-26 19:01:56 -04:00
Simplify lowlevel fuse state management and req mem
This commit is contained in:
parent
5a2a9e4530
commit
e55bb93890
14 changed files with 376 additions and 307 deletions
|
|
@ -150,7 +150,7 @@ struct fuse_operations
|
|||
int (*fsyncdir)(const fuse_req_ctx_t *,
|
||||
const fuse_file_info_t *,
|
||||
int);
|
||||
void *(*init)(struct fuse_conn_info *conn);
|
||||
void *(*init)(fuse_conn_info_t *conn);
|
||||
void (*destroy)(void);
|
||||
int (*access)(const fuse_req_ctx_t *,
|
||||
const char *,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "extern_c.h"
|
||||
#include "fuse_conn_info.hpp"
|
||||
#include "fuse_opt.h"
|
||||
#include "fuse_timeouts.h"
|
||||
|
||||
|
|
@ -76,7 +77,7 @@ struct fuse_file_info_t
|
|||
};
|
||||
|
||||
/**
|
||||
* Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want'
|
||||
* Capability bits for 'fuse_conn_info_t.capable' and 'fuse_conn_info_t.want'
|
||||
*
|
||||
* FUSE_CAP_ASYNC_READ: filesystem supports asynchronous read requests
|
||||
* FUSE_CAP_POSIX_LOCKS: filesystem supports "remote" locking
|
||||
|
|
@ -128,21 +129,6 @@ struct fuse_file_info_t
|
|||
|
||||
#define FUSE_IOCTL_MAX_IOV 256
|
||||
|
||||
/**
|
||||
* Connection information, passed to the ->init() method
|
||||
*
|
||||
* Some of the elements are read-write, these can be changed to
|
||||
* indicate the value requested by the filesystem. The requested
|
||||
* value must usually be smaller than the indicated value.
|
||||
*/
|
||||
struct fuse_conn_info
|
||||
{
|
||||
unsigned proto_major;
|
||||
unsigned proto_minor;
|
||||
uint64_t capable;
|
||||
uint64_t want;
|
||||
};
|
||||
|
||||
struct fuse_session;
|
||||
struct fuse_chan;
|
||||
struct fuse_pollhandle_t;
|
||||
|
|
|
|||
12
libfuse/include/fuse_conn_info.hpp
Normal file
12
libfuse/include/fuse_conn_info.hpp
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include "base_types.h"
|
||||
|
||||
typedef struct fuse_conn_info_t fuse_conn_info_t;
|
||||
struct fuse_conn_info_t
|
||||
{
|
||||
u32 proto_major;
|
||||
u32 proto_minor;
|
||||
u64 capable;
|
||||
u64 want;
|
||||
};
|
||||
|
|
@ -3,7 +3,7 @@
|
|||
#include "extern_c.h"
|
||||
#include "fuse_common.h"
|
||||
#include "fuse_kernel.h"
|
||||
#include "fuse_req.h"
|
||||
#include "fuse_req.hpp"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -119,7 +119,7 @@ struct fuse_lowlevel_ops
|
|||
void (*getattr)(fuse_req_t *req, struct fuse_in_header *hdr);
|
||||
void (*getlk)(fuse_req_t *req, const struct fuse_in_header *hdr);
|
||||
void (*getxattr)(fuse_req_t *req, struct fuse_in_header *hdr);
|
||||
void (*init)(void *userdata, struct fuse_conn_info *conn);
|
||||
void (*init)(void *userdata, fuse_conn_info_t *conn);
|
||||
void (*ioctl)(fuse_req_t *req, const struct fuse_in_header *hdr);
|
||||
void (*link)(fuse_req_t *req, struct fuse_in_header *hdr);
|
||||
void (*listxattr)(fuse_req_t *req, struct fuse_in_header *hdr);
|
||||
|
|
|
|||
|
|
@ -3,12 +3,10 @@
|
|||
#include <stdint.h>
|
||||
|
||||
struct fuse_chan;
|
||||
struct fuse_ll;
|
||||
|
||||
typedef struct fuse_pollhandle_t fuse_pollhandle_t;
|
||||
struct fuse_pollhandle_t
|
||||
{
|
||||
uint64_t kh;
|
||||
struct fuse_chan *ch;
|
||||
struct fuse_ll *f;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,15 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include "fuse_req_ctx.h"
|
||||
#include "fuse_conn_info.hpp"
|
||||
|
||||
struct fuse_ll;
|
||||
struct fuse_chan;
|
||||
|
||||
typedef struct fuse_req_t fuse_req_t;
|
||||
struct fuse_req_t
|
||||
{
|
||||
fuse_req_ctx_t ctx;
|
||||
struct fuse_ll *f;
|
||||
struct fuse_chan *ch;
|
||||
fuse_conn_info_t conn;
|
||||
unsigned int ioctl_64bit : 1;
|
||||
};
|
||||
|
||||
fuse_req_t* fuse_req_alloc();
|
||||
void fuse_req_free(fuse_req_t*);
|
||||
136
libfuse/include/objpool.hpp
Normal file
136
libfuse/include/objpool.hpp
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
ISC License
|
||||
|
||||
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 <mutex>
|
||||
#include <new>
|
||||
#include <utility>
|
||||
#include <type_traits>
|
||||
|
||||
template<typename T>
|
||||
class ObjPool
|
||||
{
|
||||
private:
|
||||
struct alignas(alignof(T)) Node
|
||||
{
|
||||
Node *next;
|
||||
};
|
||||
|
||||
private:
|
||||
static_assert(sizeof(T) >= sizeof(Node), "T must be at least pointer-sized");
|
||||
static_assert(std::is_nothrow_destructible_v<T>, "T must be nothrow destructible");
|
||||
|
||||
private:
|
||||
static
|
||||
Node*
|
||||
to_node(T *obj_)
|
||||
{
|
||||
return reinterpret_cast<Node*>(obj_);
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex _mtx;
|
||||
Node *_head = nullptr;
|
||||
|
||||
public:
|
||||
ObjPool() = default;
|
||||
ObjPool(const ObjPool&) = delete;
|
||||
ObjPool& operator=(const ObjPool&) = delete;
|
||||
ObjPool(ObjPool&&) = delete;
|
||||
ObjPool& operator=(ObjPool&&) = delete;
|
||||
|
||||
~ObjPool()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
private:
|
||||
Node*
|
||||
_pop_node()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mtx);
|
||||
|
||||
Node *node = _head;
|
||||
if(node)
|
||||
_head = node->next;
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void
|
||||
_push_node(Node *node_)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mtx);
|
||||
|
||||
node_->next = _head;
|
||||
_head = node_;
|
||||
}
|
||||
|
||||
public:
|
||||
void
|
||||
clear() noexcept
|
||||
{
|
||||
Node *head;
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(_mtx);
|
||||
head = _head;
|
||||
_head = nullptr;
|
||||
}
|
||||
|
||||
while(head)
|
||||
{
|
||||
Node *next = head->next;
|
||||
::operator delete(head, std::align_val_t{alignof(T)});
|
||||
head = next;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
T*
|
||||
alloc(Args&&... args_)
|
||||
{
|
||||
void *mem;
|
||||
Node *node;
|
||||
|
||||
node = _pop_node();
|
||||
mem = (node ?
|
||||
static_cast<void*>(node) :
|
||||
::operator new(sizeof(T), std::align_val_t{alignof(T)}));
|
||||
|
||||
try
|
||||
{
|
||||
return new(mem) T(std::forward<Args>(args_)...);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
_push_node(static_cast<Node*>(mem));
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
free(T *obj_) noexcept
|
||||
{
|
||||
if(not obj_)
|
||||
return;
|
||||
|
||||
obj_->~T();
|
||||
|
||||
_push_node(to_node(obj_));
|
||||
}
|
||||
};
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
#include "node.hpp"
|
||||
|
||||
#include "fuse_cfg.hpp"
|
||||
#include "fuse_req.h"
|
||||
#include "fuse_req.hpp"
|
||||
#include "fuse_dirents.hpp"
|
||||
#include "fuse_i.h"
|
||||
#include "fuse_kernel.h"
|
||||
|
|
@ -1323,8 +1323,8 @@ reply_entry(fuse_req_t *req_,
|
|||
|
||||
static
|
||||
void
|
||||
fuse_lib_init(void *data,
|
||||
struct fuse_conn_info *conn)
|
||||
fuse_lib_init(void *data,
|
||||
fuse_conn_info_t *conn)
|
||||
{
|
||||
f.ops.init(conn);
|
||||
}
|
||||
|
|
@ -1747,7 +1747,7 @@ fuse_lib_mknod(fuse_req_t *req_,
|
|||
arg = (fuse_mknod_in*)fuse_hdr_arg(hdr_);
|
||||
name = (const char*)PARAM(arg);
|
||||
|
||||
if(req_->f->conn.proto_minor >= 12)
|
||||
if(req_->conn.proto_minor >= 12)
|
||||
req_->ctx.umask = arg->umask;
|
||||
else
|
||||
name = (char*)arg + FUSE_COMPAT_MKNOD_IN_SIZE;
|
||||
|
|
@ -1803,7 +1803,7 @@ fuse_lib_mkdir(fuse_req_t *req_,
|
|||
|
||||
arg = (fuse_mkdir_in*)fuse_hdr_arg(hdr_);
|
||||
name = (const char*)PARAM(arg);
|
||||
if(req_->f->conn.proto_minor >= 12)
|
||||
if(req_->conn.proto_minor >= 12)
|
||||
req_->ctx.umask = arg->umask;
|
||||
|
||||
err = get_path_name(hdr_->nodeid,name,&fusepath);
|
||||
|
|
@ -2040,7 +2040,7 @@ fuse_lib_create(fuse_req_t *req_,
|
|||
|
||||
ffi.flags = arg->flags;
|
||||
|
||||
if(req_->f->conn.proto_minor >= 12)
|
||||
if(req_->conn.proto_minor >= 12)
|
||||
req_->ctx.umask = arg->umask;
|
||||
else
|
||||
name = ((char*)arg + sizeof(struct fuse_open_in));
|
||||
|
|
@ -2194,7 +2194,7 @@ fuse_lib_read(fuse_req_t *req_,
|
|||
|
||||
arg = (fuse_read_in*)fuse_hdr_arg(hdr_);
|
||||
ffi.fh = arg->fh;
|
||||
if(req_->f->conn.proto_minor >= 9)
|
||||
if(req_->conn.proto_minor >= 9)
|
||||
{
|
||||
ffi.flags = arg->flags;
|
||||
ffi.lock_owner = arg->lock_owner;
|
||||
|
|
@ -2229,7 +2229,7 @@ fuse_lib_write(fuse_req_t *req_,
|
|||
arg = (fuse_write_in*)fuse_hdr_arg(hdr_);
|
||||
ffi.fh = arg->fh;
|
||||
ffi.writepage = !!(arg->write_flags & 1);
|
||||
if(req_->f->conn.proto_minor < 9)
|
||||
if(req_->conn.proto_minor < 9)
|
||||
{
|
||||
data = ((char*)arg) + FUSE_COMPAT_WRITE_IN_SIZE;
|
||||
}
|
||||
|
|
@ -2549,8 +2549,8 @@ fuse_lib_setxattr(fuse_req_t *req_,
|
|||
struct fuse_setxattr_in *arg;
|
||||
|
||||
arg = (fuse_setxattr_in*)fuse_hdr_arg(hdr_);
|
||||
if((req_->f->conn.capable & FUSE_SETXATTR_EXT) &&
|
||||
(req_->f->conn.want & FUSE_SETXATTR_EXT))
|
||||
if((req_->conn.capable & FUSE_SETXATTR_EXT) &&
|
||||
(req_->conn.want & FUSE_SETXATTR_EXT))
|
||||
name = (const char*)PARAM(arg);
|
||||
else
|
||||
name = (((char*)arg) + FUSE_COMPAT_SETXATTR_IN_SIZE);
|
||||
|
|
@ -2791,7 +2791,7 @@ fuse_lib_tmpfile(fuse_req_t *req_,
|
|||
|
||||
ffi.flags = arg->flags;
|
||||
|
||||
if(req_->f->conn.proto_minor >= 12)
|
||||
if(req_->conn.proto_minor >= 12)
|
||||
req_->ctx.umask = arg->umask;
|
||||
else
|
||||
name = (char*)arg + sizeof(struct fuse_open_in);
|
||||
|
|
@ -3035,7 +3035,7 @@ fuse_lib_release(fuse_req_t *req_,
|
|||
arg = (fuse_release_in*)fuse_hdr_arg(hdr_);
|
||||
ffi.fh = arg->fh;
|
||||
ffi.flags = arg->flags;
|
||||
if(req_->f->conn.proto_minor >= 8)
|
||||
if(req_->conn.proto_minor >= 8)
|
||||
{
|
||||
ffi.flush = !!(arg->release_flags & FUSE_RELEASE_FLUSH);
|
||||
ffi.lock_owner = arg->lock_owner;
|
||||
|
|
@ -3073,7 +3073,7 @@ fuse_lib_flush(fuse_req_t *req_,
|
|||
|
||||
ffi.fh = arg->fh;
|
||||
ffi.flush = 1;
|
||||
if(req_->f->conn.proto_minor >= 7)
|
||||
if(req_->conn.proto_minor >= 7)
|
||||
ffi.lock_owner = arg->lock_owner;
|
||||
|
||||
err = fuse_flush_common(req_,hdr_->nodeid,&ffi);
|
||||
|
|
@ -3233,14 +3233,14 @@ fuse_lib_ioctl(fuse_req_t *req_,
|
|||
const struct fuse_ioctl_in *arg;
|
||||
|
||||
arg = (fuse_ioctl_in*)fuse_hdr_arg(hdr_);
|
||||
if((arg->flags & FUSE_IOCTL_DIR) && !(req_->f->conn.want & FUSE_CAP_IOCTL_DIR))
|
||||
if((arg->flags & FUSE_IOCTL_DIR) && !(req_->conn.want & FUSE_CAP_IOCTL_DIR))
|
||||
{
|
||||
fuse_reply_err(req_,ENOTTY);
|
||||
return;
|
||||
}
|
||||
|
||||
if((sizeof(void*) == 4) &&
|
||||
(req_->f->conn.proto_minor >= 16) &&
|
||||
(req_->conn.proto_minor >= 16) &&
|
||||
!(arg->flags & FUSE_IOCTL_32BIT))
|
||||
{
|
||||
req_->ioctl_64bit = 1;
|
||||
|
|
@ -3314,7 +3314,6 @@ fuse_lib_poll(fuse_req_t *req_,
|
|||
|
||||
ph->kh = arg->kh;
|
||||
ph->ch = req_->ch;
|
||||
ph->f = req_->f;
|
||||
}
|
||||
|
||||
err = f.ops.poll(&req_->ctx,
|
||||
|
|
|
|||
|
|
@ -43,19 +43,6 @@ struct fuse_notify_req
|
|||
struct fuse_notify_req *prev;
|
||||
};
|
||||
|
||||
struct fuse_ll
|
||||
{
|
||||
struct fuse_lowlevel_ops op;
|
||||
void *userdata;
|
||||
uid_t owner;
|
||||
struct fuse_conn_info conn;
|
||||
pthread_mutex_t lock;
|
||||
int got_init;
|
||||
int got_destroy;
|
||||
uint64_t notify_ctr;
|
||||
struct fuse_notify_req notify_list;
|
||||
};
|
||||
|
||||
struct fuse_cmd
|
||||
{
|
||||
char *buf;
|
||||
|
|
@ -80,11 +67,6 @@ 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);
|
||||
|
||||
int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
|
||||
int count);
|
||||
void fuse_free_req(fuse_req_t req);
|
||||
|
||||
|
||||
struct fuse *fuse_setup_common(int argc,
|
||||
char *argv[],
|
||||
const struct fuse_operations *op,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@
|
|||
|
||||
#include "fuse_cfg.hpp"
|
||||
#include "fuse_msgbuf.hpp"
|
||||
#include "fuse_ll.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <memory>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
18
libfuse/lib/fuse_req.cpp
Normal file
18
libfuse/lib/fuse_req.cpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
#include "fuse_req.hpp"
|
||||
|
||||
#include "objpool.hpp"
|
||||
|
||||
|
||||
static ObjPool<fuse_req_t> g_pool;
|
||||
|
||||
fuse_req_t*
|
||||
fuse_req_alloc()
|
||||
{
|
||||
return g_pool.alloc();
|
||||
}
|
||||
|
||||
void
|
||||
fuse_req_free(fuse_req_t *req_)
|
||||
{
|
||||
return g_pool.free(req_);
|
||||
}
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
static
|
||||
void
|
||||
_want(fuse_conn_info *conn_,
|
||||
_want(fuse_conn_info_t *conn_,
|
||||
const int flag_)
|
||||
{
|
||||
conn_->want |= flag_;
|
||||
|
|
@ -43,7 +43,7 @@ _want(fuse_conn_info *conn_,
|
|||
|
||||
static
|
||||
bool
|
||||
_capable(fuse_conn_info *conn_,
|
||||
_capable(fuse_conn_info_t *conn_,
|
||||
const int flag_)
|
||||
{
|
||||
return !!(conn_->capable & flag_);
|
||||
|
|
@ -51,7 +51,7 @@ _capable(fuse_conn_info *conn_,
|
|||
|
||||
static
|
||||
void
|
||||
_want_if_capable(fuse_conn_info *conn_,
|
||||
_want_if_capable(fuse_conn_info_t *conn_,
|
||||
const int flag_)
|
||||
{
|
||||
if(::_capable(conn_,flag_))
|
||||
|
|
@ -60,7 +60,7 @@ _want_if_capable(fuse_conn_info *conn_,
|
|||
|
||||
static
|
||||
void
|
||||
_want_if_capable(fuse_conn_info *conn_,
|
||||
_want_if_capable(fuse_conn_info_t *conn_,
|
||||
const int flag_,
|
||||
ConfigBOOL *want_)
|
||||
{
|
||||
|
|
@ -78,7 +78,7 @@ static const char MAX_PAGES_LIMIT_FILEPATH[] = "/proc/sys/fs/fuse/max_pages_limi
|
|||
|
||||
static
|
||||
void
|
||||
_want_if_capable_max_pages(fuse_conn_info *conn_,
|
||||
_want_if_capable_max_pages(fuse_conn_info_t *conn_,
|
||||
Config &cfg_)
|
||||
{
|
||||
std::fstream f;
|
||||
|
|
@ -184,7 +184,7 @@ _spawn_thread_to_set_readahead()
|
|||
}
|
||||
|
||||
void *
|
||||
FUSE::init(fuse_conn_info *conn_)
|
||||
FUSE::init(fuse_conn_info_t *conn_)
|
||||
{
|
||||
procfs::init();
|
||||
cfg.readdir.initialize();
|
||||
|
|
|
|||
|
|
@ -22,5 +22,5 @@
|
|||
namespace FUSE
|
||||
{
|
||||
void *
|
||||
init(fuse_conn_info *conn);
|
||||
init(fuse_conn_info_t *conn);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue