13 #include "fuse_misc.h"    14 #include "fuse_kernel.h"    22 #include <semaphore.h>    25 #include <sys/ioctl.h>    29 #define ENVNAME_THREAD_STACK "FUSE_THREAD_STACK"    32         struct fuse_worker *prev;
    33         struct fuse_worker *next;
    48         struct fuse_session *se;
    49         struct fuse_worker main;
    57 static struct fuse_chan *fuse_chan_new(
int fd)
    59         struct fuse_chan *ch = (
struct fuse_chan *) malloc(
sizeof(*ch));
    61                 fprintf(stderr, 
"fuse: failed to allocate channel\n");
    65         memset(ch, 0, 
sizeof(*ch));
    68         fuse_mutex_init(&ch->lock);
    73 struct fuse_chan *fuse_chan_get(
struct fuse_chan *ch)
    76         pthread_mutex_lock(&ch->lock);
    78         pthread_mutex_unlock(&ch->lock);
    83 void fuse_chan_put(
struct fuse_chan *ch)
    87         pthread_mutex_lock(&ch->lock);
    90                 pthread_mutex_unlock(&ch->lock);
    92                 pthread_mutex_destroy(&ch->lock);
    95                 pthread_mutex_unlock(&ch->lock);
    98 static void list_add_worker(
struct fuse_worker *w, 
struct fuse_worker *next)
   100         struct fuse_worker *prev = next->prev;
   107 static void list_del_worker(
struct fuse_worker *w)
   109         struct fuse_worker *prev = w->prev;
   110         struct fuse_worker *next = w->next;
   115 static int fuse_loop_start_thread(
struct fuse_mt *mt);
   117 static void *fuse_do_work(
void *data)
   119         struct fuse_worker *w = (
struct fuse_worker *) data;
   120         struct fuse_mt *mt = w->mt;
   126                 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
   127                 res = fuse_session_receive_buf_int(mt->se, &w->fbuf, w->ch);
   128                 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
   139                 pthread_mutex_lock(&mt->lock);
   141                         pthread_mutex_unlock(&mt->lock);
   150                         struct fuse_in_header *in = w->fbuf.mem;
   152                         if (in->opcode == FUSE_FORGET ||
   153                             in->opcode == FUSE_BATCH_FORGET)
   159                 if (mt->numavail == 0)
   160                         fuse_loop_start_thread(mt);
   161                 pthread_mutex_unlock(&mt->lock);
   163                 fuse_session_process_buf_int(mt->se, &w->fbuf, w->ch);
   165                 pthread_mutex_lock(&mt->lock);
   168                 if (mt->numavail > mt->max_idle) {
   170                                 pthread_mutex_unlock(&mt->lock);
   176                         pthread_mutex_unlock(&mt->lock);
   178                         pthread_detach(w->thread_id);
   180                         fuse_chan_put(w->ch);
   184                 pthread_mutex_unlock(&mt->lock);
   187         sem_post(&mt->finish);
   192 int fuse_start_thread(pthread_t *thread_id, 
void *(*func)(
void *), 
void *arg)
   201         pthread_attr_init(&attr);
   202         stack_size = getenv(ENVNAME_THREAD_STACK);
   203         if (stack_size && pthread_attr_setstacksize(&attr, atoi(stack_size)))
   204                 fprintf(stderr, 
"fuse: invalid stack size: %s\n", stack_size);
   207         sigemptyset(&newset);
   208         sigaddset(&newset, SIGTERM);
   209         sigaddset(&newset, SIGINT);
   210         sigaddset(&newset, SIGHUP);
   211         sigaddset(&newset, SIGQUIT);
   212         pthread_sigmask(SIG_BLOCK, &newset, &oldset);
   213         res = pthread_create(thread_id, &attr, func, arg);
   214         pthread_sigmask(SIG_SETMASK, &oldset, NULL);
   215         pthread_attr_destroy(&attr);
   217                 fprintf(stderr, 
"fuse: error creating thread: %s\n",
   225 static struct fuse_chan *fuse_clone_chan(
struct fuse_mt *mt)
   230         struct fuse_chan *newch;
   231         const char *devname = 
"/dev/fuse";
   236         clonefd = open(devname, O_RDWR | O_CLOEXEC);
   238                 fprintf(stderr, 
"fuse: failed to open %s: %s\n", devname,
   242         fcntl(clonefd, F_SETFD, FD_CLOEXEC);
   244         masterfd = mt->se->fd;
   245         res = ioctl(clonefd, FUSE_DEV_IOC_CLONE, &masterfd);
   247                 fprintf(stderr, 
"fuse: failed to clone device fd: %s\n",
   252         newch = fuse_chan_new(clonefd);
   259 static int fuse_loop_start_thread(
struct fuse_mt *mt)
   263         struct fuse_worker *w = malloc(
sizeof(
struct fuse_worker));
   265                 fprintf(stderr, 
"fuse: failed to allocate worker structure\n");
   268         memset(w, 0, 
sizeof(
struct fuse_worker));
   274                 w->ch = fuse_clone_chan(mt);
   277                         fprintf(stderr, 
"fuse: trying to continue "   278                                 "without -o clone_fd.\n");
   283         res = fuse_start_thread(&w->thread_id, fuse_do_work, w);
   285                 fuse_chan_put(w->ch);
   289         list_add_worker(w, &mt->main);
   296 static void fuse_join_worker(
struct fuse_mt *mt, 
struct fuse_worker *w)
   298         pthread_join(w->thread_id, NULL);
   299         pthread_mutex_lock(&mt->lock);
   301         pthread_mutex_unlock(&mt->lock);
   303         fuse_chan_put(w->ch);
   307 FUSE_SYMVER(
".symver fuse_session_loop_mt_32,fuse_session_loop_mt@@FUSE_3.2");
   308 int fuse_session_loop_mt_32(
struct fuse_session *se, 
struct fuse_loop_config *config)
   312         struct fuse_worker *w;
   314         memset(&mt, 0, 
sizeof(
struct fuse_mt));
   321         mt.main.thread_id = pthread_self();
   322         mt.main.prev = mt.main.next = &mt.main;
   323         sem_init(&mt.finish, 0, 0);
   324         fuse_mutex_init(&mt.lock);
   326         pthread_mutex_lock(&mt.lock);
   327         err = fuse_loop_start_thread(&mt);
   328         pthread_mutex_unlock(&mt.lock);
   332                         sem_wait(&mt.finish);
   334                 pthread_mutex_lock(&mt.lock);
   335                 for (w = mt.main.next; w != &mt.main; w = w->next)
   336                         pthread_cancel(w->thread_id);
   338                 pthread_mutex_unlock(&mt.lock);
   340                 while (mt.main.next != &mt.main)
   341                         fuse_join_worker(&mt, mt.main.next);
   346         pthread_mutex_destroy(&mt.lock);
   347         sem_destroy(&mt.finish);
   355 FUSE_SYMVER(
".symver fuse_session_loop_mt_31,fuse_session_loop_mt@FUSE_3.0");
   361         return fuse_session_loop_mt_32(se, &config);
 void fuse_session_exit(struct fuse_session *se)
unsigned int max_idle_threads
int fuse_session_loop_mt_31(struct fuse_session *se, int clone_fd)
int fuse_session_exited(struct fuse_session *se)
void fuse_session_reset(struct fuse_session *se)