static Bool fuseProcessMessages(void *data) { CompDisplay *d = (CompDisplay *)data; struct fuse_chan *channel; size_t bufferSize; int res = 0; FUSE_DISPLAY(d); channel = fuse_session_next_chan(fd->session, NULL); bufferSize = fuse_chan_bufsize(channel); if (fuse_session_exited(fd->session)) return FALSE; for (;; ) { struct fuse_chan *tmpch = channel; res = fuse_chan_recv(&tmpch, fd->buffer, bufferSize); if (res == -EINTR) continue; if (res > 0) fuse_session_process(fd->session, fd->buffer, res, tmpch); break; } return TRUE; }
static gboolean manage_fuse_st (GIOChannel *source, GIOCondition condition, gpointer data) { int res; char *buf; gboolean ret; size_t bufsize; struct fuse *fuse; struct fuse_session *se; struct fuse_chan *ch; fuse = (struct fuse*) data; se = fuse_get_session (fuse); ch = fuse_session_next_chan (se, NULL); bufsize = fuse_chan_bufsize (ch); buf = alloca (bufsize); ret = TRUE; res = fuse_chan_recv (&ch, buf, bufsize); if (res == -EINTR) ret = TRUE; else if (res <= 0) ret = FALSE; else fuse_session_process (se, buf, res, ch); return ret; }
int fuse_session_loop(struct fuse_session *se) { int res = 0; struct fuse_chan *ch = fuse_session_next_chan(se, NULL); size_t bufsize = fuse_chan_bufsize(ch); char *buf = (char *) malloc(bufsize); if (!buf) { fprintf(stderr, "fuse: failed to allocate read buffer\n"); return -1; } while (!fuse_session_exited(se)) { 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, tmpch); } free(buf); fuse_session_reset(se); return res < 0 ? -1 : 0; }
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); fuse_remove_signal_handlers(se); fuse_unmount_common(mountpoint, ch); fuse_destroy(fuse); free(mountpoint); }
static gboolean manage_fuse_mt (GIOChannel *source, GIOCondition condition, gpointer data) { int res; char *buf; size_t bufsize; struct fuse *fuse; struct fuse_session *se; struct fuse_chan *ch; GThreadPool *pool; GError *error; ThreadsData *info; fuse = (struct fuse*) data; error = NULL; pool = g_thread_pool_new (manage_request, fuse, -1, FALSE, &error); if (pool == NULL) { g_warning ("Unable to start thread pool: %s", error->message); g_error_free (error); return NULL; } se = fuse_get_session (fuse); ch = fuse_session_next_chan (se, NULL); bufsize = fuse_chan_bufsize (ch); while (1) { buf = (char*) malloc (bufsize); res = fuse_chan_recv (&ch, buf, bufsize); if (res == -EINTR) { free (buf); continue; } else if (res <= 0) { free (buf); break; } info = do_threads_data (buf, res); error = NULL; g_thread_pool_push (pool, info, &error); if (error != NULL) { g_warning ("Unable to start processing request: %s", error->message); g_error_free (error); free_threads_data (info); } } g_thread_pool_free (pool, TRUE, TRUE); return NULL; }
static void manage_request (gpointer data, gpointer user) { struct fuse *fuse; struct fuse_session *se; struct fuse_chan *ch; ThreadsData *info; fuse = (struct fuse*) user; info = (ThreadsData*) data; se = fuse_get_session (fuse); ch = fuse_session_next_chan (se, NULL); fuse_session_process (se, info->buf, info->res, ch); free_threads_data (info); }
/** * gfuse_loop_run: * @loop: the #GFuseLoop to run * * Runs a #GFuseLoop, mounting it and adding polling of the FUSE channel in * the mainloop. If multi-thread is required, also allocates all working * threads */ void gfuse_loop_run (GFuseLoop *loop) { int thread; struct fuse_session *se; struct fuse_chan *ch; struct fuse *fuse_session; if (loop->priv->real_ops == NULL) { g_warning ("Invalid initialization of GFuseLoop, no operations loaded"); return; } loop->priv->runtime_data = g_new0 (PrivateDataBlock, 1); loop->priv->runtime_data->loop = loop; loop->priv->shadow_ops = g_new0 (struct fuse_operations, 1); memcpy (loop->priv->shadow_ops, loop->priv->real_ops, sizeof (struct fuse_operations)); loop->priv->shadow_ops->init = internal_init_wrapper; fuse_session = fuse_setup (loop->priv->startup_argc, loop->priv->startup_argv, loop->priv->shadow_ops, sizeof (struct fuse_operations), &loop->priv->mountpoint, &thread, loop->priv->runtime_data); loop->priv->threads = (thread != 0); se = fuse_get_session (fuse_session); ch = fuse_session_next_chan (se, NULL); loop->priv->fuse_fd = g_io_channel_unix_new (fuse_chan_fd (ch)); /** TODO Provide implementation also for multi-threads */ /* if (thread) g_io_add_watch (loop->priv->fuse_fd, G_IO_IN, manage_fuse_mt, fuse_session); else g_io_add_watch (loop->priv->fuse_fd, G_IO_IN, manage_fuse_st, fuse_session); */ g_io_add_watch (loop->priv->fuse_fd, G_IO_IN, manage_fuse_st, fuse_session); }
int fuse_session_loop_mt(struct fuse_session *se) { int err; struct fuse_mt mt; struct fuse_worker *w; memset(&mt, 0, sizeof(struct fuse_mt)); mt.se = se; mt.prevch = fuse_session_next_chan(se, NULL); mt.error = 0; mt.numworker = 0; mt.numavail = 0; mt.main.thread_id = pthread_self(); mt.main.prev = mt.main.next = &mt.main; sem_init(&mt.finish, 0, 0); fuse_mutex_init(&mt.lock); pthread_mutex_lock(&mt.lock); err = fuse_start_thread(&mt); pthread_mutex_unlock(&mt.lock); if (!err) { /* sem_wait() is interruptible */ while (!fuse_session_exited(se)) sem_wait(&mt.finish); for (w = mt.main.next; w != &mt.main; w = w->next) pthread_cancel(w->thread_id); mt.exit = 1; pthread_mutex_unlock(&mt.lock); while (mt.main.next != &mt.main) fuse_join_worker(&mt, mt.main.next); err = mt.error; } pthread_mutex_destroy(&mt.lock); sem_destroy(&mt.finish); fuse_session_reset(se); return err; }
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, .send = mt_chan_send, }; 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_session_destroy(se); return res; }
/* **__________________________________________________________________________ */ int rozofs_fuse_session_loop(rozofs_fuse_ctx_t *ctx_p) { int res = 0; char *buf; struct fuse_buf fbuf; int exit_req = 0; struct fuse_session *se = ctx_p->se; struct fuse_chan *ch = fuse_session_next_chan(se, NULL); /* ** Get a buffer from the rozofs_fuse context. That buffer is unique and is allocated ** at startup. */ buf = ctx_p->buf_fuse_req_p; while (1) { struct fuse_chan *tmpch = ch; /* ** set the reference of the buffer that will be used by fuse */ fbuf.mem = buf; fbuf.flags = 0; fbuf.size = ctx_p->bufsize; res = fuse_session_receive_buf(se, &fbuf, &tmpch); if (res == 0) { /* ** session has been exited */ exit_req = 1; break; } if (res < 0) { switch(errno) { case EINTR: continue; case EAGAIN: /* ** the fuse queue is empty */ return 0; break; default: /* ** fatal error */ exit_req = 1; break; } } /* ** OK it looks like that there is a valid message */ if ( exit_req == 0) fuse_session_process_buf(se, &fbuf, tmpch); if (fuse_session_exited(se) == 1) { exit_req = 1; break; } break; } /* ** to be reworked */ // free(buf); // fuse_session_reset(se); return res < 0 ? -1 : 0; }
/* **__________________________________________________________________________ */ int rozofs_fuse_session_loop(rozofs_fuse_ctx_t *ctx_p, int * empty) { int res = 0; char *buf; struct fuse_buf fbuf; int exit_req = 0; struct fuse_session *se = ctx_p->se; struct fuse_chan *ch = fuse_session_next_chan(se, NULL); *empty = 0; /* ** Get a buffer from the rozofs_fuse context. That buffer is unique and is allocated ** at startup. */ // START_PROFILING_FUSE(); // buf = ctx_p->buf_fuse_req_p; if (rozofs_fuse_cur_rcv_buf == NULL) { /* ** Allocate a buffer for receiving message from fuse kernel */ rozofs_fuse_cur_rcv_buf = rozofs_fuse_alloc_rcv_buffer_pool(); if (rozofs_fuse_cur_rcv_buf == NULL) { /* ** force empty in order to exit from the polling loop */ *empty = 1; return 0; } } buf = rozofs_fuse_cur_rcv_buf->buf; while (1) { struct fuse_chan *tmpch = ch; /* ** set the reference of the buffer that will be used by fuse */ fbuf.mem = buf; fbuf.flags = 0; fbuf.size = ctx_p->bufsize; res = fuse_session_receive_buf(se, &fbuf, &tmpch); if (res == 0) { /* ** session has been exited */ exit_req = 1; break; } if (res < 0) { switch(errno) { case EINTR: continue; case EAGAIN: /* ** the fuse queue is empty */ *empty = 1; return 0; break; default: /* ** fatal error */ exit_req = 1; break; } } /* ** OK it looks like that there is a valid message */ // STOP_PROFILING_FUSE(); if ( exit_req == 0) fuse_session_process_buf(se, &fbuf, tmpch); if (fuse_session_exited(se) == 1) { exit_req = 1; break; } break; } /* ** to be reworked */ // free(buf); // fuse_session_reset(se); return res < 0 ? -1 : 0; }