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; struct fuse_buf fbuf = { .mem = w->buf, .size = w->bufsize, }; int res; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); res = fuse_session_receive_buf(mt->se, &fbuf, &ch); 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 (!(fbuf.flags & FUSE_BUF_IS_FD)) { struct fuse_in_header *in = fbuf.mem; if (in->opcode == FUSE_FORGET || in->opcode == FUSE_BATCH_FORGET) isforget = 1; } if (!isforget) mt->numavail--; if (mt->numavail == 0) fuse_loop_start_thread(mt); pthread_mutex_unlock(&mt->lock); fuse_session_process_buf(mt->se, &fbuf, 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); return NULL; } int fuse_start_thread(pthread_t *thread_id, void *(*func)(void *), void *arg) { sigset_t oldset; sigset_t newset; int res; pthread_attr_t attr; char *stack_size; /* Override default stack size */ pthread_attr_init(&attr); stack_size = getenv(ENVNAME_THREAD_STACK); if (stack_size && pthread_attr_setstacksize(&attr, atoi(stack_size))) fprintf(stderr, "fuse: invalid stack size: %s\n", stack_size); /* Disallow signal reception in worker threads */ sigemptyset(&newset); sigaddset(&newset, SIGTERM); sigaddset(&newset, SIGINT); sigaddset(&newset, SIGHUP); sigaddset(&newset, SIGQUIT); pthread_sigmask(SIG_BLOCK, &newset, &oldset); res = pthread_create(thread_id, &attr, func, arg); pthread_sigmask(SIG_SETMASK, &oldset, NULL); pthread_attr_destroy(&attr); if (res != 0) { fprintf(stderr, "fuse: error creating thread: %s\n", strerror(res)); return -1; } return 0; }
/* **__________________________________________________________________________ */ 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; }