This commit is contained in:
Miklos Szeredi 2006-03-17 15:56:05 +00:00
parent 6f385414b2
commit 8d975f6fb3
11 changed files with 108 additions and 45 deletions

View File

@ -16,6 +16,9 @@
* new exported functions: fuse_session_remove_chan(),
fuse_get_session(), fuse_daemonize()
* fuse_chan_recv() may now return a new channel which will be used
to send the reply
2006-03-16 Miklos Szeredi <miklos@szeredi.hu>
* Released 2.6.0-pre2

View File

@ -1102,12 +1102,12 @@ struct fuse_chan_ops {
/**
* Hook for receiving a raw request
*
* @param ch the channel
* @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 *ch, char *buf, size_t size);
int (*receive)(struct fuse_chan **chp, char *buf, size_t size);
/**
* Hook for sending a raw reply
@ -1120,8 +1120,7 @@ struct fuse_chan_ops {
* @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);
int (*send)(struct fuse_chan *ch, const struct iovec iov[], size_t count);
/**
* Destroy the channel
@ -1180,12 +1179,12 @@ struct fuse_session *fuse_chan_session(struct fuse_chan *ch);
*
* A return value of -ENODEV means, that the filesystem was unmounted
*
* @param ch the channel
* @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);
int fuse_chan_recv(struct fuse_chan **ch, char *buf, size_t size);
/**
* Send a raw reply
@ -1218,6 +1217,8 @@ void fuse_chan_destroy(struct fuse_chan *ch);
# if FUSE_USE_VERSION == 25
# define fuse_lowlevel_ops fuse_lowlevel_ops_compat25
# define fuse_lowlevel_new fuse_lowlevel_new_compat25
# define fuse_chan_ops fuse_chan_ops_compat25
# define fuse_chan_new fuse_chan_new_compat25
# elif FUSE_USE_VERSION == 24
# define fuse_file_info fuse_file_info_compat
# define fuse_reply_statfs fuse_reply_statfs_compat

View File

@ -88,6 +88,16 @@ struct fuse_session *fuse_lowlevel_new_compat(const char *opts,
const struct fuse_lowlevel_ops *op,
size_t op_size, void *userdata);
#endif /* __FreeBSD__ */
struct fuse_chan_ops_compat24 {
int (*receive)(struct fuse_chan *ch, char *buf, size_t size);
int (*send)(struct fuse_chan *ch, const struct iovec iov[], size_t count);
void (*destroy)(struct fuse_chan *ch);
};
struct fuse_chan *fuse_chan_new_compat24(struct fuse_chan_ops_compat24 *op,
int fd, size_t bufsize, void *data);
int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size);
#endif /* __FreeBSD__ */

View File

@ -1881,7 +1881,7 @@ struct fuse_cmd *fuse_read_cmd(struct fuse *f)
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);
if (res < 0 && res != -EINTR && res != -EAGAIN)

View File

@ -14,8 +14,10 @@
#include <unistd.h>
#include <assert.h>
static int fuse_kern_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
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);
@ -50,18 +52,20 @@ static int fuse_kern_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[],
size_t count)
{
ssize_t res = writev(fuse_chan_fd(ch), iov, count);
int err = errno;
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);
if (res == -1) {
struct fuse_session *se = fuse_chan_session(ch);
assert(se != NULL);
assert(se != NULL);
/* ENOENT means the operation was interrupted */
if (!fuse_session_exited(se) && err != ENOENT)
perror("fuse: writing device");
return -err;
/* ENOENT means the operation was interrupted */
if (!fuse_session_exited(se) && err != ENOENT)
perror("fuse: writing device");
return -err;
}
}
return 0;
}

View File

@ -24,12 +24,13 @@ int fuse_session_loop(struct fuse_session *se)
}
while (!fuse_session_exited(se)) {
res = fuse_chan_recv(ch, buf, bufsize);
struct fuse_chan *tmpch = ch;
res = fuse_chan_recv(&tmpch, buf, bufsize);
if (res == -EINTR)
continue;
if (res <= 0)
break;
fuse_session_process(se, buf, res, ch);
fuse_session_process(se, buf, res, tmpch);
}
free(buf);

View File

@ -24,7 +24,6 @@ struct fuse_worker {
int numworker;
int numavail;
struct fuse_session *se;
struct fuse_chan *ch;
struct fuse_chan *prevch;
pthread_t threads[FUSE_MAX_WORKERS];
pthread_t main_thread;
@ -32,6 +31,11 @@ struct fuse_worker {
int error;
};
struct fuse_wchan {
struct fuse_worker *w;
struct fuse_chan *prevch;
};
#ifndef USE_UCLIBC
#define mutex_init(mut) pthread_mutex_init(mut, NULL)
#else
@ -48,11 +52,15 @@ static void mutex_init(pthread_mutex_t *mut)
static int fuse_loop_mt_send(struct fuse_chan *ch, const struct iovec iov[],
size_t count)
{
struct fuse_worker *w = (struct fuse_worker *) fuse_chan_data(ch);
pthread_mutex_lock(&w->lock);
w->numavail ++;
pthread_mutex_unlock(&w->lock);
return fuse_chan_send(w->prevch, iov, count);
int res;
struct fuse_wchan *wchan_data = (struct fuse_wchan *) fuse_chan_data(ch);
pthread_mutex_lock(&wchan_data->w->lock);
wchan_data->w->numavail ++;
pthread_mutex_unlock(&wchan_data->w->lock);
res = fuse_chan_send(wchan_data->prevch, iov, count);
fuse_chan_destroy(ch);
free(wchan_data);
return res;
}
static int start_thread(struct fuse_worker *w, pthread_t *thread_id);
@ -74,7 +82,11 @@ static void *do_work(void *data)
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
while (!fuse_session_exited(w->se)) {
int res = fuse_chan_recv(w->prevch, buf, bufsize);
struct fuse_chan *ch = w->prevch;
struct fuse_chan *wchan;
struct fuse_wchan *wchan_data;
struct fuse_chan_ops cop = { .send = fuse_loop_mt_send };
int res = fuse_chan_recv(&ch, buf, bufsize);
if (res == -EINTR)
continue;
if (res <= 0) {
@ -105,7 +117,17 @@ static void *do_work(void *data)
}
}
pthread_mutex_unlock(&w->lock);
fuse_session_process(w->se, buf, res, w->ch);
wchan_data = malloc(sizeof(struct fuse_wchan));
wchan = fuse_chan_new(&cop, -1, fuse_chan_bufsize(ch), wchan_data);
if (!wchan_data || !wchan) {
free(wchan_data);
fuse_session_exit(w->se);
w->error = -1;
break;
}
wchan_data->w = w;
wchan_data->prevch = ch;
fuse_session_process(w->se, buf, res, wchan);
}
pthread_cleanup_pop(1);
@ -145,10 +167,6 @@ int fuse_session_loop_mt(struct fuse_session *se)
int i;
int err;
struct fuse_worker *w;
struct fuse_chan_ops cop = {
.send = fuse_loop_mt_send,
};
w = (struct fuse_worker *) malloc(sizeof(struct fuse_worker));
if (w == NULL) {
fprintf(stderr, "fuse: failed to allocate worker structure\n");
@ -157,11 +175,6 @@ int fuse_session_loop_mt(struct fuse_session *se)
memset(w, 0, sizeof(struct fuse_worker));
w->se = se;
w->prevch = fuse_session_next_chan(se, NULL);
w->ch = fuse_chan_new(&cop, -1, fuse_chan_bufsize(w->prevch), w);
if (w->ch == NULL) {
free(w);
return -1;
}
w->error = 0;
w->numworker = 1;
w->numavail = 1;
@ -179,7 +192,6 @@ int fuse_session_loop_mt(struct fuse_session *se)
pthread_join(w->threads[i], NULL);
pthread_mutex_destroy(&w->lock);
err = w->error;
fuse_chan_destroy(w->ch);
free(w);
fuse_session_reset(se);
return err;

View File

@ -223,6 +223,7 @@ int fuse_reply_err(fuse_req_t req, int err)
void fuse_reply_none(fuse_req_t req)
{
fuse_chan_send(req->ch, NULL, 0);
free_req(req);
}

View File

@ -104,10 +104,10 @@ static int mt_session_exited(void *data)
return fuse_session_exited(pd->prevse);
}
static int mt_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
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(ch);
struct procdata *pd = (struct procdata *) fuse_chan_data(*chp);
assert(size >= sizeof(cmd));

View File

@ -7,6 +7,7 @@
*/
#include "fuse_lowlevel.h"
#include "fuse_lowlevel_compat.h"
#include <stdio.h>
#include <stdlib.h>
@ -34,6 +35,8 @@ struct fuse_chan {
size_t bufsize;
void *data;
int compat;
};
struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data)
@ -116,8 +119,8 @@ int fuse_session_exited(struct fuse_session *se)
return se->exited;
}
struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd,
size_t bufsize, void *data)
struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd,
size_t bufsize, void *data, int compat)
{
struct fuse_chan *ch = (struct fuse_chan *) malloc(sizeof(*ch));
if (ch == NULL) {
@ -130,10 +133,24 @@ struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd,
ch->fd = fd;
ch->bufsize = bufsize;
ch->data = data;
ch->compat = compat;
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, 0);
}
struct fuse_chan *fuse_chan_new_compat24(struct fuse_chan_ops_compat24 *op,
int fd, size_t bufsize, void *data)
{
return fuse_chan_new_common((struct fuse_chan_ops *) op, fd, bufsize,
data, 24);
}
int fuse_chan_fd(struct fuse_chan *ch)
{
return ch->fd;
@ -154,14 +171,22 @@ struct fuse_session *fuse_chan_session(struct fuse_chan *ch)
return ch->se;
}
int fuse_chan_recv(struct fuse_chan *ch, char *buf, size_t size)
int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size)
{
return ch->op.receive(ch, buf, size);
struct fuse_chan *ch = *chp;
if (ch->compat)
return ((struct fuse_chan_ops_compat24 *) &ch->op)
->receive(ch, buf, size);
else
return ch->op.receive(chp, buf, size);
}
int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
{
int res = fuse_chan_recv(ch, buf, size);
int res;
assert(ch->compat);
res = fuse_chan_recv(&ch, buf, size);
return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0;
}
@ -177,3 +202,7 @@ void fuse_chan_destroy(struct fuse_chan *ch)
ch->op.destroy(ch);
free(ch);
}
#ifndef __FreeBSD__
__asm__(".symver fuse_chan_new_compat24,fuse_chan_new@FUSE_2.4");
#endif

View File

@ -83,6 +83,8 @@ FUSE_2.5 {
FUSE_2.6 {
global:
fuse_add_direntry;
fuse_chan_new;
fuse_chan_new_compat24;
fuse_daemonize;
fuse_get_session;
fuse_lowlevel_new;