Пример #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;
}
Пример #2
0
// Do a mount for helper_thread()
static void helper_thread_mount(mount_t * m)
{
	Dprintf("%s(\"%s\")\n", __FUNCTION__, m->fstitch_path);

	if ((m->channel_fd = fuse_mount(m->mountpoint, &m->args)) == -1)
	{
		fprintf(stderr, "%s(): fuse_mount(\"%s\") failed. (Does the mountpoint exist?)\n", __FUNCTION__, m->mountpoint);
		return;
	}

	if (!(m->session = fuse_lowlevel_new(&m->args, ops, ops_len, m)))
	{
		fprintf(stderr, "%s(): fuse_lowlevel_new() failed\n", __FUNCTION__);
		return;
	}

	if (!(m->channel = fuse_kern_chan_new(m->channel_fd)))
	{
		fprintf(stderr, "%s(): fuse_kern_chan_new() failed\n", __FUNCTION__);
		return;
	}

	fuse_session_add_chan(m->session, m->channel);

	if (fuse_chan_bufsize(m->channel) != fuse_serve_mount_chan_bufsize())
		fprintf(stderr, "bufsizes differ!\n");

	m->mounted = 1;

	printf("Mounted \"%s\" from %s\n", m->fstitch_path, modman_name_cfs(m->cfs));
}
Пример #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;
}
Пример #4
0
static int fuse_loop_start_thread(struct fuse_mt *mt)
{
	int res;
	struct fuse_worker *w = malloc(sizeof(struct fuse_worker));
	if (!w) {
		fprintf(stderr, "fuse: failed to allocate worker structure\n");
		return -1;
	}
	memset(w, 0, sizeof(struct fuse_worker));
	w->bufsize = fuse_chan_bufsize(mt->prevch);
	w->buf = malloc(w->bufsize);
	w->mt = mt;
	if (!w->buf) {
		fprintf(stderr, "fuse: failed to allocate read buffer\n");
		free(w);
		return -1;
	}

	res = fuse_start_thread(&w->thread_id, fuse_do_work, w);
	if (res == -1) {
		free(w->buf);
		free(w);
		return -1;
	}
	list_add_worker(w, &mt->main);
	mt->numavail ++;
	mt->numworker ++;

	return 0;
}
Пример #5
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;
}
Пример #6
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;
}
Пример #7
0
static int fuse_start_thread(struct fuse_mt *mt)
{
	sigset_t oldset;
	sigset_t newset;
	int res;
	pthread_attr_t attr;
	char *stack_size;
	struct fuse_worker *w = malloc(sizeof(struct fuse_worker));
	if (!w) {
		fprintf(stderr, "fuse: failed to allocate worker structure\n");
		return -1;
	}
	memset(w, 0, sizeof(struct fuse_worker));
	w->bufsize = fuse_chan_bufsize(mt->prevch);
	w->buf = malloc(w->bufsize);
	w->mt = mt;
	if (!w->buf) {
		fprintf(stderr, "fuse: failed to allocate read buffer\n");
		free(w);
		return -1;
	}

	/* 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(&w->thread_id, &attr, fuse_do_work, w);
	pthread_sigmask(SIG_SETMASK, &oldset, NULL);
	pthread_attr_destroy(&attr);
	if (res != 0) {
		fprintf(stderr, "fuse: error creating thread: %s\n",
			strerror(res));
		free(w->buf);
		free(w);
		return -1;
	}
	list_add_worker(w, &mt->main);
	mt->numavail ++;
	mt->numworker ++;

	return 0;
}
Пример #8
0
static void
fuseMount(CompDisplay *d)
{
   char *mountPoint;
   struct fuse_args args = FUSE_ARGS_INIT(0, NULL);

   FUSE_DISPLAY(d);

   mountPoint = strdup(fd->opt[FUSE_DISPLAY_OPTION_MOUNT_POINT].value.s);
   if (!mountPoint)
     return;

   fuse_opt_add_arg(&args, "");
   fuse_opt_add_arg(&args, "-o");
   fuse_opt_add_arg(&args, "allow_root");

   fd->channel = fuse_mount(mountPoint, &args);
   if (!fd->channel)
     {
        fuse_opt_free_args(&args);
        free(mountPoint);
        return;
     }

   fuse_opt_free_args(&args);

   fd->buffer = malloc(fuse_chan_bufsize(fd->channel));
   if (!fd->buffer)
     {
        fuse_unmount(mountPoint, fd->channel);
        free(mountPoint);
        fd->channel = NULL;
        return;
     }

   fd->mountPoint = mountPoint;

   fuse_session_add_chan(fd->session, fd->channel);

   fd->watchFdHandle = compAddWatchFd(fuse_chan_fd(fd->channel),
                                      POLLIN | POLLPRI | POLLHUP | POLLERR,
                                      fuseProcessMessages,
                                      d);
}
Пример #9
0
int
zfsfuse_newfs(char *mntpoint, struct fuse_chan *ch)
{
	fuse_fs_info_t info = { 0 };

	info.fd = fuse_chan_fd(ch);
	info.bufsize = fuse_chan_bufsize(ch);
	info.ch = ch;
	info.se = fuse_chan_session(ch);
	info.mntlen = strlen(mntpoint);

	if(write(newfs_fd[1], &info, sizeof(info)) != sizeof(info)) {
		perror("Warning (while writing fsinfo to newfs_fd)");
		return -1;
	}

	if(write(newfs_fd[1], mntpoint, info.mntlen) != info.mntlen) {
		perror("Warning (while writing mntpoint to newfs_fd)");
		return -1;
	}
	return 0;
}
void cuse_lowlevel_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
	struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
	struct cuse_init_out outarg;
	struct fuse_ll *f = req->f;
	struct cuse_data *cd = f->cuse_data;
	size_t bufsize = fuse_chan_bufsize(req->ch);
	struct cuse_lowlevel_ops *clop = req_clop(req);

	(void) nodeid;
	if (f->debug) {
		fprintf(stderr, "CUSE_INIT: %u.%u\n", arg->major, arg->minor);
		fprintf(stderr, "flags=0x%08x\n", arg->flags);
	}
	f->conn.proto_major = arg->major;
	f->conn.proto_minor = arg->minor;
	f->conn.capable = 0;
	f->conn.want = 0;

	if (arg->major < 7) {
		fprintf(stderr, "cuse: unsupported protocol version: %u.%u\n",
			arg->major, arg->minor);
		fuse_reply_err(req, EPROTO);
		return;
	}

	if (bufsize < FUSE_MIN_READ_BUFFER) {
		fprintf(stderr, "cuse: warning: buffer size too small: %zu\n",
			bufsize);
		bufsize = FUSE_MIN_READ_BUFFER;
	}

	bufsize -= 4096;
	if (bufsize < f->conn.max_write)
		f->conn.max_write = bufsize;

	f->got_init = 1;
	if (f->op.init)
		f->op.init(f->userdata, &f->conn);

	memset(&outarg, 0, sizeof(outarg));
	outarg.major = FUSE_KERNEL_VERSION;
	outarg.minor = FUSE_KERNEL_MINOR_VERSION;
	outarg.flags = cd->flags;
	outarg.max_read = cd->max_read;
	outarg.max_write = f->conn.max_write;
	outarg.dev_major = cd->dev_major;
	outarg.dev_minor = cd->dev_minor;

	if (f->debug) {
		fprintf(stderr, "   CUSE_INIT: %u.%u\n",
			outarg.major, outarg.minor);
		fprintf(stderr, "   flags=0x%08x\n", outarg.flags);
		fprintf(stderr, "   max_read=0x%08x\n", outarg.max_read);
		fprintf(stderr, "   max_write=0x%08x\n", outarg.max_write);
		fprintf(stderr, "   dev_major=%u\n", outarg.dev_major);
		fprintf(stderr, "   dev_minor=%u\n", outarg.dev_minor);
		fprintf(stderr, "   dev_info: %.*s\n", cd->dev_info_len,
			cd->dev_info);
	}

	cuse_reply_init(req, &outarg, cd->dev_info, cd->dev_info_len);

	if (clop->init_done)
		clop->init_done(f->userdata);

	fuse_free_req(req);
}
Пример #11
0
size_t fuse_serve_mount_chan_bufsize(void)
{
	assert(root && root->mounted);
	return fuse_chan_bufsize(root->channel);
}
Пример #12
0
/**
*  Init of the pseudo fuse thread 

  @param ch : initial channel
  @param se : initial session
  @param rozofs_fuse_buffer_count : number of request buffers (corresponds to the number of fuse save context)  
  
  @retval 0 on success
  @retval -1 on error
*/
int rozofs_fuse_init(struct fuse_chan *ch,struct fuse_session *se,int rozofs_fuse_buffer_count)
{
  int status = 0;
  
//   return 0;
   
  int fileflags;
  rozofs_fuse_ctx_p = malloc(sizeof (rozofs_fuse_ctx_t));
  if (rozofs_fuse_ctx_p == NULL) 
  {
    /*
    ** cannot allocate memory for fuse rozofs context
    */
    return -1;
  }
  /*
  ** clear read/write merge stats table
  */
  memset(rozofs_write_merge_stats_tab,0,sizeof(uint64_t)*RZ_FUSE_WRITE_MAX);
  memset (rozofs_write_buf_section_table,0,sizeof(uint64_t)*ROZOFS_FUSE_NB_OF_BUSIZE_SECTION_MAX);
  memset (rozofs_read_buf_section_table,0,sizeof(uint64_t)*ROZOFS_FUSE_NB_OF_BUSIZE_SECTION_MAX);
  memset(&rozofs_fuse_read_write_stats_buf,0,sizeof(rozofs_fuse_read_write_stats));
  /*
  ** init of the context
  */
  rozofs_fuse_ctx_p->fuseReqPoolRef = NULL;
  rozofs_fuse_ctx_p->ch             = NULL;
  rozofs_fuse_ctx_p->se             = se;
  rozofs_fuse_ctx_p->bufsize        = 0; 
  rozofs_fuse_ctx_p->buf_fuse_req_p = NULL;
  rozofs_fuse_ctx_p->initBufCount   = rozofs_fuse_buffer_count;
  
  while (1)
  {
     /*
     ** get the receive buffer size for former channel in order to create the request distributor
     */
     int bufsize = fuse_chan_bufsize(ch);
     rozofs_fuse_ctx_p->bufsize = bufsize;
     /*
     ** create the pool
     */
     rozofs_fuse_ctx_p->fuseReqPoolRef = ruc_buf_poolCreate(rozofs_fuse_buffer_count,sizeof(rozofs_fuse_save_ctx_t));
     if (rozofs_fuse_ctx_p->fuseReqPoolRef == NULL)
     {
        ERRLOG "rozofs_fuse_init buffer pool creation error(%d,%d)", (int)rozofs_fuse_buffer_count, (int)sizeof(rozofs_fuse_save_ctx_t) ENDERRLOG ;
        status = -1;
        break;
     }
     /*
     ** allocate a buffer for receiving the fuse request
     */
     rozofs_fuse_ctx_p->buf_fuse_req_p = malloc(bufsize);
     if (rozofs_fuse_ctx_p == NULL) 
     {     
        ERRLOG "rozofs_fuse_init out of memory %d", bufsize ENDERRLOG ;
        status = -1;
        break;     
     }
     /*
     ** get the fd of the channel
     */
     rozofs_fuse_ctx_p->fd = fuse_chan_fd(ch);
     /*
     ** create a new channel with the specific operation for rozofs (non-blocking)
     */  
     rozofs_fuse_ctx_p->ch = fuse_chan_new(&rozofs_fuse_ch_ops,fuse_chan_fd(ch),fuse_chan_bufsize(ch),rozofs_fuse_ctx_p);  
     if (rozofs_fuse_ctx_p->ch == NULL)
     {
        ERRLOG "rozofs_fuse_init fuse_chan_new error"  ENDERRLOG ;
        status = -1;
        break;          
     }
     /*
     ** remove the association between the initial session and channel
     */
     fuse_session_remove_chan(ch);  
     /*
     ** OK, now add the new channel
     */
     fuse_session_add_chan(se,rozofs_fuse_ctx_p->ch );  
     /*
     ** set the channel in non blocking mode
     */
     if((fileflags=fcntl(rozofs_fuse_ctx_p->fd,F_GETFL,0))==-1)
     {
       RUC_WARNING(errno);
       status = -1; 
       break;   
     }

     if((fcntl(rozofs_fuse_ctx_p->fd,F_SETFL,fileflags|O_NDELAY))==-1)
     {
       RUC_WARNING(errno);
       status = -1; 
       break;   
     }
     /*
     ** perform the connection with the socket controller
     */
   /*
   ** OK, we are almost done, just need to connect with the socket controller
   */
   rozofs_fuse_ctx_p->connectionId = ruc_sockctl_connect(rozofs_fuse_ctx_p->fd,  // Reference of the socket
                                              "rozofs_fuse",                 // name of the socket
                                              3,                             // Priority within the socket controller
                                              (void*)rozofs_fuse_ctx_p,      // user param for socketcontroller callback
                                              &rozofs_fuse_callBack_sock);   // Default callbacks
    if (rozofs_fuse_ctx_p->connectionId == NULL)
    {
       /*
       ** Fail to connect with the socket controller
       */
       RUC_WARNING(-1);
       status = -1; 
       break;   
    } 

     status = 0;
     break;
  }
  
  uma_dbg_addTopic("fuse", rozofs_fuse_show);
  return status;
  
}
Пример #13
0
static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
    struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
    struct fuse_init_out outarg;
    struct fuse_ll *f = req->f;
    size_t bufsize = fuse_chan_bufsize(req->ch);

    (void) nodeid;
    if (f->debug) {
        fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
        if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
            fprintf(stderr, "flags=0x%08x\n", arg->flags);
            fprintf(stderr, "max_readahead=0x%08x\n", arg->max_readahead);
        }
    }
    f->conn.proto_major = arg->major;
    f->conn.proto_minor = arg->minor;

    if (arg->major < 7) {
        fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
                arg->major, arg->minor);
        fuse_reply_err(req, EPROTO);
        return;
    }

    if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
        if (f->conn.async_read)
            f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
        if (arg->max_readahead < f->conn.max_readahead)
            f->conn.max_readahead = arg->max_readahead;
    } else {
        f->conn.async_read = 0;
        f->conn.max_readahead = 0;
    }

    if (bufsize < FUSE_MIN_READ_BUFFER) {
        fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
                bufsize);
        bufsize = FUSE_MIN_READ_BUFFER;
    }

    bufsize -= 4096;
    if (bufsize < f->conn.max_write)
        f->conn.max_write = bufsize;

    f->got_init = 1;
    if (f->op.init)
        f->op.init(f->userdata, &f->conn);

    memset(&outarg, 0, sizeof(outarg));
    outarg.major = FUSE_KERNEL_VERSION;
    outarg.minor = FUSE_KERNEL_MINOR_VERSION;
    if (f->conn.async_read)
        outarg.flags |= FUSE_ASYNC_READ;
    if (f->op.getlk && f->op.setlk)
        outarg.flags |= FUSE_POSIX_LOCKS;
    outarg.max_readahead = f->conn.max_readahead;
    outarg.max_write = f->conn.max_write;

    if (f->debug) {
        fprintf(stderr, "   INIT: %u.%u\n", outarg.major, outarg.minor);
        fprintf(stderr, "   flags=0x%08x\n", outarg.flags);
        fprintf(stderr, "   max_readahead=0x%08x\n", outarg.max_readahead);
        fprintf(stderr, "   max_write=0x%08x\n", outarg.max_write);
    }

    send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
}
static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
	struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
	struct fuse_init_out outarg;
	struct fuse_ll *f = req->f;
	size_t bufsize = fuse_chan_bufsize(req->ch);

	(void) nodeid;
	if (f->debug) {
		fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
		if (arg->major == 7 && arg->minor >= 6) {
			fprintf(stderr, "flags=0x%08x\n", arg->flags);
			fprintf(stderr, "max_readahead=0x%08x\n",
				arg->max_readahead);
		}
	}
	f->conn.proto_major = arg->major;
	f->conn.proto_minor = arg->minor;
	f->conn.capable = 0;
	f->conn.want = 0;

	memset(&outarg, 0, sizeof(outarg));
	outarg.major = FUSE_KERNEL_VERSION;
	outarg.minor = FUSE_KERNEL_MINOR_VERSION;

	if (arg->major < 7) {
		fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
			arg->major, arg->minor);
		fuse_reply_err(req, EPROTO);
		return;
	}

	if (arg->major > 7) {
		/* Wait for a second INIT request with a 7.X version */
		send_reply_ok(req, &outarg, sizeof(outarg));
		return;
	}

	if (arg->minor >= 6) {
		if (f->conn.async_read)
			f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
		if (arg->max_readahead < f->conn.max_readahead)
			f->conn.max_readahead = arg->max_readahead;
		if (arg->flags & FUSE_ASYNC_READ)
			f->conn.capable |= FUSE_CAP_ASYNC_READ;
		if (arg->flags & FUSE_POSIX_LOCKS)
			f->conn.capable |= FUSE_CAP_POSIX_LOCKS;
		if (arg->flags & FUSE_ATOMIC_O_TRUNC)
			f->conn.capable |= FUSE_CAP_ATOMIC_O_TRUNC;
		if (arg->flags & FUSE_EXPORT_SUPPORT)
			f->conn.capable |= FUSE_CAP_EXPORT_SUPPORT;
		if (arg->flags & FUSE_BIG_WRITES)
			f->conn.capable |= FUSE_CAP_BIG_WRITES;
		if (arg->flags & FUSE_DONT_MASK)
			f->conn.capable |= FUSE_CAP_DONT_MASK;
	} else {
		f->conn.async_read = 0;
		f->conn.max_readahead = 0;
	}

	if (f->atomic_o_trunc)
		f->conn.want |= FUSE_CAP_ATOMIC_O_TRUNC;
	if (f->op.getlk && f->op.setlk && !f->no_remote_lock)
		f->conn.want |= FUSE_CAP_POSIX_LOCKS;
	if (f->big_writes)
		f->conn.want |= FUSE_CAP_BIG_WRITES;

	if (bufsize < FUSE_MIN_READ_BUFFER) {
		fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
			bufsize);
		bufsize = FUSE_MIN_READ_BUFFER;
	}

	bufsize -= 4096;
	if (bufsize < f->conn.max_write)
		f->conn.max_write = bufsize;

	f->got_init = 1;
	if (f->op.init)
		f->op.init(f->userdata, &f->conn);

	if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ))
		outarg.flags |= FUSE_ASYNC_READ;
	if (f->conn.want & FUSE_CAP_POSIX_LOCKS)
		outarg.flags |= FUSE_POSIX_LOCKS;
	if (f->conn.want & FUSE_CAP_ATOMIC_O_TRUNC)
		outarg.flags |= FUSE_ATOMIC_O_TRUNC;
	if (f->conn.want & FUSE_CAP_EXPORT_SUPPORT)
		outarg.flags |= FUSE_EXPORT_SUPPORT;
	if (f->conn.want & FUSE_CAP_BIG_WRITES)
		outarg.flags |= FUSE_BIG_WRITES;
	if (f->conn.want & FUSE_CAP_DONT_MASK)
		outarg.flags |= FUSE_DONT_MASK;
	outarg.max_readahead = f->conn.max_readahead;
	outarg.max_write = f->conn.max_write;

	if (f->debug) {
		fprintf(stderr, "   INIT: %u.%u\n", outarg.major, outarg.minor);
		fprintf(stderr, "   flags=0x%08x\n", outarg.flags);
		fprintf(stderr, "   max_readahead=0x%08x\n",
			outarg.max_readahead);
		fprintf(stderr, "   max_write=0x%08x\n", outarg.max_write);
	}

	send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
}
static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
    const struct fuse_init_in *arg = (const struct fuse_init_in *) inarg;
    struct fuse_init_out outarg;
    struct fuse_ll *f = req->f;
    size_t bufsize = fuse_chan_bufsize(req->ch);

    (void) nodeid;
    if (f->debug) {
        fprintf(stderr, "INIT: %u.%u\n", arg->major, arg->minor);
        if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
            fprintf(stderr, "flags=0x%08x\n", arg->flags);
            fprintf(stderr, "max_readahead=0x%08x\n", arg->max_readahead);
        }
    }
    f->conn.proto_major = arg->major;
    f->conn.proto_minor = arg->minor;

    if (arg->major < 7) {
        fprintf(stderr, "fuse: unsupported protocol version: %u.%u\n",
                arg->major, arg->minor);
        fuse_reply_err(req, EPROTO);
        return;
    }

    if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
        if (f->conn.async_read)
            f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
        if (arg->max_readahead < f->conn.max_readahead)
            f->conn.max_readahead = arg->max_readahead;
#ifdef POSIXACLS
	if (arg->flags & FUSE_DONT_MASK)
	    f->conn.capable |= FUSE_CAP_DONT_MASK;
#endif
    } else {
        f->conn.async_read = 0;
        f->conn.max_readahead = 0;
    }

    if (bufsize < FUSE_MIN_READ_BUFFER) {
        fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
                bufsize);
        bufsize = FUSE_MIN_READ_BUFFER;
    }

    bufsize -= 4096;
    if (bufsize < f->conn.max_write)
        f->conn.max_write = bufsize;

    f->got_init = 1;
    if (f->op.init)
        f->op.init(f->userdata, &f->conn);

    memset(&outarg, 0, sizeof(outarg));
    outarg.major = FUSE_KERNEL_VERSION;
	/*
	 * if POSIXACLS is not set, protocol 7.8 provides a good
	 * compatibility with older kernel modules.
	 * if POSIXACLS is set, we try to use protocol 7.12 supposed
	 * to have the ability to process the umask conditionnally,
	 * but, when using an older kernel module, we fallback to 7.8
	 */
#ifdef POSIXACLS
    if (arg->major > 7 || (arg->major == 7 && arg->minor >= 12))
	    outarg.minor = FUSE_KERNEL_MINOR_VERSION;
    else
	    outarg.minor = FUSE_KERNEL_MINOR_FALLBACK;
#else
    outarg.minor = FUSE_KERNEL_MINOR_VERSION;
#endif
    if (f->conn.async_read)
        outarg.flags |= FUSE_ASYNC_READ;
    if (f->op.getlk && f->op.setlk)
        outarg.flags |= FUSE_POSIX_LOCKS;
#ifdef POSIXACLS
    if (f->conn.want & FUSE_CAP_DONT_MASK)
	outarg.flags |= FUSE_DONT_MASK;
#endif
    outarg.flags |= FUSE_BIG_WRITES	 ;
    outarg.max_readahead = f->conn.max_readahead;
    outarg.max_write = f->conn.max_write;

    if (f->debug) {
        fprintf(stderr, "   INIT: %u.%u\n", outarg.major, outarg.minor);
        fprintf(stderr, "   flags=0x%08x\n", outarg.flags);
        fprintf(stderr, "   max_readahead=0x%08x\n", outarg.max_readahead);
        fprintf(stderr, "   max_write=0x%08x\n", outarg.max_write);
    }

    send_reply_ok(req, &outarg, arg->minor < 5 ? 8 : sizeof(outarg));
}
Пример #16
0
/**
*  Init of the pseudo fuse thread 

  @param ch : initial channel
  @param se : initial session
  @param rozofs_fuse_buffer_count : number of request buffers (corresponds to the number of fuse save context)  
  
  @retval 0 on success
  @retval -1 on error
*/
int rozofs_fuse_init(struct fuse_chan *ch,struct fuse_session *se,int rozofs_fuse_buffer_count)
{
  int status = 0;
  int i;
  
//   return 0;

  fuse_sharemem_init_done = 0;   
  
  int fileflags;
  rozofs_fuse_ctx_p = malloc(sizeof (rozofs_fuse_ctx_t));
  if (rozofs_fuse_ctx_p == NULL) 
  {
    /*
    ** cannot allocate memory for fuse rozofs context
    */
    return -1;
  }
  memset(rozofs_fuse_ctx_p,0,sizeof (rozofs_fuse_ctx_t));
  /*
  ** clear read/write merge stats table
  */
  memset(rozofs_write_merge_stats_tab,0,sizeof(uint64_t)*RZ_FUSE_WRITE_MAX);
  memset (rozofs_write_buf_section_table,0,sizeof(uint64_t)*ROZOFS_FUSE_NB_OF_BUSIZE_SECTION_MAX);
  memset (rozofs_read_buf_section_table,0,sizeof(uint64_t)*ROZOFS_FUSE_NB_OF_BUSIZE_SECTION_MAX);
  memset(&rozofs_fuse_read_write_stats_buf,0,sizeof(rozofs_fuse_read_write_stats));
  /*
  ** init of the context
  */
  rozofs_fuse_ctx_p->fuseReqPoolRef = NULL;
  rozofs_fuse_ctx_p->ch             = NULL;
  rozofs_fuse_ctx_p->se             = se;
  rozofs_fuse_ctx_p->bufsize        = 0; 
  rozofs_fuse_ctx_p->buf_fuse_req_p = NULL;
  rozofs_fuse_ctx_p->dir_attr_invalidate = 0;
  rozofs_fuse_ctx_p->initBufCount   = rozofs_fuse_buffer_count;
  
  while (1)
  {
     /*
     ** get the receive buffer size for former channel in order to create the request distributor:
     ** note: by default the fuse buffer is 4K+128K: for RozoFS the payload can reach 512K (x4)
     */
     int bufsize = fuse_chan_bufsize(ch)*4;
     rozofs_fuse_ctx_p->bufsize = bufsize;
     /*
     ** create the distributor fro receiving data from fuse kernel
     */
     status = rozofs_fuse_init_rcv_buffer_pool(ROZOFS_FUSE_RECV_BUF_COUNT,bufsize);
     if (status < 0)
     {
        severe( "rozofs_fuse_init fuse buffer pool creation error(%d,%d)", (int)ROZOFS_FUSE_RECV_BUF_COUNT, (int)bufsize ) ;
        status = -1;
        break;     
     
     }
     /*
     ** create the pool
     */
     rozofs_fuse_ctx_p->fuseReqPoolRef = ruc_buf_poolCreate(rozofs_fuse_buffer_count,sizeof(rozofs_fuse_save_ctx_t));
     if (rozofs_fuse_ctx_p->fuseReqPoolRef == NULL)
     {
        severe( "rozofs_fuse_init buffer pool creation error(%d,%d)", (int)rozofs_fuse_buffer_count, (int)sizeof(rozofs_fuse_save_ctx_t) ) ;
        status = -1;
        break;
     }
     ruc_buffer_debug_register_pool("fuseCtx",  rozofs_fuse_ctx_p->fuseReqPoolRef);
     /*
     ** Allocate a head of list for queueing pending lookup requests
     */
     for (i=0; i< ROZOFS_MAX_LKUP_QUEUE ; i++)
     {
       ruc_listHdrInit(&rozofs_lookup_queue[i]);
     }
     
     
     /*
     ** allocate a buffer for receiving the fuse request
     */
     rozofs_fuse_ctx_p->buf_fuse_req_p = malloc(bufsize);
     if (rozofs_fuse_ctx_p == NULL) 
     {     
        severe( "rozofs_fuse_init out of memory %d", bufsize ) ;
        status = -1;
        break;     
     }
     /*
     ** get the fd of the channel
     */
     rozofs_fuse_ctx_p->fd = fuse_chan_fd(ch);
     /*
     ** wait the end of the share memroy init prior providing it to fuse
     */
     while (rozofs_shared_mem_init_done == 0) sleep(1);  
     /*
     ** create a new channel with the specific operation for rozofs (non-blocking)
     */  
     rozofs_fuse_ctx_p->ch = fuse_chan_new(&rozofs_fuse_ch_ops,fuse_chan_fd(ch),bufsize,rozofs_fuse_ctx_p);  
     if (rozofs_fuse_ctx_p->ch == NULL)
     {
        severe( "rozofs_fuse_init fuse_chan_new error"  ) ;
        status = -1;
        break;          
     }
     /*
     ** remove the association between the initial session and channel
     */
     fuse_session_remove_chan(ch);  
     /*
     ** OK, now add the new channel
     */
     fuse_session_add_chan(se,rozofs_fuse_ctx_p->ch );  
     /*
     ** set the channel in non blocking mode
     */
     if((fileflags=fcntl(rozofs_fuse_ctx_p->fd,F_GETFL,0))==-1)
     {
       RUC_WARNING(errno);
       status = -1; 
       break;   
     }

     if((fcntl(rozofs_fuse_ctx_p->fd,F_SETFL,fileflags|O_NDELAY))==-1)
     {
       RUC_WARNING(errno);
       status = -1; 
       break;   
     }
     /*
     ** send XON to the fuse channel
     */
     {
        int ret;
	rozofs_fuse_ctx_p->ioctl_supported = 1;
	rozofs_fuse_ctx_p->data_xon        = 1;
     
        while(1)
	{	
	  ret = ioctl(rozofs_fuse_ctx_p->fd,1,NULL);
	  if (ret < 0) 
	  {
	     warning("ioctl error %s",strerror(errno));
	     rozofs_fuse_ctx_p->ioctl_supported = 0;
	     break;

	  }
          if (rozofs_fuse_ctx_p->dir_attr_invalidate == 0)
	  {
	    ret = ioctl(rozofs_fuse_ctx_p->fd,3,NULL);
	    if (ret < 0) 
	    {
	       warning("ioctl error %s",strerror(errno));
//	       rozofs_fuse_ctx_p->ioctl_supported = 0;
	       rozofs_fuse_ctx_p->dir_attr_invalidate = 1;
	       break;
	    }		
	  }
	  break;     
        }
     }
     /*
     ** perform the connection with the socket controller
     */
   /*
   ** OK, we are almost done, just need to connect with the socket controller
   */
   rozofs_fuse_ctx_p->connectionId = ruc_sockctl_connect(rozofs_fuse_ctx_p->fd,  // Reference of the socket
                                              "rozofs_fuse",                 // name of the socket
                                              3,                             // Priority within the socket controller
                                              (void*)rozofs_fuse_ctx_p,      // user param for socketcontroller callback
                                              &rozofs_fuse_callBack_sock);   // Default callbacks
    if (rozofs_fuse_ctx_p->connectionId == NULL)
    {
       /*
       ** Fail to connect with the socket controller
       */
       RUC_WARNING(-1);
       status = -1; 
       break;   
    } 
    rozofs_fuse_get_ticker();

     status = 0;
     break;
  }
  /*
  ** attach the callback on socket controller
  */
//#warning no poller
  ruc_sockCtrl_attach_applicative_poller(rozofs_fuse_scheduler_entry_point); 
  for(i = 0; i < 3;i++) fuse_profile[i] = 0;
  
  uma_dbg_addTopic("fuse", rozofs_fuse_show);
  return status;
  
}