int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent,
                                     const char *name, size_t namelen)
{
	struct fuse_notify_inval_entry_out outarg;
	struct fuse_ll *f;
	struct iovec iov[3];

	if (!ch)
		return -EINVAL;

	f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
	if (!f)
		return -ENODEV;

	outarg.parent = parent;
	outarg.namelen = namelen;
	outarg.padding = 0;

	iov[1].iov_base = &outarg;
	iov[1].iov_len = sizeof(outarg);
	iov[2].iov_base = (void *)name;
	iov[2].iov_len = namelen + 1;

	return send_notify_iov(f, ch, FUSE_NOTIFY_INVAL_ENTRY, iov, 3);
}
Example #2
0
/**
*  Rozofs_fuse channel send:
*  Since Rozofs operates in non-blocking mode it cannot rely on the 
   default fuse_kern_chan_send() operation of fuse since if there is
   a congestion on the fuse device, the response or notification will
   be lost since the caller release the ressource allocated for sending
   the response once it returns from fuse_kern_chan_send().
   To avoid that issue, rozofs MUST be tracked of the response that has
   not been sent and must save it in some internals buffers.
   
    @param ch: fuse channel (contains the reference of the file descriptor to use
    @param iov: list of the vectors to send
    @param count: number of vectors to send
    
    @retval 0 on success 
    @retval < 0 on error
*/
int rozofs_fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[],
			       size_t count)
{
	if (iov) {
		ssize_t res = writev(fuse_chan_fd(ch), iov, count);
		int err = errno;

		if (res == -1) {
			struct fuse_session *se = fuse_chan_session(ch);

			assert(se != NULL);
            
            if(err == EAGAIN)
            {
              /*
              ** fuse device is congestion, so we store the reply and assert 
              ** the congestion flag in the rozofs_fuse context
              */
              
              return 0;
            
            }
			/* ENOENT means the operation was interrupted */
			if (!fuse_session_exited(se) && err != ENOENT)
				perror("fuse: writing device");
			return -err;
		}
	}
	return 0;
}
Example #3
0
/**
* internal function that is called from processing a message that 
  has been queued on the /dev/fuse socket. That function is
  inherited from fuse_kern_chan_receive
  
  @param chp : pointer to the channel
  @param  buf: pointer to the buffer where data will be copied
  @param  size : max size of the receive buffer
 
  @retval > 0 : number of byte read
  @retval = 0 : session has been exited
  @retval  < 0 : error
 */
int rozofs_fuse_kern_chan_receive(struct fuse_chan **chp, char *buf,
				  size_t size)
{
	struct fuse_chan *ch = *chp;
	int err;
	ssize_t res;
	struct fuse_session *se = fuse_chan_session(ch);
	assert(se != NULL);

restart:
	res = read(fuse_chan_fd(ch), buf, size);

	if (fuse_session_exited(se))
		return 0;
	if (res == -1) 
	{
	  /* ENOENT means the operation was interrupted, it's safe
	  to restart */
	  err = errno;
	  if (err == ENOENT)
	  {
	    rozofs_fuse_req_enoent_count++;
	    goto restart;
	  }
	  if (err == ENODEV) {
	    severe("Exit from RozofsMount required!!!");
	    fuse_session_exit(se);
	    rozofs_exit();
	    return 0;
	  }
	  /* Errors occurring during normal operation: EINTR (read
	     interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem
	     umounted) */
	  if (err != EINTR && err != EAGAIN) severe("fuse: reading device");
	  if ((err == EAGAIN)|| (err == EINTR)) rozofs_fuse_req_eagain_count++;
	  return -err;
	}
#if 0
	if ((size_t) res < sizeof(struct fuse_in_header)) {
		fprintf(stderr, "short read on fuse device\n");
		return -EIO;
	}
#endif
	rozofs_fuse_req_count++;
	rozofs_fuse_req_byte_in+=res;
	return res;
}
Example #4
0
static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[],
			       size_t count)
{
	if (iov) {
		ssize_t res = writev(fuse_chan_fd(ch), iov, count);
		int err = errno;

		if (res == -1) {
			struct fuse_session *se = fuse_chan_session(ch);

			assert(se != NULL);

			/* ENOENT means the operation was interrupted */
			if (!fuse_session_exited(se) && err != ENOENT)
				perror("fuse: writing device");
			return -err;
		}
	}
	return 0;
}
Example #5
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;
}
Example #6
0
static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf,
				  size_t size)
{
	struct fuse_chan *ch = *chp;
	int err;
	ssize_t res;
	struct fuse_session *se = fuse_chan_session(ch);
	assert(se != NULL);

restart:
	res = read(fuse_chan_fd(ch), buf, size);
	err = errno;

	if (fuse_session_exited(se))
		return 0;
	if (res == -1) {
		/* ENOENT means the operation was interrupted, it's safe
		   to restart */
		if (err == ENOENT)
			goto restart;

		if (err == ENODEV) {
			fuse_session_exit(se);
			return 0;
		}
		/* Errors occurring during normal operation: EINTR (read
		   interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem
		   umounted) */
		if (err != EINTR && err != EAGAIN)
			perror("fuse: reading device");
		return -err;
	}
	if ((size_t) res < sizeof(struct fuse_in_header)) {
		fprintf(stderr, "short read on fuse device\n");
		return -EIO;
	}
	return res;
}
int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino,
                                     off_t off, off_t len)
{
	struct fuse_notify_inval_inode_out outarg;
	struct fuse_ll *f;
	struct iovec iov[2];

	if (!ch)
		return -EINVAL;

	f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
	if (!f)
		return -ENODEV;

	outarg.ino = ino;
	outarg.off = off;
	outarg.len = len;

	iov[1].iov_base = &outarg;
	iov[1].iov_len = sizeof(outarg);

	return send_notify_iov(f, ch, FUSE_NOTIFY_INVAL_INODE, iov, 2);
}