12 #include "fuse_lowlevel.h" 
   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;
 
   47         struct fuse_session *se;
 
   48         struct fuse_worker main;
 
   56 static struct fuse_chan *fuse_chan_new(
int fd)
 
   58         struct fuse_chan *ch = (
struct fuse_chan *) malloc(
sizeof(*ch));
 
   60                 fuse_log(FUSE_LOG_ERR, 
"fuse: failed to allocate channel\n");
 
   64         memset(ch, 0, 
sizeof(*ch));
 
   67         pthread_mutex_init(&ch->lock, NULL);
 
   72 struct fuse_chan *fuse_chan_get(
struct fuse_chan *ch)
 
   75         pthread_mutex_lock(&ch->lock);
 
   77         pthread_mutex_unlock(&ch->lock);
 
   82 void fuse_chan_put(
struct fuse_chan *ch)
 
   86         pthread_mutex_lock(&ch->lock);
 
   89                 pthread_mutex_unlock(&ch->lock);
 
   91                 pthread_mutex_destroy(&ch->lock);
 
   94                 pthread_mutex_unlock(&ch->lock);
 
   97 static void list_add_worker(
struct fuse_worker *w, 
struct fuse_worker *next)
 
   99         struct fuse_worker *prev = next->prev;
 
  106 static void list_del_worker(
struct fuse_worker *w)
 
  108         struct fuse_worker *prev = w->prev;
 
  109         struct fuse_worker *next = w->next;
 
  114 static int fuse_loop_start_thread(
struct fuse_mt *mt);
 
  116 static void *fuse_do_work(
void *data)
 
  118         struct fuse_worker *w = (
struct fuse_worker *) data;
 
  119         struct fuse_mt *mt = w->mt;
 
  125                 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
 
  126                 res = fuse_session_receive_buf_int(mt->se, &w->fbuf, w->ch);
 
  127                 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
 
  138                 pthread_mutex_lock(&mt->lock);
 
  140                         pthread_mutex_unlock(&mt->lock);
 
  149                         struct fuse_in_header *in = w->fbuf.mem;
 
  151                         if (in->opcode == FUSE_FORGET ||
 
  152                             in->opcode == FUSE_BATCH_FORGET)
 
  158                 if (mt->numavail == 0)
 
  159                         fuse_loop_start_thread(mt);
 
  160                 pthread_mutex_unlock(&mt->lock);
 
  162                 fuse_session_process_buf_int(mt->se, &w->fbuf, w->ch);
 
  164                 pthread_mutex_lock(&mt->lock);
 
  167                 if (mt->numavail > mt->max_idle) {
 
  169                                 pthread_mutex_unlock(&mt->lock);
 
  175                         pthread_mutex_unlock(&mt->lock);
 
  177                         pthread_detach(w->thread_id);
 
  179                         fuse_chan_put(w->ch);
 
  183                 pthread_mutex_unlock(&mt->lock);
 
  186         sem_post(&mt->finish);
 
  191 int fuse_start_thread(pthread_t *thread_id, 
void *(*func)(
void *), 
void *arg)
 
  200         pthread_attr_init(&attr);
 
  201         stack_size = getenv(ENVNAME_THREAD_STACK);
 
  202         if (stack_size && pthread_attr_setstacksize(&attr, atoi(stack_size)))
 
  203                 fuse_log(FUSE_LOG_ERR, 
"fuse: invalid stack size: %s\n", stack_size);
 
  206         sigemptyset(&newset);
 
  207         sigaddset(&newset, SIGTERM);
 
  208         sigaddset(&newset, SIGINT);
 
  209         sigaddset(&newset, SIGHUP);
 
  210         sigaddset(&newset, SIGQUIT);
 
  211         pthread_sigmask(SIG_BLOCK, &newset, &oldset);
 
  212         res = pthread_create(thread_id, &attr, func, arg);
 
  213         pthread_sigmask(SIG_SETMASK, &oldset, NULL);
 
  214         pthread_attr_destroy(&attr);
 
  216                 fuse_log(FUSE_LOG_ERR, 
"fuse: error creating thread: %s\n",
 
  224 static struct fuse_chan *fuse_clone_chan(
struct fuse_mt *mt)
 
  229         struct fuse_chan *newch;
 
  230         const char *devname = 
"/dev/fuse";
 
  235         clonefd = open(devname, O_RDWR | O_CLOEXEC);
 
  237                 fuse_log(FUSE_LOG_ERR, 
"fuse: failed to open %s: %s\n", devname,
 
  241         fcntl(clonefd, F_SETFD, FD_CLOEXEC);
 
  243         masterfd = mt->se->fd;
 
  244         res = ioctl(clonefd, FUSE_DEV_IOC_CLONE, &masterfd);
 
  246                 fuse_log(FUSE_LOG_ERR, 
"fuse: failed to clone device fd: %s\n",
 
  251         newch = fuse_chan_new(clonefd);
 
  258 static int fuse_loop_start_thread(
struct fuse_mt *mt)
 
  262         struct fuse_worker *w = malloc(
sizeof(
struct fuse_worker));
 
  264                 fuse_log(FUSE_LOG_ERR, 
"fuse: failed to allocate worker structure\n");
 
  267         memset(w, 0, 
sizeof(
struct fuse_worker));
 
  273                 w->ch = fuse_clone_chan(mt);
 
  276                         fuse_log(FUSE_LOG_ERR, 
"fuse: trying to continue " 
  277                                 "without -o clone_fd.\n");
 
  282         res = fuse_start_thread(&w->thread_id, fuse_do_work, w);
 
  284                 fuse_chan_put(w->ch);
 
  288         list_add_worker(w, &mt->main);
 
  295 static void fuse_join_worker(
struct fuse_mt *mt, 
struct fuse_worker *w)
 
  297         pthread_join(w->thread_id, NULL);
 
  298         pthread_mutex_lock(&mt->lock);
 
  300         pthread_mutex_unlock(&mt->lock);
 
  302         fuse_chan_put(w->ch);
 
  306 FUSE_SYMVER(
"fuse_session_loop_mt_32", 
"fuse_session_loop_mt@@FUSE_3.2")
 
  307 int fuse_session_loop_mt_32(struct fuse_session *se, struct 
fuse_loop_config *config)
 
  311         struct fuse_worker *w;
 
  313         memset(&mt, 0, 
sizeof(
struct fuse_mt));
 
  315         mt.clone_fd = config->clone_fd;
 
  319         mt.max_idle = config->max_idle_threads;
 
  320         mt.main.thread_id = pthread_self();
 
  321         mt.main.prev = mt.main.next = &mt.main;
 
  322         sem_init(&mt.finish, 0, 0);
 
  323         pthread_mutex_init(&mt.lock, NULL);
 
  325         pthread_mutex_lock(&mt.lock);
 
  326         err = fuse_loop_start_thread(&mt);
 
  327         pthread_mutex_unlock(&mt.lock);
 
  331                         sem_wait(&mt.finish);
 
  333                 pthread_mutex_lock(&mt.lock);
 
  334                 for (w = mt.main.next; w != &mt.main; w = w->next)
 
  335                         pthread_cancel(w->thread_id);
 
  337                 pthread_mutex_unlock(&mt.lock);
 
  339                 while (mt.main.next != &mt.main)
 
  340                         fuse_join_worker(&mt, mt.main.next);
 
  345         pthread_mutex_destroy(&mt.lock);
 
  346         sem_destroy(&mt.finish);
 
  353 int fuse_session_loop_mt_31(
struct fuse_session *se, 
int clone_fd);
 
  354 FUSE_SYMVER(
"fuse_session_loop_mt_31", 
"fuse_session_loop_mt@FUSE_3.0")
 
  355 int fuse_session_loop_mt_31(struct fuse_session *se, 
int clone_fd)
 
  359         config.max_idle_threads = 10;
 
  360         return fuse_session_loop_mt_32(se, &config);
 
void fuse_log(enum fuse_log_level level, const char *fmt,...)
void fuse_session_exit(struct fuse_session *se)
int fuse_session_exited(struct fuse_session *se)
void fuse_session_reset(struct fuse_session *se)