Beispiel #1
0
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;
}
Beispiel #2
0
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;
}
Beispiel #3
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;
}
Beispiel #4
0
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;
}
Beispiel #5
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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;
}