Browse Source

Merge pull request #1091 from trapexit/cleanup

Remove unnecessary libfuse abstractions
pull/1092/head
trapexit 2 years ago
committed by GitHub
parent
commit
fea499e220
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3547
      libfuse/ChangeLog
  2. 1
      libfuse/Makefile
  3. 257
      libfuse/include/fuse_lowlevel.h
  4. 14
      libfuse/lib/fuse.c
  5. 14
      libfuse/lib/fuse_i.h
  6. 103
      libfuse/lib/fuse_kern_chan.c
  7. 17
      libfuse/lib/fuse_loop_mt.c
  8. 40
      libfuse/lib/fuse_lowlevel.c
  9. 94
      libfuse/lib/fuse_mt.c
  10. 210
      libfuse/lib/fuse_session.c
  11. 15
      libfuse/lib/helper.c

3547
libfuse/ChangeLog
File diff suppressed because it is too large
View File

1
libfuse/Makefile

@ -37,7 +37,6 @@ SRC = \
lib/debug.c \ lib/debug.c \
lib/fuse.c \ lib/fuse.c \
lib/fuse_dirents.c \ lib/fuse_dirents.c \
lib/fuse_kern_chan.c \
lib/fuse_loop_mt.c \ lib/fuse_loop_mt.c \
lib/fuse_lowlevel.c \ lib/fuse_lowlevel.c \
lib/fuse_mt.c \ lib/fuse_mt.c \

257
libfuse/include/fuse_lowlevel.h

@ -1503,231 +1503,29 @@ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
* Session interface * * 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); 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); 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); void fuse_session_destroy(struct fuse_session *se);
/**
* Exit a session
*
* @param se the session
*/
void fuse_session_exit(struct fuse_session *se); 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); 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); 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); int fuse_session_loop_mt(struct fuse_session *se, const int threads);
/* ----------------------------------------------------------- * /* ----------------------------------------------------------- *
* Channel interface * * 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 * 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); 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); size_t count);
/**
* Destroy a channel
*
* @param ch the channel
*/
void fuse_chan_destroy(struct fuse_chan *ch); void fuse_chan_destroy(struct fuse_chan *ch);
EXTERN_C_END EXTERN_C_END

14
libfuse/lib/fuse.c

@ -3817,14 +3817,6 @@ free_cmd(struct fuse_cmd *cmd)
free(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 int
fuse_exited(struct fuse *f) fuse_exited(struct fuse *f)
{ {
@ -3863,13 +3855,13 @@ fuse_alloc_cmd(size_t bufsize)
struct fuse_cmd* struct fuse_cmd*
fuse_read_cmd(struct fuse *f) 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); size_t bufsize = fuse_chan_bufsize(ch);
struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize); struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize);
if(cmd != NULL) if(cmd != NULL)
{ {
int res = fuse_chan_recv(&ch,cmd->buf,bufsize);
int res = fuse_chan_recv(ch,cmd->buf,bufsize);
if(res <= 0) if(res <= 0)
{ {
free_cmd(cmd); free_cmd(cmd);
@ -3887,7 +3879,7 @@ fuse_read_cmd(struct fuse *f)
void void
fuse_exit(struct fuse *f) fuse_exit(struct fuse *f)
{ {
fuse_session_exit(f->se);
f->se->exited = 1;
} }
struct fuse_context* struct fuse_context*

14
libfuse/lib/fuse_i.h

@ -16,18 +16,18 @@ struct fuse_ll;
struct fuse_session struct fuse_session
{ {
struct fuse_session_ops op;
int (*receive_buf)(struct fuse_session *se, struct fuse_buf *buf,
struct fuse_chan **chp);
int (*receive_buf)(struct fuse_session *se,
struct fuse_buf *buf,
struct fuse_chan *ch);
void (*process_buf)(void *data, const struct fuse_buf *buf,
void (*process_buf)(void *data,
const struct fuse_buf *buf,
struct fuse_chan *ch); struct fuse_chan *ch);
void *data;
void (*destroy)(void *data);
void *data;
volatile int exited; volatile int exited;
struct fuse_chan *ch; struct fuse_chan *ch;
}; };

103
libfuse/lib/fuse_kern_chan.c

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

17
libfuse/lib/fuse_loop_mt.c

@ -37,7 +37,6 @@ struct fuse_worker
struct fuse_mt struct fuse_mt
{ {
struct fuse_session *se; struct fuse_session *se;
struct fuse_chan *prevch;
struct fuse_worker main; struct fuse_worker main;
sem_t finish; sem_t finish;
int exit; int exit;
@ -77,19 +76,20 @@ fuse_do_work(void *data)
{ {
int res; int res;
struct fuse_buf fbuf; struct fuse_buf fbuf;
struct fuse_chan *ch = mt->prevch;
fbuf = (struct fuse_buf){ .mem = w->buf, fbuf = (struct fuse_buf){ .mem = w->buf,
.size = w->bufsize }; .size = w->bufsize };
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 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); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
if(res == -EINTR) if(res == -EINTR)
continue; continue;
if(res <= 0) {
if(res < 0) {
fuse_session_exit(mt->se);
if(res <= 0)
{
if(res < 0)
{
mt->se->exited = 1;
mt->error = -1; mt->error = -1;
} }
break; break;
@ -98,7 +98,7 @@ fuse_do_work(void *data)
if(mt->exit) if(mt->exit)
return NULL; return NULL;
fuse_session_process_buf(mt->se, &fbuf, ch);
fuse_session_process(mt->se,&fbuf);
} }
sem_post(&mt->finish); sem_post(&mt->finish);
@ -144,7 +144,7 @@ static int fuse_loop_start_thread(struct fuse_mt *mt)
return -1; return -1;
} }
memset(w, 0, sizeof(struct fuse_worker)); 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->buf = calloc(w->bufsize,1);
w->mt = mt; w->mt = mt;
if(!w->buf) { if(!w->buf) {
@ -193,7 +193,6 @@ fuse_session_loop_mt(struct fuse_session *se_,
memset(&mt,0,sizeof(struct fuse_mt)); memset(&mt,0,sizeof(struct fuse_mt));
mt.se = se_; mt.se = se_;
mt.prevch = fuse_session_next_chan(se_,NULL);
mt.error = 0; mt.error = 0;
mt.main.thread_id = pthread_self(); mt.main.thread_id = pthread_self();
mt.main.prev = mt.main.next = &mt.main; mt.main.prev = mt.main.next = &mt.main;

40
libfuse/lib/fuse_lowlevel.c

@ -2515,21 +2515,6 @@ fuse_ll_process_buf(void *data,
goto out_free; 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 { enum {
KEY_HELP, KEY_HELP,
KEY_VERSION, KEY_VERSION,
@ -2653,10 +2638,8 @@ fuse_ll_pipe_destructor(void *data)
static static
int int
fuse_ll_receive_buf(struct fuse_session *se, fuse_ll_receive_buf(struct fuse_session *se,
struct fuse_buf *buf,
struct fuse_chan **chp)
struct fuse_buf *buf)
{ {
struct fuse_chan *ch = *chp;
struct fuse_ll *f = fuse_session_data(se); struct fuse_ll *f = fuse_session_data(se);
size_t bufsize = buf->size; size_t bufsize = buf->size;
struct fuse_ll_pipe *llp; struct fuse_ll_pipe *llp;
@ -2687,7 +2670,7 @@ fuse_ll_receive_buf(struct fuse_session *se,
goto fallback; 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; err = errno;
if(fuse_session_exited(se)) if(fuse_session_exited(se))
@ -2755,7 +2738,7 @@ fuse_ll_receive_buf(struct fuse_session *se,
return res; return res;
fallback: fallback:
res = fuse_chan_recv(chp, buf->mem, bufsize);
res = fuse_chan_recv(se->ch, buf->mem, bufsize);
if (res <= 0) if (res <= 0)
return res; return res;
@ -2767,12 +2750,11 @@ fuse_ll_receive_buf(struct fuse_session *se,
static static
int int
fuse_ll_receive_buf(struct fuse_session *se, fuse_ll_receive_buf(struct fuse_session *se,
struct fuse_buf *buf,
struct fuse_chan **chp)
struct fuse_buf *buf)
{ {
(void) se; (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) if (res <= 0)
return res; return res;
@ -2796,10 +2778,6 @@ fuse_lowlevel_new_common(struct fuse_args *args,
int err; int err;
struct fuse_ll *f; struct fuse_ll *f;
struct fuse_session *se; 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) if (sizeof(struct fuse_lowlevel_ops) < op_size)
{ {
@ -2835,13 +2813,13 @@ fuse_lowlevel_new_common(struct fuse_args *args,
f->owner = getuid(); f->owner = getuid();
f->userdata = userdata; 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) if (!se)
goto out_key_destroy; goto out_key_destroy;
se->receive_buf = fuse_ll_receive_buf;
se->process_buf = fuse_ll_process_buf;
return se; return se;
out_key_destroy: out_key_destroy:

94
libfuse/lib/fuse_mt.c

@ -16,98 +16,8 @@
#include <pthread.h> #include <pthread.h>
#include <assert.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) if (f == NULL)
return -1; return -1;

210
libfuse/lib/fuse_session.c

@ -8,23 +8,28 @@
#include "fuse_i.h" #include "fuse_i.h"
#include "fuse_misc.h" #include "fuse_misc.h"
#include "fuse_kernel.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <assert.h>
#include <errno.h>
#include <unistd.h>
#include <sys/uio.h>
struct fuse_chan struct fuse_chan
{ {
struct fuse_chan_ops op;
struct fuse_session *se; struct fuse_session *se;
int fd; int fd;
size_t bufsize; 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)); struct fuse_session *se = (struct fuse_session *) malloc(sizeof(*se));
if (se == NULL) { 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)); memset(se, 0, sizeof(*se));
se->op = *op;
se->data = data; se->data = data;
se->receive_buf = receive_buf;
se->process_buf = process_buf;
se->destroy = destroy;
return se; return se;
} }
@ -57,110 +64,72 @@ void fuse_session_remove_chan(struct fuse_chan *ch)
} }
} }
struct fuse_chan *fuse_session_next_chan(struct fuse_session *se,
struct fuse_chan *ch)
{
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)
void
fuse_session_destroy(struct fuse_session *se)
{ {
se->op.process(se->data, buf, len, ch);
se->destroy(se->data);
if(se->ch != NULL)
fuse_chan_destroy(se->ch);
free(se);
} }
void fuse_session_process_buf(struct fuse_session *se,
const struct fuse_buf *buf, struct fuse_chan *ch)
void fuse_session_reset(struct fuse_session *se)
{ {
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);
}
se->exited = 0;
} }
int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
struct fuse_chan **chp)
int
fuse_session_exited(struct fuse_session *se)
{ {
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;
return se->exited;
} }
void fuse_session_destroy(struct fuse_session *se)
void
fuse_session_exit(struct fuse_session *se_)
{ {
if (se->op.destroy)
se->op.destroy(se->data);
if (se->ch != NULL)
fuse_chan_destroy(se->ch);
free(se);
se_->exited = 1;
} }
void fuse_session_exit(struct fuse_session *se)
void *fuse_session_data(struct fuse_session *se)
{ {
if (se->op.exit)
se->op.exit(se->data, 1);
se->exited = 1;
return se->data;
} }
void fuse_session_reset(struct fuse_session *se)
int
fuse_session_receive(struct fuse_session *se_,
struct fuse_buf *buf_)
{ {
if (se->op.exit)
se->op.exit(se->data, 0);
se->exited = 0;
return se_->receive_buf(se_,buf_,se_->ch);
} }
int fuse_session_exited(struct fuse_session *se)
void
fuse_session_process(struct fuse_session *se_,
const struct fuse_buf *buf_)
{ {
if (se->op.exited)
return se->op.exited(se->data);
else
return se->exited;
se_->process_buf(se_->data,buf_,se_->ch);
} }
void *fuse_session_data(struct fuse_session *se)
struct fuse_chan *
fuse_chan_new(int fd,
size_t bufsize)
{ {
return se->data;
}
struct fuse_chan *ch;
static struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd,
size_t bufsize, void *data)
ch = (struct fuse_chan*)malloc(sizeof(*ch));
if(ch == NULL)
{ {
struct fuse_chan *ch = (struct fuse_chan *) malloc(sizeof(*ch));
if (ch == NULL) {
fprintf(stderr, "fuse: failed to allocate channel\n"); fprintf(stderr, "fuse: failed to allocate channel\n");
return NULL; return NULL;
} }
memset(ch, 0, sizeof(*ch)); memset(ch, 0, sizeof(*ch));
ch->op = *op;
ch->fd = fd; ch->fd = fd;
ch->bufsize = bufsize; ch->bufsize = bufsize;
ch->data = data;
return ch; return ch;
} }
struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd,
size_t bufsize, void *data)
{
return fuse_chan_new_common(op, fd, bufsize, data);
}
int fuse_chan_fd(struct fuse_chan *ch) int fuse_chan_fd(struct fuse_chan *ch)
{ {
return ch->fd; return ch->fd;
@ -178,40 +147,97 @@ size_t fuse_chan_bufsize(struct fuse_chan *ch)
return ch->bufsize; return ch->bufsize;
} }
void *fuse_chan_data(struct fuse_chan *ch)
{
return ch->data;
}
struct fuse_session *fuse_chan_session(struct fuse_chan *ch) struct fuse_session *fuse_chan_session(struct fuse_chan *ch)
{ {
return ch->se; 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)
{
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)
{ {
struct fuse_chan *ch = *chp;
se->exited = 1;
return 0;
}
return ch->op.receive(chp, buf, size);
/* 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;
} }
int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
if((size_t) res < sizeof(struct fuse_in_header))
{ {
int res;
fprintf(stderr, "short read on fuse device\n");
return -EIO;
}
res = fuse_chan_recv(&ch, buf, size);
return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0;
return res;
} }
int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count)
int
fuse_chan_send(struct fuse_chan *ch,
const struct iovec iov[],
size_t count)
{
if(!iov)
return 0;
int err;
ssize_t res;
res = writev(fuse_chan_fd(ch), iov, count);
err = errno;
if(res == -1)
{ {
return ch->op.send(ch, iov, count);
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;
} }
void fuse_chan_destroy(struct fuse_chan *ch)
void
fuse_chan_destroy(struct fuse_chan *ch)
{ {
int fd;
fuse_session_remove_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); free(ch);
} }

15
libfuse/lib/helper.c

@ -237,8 +237,10 @@ struct fuse_chan *
fuse_mount_common(const char *mountpoint_, fuse_mount_common(const char *mountpoint_,
struct fuse_args *args_) struct fuse_args *args_)
{ {
struct fuse_chan *ch;
int fd; int fd;
long bufsize;
long pagesize;
struct fuse_chan *ch;
/* /*
* Make sure file descriptors 0, 1 and 2 are open, otherwise chaos * 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) if(fd == -1)
return NULL; 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) if(!ch)
fuse_kern_unmount(mountpoint_, fd); fuse_kern_unmount(mountpoint_, fd);
@ -284,7 +289,9 @@ void fuse_unmount(const char *mountpoint, struct fuse_chan *ch)
fuse_unmount_common(mountpoint, ch); fuse_unmount_common(mountpoint, ch);
} }
struct fuse *fuse_setup_common(int argc, char *argv[],
struct fuse *
fuse_setup_common(int argc,
char *argv[],
const struct fuse_operations *op, const struct fuse_operations *op,
size_t op_size, size_t op_size,
char **mountpoint, char **mountpoint,
@ -344,7 +351,7 @@ struct fuse *fuse_setup(int argc, char *argv[],
static void fuse_teardown_common(struct fuse *fuse, char *mountpoint) static void fuse_teardown_common(struct fuse *fuse, char *mountpoint)
{ {
struct fuse_session *se = fuse_get_session(fuse); 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_remove_signal_handlers(se);
fuse_unmount_common(mountpoint, ch); fuse_unmount_common(mountpoint, ch);
fuse_destroy(fuse); fuse_destroy(fuse);

Loading…
Cancel
Save