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_chan_receive(struct fuse_chan *ch, char *buf, size_t size) { int res; res = fuse_chan_recv(&ch, buf, size); return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0; }
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; }
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 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; }
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; }
static void *fuse_do_work(void *data) { struct fuse_worker *w = (struct fuse_worker *) data; struct fuse_mt *mt = w->mt; while (!fuse_session_exited(mt->se)) { int isforget = 0; struct fuse_chan *ch = mt->prevch; int res; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); res = fuse_chan_recv(&ch, w->buf, w->bufsize); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); if (res == -EINTR) continue; if (res <= 0) { if (res < 0) { fuse_session_exit(mt->se); mt->error = -1; } break; } pthread_mutex_lock(&mt->lock); if (mt->exit) { pthread_mutex_unlock(&mt->lock); return NULL; } /* * This disgusting hack is needed so that zillions of threads * are not created on a burst of FORGET messages */ if (((struct fuse_in_header *) w->buf)->opcode == FUSE_FORGET) isforget = 1; if (!isforget) mt->numavail--; if (mt->numavail == 0) fuse_start_thread(mt); pthread_mutex_unlock(&mt->lock); fuse_session_process(mt->se, w->buf, res, ch); pthread_mutex_lock(&mt->lock); if (!isforget) mt->numavail++; if (mt->numavail > 10) { if (mt->exit) { pthread_mutex_unlock(&mt->lock); return NULL; } list_del_worker(w); mt->numavail--; mt->numworker--; pthread_mutex_unlock(&mt->lock); pthread_detach(w->thread_id); free(w->buf); free(w); return NULL; } pthread_mutex_unlock(&mt->lock); } sem_post(&mt->finish); #ifdef __APPLE__ { sigset_t set; (void) sigprocmask(0, NULL, &set); (void) sigsuspend(&set); /* want cancelable */ } #else /* !__APPLE__ */ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pause(); #endif /* __APPLE__ */ return NULL; }
static void *zfsfuse_listener_loop(void *arg) { size_t bufsize = 0; char *buf = NULL; VERIFY(pthread_mutex_lock(&mtx) == 0); fuse_listeners_count++; while(!exit_fuse_listener) { int ret = poll(fds, nfds, 1000); if(ret == 0 || (ret == -1 && errno == EINTR)) continue; if(ret == -1) { perror("poll"); continue; } int oldfds = nfds; for(int i = 0; i < oldfds; i++) { short rev = fds[i].revents; if(rev == 0) continue; fds[i].revents = 0; if (rev & POLLNVAL) { // already closed // fuse_unmount_all triggers this fds[i].fd = -1; continue; } if(!(rev & POLLIN) && !(rev & POLLERR) && !(rev & POLLHUP)) continue; if(i == 0) { new_fs(); } else { /* Handle request */ if(fsinfo[i].bufsize > bufsize) { char *new_buf = realloc(buf, fsinfo[i].bufsize); if(new_buf == NULL) { fprintf(stderr, "Warning: out of memory!\n"); continue; } buf = new_buf; bufsize = fsinfo[i].bufsize; } if (!fsinfo[i].se) { destroy_fs(i); continue; } int res = fuse_chan_recv(&fsinfo[i].ch, buf, fsinfo[i].bufsize); if(res == -1 || fuse_session_exited(fsinfo[i].se)) { destroy_fs(i); continue; } if(res == 0) continue; struct fuse_session *se = fsinfo[i].se; struct fuse_chan *ch = fsinfo[i].ch; /* * While we process this request, we let another * thread receive new events */ VERIFY(pthread_mutex_unlock(&mtx) == 0); fuse_session_process(se, buf, res, ch); /* Acquire the mutex before proceeding */ VERIFY(pthread_mutex_lock(&mtx) == 0); /* * At this point, we can no longer trust oldfds * to be accurate, so we exit this loop * * Also, exit_fuse_listener might have been set in the mean * time */ break; } } /* Free the closed file descriptors entries */ int write_ptr = 0; for(int read_ptr = 0; read_ptr < nfds; read_ptr++) { if(fds[read_ptr].fd == -1) continue; if(read_ptr != write_ptr) { fds[write_ptr] = fds[read_ptr]; fsinfo[write_ptr] = fsinfo[read_ptr]; mountpoints[write_ptr] = mountpoints[read_ptr]; } write_ptr++; } nfds = write_ptr; } fuse_listeners_count--; VERIFY(0 == pthread_cond_signal(&exiting_fuse_listener)); VERIFY(pthread_mutex_unlock(&mtx) == 0); return NULL; }