mirror of
https://github.com/trapexit/mergerfs.git
synced 2024-11-22 14:54:38 +08:00
Remove unnecessary libfuse abstractions
This commit is contained in:
parent
32e2c9c48e
commit
9d056d609f
3547
libfuse/ChangeLog
3547
libfuse/ChangeLog
File diff suppressed because it is too large
Load Diff
|
@ -37,7 +37,6 @@ SRC = \
|
|||
lib/debug.c \
|
||||
lib/fuse.c \
|
||||
lib/fuse_dirents.c \
|
||||
lib/fuse_kern_chan.c \
|
||||
lib/fuse_loop_mt.c \
|
||||
lib/fuse_lowlevel.c \
|
||||
lib/fuse_mt.c \
|
||||
|
|
|
@ -1503,231 +1503,29 @@ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
|
|||
* Session interface *
|
||||
* ----------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Session operations
|
||||
*
|
||||
* This is used in session creation
|
||||
*/
|
||||
struct fuse_session_ops
|
||||
{
|
||||
/**
|
||||
* Hook to process a request (mandatory)
|
||||
*
|
||||
* @param data user data passed to fuse_session_new()
|
||||
* @param buf buffer containing the raw request
|
||||
* @param len request length
|
||||
* @param ch channel on which the request was received
|
||||
*/
|
||||
void (*process)(void *data, const char *buf, size_t len,
|
||||
struct fuse_chan *ch);
|
||||
|
||||
/**
|
||||
* Hook for session exit and reset (optional)
|
||||
*
|
||||
* @param data user data passed to fuse_session_new()
|
||||
* @param val exited status (1 - exited, 0 - not exited)
|
||||
*/
|
||||
void (*exit)(void *data, int val);
|
||||
|
||||
/**
|
||||
* Hook for querying the current exited status (optional)
|
||||
*
|
||||
* @param data user data passed to fuse_session_new()
|
||||
* @return 1 if exited, 0 if not exited
|
||||
*/
|
||||
int (*exited)(void *data);
|
||||
|
||||
/**
|
||||
* Hook for cleaning up the channel on destroy (optional)
|
||||
*
|
||||
* @param data user data passed to fuse_session_new()
|
||||
*/
|
||||
void (*destroy)(void *data);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new session
|
||||
*
|
||||
* @param op session operations
|
||||
* @param data user data
|
||||
* @return new session object, or NULL on failure
|
||||
*/
|
||||
struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data);
|
||||
|
||||
/**
|
||||
* Assign a channel to a session
|
||||
*
|
||||
* Note: currently only a single channel may be assigned. This may
|
||||
* change in the future
|
||||
*
|
||||
* If a session is destroyed, the assigned channel is also destroyed
|
||||
*
|
||||
* @param se the session
|
||||
* @param ch the channel
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* Remove a channel from a session
|
||||
*
|
||||
* If the channel is not assigned to a session, then this is a no-op
|
||||
*
|
||||
* @param ch the channel to remove
|
||||
*/
|
||||
void fuse_session_remove_chan(struct fuse_chan *ch);
|
||||
|
||||
/**
|
||||
* Iterate over the channels assigned to a session
|
||||
*
|
||||
* The iterating function needs to start with a NULL channel, and
|
||||
* after that needs to pass the previously returned channel to the
|
||||
* function.
|
||||
*
|
||||
* @param se the session
|
||||
* @param ch the previous channel, or NULL
|
||||
* @return the next channel, or NULL if no more channels exist
|
||||
*/
|
||||
struct fuse_chan *fuse_session_next_chan(struct fuse_session *se,
|
||||
struct fuse_chan *ch);
|
||||
|
||||
/**
|
||||
* Process a raw request
|
||||
*
|
||||
* @param se the session
|
||||
* @param buf buffer containing the raw request
|
||||
* @param len request length
|
||||
* @param ch channel on which the request was received
|
||||
*/
|
||||
void fuse_session_process(struct fuse_session *se, const char *buf, size_t len,
|
||||
struct fuse_chan *ch);
|
||||
|
||||
/**
|
||||
* Process a raw request supplied in a generic buffer
|
||||
*
|
||||
* This is a more generic version of fuse_session_process(). The
|
||||
* fuse_buf may contain a memory buffer or a pipe file descriptor.
|
||||
*
|
||||
* @param se the session
|
||||
* @param buf the fuse_buf containing the request
|
||||
* @param ch channel on which the request was received
|
||||
*/
|
||||
void fuse_session_process_buf(struct fuse_session *se,
|
||||
const struct fuse_buf *buf, struct fuse_chan *ch);
|
||||
|
||||
/**
|
||||
* Receive a raw request supplied in a generic buffer
|
||||
*
|
||||
* This is a more generic version of fuse_chan_recv(). The fuse_buf
|
||||
* supplied to this function contains a suitably allocated memory
|
||||
* buffer. This may be overwritten with a file descriptor buffer.
|
||||
*
|
||||
* @param se the session
|
||||
* @param buf the fuse_buf to store the request in
|
||||
* @param chp pointer to the channel
|
||||
* @return the actual size of the raw request, or -errno on error
|
||||
*/
|
||||
int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
|
||||
struct fuse_chan **chp);
|
||||
|
||||
/**
|
||||
* Destroy a session
|
||||
*
|
||||
* @param se the session
|
||||
*/
|
||||
void fuse_session_destroy(struct fuse_session *se);
|
||||
|
||||
/**
|
||||
* Exit a session
|
||||
*
|
||||
* @param se the session
|
||||
*/
|
||||
void fuse_session_exit(struct fuse_session *se);
|
||||
|
||||
/**
|
||||
* Reset the exited status of a session
|
||||
*
|
||||
* @param se the session
|
||||
*/
|
||||
void fuse_session_reset(struct fuse_session *se);
|
||||
|
||||
/**
|
||||
* Query the exited status of a session
|
||||
*
|
||||
* @param se the session
|
||||
* @return 1 if exited, 0 if not exited
|
||||
*/
|
||||
int fuse_session_exited(struct fuse_session *se);
|
||||
|
||||
/**
|
||||
* Get the user data provided to the session
|
||||
*
|
||||
* @param se the session
|
||||
* @return the user data
|
||||
*/
|
||||
void fuse_session_reset(struct fuse_session *se);
|
||||
void *fuse_session_data(struct fuse_session *se);
|
||||
int fuse_session_receive(struct fuse_session *se,
|
||||
struct fuse_buf *buf);
|
||||
void fuse_session_process(struct fuse_session *se,
|
||||
const struct fuse_buf *buf);
|
||||
|
||||
/**
|
||||
* Enter a multi-threaded event loop
|
||||
*
|
||||
* @param se the session
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int fuse_session_loop_mt(struct fuse_session *se, const int threads);
|
||||
|
||||
/* ----------------------------------------------------------- *
|
||||
* Channel interface *
|
||||
* ----------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Channel operations
|
||||
*
|
||||
* This is used in channel creation
|
||||
*/
|
||||
struct fuse_chan_ops
|
||||
{
|
||||
/**
|
||||
* Hook for receiving a raw request
|
||||
*
|
||||
* @param ch pointer to the channel
|
||||
* @param buf the buffer to store the request in
|
||||
* @param size the size of the buffer
|
||||
* @return the actual size of the raw request, or -1 on error
|
||||
*/
|
||||
int (*receive)(struct fuse_chan **chp, char *buf, size_t size);
|
||||
|
||||
/**
|
||||
* Hook for sending a raw reply
|
||||
*
|
||||
* A return value of -ENOENT means, that the request was
|
||||
* interrupted, and the reply was discarded
|
||||
*
|
||||
* @param ch the channel
|
||||
* @param iov vector of blocks
|
||||
* @param count the number of blocks in vector
|
||||
* @return zero on success, -errno on failure
|
||||
*/
|
||||
int (*send)(struct fuse_chan *ch, const struct iovec iov[],
|
||||
size_t count);
|
||||
|
||||
/**
|
||||
* Destroy the channel
|
||||
*
|
||||
* @param ch the channel
|
||||
*/
|
||||
void (*destroy)(struct fuse_chan *ch);
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new channel
|
||||
*
|
||||
* @param op channel operations
|
||||
* @param fd file descriptor of the channel
|
||||
* @param bufsize the minimal receive buffer size
|
||||
* @param data user data
|
||||
* @return the new channel object, or NULL on failure
|
||||
*/
|
||||
struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd,
|
||||
size_t bufsize, void *data);
|
||||
struct fuse_chan *fuse_chan_new(int fd, size_t bufsize);
|
||||
|
||||
/**
|
||||
* Query the file descriptor of the channel
|
||||
|
@ -1761,37 +1559,12 @@ void *fuse_chan_data(struct fuse_chan *ch);
|
|||
*/
|
||||
struct fuse_session *fuse_chan_session(struct fuse_chan *ch);
|
||||
|
||||
/**
|
||||
* Receive a raw request
|
||||
*
|
||||
* A return value of -ENODEV means, that the filesystem was unmounted
|
||||
*
|
||||
* @param ch pointer to the channel
|
||||
* @param buf the buffer to store the request in
|
||||
* @param size the size of the buffer
|
||||
* @return the actual size of the raw request, or -errno on error
|
||||
*/
|
||||
int fuse_chan_recv(struct fuse_chan **ch, char *buf, size_t size);
|
||||
|
||||
/**
|
||||
* Send a raw reply
|
||||
*
|
||||
* A return value of -ENOENT means, that the request was
|
||||
* interrupted, and the reply was discarded
|
||||
*
|
||||
* @param ch the channel
|
||||
* @param iov vector of blocks
|
||||
* @param count the number of blocks in vector
|
||||
* @return zero on success, -errno on failure
|
||||
*/
|
||||
int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[],
|
||||
int fuse_chan_recv(struct fuse_chan *ch,
|
||||
char *buf,
|
||||
size_t size);
|
||||
int fuse_chan_send(struct fuse_chan *ch,
|
||||
const struct iovec iov[],
|
||||
size_t count);
|
||||
|
||||
/**
|
||||
* Destroy a channel
|
||||
*
|
||||
* @param ch the channel
|
||||
*/
|
||||
void fuse_chan_destroy(struct fuse_chan *ch);
|
||||
|
||||
EXTERN_C_END
|
||||
|
|
|
@ -3817,14 +3817,6 @@ free_cmd(struct fuse_cmd *cmd)
|
|||
free(cmd);
|
||||
}
|
||||
|
||||
void
|
||||
fuse_process_cmd(struct fuse *f,
|
||||
struct fuse_cmd *cmd)
|
||||
{
|
||||
fuse_session_process(f->se,cmd->buf,cmd->buflen,cmd->ch);
|
||||
free_cmd(cmd);
|
||||
}
|
||||
|
||||
int
|
||||
fuse_exited(struct fuse *f)
|
||||
{
|
||||
|
@ -3863,13 +3855,13 @@ fuse_alloc_cmd(size_t bufsize)
|
|||
struct fuse_cmd*
|
||||
fuse_read_cmd(struct fuse *f)
|
||||
{
|
||||
struct fuse_chan *ch = fuse_session_next_chan(f->se,NULL);
|
||||
struct fuse_chan *ch = f->se->ch;
|
||||
size_t bufsize = fuse_chan_bufsize(ch);
|
||||
struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize);
|
||||
|
||||
if(cmd != NULL)
|
||||
{
|
||||
int res = fuse_chan_recv(&ch,cmd->buf,bufsize);
|
||||
int res = fuse_chan_recv(ch,cmd->buf,bufsize);
|
||||
if(res <= 0)
|
||||
{
|
||||
free_cmd(cmd);
|
||||
|
@ -3887,7 +3879,7 @@ fuse_read_cmd(struct fuse *f)
|
|||
void
|
||||
fuse_exit(struct fuse *f)
|
||||
{
|
||||
fuse_session_exit(f->se);
|
||||
f->se->exited = 1;
|
||||
}
|
||||
|
||||
struct fuse_context*
|
||||
|
|
|
@ -16,18 +16,18 @@ struct fuse_ll;
|
|||
|
||||
struct fuse_session
|
||||
{
|
||||
struct fuse_session_ops op;
|
||||
int (*receive_buf)(struct fuse_session *se,
|
||||
struct fuse_buf *buf,
|
||||
struct fuse_chan *ch);
|
||||
|
||||
int (*receive_buf)(struct fuse_session *se, struct fuse_buf *buf,
|
||||
struct fuse_chan **chp);
|
||||
|
||||
void (*process_buf)(void *data, const struct fuse_buf *buf,
|
||||
void (*process_buf)(void *data,
|
||||
const struct fuse_buf *buf,
|
||||
struct fuse_chan *ch);
|
||||
|
||||
void (*destroy)(void *data);
|
||||
|
||||
void *data;
|
||||
|
||||
volatile int exited;
|
||||
|
||||
struct fuse_chan *ch;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,103 +0,0 @@
|
|||
/*
|
||||
FUSE: Filesystem in Userspace
|
||||
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
|
||||
|
||||
This program can be distributed under the terms of the GNU LGPLv2.
|
||||
See the file COPYING.LIB
|
||||
*/
|
||||
|
||||
#include "fuse_lowlevel.h"
|
||||
#include "fuse_kernel.h"
|
||||
#include "fuse_i.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf,
|
||||
size_t size)
|
||||
{
|
||||
struct fuse_chan *ch = *chp;
|
||||
int err;
|
||||
ssize_t res;
|
||||
struct fuse_session *se = fuse_chan_session(ch);
|
||||
assert(se != NULL);
|
||||
|
||||
restart:
|
||||
res = read(fuse_chan_fd(ch), buf, size);
|
||||
err = errno;
|
||||
|
||||
if (fuse_session_exited(se))
|
||||
return 0;
|
||||
if (res == -1) {
|
||||
/* ENOENT means the operation was interrupted, it's safe
|
||||
to restart */
|
||||
if (err == ENOENT)
|
||||
goto restart;
|
||||
|
||||
if (err == ENODEV) {
|
||||
fuse_session_exit(se);
|
||||
return 0;
|
||||
}
|
||||
/* Errors occurring during normal operation: EINTR (read
|
||||
interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem
|
||||
umounted) */
|
||||
if (err != EINTR && err != EAGAIN)
|
||||
perror("fuse: reading device");
|
||||
return -err;
|
||||
}
|
||||
if ((size_t) res < sizeof(struct fuse_in_header)) {
|
||||
fprintf(stderr, "short read on fuse device\n");
|
||||
return -EIO;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[],
|
||||
size_t count)
|
||||
{
|
||||
if (iov) {
|
||||
ssize_t res = writev(fuse_chan_fd(ch), iov, count);
|
||||
int err = errno;
|
||||
|
||||
if (res == -1) {
|
||||
struct fuse_session *se = fuse_chan_session(ch);
|
||||
|
||||
assert(se != NULL);
|
||||
|
||||
/* ENOENT means the operation was interrupted */
|
||||
if (!fuse_session_exited(se) && err != ENOENT)
|
||||
perror("fuse: writing device");
|
||||
return -err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fuse_kern_chan_destroy(struct fuse_chan *ch)
|
||||
{
|
||||
int fd = fuse_chan_fd(ch);
|
||||
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
struct fuse_chan *
|
||||
fuse_kern_chan_new(int fd_)
|
||||
{
|
||||
long pagesize;
|
||||
size_t bufsize;
|
||||
struct fuse_chan_ops op =
|
||||
{
|
||||
.receive = fuse_kern_chan_receive,
|
||||
.send = fuse_kern_chan_send,
|
||||
.destroy = fuse_kern_chan_destroy,
|
||||
};
|
||||
|
||||
pagesize = sysconf(_SC_PAGESIZE);
|
||||
|
||||
bufsize = ((FUSE_MAX_MAX_PAGES * pagesize) + 0x1000);
|
||||
|
||||
return fuse_chan_new(&op, fd_, bufsize, NULL);
|
||||
}
|
|
@ -37,7 +37,6 @@ struct fuse_worker
|
|||
struct fuse_mt
|
||||
{
|
||||
struct fuse_session *se;
|
||||
struct fuse_chan *prevch;
|
||||
struct fuse_worker main;
|
||||
sem_t finish;
|
||||
int exit;
|
||||
|
@ -77,28 +76,29 @@ fuse_do_work(void *data)
|
|||
{
|
||||
int res;
|
||||
struct fuse_buf fbuf;
|
||||
struct fuse_chan *ch = mt->prevch;
|
||||
|
||||
fbuf = (struct fuse_buf){ .mem = w->buf,
|
||||
.size = w->bufsize };
|
||||
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
|
||||
res = fuse_session_receive_buf(mt->se, &fbuf, &ch);
|
||||
res = fuse_session_receive(mt->se,&fbuf);
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
|
||||
if(res == -EINTR)
|
||||
continue;
|
||||
if(res <= 0) {
|
||||
if(res < 0) {
|
||||
fuse_session_exit(mt->se);
|
||||
mt->error = -1;
|
||||
if(res <= 0)
|
||||
{
|
||||
if(res < 0)
|
||||
{
|
||||
mt->se->exited = 1;
|
||||
mt->error = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if(mt->exit)
|
||||
return NULL;
|
||||
|
||||
fuse_session_process_buf(mt->se, &fbuf, ch);
|
||||
fuse_session_process(mt->se,&fbuf);
|
||||
}
|
||||
|
||||
sem_post(&mt->finish);
|
||||
|
@ -144,7 +144,7 @@ static int fuse_loop_start_thread(struct fuse_mt *mt)
|
|||
return -1;
|
||||
}
|
||||
memset(w, 0, sizeof(struct fuse_worker));
|
||||
w->bufsize = fuse_chan_bufsize(mt->prevch);
|
||||
w->bufsize = fuse_chan_bufsize(mt->se->ch);
|
||||
w->buf = calloc(w->bufsize,1);
|
||||
w->mt = mt;
|
||||
if(!w->buf) {
|
||||
|
@ -193,7 +193,6 @@ fuse_session_loop_mt(struct fuse_session *se_,
|
|||
|
||||
memset(&mt,0,sizeof(struct fuse_mt));
|
||||
mt.se = se_;
|
||||
mt.prevch = fuse_session_next_chan(se_,NULL);
|
||||
mt.error = 0;
|
||||
mt.main.thread_id = pthread_self();
|
||||
mt.main.prev = mt.main.next = &mt.main;
|
||||
|
|
|
@ -2515,21 +2515,6 @@ fuse_ll_process_buf(void *data,
|
|||
goto out_free;
|
||||
}
|
||||
|
||||
static
|
||||
void
|
||||
fuse_ll_process(void *data,
|
||||
const char *buf,
|
||||
size_t len,
|
||||
struct fuse_chan *ch)
|
||||
{
|
||||
struct fuse_buf fbuf = {
|
||||
.mem = (void *) buf,
|
||||
.size = len,
|
||||
};
|
||||
|
||||
fuse_ll_process_buf(data, &fbuf, ch);
|
||||
}
|
||||
|
||||
enum {
|
||||
KEY_HELP,
|
||||
KEY_VERSION,
|
||||
|
@ -2652,11 +2637,9 @@ fuse_ll_pipe_destructor(void *data)
|
|||
#ifdef HAVE_SPLICE
|
||||
static
|
||||
int
|
||||
fuse_ll_receive_buf(struct fuse_session *se,
|
||||
struct fuse_buf *buf,
|
||||
struct fuse_chan **chp)
|
||||
fuse_ll_receive_buf(struct fuse_session *se,
|
||||
struct fuse_buf *buf)
|
||||
{
|
||||
struct fuse_chan *ch = *chp;
|
||||
struct fuse_ll *f = fuse_session_data(se);
|
||||
size_t bufsize = buf->size;
|
||||
struct fuse_ll_pipe *llp;
|
||||
|
@ -2687,27 +2670,27 @@ fuse_ll_receive_buf(struct fuse_session *se,
|
|||
goto fallback;
|
||||
}
|
||||
|
||||
res = splice(fuse_chan_fd(ch), NULL, llp->pipe[1], NULL, bufsize, 0);
|
||||
res = splice(fuse_chan_fd(se->ch), NULL, llp->pipe[1], NULL, bufsize, 0);
|
||||
err = errno;
|
||||
|
||||
if(fuse_session_exited(se))
|
||||
return 0;
|
||||
|
||||
if (res == -1)
|
||||
if(res == -1)
|
||||
{
|
||||
if (err == ENODEV)
|
||||
if(err == ENODEV)
|
||||
{
|
||||
fuse_session_exit(se);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (err != EINTR && err != EAGAIN)
|
||||
if(err != EINTR && err != EAGAIN)
|
||||
perror("fuse: splice from device");
|
||||
|
||||
return -err;
|
||||
}
|
||||
|
||||
if (res < sizeof(struct fuse_in_header))
|
||||
if(res < sizeof(struct fuse_in_header))
|
||||
{
|
||||
fprintf(stderr, "short splice from fuse device\n");
|
||||
return -EIO;
|
||||
|
@ -2755,7 +2738,7 @@ fuse_ll_receive_buf(struct fuse_session *se,
|
|||
return res;
|
||||
|
||||
fallback:
|
||||
res = fuse_chan_recv(chp, buf->mem, bufsize);
|
||||
res = fuse_chan_recv(se->ch, buf->mem, bufsize);
|
||||
if (res <= 0)
|
||||
return res;
|
||||
|
||||
|
@ -2766,13 +2749,12 @@ fuse_ll_receive_buf(struct fuse_session *se,
|
|||
#else
|
||||
static
|
||||
int
|
||||
fuse_ll_receive_buf(struct fuse_session *se,
|
||||
struct fuse_buf *buf,
|
||||
struct fuse_chan **chp)
|
||||
fuse_ll_receive_buf(struct fuse_session *se,
|
||||
struct fuse_buf *buf)
|
||||
{
|
||||
(void) se;
|
||||
|
||||
int res = fuse_chan_recv(chp, buf->mem, buf->size);
|
||||
int res = fuse_chan_recv(se->ch, buf->mem, buf->size);
|
||||
if (res <= 0)
|
||||
return res;
|
||||
|
||||
|
@ -2796,10 +2778,6 @@ fuse_lowlevel_new_common(struct fuse_args *args,
|
|||
int err;
|
||||
struct fuse_ll *f;
|
||||
struct fuse_session *se;
|
||||
struct fuse_session_ops sop = {
|
||||
.process = fuse_ll_process,
|
||||
.destroy = fuse_ll_destroy,
|
||||
};
|
||||
|
||||
if (sizeof(struct fuse_lowlevel_ops) < op_size)
|
||||
{
|
||||
|
@ -2835,13 +2813,13 @@ fuse_lowlevel_new_common(struct fuse_args *args,
|
|||
f->owner = getuid();
|
||||
f->userdata = userdata;
|
||||
|
||||
se = fuse_session_new(&sop, f);
|
||||
se = fuse_session_new(f,
|
||||
fuse_ll_receive_buf,
|
||||
fuse_ll_process_buf,
|
||||
fuse_ll_destroy);
|
||||
if (!se)
|
||||
goto out_key_destroy;
|
||||
|
||||
se->receive_buf = fuse_ll_receive_buf;
|
||||
se->process_buf = fuse_ll_process_buf;
|
||||
|
||||
return se;
|
||||
|
||||
out_key_destroy:
|
||||
|
|
|
@ -16,98 +16,8 @@
|
|||
#include <pthread.h>
|
||||
#include <assert.h>
|
||||
|
||||
struct procdata
|
||||
{
|
||||
struct fuse *f;
|
||||
struct fuse_chan *prevch;
|
||||
struct fuse_session *prevse;
|
||||
fuse_processor_t proc;
|
||||
void *data;
|
||||
};
|
||||
|
||||
static void mt_session_proc(void *data, const char *buf, size_t len,
|
||||
struct fuse_chan *ch)
|
||||
{
|
||||
struct procdata *pd = (struct procdata *) data;
|
||||
struct fuse_cmd *cmd = *(struct fuse_cmd **) buf;
|
||||
|
||||
(void) len;
|
||||
(void) ch;
|
||||
pd->proc(pd->f, cmd, pd->data);
|
||||
}
|
||||
|
||||
static void mt_session_exit(void *data, int val)
|
||||
{
|
||||
struct procdata *pd = (struct procdata *) data;
|
||||
if (val)
|
||||
fuse_session_exit(pd->prevse);
|
||||
else
|
||||
fuse_session_reset(pd->prevse);
|
||||
}
|
||||
|
||||
static int mt_session_exited(void *data)
|
||||
{
|
||||
struct procdata *pd = (struct procdata *) data;
|
||||
return fuse_session_exited(pd->prevse);
|
||||
}
|
||||
|
||||
static int mt_chan_receive(struct fuse_chan **chp, char *buf, size_t size)
|
||||
{
|
||||
struct fuse_cmd *cmd;
|
||||
struct procdata *pd = (struct procdata *) fuse_chan_data(*chp);
|
||||
|
||||
assert(size >= sizeof(cmd));
|
||||
|
||||
cmd = fuse_read_cmd(pd->f);
|
||||
if (cmd == NULL)
|
||||
return 0;
|
||||
|
||||
*(struct fuse_cmd **)buf = cmd;
|
||||
|
||||
return sizeof(cmd);
|
||||
}
|
||||
|
||||
int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data)
|
||||
{
|
||||
int res;
|
||||
struct procdata pd;
|
||||
struct fuse_session *prevse = fuse_get_session(f);
|
||||
struct fuse_session *se;
|
||||
struct fuse_chan *prevch = fuse_session_next_chan(prevse, NULL);
|
||||
struct fuse_chan *ch;
|
||||
struct fuse_session_ops sop = {
|
||||
.exit = mt_session_exit,
|
||||
.exited = mt_session_exited,
|
||||
.process = mt_session_proc,
|
||||
};
|
||||
struct fuse_chan_ops cop = {
|
||||
.receive = mt_chan_receive,
|
||||
};
|
||||
|
||||
pd.f = f;
|
||||
pd.prevch = prevch;
|
||||
pd.prevse = prevse;
|
||||
pd.proc = proc;
|
||||
pd.data = data;
|
||||
|
||||
se = fuse_session_new(&sop, &pd);
|
||||
if (se == NULL)
|
||||
return -1;
|
||||
|
||||
ch = fuse_chan_new(&cop, fuse_chan_fd(prevch),
|
||||
sizeof(struct fuse_cmd *), &pd);
|
||||
if (ch == NULL) {
|
||||
fuse_session_destroy(se);
|
||||
return -1;
|
||||
}
|
||||
fuse_session_add_chan(se, ch);
|
||||
res = fuse_session_loop_mt(se,
|
||||
fuse_config_num_threads(f));
|
||||
fuse_session_destroy(se);
|
||||
return res;
|
||||
}
|
||||
|
||||
int fuse_loop_mt(struct fuse *f)
|
||||
int
|
||||
fuse_loop_mt(struct fuse *f)
|
||||
{
|
||||
if (f == NULL)
|
||||
return -1;
|
||||
|
|
|
@ -8,23 +8,28 @@
|
|||
|
||||
#include "fuse_i.h"
|
||||
#include "fuse_misc.h"
|
||||
#include "fuse_kernel.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
|
||||
struct fuse_chan
|
||||
{
|
||||
struct fuse_chan_ops op;
|
||||
struct fuse_session *se;
|
||||
int fd;
|
||||
size_t bufsize;
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data)
|
||||
struct fuse_session *fuse_session_new(void *data,
|
||||
void *receive_buf,
|
||||
void *process_buf,
|
||||
void *destroy)
|
||||
{
|
||||
struct fuse_session *se = (struct fuse_session *) malloc(sizeof(*se));
|
||||
if (se == NULL) {
|
||||
|
@ -33,8 +38,10 @@ struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data)
|
|||
}
|
||||
|
||||
memset(se, 0, sizeof(*se));
|
||||
se->op = *op;
|
||||
se->data = data;
|
||||
se->receive_buf = receive_buf;
|
||||
se->process_buf = process_buf;
|
||||
se->destroy = destroy;
|
||||
|
||||
return se;
|
||||
}
|
||||
|
@ -57,79 +64,30 @@ void fuse_session_remove_chan(struct fuse_chan *ch)
|
|||
}
|
||||
}
|
||||
|
||||
struct fuse_chan *fuse_session_next_chan(struct fuse_session *se,
|
||||
struct fuse_chan *ch)
|
||||
void
|
||||
fuse_session_destroy(struct fuse_session *se)
|
||||
{
|
||||
assert(ch == NULL || ch == se->ch);
|
||||
if (ch == NULL)
|
||||
return se->ch;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void fuse_session_process(struct fuse_session *se, const char *buf, size_t len,
|
||||
struct fuse_chan *ch)
|
||||
{
|
||||
se->op.process(se->data, buf, len, ch);
|
||||
}
|
||||
|
||||
void fuse_session_process_buf(struct fuse_session *se,
|
||||
const struct fuse_buf *buf, struct fuse_chan *ch)
|
||||
{
|
||||
if (se->process_buf) {
|
||||
se->process_buf(se->data, buf, ch);
|
||||
} else {
|
||||
assert(!(buf->flags & FUSE_BUF_IS_FD));
|
||||
fuse_session_process(se->data, buf->mem, buf->size, ch);
|
||||
}
|
||||
}
|
||||
|
||||
int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
|
||||
struct fuse_chan **chp)
|
||||
{
|
||||
int res;
|
||||
|
||||
if (se->receive_buf) {
|
||||
res = se->receive_buf(se, buf, chp);
|
||||
} else {
|
||||
res = fuse_chan_recv(chp, buf->mem, buf->size);
|
||||
if (res > 0)
|
||||
buf->size = res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void fuse_session_destroy(struct fuse_session *se)
|
||||
{
|
||||
if (se->op.destroy)
|
||||
se->op.destroy(se->data);
|
||||
if (se->ch != NULL)
|
||||
se->destroy(se->data);
|
||||
if(se->ch != NULL)
|
||||
fuse_chan_destroy(se->ch);
|
||||
free(se);
|
||||
}
|
||||
|
||||
void fuse_session_exit(struct fuse_session *se)
|
||||
{
|
||||
if (se->op.exit)
|
||||
se->op.exit(se->data, 1);
|
||||
se->exited = 1;
|
||||
}
|
||||
|
||||
void fuse_session_reset(struct fuse_session *se)
|
||||
{
|
||||
if (se->op.exit)
|
||||
se->op.exit(se->data, 0);
|
||||
se->exited = 0;
|
||||
}
|
||||
|
||||
int fuse_session_exited(struct fuse_session *se)
|
||||
int
|
||||
fuse_session_exited(struct fuse_session *se)
|
||||
{
|
||||
if (se->op.exited)
|
||||
return se->op.exited(se->data);
|
||||
else
|
||||
return se->exited;
|
||||
return se->exited;
|
||||
}
|
||||
|
||||
void
|
||||
fuse_session_exit(struct fuse_session *se_)
|
||||
{
|
||||
se_->exited = 1;
|
||||
}
|
||||
|
||||
void *fuse_session_data(struct fuse_session *se)
|
||||
|
@ -137,28 +95,39 @@ void *fuse_session_data(struct fuse_session *se)
|
|||
return se->data;
|
||||
}
|
||||
|
||||
static struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd,
|
||||
size_t bufsize, void *data)
|
||||
int
|
||||
fuse_session_receive(struct fuse_session *se_,
|
||||
struct fuse_buf *buf_)
|
||||
{
|
||||
struct fuse_chan *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->op = *op;
|
||||
ch->fd = fd;
|
||||
ch->bufsize = bufsize;
|
||||
ch->data = data;
|
||||
|
||||
return ch;
|
||||
return se_->receive_buf(se_,buf_,se_->ch);
|
||||
}
|
||||
|
||||
struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd,
|
||||
size_t bufsize, void *data)
|
||||
void
|
||||
fuse_session_process(struct fuse_session *se_,
|
||||
const struct fuse_buf *buf_)
|
||||
{
|
||||
return fuse_chan_new_common(op, fd, bufsize, data);
|
||||
se_->process_buf(se_->data,buf_,se_->ch);
|
||||
}
|
||||
|
||||
struct fuse_chan *
|
||||
fuse_chan_new(int fd,
|
||||
size_t bufsize)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
int fuse_chan_fd(struct fuse_chan *ch)
|
||||
|
@ -178,40 +147,97 @@ size_t fuse_chan_bufsize(struct fuse_chan *ch)
|
|||
return ch->bufsize;
|
||||
}
|
||||
|
||||
void *fuse_chan_data(struct fuse_chan *ch)
|
||||
{
|
||||
return ch->data;
|
||||
}
|
||||
|
||||
struct fuse_session *fuse_chan_session(struct fuse_chan *ch)
|
||||
{
|
||||
return ch->se;
|
||||
}
|
||||
|
||||
int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size)
|
||||
int
|
||||
fuse_chan_recv(struct fuse_chan *ch,
|
||||
char *buf,
|
||||
size_t size)
|
||||
{
|
||||
struct fuse_chan *ch = *chp;
|
||||
int err;
|
||||
ssize_t res;
|
||||
struct fuse_session *se = fuse_chan_session(ch);
|
||||
assert(se != NULL);
|
||||
|
||||
return ch->op.receive(chp, buf, size);
|
||||
restart:
|
||||
res = read(fuse_chan_fd(ch), buf, size);
|
||||
err = errno;
|
||||
|
||||
if(fuse_session_exited(se))
|
||||
return 0;
|
||||
|
||||
if(res == -1)
|
||||
{
|
||||
/* ENOENT means the operation was interrupted, it's safe
|
||||
to restart */
|
||||
if (err == ENOENT)
|
||||
goto restart;
|
||||
|
||||
if(err == ENODEV)
|
||||
{
|
||||
se->exited = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Errors occurring during normal operation: EINTR (read
|
||||
interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem
|
||||
umounted) */
|
||||
if(err != EINTR && err != EAGAIN)
|
||||
perror("fuse: reading device");
|
||||
return -err;
|
||||
}
|
||||
|
||||
if((size_t) res < sizeof(struct fuse_in_header))
|
||||
{
|
||||
fprintf(stderr, "short read on fuse device\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
|
||||
int
|
||||
fuse_chan_send(struct fuse_chan *ch,
|
||||
const struct iovec iov[],
|
||||
size_t count)
|
||||
{
|
||||
int res;
|
||||
if(!iov)
|
||||
return 0;
|
||||
|
||||
res = fuse_chan_recv(&ch, buf, size);
|
||||
return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0;
|
||||
int err;
|
||||
ssize_t res;
|
||||
|
||||
res = writev(fuse_chan_fd(ch), iov, count);
|
||||
err = errno;
|
||||
|
||||
if(res == -1)
|
||||
{
|
||||
struct fuse_session *se = fuse_chan_session(ch);
|
||||
|
||||
assert(se != NULL);
|
||||
|
||||
/* ENOENT means the operation was interrupted */
|
||||
if(!fuse_session_exited(se) && err != ENOENT)
|
||||
perror("fuse: writing device");
|
||||
return -err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count)
|
||||
void
|
||||
fuse_chan_destroy(struct fuse_chan *ch)
|
||||
{
|
||||
return ch->op.send(ch, iov, count);
|
||||
}
|
||||
int fd;
|
||||
|
||||
void fuse_chan_destroy(struct fuse_chan *ch)
|
||||
{
|
||||
fuse_session_remove_chan(ch);
|
||||
if (ch->op.destroy)
|
||||
ch->op.destroy(ch);
|
||||
|
||||
fd = fuse_chan_fd(ch);
|
||||
if(fd != -1)
|
||||
close(fd);
|
||||
|
||||
free(ch);
|
||||
}
|
||||
|
|
|
@ -237,8 +237,10 @@ struct fuse_chan *
|
|||
fuse_mount_common(const char *mountpoint_,
|
||||
struct fuse_args *args_)
|
||||
{
|
||||
struct fuse_chan *ch;
|
||||
int fd;
|
||||
long bufsize;
|
||||
long pagesize;
|
||||
struct fuse_chan *ch;
|
||||
|
||||
/*
|
||||
* Make sure file descriptors 0, 1 and 2 are open, otherwise chaos
|
||||
|
@ -255,7 +257,10 @@ fuse_mount_common(const char *mountpoint_,
|
|||
if(fd == -1)
|
||||
return NULL;
|
||||
|
||||
ch = fuse_kern_chan_new(fd);
|
||||
pagesize = sysconf(_SC_PAGESIZE);
|
||||
bufsize = ((FUSE_MAX_MAX_PAGES + 1) * pagesize);
|
||||
|
||||
ch = fuse_chan_new(fd,bufsize);
|
||||
if(!ch)
|
||||
fuse_kern_unmount(mountpoint_, fd);
|
||||
|
||||
|
@ -284,11 +289,13 @@ void fuse_unmount(const char *mountpoint, struct fuse_chan *ch)
|
|||
fuse_unmount_common(mountpoint, ch);
|
||||
}
|
||||
|
||||
struct fuse *fuse_setup_common(int argc, char *argv[],
|
||||
const struct fuse_operations *op,
|
||||
size_t op_size,
|
||||
char **mountpoint,
|
||||
int *fd)
|
||||
struct fuse *
|
||||
fuse_setup_common(int argc,
|
||||
char *argv[],
|
||||
const struct fuse_operations *op,
|
||||
size_t op_size,
|
||||
char **mountpoint,
|
||||
int *fd)
|
||||
{
|
||||
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
||||
struct fuse_chan *ch;
|
||||
|
@ -344,7 +351,7 @@ struct fuse *fuse_setup(int argc, char *argv[],
|
|||
static void fuse_teardown_common(struct fuse *fuse, char *mountpoint)
|
||||
{
|
||||
struct fuse_session *se = fuse_get_session(fuse);
|
||||
struct fuse_chan *ch = fuse_session_next_chan(se, NULL);
|
||||
struct fuse_chan *ch = se->ch;
|
||||
fuse_remove_signal_handlers(se);
|
||||
fuse_unmount_common(mountpoint, ch);
|
||||
fuse_destroy(fuse);
|
||||
|
|
Loading…
Reference in New Issue
Block a user