Ejemplo n.º 1
0
// Return the amount of time to wait between sched_run_callbacks() calls
static struct timeval fuse_serve_timeout(void)
{
	struct timeval tv = { .tv_sec = 0, .tv_usec = 1000000/HZ };
	return tv;
}

struct callback_list {
	unlock_callback_t callback;
	void * data;
	int count;
	struct callback_list * next;
};
static struct callback_list * callbacks;

int fstitchd_unlock_callback(unlock_callback_t callback, void * data)
{
	if(callbacks && callbacks->callback == callback && callbacks->data == data)
		callbacks->count++;
	else
	{
		struct callback_list * list = malloc(sizeof(*list));
		if(!list)
			return -ENOMEM;
		list->callback = callback;
		list->data = data;
		list->count = 1;
		list->next = callbacks;
		callbacks = list;
	}
	return 0;
}

// Adapted from FUSE's lib/fuse_loop.c to support sched callbacks and multiple mounts
int fuse_serve_loop(void)
{
	struct timeval tv;
	mount_t ** mp;
	int r;
	Dprintf("%s()\n", __FUNCTION__);

	if (!root_cfs)
	{
		fprintf(stderr, "%s(): no root cfs was specified; not running.\n", __FUNCTION__);
		return -1;
	}

	if ((r = fuse_serve_mount_load_mounts()) < 0)
	{
		fprintf(stderr, "%s(): fuse_serve_load_mounts: %d\n", __FUNCTION__, r);
		return r;
	}

	serving = 1;
	tv = fuse_serve_timeout();

	while ((mp = fuse_serve_mounts()) && mp && mp[0])
	{
		fd_set rfds;
		int max_fd = 0;
		struct timeval it_start, it_end;

		FD_ZERO(&rfds);

		if (shutdown_pipe[0] != -1)
		{
			FD_SET(shutdown_pipe[0], &rfds);
			if (shutdown_pipe[0] > max_fd)
				max_fd = shutdown_pipe[0];
		}

		FD_SET(remove_activity, &rfds);
		if (remove_activity > max_fd)
			max_fd = remove_activity;

		for (mp = fuse_serve_mounts(); mp && *mp; mp++)
		{
			if ((*mp)->mounted && !fuse_session_exited((*mp)->session))
			{
				//printf("[\"%s\"]", mount->fstitch_path); fflush(stdout); // debug
				int mount_fd = fuse_chan_fd((*mp)->channel);
				FD_SET(mount_fd, &rfds);
				if (mount_fd > max_fd)
					max_fd = mount_fd;
			}
		}

		r = select(max_fd+1, &rfds, NULL, NULL, &tv);

		if (r == 0)
		{
			//printf("."); fflush(stdout); // debugging output
			sched_run_callbacks();
			tv = fuse_serve_timeout();
		}
		else if (r < 0)
		{
			if (errno != EINTR)
				perror("select");
			//printf("!\n"); fflush(stdout); // debugging output
			tv = fuse_serve_timeout(); // tv may have become undefined
		}
		else
		{
			if (gettimeofday(&it_start, NULL) == -1)
			{
				perror("gettimeofday");
				break;
			}

			for (mp = fuse_serve_mounts(); mp && *mp; mp++)
			{
				if ((*mp)->mounted && FD_ISSET((*mp)->channel_fd, &rfds))
				{
					r = fuse_chan_receive((*mp)->channel, channel_buf, channel_buf_len);
					if(r <= 0)
						fprintf(stderr, "fuse_chan_receive() returned %d, ignoring!\n", r);
					//assert(r > 0); // this happens during shutdown on MacFUSE...

					Dprintf("fuse_serve: request for mount \"%s\"\n", (*mp)->fstitch_path);
					fuse_session_process((*mp)->session, channel_buf, r, (*mp)->channel);
					sched_run_cleanup();
				}
			}

			if (shutdown_pipe[0] != -1 && FD_ISSET(shutdown_pipe[0], &rfds))
			{
				// Start unmounting all filesystems
				// Looping will stop once all filesystems are unmounted
				ignore_shutdown_signals();
				if (fuse_serve_mount_start_shutdown() < 0)
				{
					fprintf(stderr, "fuse_serve_mount_start_shutdown() failed, exiting fuse_serve_loop()\n");
					return -1;
				}
			}

			if (FD_ISSET(remove_activity, &rfds))
			{
				if (fuse_serve_mount_step_remove() < 0)
				{
					fprintf(stderr, "fuse_serve_mount_step_remove() failed, exiting fuse_serve_loop()\n");
					return -1;
				}
			}


			if (gettimeofday(&it_end, NULL) == -1)
			{
				perror("gettimeofday");
				break;
			}
			tv = time_subtract(tv, time_elapsed(it_start, it_end));
		}

		while(callbacks)
		{
			struct callback_list * first = callbacks;
			callbacks = first->next;
			first->callback(first->data, first->count);
			free(first);
		}
	}

	serving = 0;

	return 0;
}
Ejemplo n.º 2
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;
  
}
Ejemplo n.º 3
0
static void fuse_unmount_common(const char *mountpoint, struct fuse_chan *ch)
{
	int fd = ch ? fuse_chan_fd(ch) : -1;
	fuse_kern_unmount(mountpoint, fd);
	fuse_chan_destroy(ch);
}