Пример #1
0
static int zfsfuse_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	znode_t *znode;

	int error = zfs_zget(zfsvfs, ino, &znode, B_TRUE);
	if(error) {
		ZFS_EXIT(zfsvfs);
		/* If the inode we are trying to get was recently deleted
		   dnode_hold_impl will return EEXIST instead of ENOENT */
		return error == EEXIST ? ENOENT : error;
	}

	ASSERT(znode != NULL);
	vnode_t *vp = ZTOV(znode);
	ASSERT(vp != NULL);

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	struct stat stbuf;
	error = zfsfuse_stat(vp, &stbuf, &cred);

	VN_RELE(vp);
	ZFS_EXIT(zfsvfs);

	if(!error)
		fuse_reply_attr(req, &stbuf, 0.0);

	return error;
}
Пример #2
0
void hsx_fuse_readdir_plus(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
			   struct fuse_file_info *fi)
{
	struct hsfs_readdir_ctx *saved_ctx, *ctx = NULL;
	struct hsfs_inode *parent;
	struct hsfs_super *sb;
	size_t res, len = 0;
	char * buf;
	int err, count = 0;

	DEBUG_IN("P_I(%lu), Size(%lld), Off(0x%llx)", ino, size, off);

	(void)fi;
	sb = fuse_req_userdata(req);
	FUSE_ASSERT(sb != NULL);

	parent = hsfs_ilookup(sb, ino);
	FUSE_ASSERT(parent != NULL);

	err = hsi_nfs3_readdir_plus(parent, size, off, &ctx, size);
	if(err)
		goto out1;
	saved_ctx = ctx;

	buf = (char *) malloc(size);
	if( NULL == buf){
		err = ENOMEM;
		goto out2;
	}
	while(ctx != NULL){
		struct fuse_entry_param e;

		hsx_fuse_fill_reply(ctx->inode, &e);
		res = fuse_add_direntry_plus(req, buf + len, size - len, ctx->name,
					     &e, ctx->off);
	  	if(res > size - len)
			break;
		else if (res == size - len){
			ctx = ctx->next;
			break;
		}
		count++;
	       	hsx_fuse_ref_inc(ctx->inode, 1);
		len += res;
		ctx = ctx->next;
	}

	if (!err)
		fuse_reply_buf(req, buf, len);
	
	free(buf);
out2:
	__free_ctx(saved_ctx, 0);
out1:
	if(err)
		fuse_reply_err(req, err);

	DEBUG_OUT("with %d, %d entries returned", err, count);
	return;
}
Пример #3
0
void hsx_fuse_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name, const
			char *value, size_t size, int flags _U_)
{
	struct hsfs_inode *hi = NULL;
	struct hsfs_super *sb = NULL;
	int type = 0;
	int err = 0;

	DEBUG_IN(" ino %lu.\n", ino);
	if ((sb = fuse_req_userdata(req)) == NULL) {
		ERR("ERR in fuse_req_userdata");
		goto out;
	}

	if ((hi = hsfs_ilookup(sb, ino)) == NULL) {
		ERR("ERR in hsfs_ilookup");
		goto out;
	}	
	
	if (strcmp(name, POSIX_ACL_XATTR_ACCESS) == 0)
		type = ACL_TYPE_ACCESS;
	else if (strcmp(name, POSIX_ACL_XATTR_DEFAULT) == 0)
		type = ACL_TYPE_DEFAULT;
	else
		goto out;
	
	err = hsi_nfs3_setxattr(hi, value, type, size);
	fuse_reply_err(req, err);

out:
	DEBUG_OUT("out,err: %d\n",err);
	fuse_reply_err(req, err);
	return;
}
Пример #4
0
static int zfsfuse_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
{
	if(strlen(name) >= MAXNAMELEN)
		return ENAMETOOLONG;

	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	znode_t *znode;

	int error = zfs_zget(zfsvfs, parent, &znode, B_TRUE);
	if(error) {
		ZFS_EXIT(zfsvfs);
		/* If the inode we are trying to get was recently deleted
		   dnode_hold_impl will return EEXIST instead of ENOENT */
		return error == EEXIST ? ENOENT : error;
	}

	ASSERT(znode != NULL);
	vnode_t *dvp = ZTOV(znode);
	ASSERT(dvp != NULL);

	vnode_t *vp = NULL;

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	error = VOP_LOOKUP(dvp, (char *) name, &vp, NULL, 0, NULL, &cred, NULL, NULL, NULL);
	if(error)
		goto out;

	struct fuse_entry_param e = { 0 };

	e.attr_timeout = 0.0;
	e.entry_timeout = 0.0;

	if(vp == NULL)
		goto out;

	e.ino = VTOZ(vp)->z_id;
	if(e.ino == 3)
		e.ino = 1;

	e.generation = VTOZ(vp)->z_phys->zp_gen;

	error = zfsfuse_stat(vp, &e.attr, &cred);

out:
	if(vp != NULL)
		VN_RELE(vp);
	VN_RELE(dvp);
	ZFS_EXIT(zfsvfs);

	if(!error)
		fuse_reply_entry(req, &e);

	return error;
}
Пример #5
0
static int zfsfuse_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	file_info_t *info = (file_info_t *)(uintptr_t) fi->fh;
	ASSERT(info->vp != NULL);
	ASSERT(VTOZ(info->vp) != NULL);
	ASSERT(VTOZ(info->vp)->z_id == ino);

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	int error = VOP_CLOSE(info->vp, info->flags, 1, (offset_t) 0, &cred, NULL);
	VERIFY(error == 0);

	VN_RELE(info->vp);

	kmem_cache_free(file_info_cache, info);

	ZFS_EXIT(zfsvfs);

	return error;
}
Пример #6
0
static void sqfs_ll_op_open(fuse_req_t req, fuse_ino_t ino,
		struct fuse_file_info *fi) {
	sqfs_inode *inode;
	sqfs_ll *ll;
	
	if (fi->flags & (O_WRONLY | O_RDWR)) {
		fuse_reply_err(req, EROFS);
		return;
	}
	
	inode = malloc(sizeof(sqfs_inode));
	if (!inode) {
		fuse_reply_err(req, ENOMEM);
		return;
	}
	
	ll = fuse_req_userdata(req);
	if (sqfs_ll_inode(ll, inode, ino)) {
		fuse_reply_err(req, ENOENT);
	} else if (!S_ISREG(inode->base.mode)) {
		fuse_reply_err(req, EISDIR);
	} else {
		fi->fh = (intptr_t)inode;
		fuse_reply_open(req, fi);
		return;
	}
	free(inode);
}
Пример #7
0
static int zfsfuse_unlink(fuse_req_t req, fuse_ino_t parent, const char *name)
{
	if(strlen(name) >= MAXNAMELEN)
		return ENAMETOOLONG;

	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	znode_t *znode;

	int error = zfs_zget(zfsvfs, parent, &znode, B_FALSE);
	if(error) {
		ZFS_EXIT(zfsvfs);
		/* If the inode we are trying to get was recently deleted
		   dnode_hold_impl will return EEXIST instead of ENOENT */
		return error == EEXIST ? ENOENT : error;
	}

	ASSERT(znode != NULL);
	vnode_t *dvp = ZTOV(znode);
	ASSERT(dvp != NULL);

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	error = VOP_REMOVE(dvp, (char *) name, &cred, NULL, 0);

	VN_RELE(dvp);
	ZFS_EXIT(zfsvfs);

	return error;
}
Пример #8
0
static void
compiz_readdir(fuse_req_t req,
               fuse_ino_t ino,
               size_t size,
               off_t off,
               struct fuse_file_info *fi)
{
   CompDisplay *d = (CompDisplay *)fuse_req_userdata(req);
   FuseInode *inode, *c;
   struct dirbuf b;

   inode = fuseFindInode(inodes, ino, DIR_MASK);
   if (!inode)
     {
        fuse_reply_err(req, ENOTDIR);
        return;
     }

   memset(&b, 0, sizeof (b));

   dirbuf_add(req, &b, ".", ino);
   dirbuf_add(req, &b, "..", inode->parent ? inode->parent->ino : ino);

   if (!inode->child || !(inode->type & CONST_DIR_MASK))
     fuseUpdateInode(d, inode);

   for (c = inode->child; c; c = c->sibling)
     dirbuf_add(req, &b, c->name, c->ino);

   reply_buf_limited(req, b.p, b.size, off, size);

   free(b.p);
}
Пример #9
0
// Return the fuse_ino_t corresponding to the given request's inode_t
static fuse_ino_t cfsfuseino(fuse_req_t req, inode_t cfs_ino)
{
	inode_t root_cfs_ino = ((mount_t *) fuse_req_userdata(req))->root_ino;
	if (cfs_ino == root_cfs_ino)
		return FUSE_ROOT_ID;
	else if (cfs_ino == FUSE_ROOT_ID)
		return (fuse_ino_t) root_cfs_ino;
	else
		return (fuse_ino_t) cfs_ino;
}
Пример #10
0
// Return the request's inode_t corresponding to the fuse_ino_t
static inode_t fusecfsino(fuse_req_t req, fuse_ino_t fuse_ino)
{
	inode_t root_cfs_ino = ((mount_t *) fuse_req_userdata(req))->root_ino;
	if (fuse_ino == root_cfs_ino)
		return FUSE_ROOT_ID;
	if (fuse_ino == FUSE_ROOT_ID)
		return root_cfs_ino;
	else
		return (inode_t) fuse_ino;
}
Пример #11
0
void hsx_fuse_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
                          size_t size, off_t off, struct fuse_file_info *fi)
{
	struct hsfs_rw_info winfo;
	struct hsfs_super * sb = (struct hsfs_super *)fuse_req_userdata(req);
	size_t cnt = 0;
	int err = 0;
	char * buffer = NULL;
	
	DEBUG_IN("offset 0x%x size 0x%x", (unsigned int)off, (unsigned int)size);
	buffer = (char *) malloc(sb->wsize);
	if( NULL == buffer){
		err = ENOMEM;
		fuse_reply_err(req, err);
		goto out;
	}
	
	memset(&winfo, 0, sizeof(struct hsfs_rw_info));
	if(fi->direct_io)
		winfo.stable = HSFS_FILE_SYNC;
	else
		winfo.stable = HSFS_UNSTABLE;
	if(NULL == (winfo.inode = hsfs_ilookup(sb, ino))){
		err = ENOENT;
		fuse_reply_err(req, err);
		goto out;
	}
	DEBUG("ino %lu", winfo.inode->ino);	
	while(cnt < size){
		size_t tmp_size = min(size - cnt, sb->wsize);
		
		winfo.rw_size = tmp_size;
		winfo.rw_off = off + cnt;
		memcpy(buffer, buf + cnt, tmp_size);
		winfo.data.data_len = tmp_size;
		winfo.data.data_val = buffer;
		err = hsi_nfs3_write(&winfo);
		
		if(err){
			fuse_reply_err(req, err);
			goto out;
		}
			
		cnt += winfo.ret_count;
	}

	fuse_reply_write(req, cnt);
out:	
	if(NULL != buffer)
		free(buffer);
	
	DEBUG_OUT("err %d", err);		
	return;

}
Пример #12
0
void hsx_fuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
		      struct fuse_file_info *fi)
{
	struct hsfs_readdir_ctx *saved_ctx, *ctx = NULL;
	struct hsfs_inode *parent;
	struct hsfs_super *sb;
	size_t res, len = 0;
	char * buf;
	int err, count = 0;

	DEBUG_IN("P_I(%lu), Size(%lld), Off(0x%llx)", ino, size, off);

	(void)fi;
	sb = fuse_req_userdata(req);
	FUSE_ASSERT(sb != NULL);

	parent = hsfs_ilookup(sb, ino);
	FUSE_ASSERT(parent != NULL);

	err = hsi_nfs3_readdir(parent, size, off, &ctx);
	if(err)
		goto out1;
	saved_ctx = ctx;

	buf = (char *) malloc(size);
	if( NULL == buf){
		err = ENOMEM;
		goto out2;
	}
	while(ctx != NULL){
		res = fuse_add_direntry(req, buf + len, size - len, ctx->name,
					&ctx->stbuf, ctx->off);
		/* From fuse doc, buf is not copied if res larger than
		 * requested */
	  	if(res >= size - len)
			break;
		len += res;
		ctx = ctx->next;
		count++;
	}
	/* If EOF, we will return an empty buffer here. */
	if (!err)
		fuse_reply_buf(req, buf, len);
	
	free(buf);
out2:
	__free_ctx(saved_ctx, 0);
out1:
	if(err)
		fuse_reply_err(req, err);

	DEBUG_OUT("with %d, %d entries returned.", err, count);
}
Пример #13
0
static int zfsfuse_readlink(fuse_req_t req, fuse_ino_t ino)
{
	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	znode_t *znode;

	int error = zfs_zget(zfsvfs, ino, &znode, B_FALSE);
	if(error) {
		ZFS_EXIT(zfsvfs);
		/* If the inode we are trying to get was recently deleted
		   dnode_hold_impl will return EEXIST instead of ENOENT */
		return error == EEXIST ? ENOENT : error;
	}

	ASSERT(znode != NULL);
	vnode_t *vp = ZTOV(znode);
	ASSERT(vp != NULL);

	char buffer[PATH_MAX + 1];

	iovec_t iovec;
	uio_t uio;
	uio.uio_iov = &iovec;
	uio.uio_iovcnt = 1;
	uio.uio_segflg = UIO_SYSSPACE;
	uio.uio_fmode = 0;
	uio.uio_llimit = RLIM64_INFINITY;
	iovec.iov_base = buffer;
	iovec.iov_len = sizeof(buffer) - 1;
	uio.uio_resid = iovec.iov_len;
	uio.uio_loffset = 0;

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	error = VOP_READLINK(vp, &uio, &cred, NULL);

	VN_RELE(vp);
	ZFS_EXIT(zfsvfs);

	if(!error) {
		VERIFY(uio.uio_loffset < sizeof(buffer));
		buffer[uio.uio_loffset] = '\0';
		fuse_reply_readlink(req, buffer);
	}

	return error;
}
Пример #14
0
static int zfsfuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
{
	file_info_t *info = (file_info_t *)(uintptr_t) fi->fh;

	vnode_t *vp = info->vp;
	ASSERT(vp != NULL);
	ASSERT(VTOZ(vp) != NULL);
	ASSERT(VTOZ(vp)->z_id == ino);

	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	char *outbuf = kmem_alloc(size, KM_NOSLEEP);
	if(outbuf == NULL)
		return ENOMEM;

	ZFS_ENTER(zfsvfs);

	iovec_t iovec;
	uio_t uio;
	uio.uio_iov = &iovec;
	uio.uio_iovcnt = 1;
	uio.uio_segflg = UIO_SYSSPACE;
	uio.uio_fmode = 0;
	uio.uio_llimit = RLIM64_INFINITY;

	iovec.iov_base = outbuf;
	iovec.iov_len = size;
	uio.uio_resid = iovec.iov_len;
	uio.uio_loffset = off;

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	int error = VOP_READ(vp, &uio, info->flags, &cred, NULL);

	ZFS_EXIT(zfsvfs);

	if(!error)
		fuse_reply_buf(req, outbuf, uio.uio_loffset - off);

	kmem_free(outbuf, size);

	return error;
}
Пример #15
0
static int zfsfuse_write(fuse_req_t req, fuse_ino_t ino, const char *buf, size_t size, off_t off, struct fuse_file_info *fi)
{
	file_info_t *info = (file_info_t *)(uintptr_t) fi->fh;

	vnode_t *vp = info->vp;
	ASSERT(vp != NULL);
	ASSERT(VTOZ(vp) != NULL);
	ASSERT(VTOZ(vp)->z_id == ino);

	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	iovec_t iovec;
	uio_t uio;
	uio.uio_iov = &iovec;
	uio.uio_iovcnt = 1;
	uio.uio_segflg = UIO_SYSSPACE;
	uio.uio_fmode = 0;
	uio.uio_llimit = RLIM64_INFINITY;

	iovec.iov_base = (void *) buf;
	iovec.iov_len = size;
	uio.uio_resid = iovec.iov_len;
	uio.uio_loffset = off;

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	int error = VOP_WRITE(vp, &uio, info->flags, &cred, NULL);

	ZFS_EXIT(zfsvfs);

	if(!error) {
		/* When not using direct_io, we must always write 'size' bytes */
		VERIFY(uio.uio_resid == 0);
		fuse_reply_write(req, size - uio.uio_resid);
	}

	return error;
}
Пример #16
0
static int zfsfuse_access(fuse_req_t req, fuse_ino_t ino, int mask)
{
	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	znode_t *znode;

	int error = zfs_zget(zfsvfs, ino, &znode, B_TRUE);
	if(error) {
		ZFS_EXIT(zfsvfs);
		/* If the inode we are trying to get was recently deleted
		   dnode_hold_impl will return EEXIST instead of ENOENT */
		return error == EEXIST ? ENOENT : error;
	}

	ASSERT(znode != NULL);
	vnode_t *vp = ZTOV(znode);
	ASSERT(vp != NULL);

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	int mode = 0;
	if(mask & R_OK)
		mode |= VREAD;
	if(mask & W_OK)
		mode |= VWRITE;
	if(mask & X_OK)
		mode |= VEXEC;

	error = VOP_ACCESS(vp, mode, 0, &cred, NULL);

	VN_RELE(vp);

	ZFS_EXIT(zfsvfs);

	return error;
}
Пример #17
0
static int zfsfuse_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
{
	if(strlen(name) >= MAXNAMELEN)
		return ENAMETOOLONG;

	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	znode_t *znode;

	int error = zfs_zget(zfsvfs, parent, &znode, B_FALSE);
	if(error) {
		ZFS_EXIT(zfsvfs);
		/* If the inode we are trying to get was recently deleted
		   dnode_hold_impl will return EEXIST instead of ENOENT */
		return error == EEXIST ? ENOENT : error;
	}

	ASSERT(znode != NULL);
	vnode_t *dvp = ZTOV(znode);
	ASSERT(dvp != NULL);

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	/* FUSE doesn't care if we remove the current working directory
	   so we just pass NULL as the cwd parameter (no problem for ZFS) */
	error = VOP_RMDIR(dvp, (char *) name, NULL, &cred, NULL, 0);

	/* Linux uses ENOTEMPTY when trying to remove a non-empty directory */
	if(error == EEXIST)
		error = ENOTEMPTY;

	VN_RELE(dvp);
	ZFS_EXIT(zfsvfs);

	return error;
}
Пример #18
0
static void
compiz_setattr(fuse_req_t req,
               fuse_ino_t ino,
               struct stat *attr,
               int to_set,
               struct fuse_file_info *fi)
{
   CompDisplay *d = (CompDisplay *)fuse_req_userdata(req);
   FuseInode *inode;

   inode = fuseFindInode(inodes, ino, WRITE_MASK);
   if (inode)
     {
        struct stat stbuf;

        if ((to_set & FUSE_SET_ATTR_SIZE) != FUSE_SET_ATTR_SIZE)
          {
             fuse_reply_err(req, EACCES);
             return;
          }

        if (attr->st_size != 0)
          {
             fuse_reply_err(req, EACCES);
             return;
          }

        inode->flags |= FUSE_INODE_FLAG_TRUNC;

        memset(&stbuf, 0, sizeof (stbuf));

        fuseInodeStat(d, inode, &stbuf);

        fuse_reply_attr(req, &stbuf, 1.0);
     }
   else
     {
        fuse_reply_err(req, ENOENT);
     }
}
Пример #19
0
void hsx_fuse_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
	       	mode_t mode)
{	
	int err = 0;
	struct hsfs_inode *hi_parent = NULL;
	struct hsfs_inode *new = NULL;
	struct fuse_entry_param e;
	struct hsfs_super *sb = NULL;
	const char *dirname = name;
	DEBUG_IN("ino:%lu.\n", parent);

	memset(&e, 0, sizeof(struct fuse_entry_param));

	sb = fuse_req_userdata(req);
	hi_parent = hsx_fuse_iget(sb, parent);
	
	if(NULL == sb) {
		ERR("ERR in fuse_req_userdata");
		goto out;
	}
	if(NULL == hi_parent) {
		ERR("ERR in hsx_fuse_iget");
		goto out;
	}

	
	err = hsi_nfs3_mkdir(hi_parent, &new, dirname, mode);
	if(0 != err ) {
		fuse_reply_err(req, err);
		goto out;
	}else {
		hsx_fuse_fill_reply(new, &e);
		fuse_reply_entry(req, &e);
		goto out;
	}
out:
	DEBUG_OUT(" out errno is: %d\n", err);
	return;
};
Пример #20
0
void hsx_fuse_readlink(fuse_req_t req, fuse_ino_t ino)
{
	int st = 0;
	int err = 0;
	struct hsfs_inode *hi = NULL;
	struct hsfs_super *hi_sb = NULL;
	char *link = NULL;
	DEBUG_IN("%s\n","THE HSX_FUSE_READLINK.");

	hi_sb = fuse_req_userdata(req);
	if(!hi_sb){
		ERR("%s gets inode->sb fails \n", progname);
		err = ENOENT;
		goto out;
	}
	hi = hsfs_ilookup(hi_sb, ino);
	if(!hi){
		ERR("%s gets inode fails \n", progname);
		err = ENOENT;
		goto out;
	}
	st = hsi_nfs3_readlink(hi,&link);
	if(st != 0){
		err = st;
		goto out;
	}
	fuse_reply_readlink(req, link);

out:
	if(link != NULL){
		free(link);
	}
	if(st != 0){
		fuse_reply_err(req, err);
	}
	DEBUG_OUT(" WITH ERRNO %d\n", err);
	return;
}
Пример #21
0
static int zfsfuse_fsync(fuse_req_t req, fuse_ino_t ino, int datasync, struct fuse_file_info *fi)
{
	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	file_info_t *info = (file_info_t *)(uintptr_t) fi->fh;
	ASSERT(info->vp != NULL);
	ASSERT(VTOZ(info->vp) != NULL);
	ASSERT(VTOZ(info->vp)->z_id == ino);

	vnode_t *vp = info->vp;

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	int error = VOP_FSYNC(vp, datasync ? FDSYNC : FSYNC, &cred, NULL);

	ZFS_EXIT(zfsvfs);

	return error;
}
Пример #22
0
static void sqfs_ll_op_read(fuse_req_t req, fuse_ino_t ino,
		size_t size, off_t off, struct fuse_file_info *fi) {
	sqfs_ll *ll = fuse_req_userdata(req);
	sqfs_inode *inode = (sqfs_inode*)(intptr_t)fi->fh;
	sqfs_err err = SQFS_OK;
	
	off_t osize;
	char *buf = malloc(size);
	if (!buf) {
		fuse_reply_err(req, ENOMEM);
		return;
	}
	
	osize = size;
	err = sqfs_read_range(&ll->fs, inode, off, &osize, buf);
	if (err) {
		fuse_reply_err(req, EIO);
	} else if (osize == 0) { /* EOF */
		fuse_reply_buf(req, NULL, 0);
	} else {
		fuse_reply_buf(req, buf, osize);
	}
	free(buf);
}
Пример #23
0
static void
compiz_getattr(fuse_req_t req,
               fuse_ino_t ino,
               struct fuse_file_info *fi)
{
   CompDisplay *d = (CompDisplay *)fuse_req_userdata(req);
   FuseInode *inode;

   inode = fuseFindInode(inodes, ino, ~0);
   if (inode)
     {
        struct stat stbuf;

        memset(&stbuf, 0, sizeof (stbuf));

        fuseInodeStat(d, inode, &stbuf);

        fuse_reply_attr(req, &stbuf, 1.0);
     }
   else
     {
        fuse_reply_err(req, ENOENT);
     }
}
Пример #24
0
static void
compiz_lookup(fuse_req_t req,
              fuse_ino_t parent,
              const char *name)
{
   CompDisplay *d = (CompDisplay *)fuse_req_userdata(req);
   FuseInode *inode;
   struct fuse_entry_param e;

   inode = fuseFindInode(inodes, parent, DIR_MASK);
   if (!inode)
     {
        fuse_reply_err(req, ENOENT);
        return;
     }

   if (!inode->child || !(inode->type & CONST_DIR_MASK))
     fuseUpdateInode(d, inode);

   inode = fuseLookupChild(inode, name);
   if (!inode)
     {
        fuse_reply_err(req, ENOENT);
        return;
     }

   memset(&e, 0, sizeof (e));

   e.attr_timeout = 1.0;
   e.entry_timeout = 1.0;
   e.ino = inode->ino;

   fuseInodeStat(d, inode, &e.attr);

   fuse_reply_entry(req, &e);
}
Пример #25
0
static int zfsfuse_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
{
	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	znode_t *znode;

	int error = zfs_zget(zfsvfs, ino, &znode, B_TRUE);
	if(error) {
		ZFS_EXIT(zfsvfs);
		/* If the inode we are trying to get was recently deleted
		   dnode_hold_impl will return EEXIST instead of ENOENT */
		return error == EEXIST ? ENOENT : error;
	}

	ASSERT(znode != NULL);
	vnode_t *vp = ZTOV(znode);
	ASSERT(vp != NULL);

	if(vp->v_type != VDIR) {
		error = ENOTDIR;
		goto out;
	}

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	/*
	 * Check permissions.
	 */
	if (error = VOP_ACCESS(vp, VREAD | VEXEC, 0, &cred, NULL))
		goto out;

	vnode_t *old_vp = vp;

	/* XXX: not sure about flags */
	error = VOP_OPEN(&vp, FREAD, &cred, NULL);

	ASSERT(old_vp == vp);

	if(!error) {
		file_info_t *info = kmem_cache_alloc(file_info_cache, KM_NOSLEEP);
		if(info == NULL) {
			error = ENOMEM;
			goto out;
		}

		info->vp = vp;
		info->flags = FREAD;

		fi->fh = (uint64_t) (uintptr_t) info;
	}

out:
	if(error)
		VN_RELE(vp);
	ZFS_EXIT(zfsvfs);

	if(!error)
		fuse_reply_open(req, fi);

	return error;
}
Пример #26
0
static struct lo_data *lo_data(fuse_req_t req)
{
	return (struct lo_data *) fuse_req_userdata(req);
}
Пример #27
0
void hsx_fuse_rename(fuse_req_t req, fuse_ino_t parent, const char *name,
				fuse_ino_t newparent, const char *newname)
{
	int err = 0;
	struct hsfs_super *sb = NULL;
	struct hsfs_inode *hi = NULL, *newhi = NULL;

	DEBUG_IN(" %s to %s", name, newname);

	if (name == NULL) {
		ERR("Source name is NULL\n");
		err = EINVAL;
		goto out;
	}
	else if (newname == NULL) {
		ERR("Target name is NULL\n");
		err = EINVAL;
		goto out;
	}
	else if (!(strcmp(name, ""))) {
		ERR("Source name is empty\n");
		err = EINVAL;
		goto out;
	}
	else if (!(strcmp(newname, ""))) {
		ERR("Target name is empty\n");
		err = EINVAL;
		goto out;
	}
	else if (strlen(name) > NAME_MAX) {
		ERR("Source name is too long\n");
		err = ENAMETOOLONG;
		goto out;
	}
	else if (strlen(newname) > NAME_MAX) {
		ERR("Target name is too long\n");
		err = ENAMETOOLONG;
		goto out;
	}

	if (!(sb = fuse_req_userdata(req))) {
		ERR("Get user data failed\n");
		err = EIO;
		goto out;
	}
	if (!(hi = hsx_fuse_iget(sb, parent))) {
		ERR("Get hsfs inode failed\n");
		err = ENOENT;
		goto out;
	}
	if (!(newhi = hsx_fuse_iget(sb, newparent))) {
		ERR("Get hsfs inode failed\n");
		err = ENOENT;
		goto out;
	}

	if ((err = hsi_nfs3_rename(hi, name, newhi, newname))) {
		goto out;
	}
out:
	fuse_reply_err(req, err);
	DEBUG_OUT(" %s to %s errno:%d", name, newname, err);
}
Пример #28
0
static int zfsfuse_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, struct fuse_file_info *fi)
{
	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	vnode_t *vp;
	boolean_t release;

	int error;

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	if(fi == NULL) {
		znode_t *znode;

		error = zfs_zget(zfsvfs, ino, &znode, B_TRUE);
		if(error) {
			ZFS_EXIT(zfsvfs);
			/* If the inode we are trying to get was recently deleted
			   dnode_hold_impl will return EEXIST instead of ENOENT */
			return error == EEXIST ? ENOENT : error;
		}
		ASSERT(znode != NULL);
		vp = ZTOV(znode);
		release = B_TRUE;
	} else {
		file_info_t *info = (file_info_t *)(uintptr_t) fi->fh;
		vp = info->vp;
		release = B_FALSE;

		/*
		 * Special treatment for ftruncate().
		 * This is needed because otherwise ftruncate() would
		 * fail with permission denied on read-only files.
		 * (Solaris calls VOP_SPACE instead of VOP_SETATTR on
		 * ftruncate).
		 */
		if(to_set & FUSE_SET_ATTR_SIZE) {
			/* Check if file is opened for writing */
			if((info->flags & FWRITE) == 0) {
				error = EBADF;
				goto out;
			}
			/* Sanity check */
			if(vp->v_type != VREG) {
				error = EINVAL;
				goto out;
			}

			flock64_t bf;

			bf.l_whence = 0; /* beginning of file */
			bf.l_start = attr->st_size;
			bf.l_type = F_WRLCK;
			bf.l_len = (off_t) 0;

			/* FIXME: check locks */
			error = VOP_SPACE(vp, F_FREESP, &bf, info->flags, 0, &cred, NULL);
			if(error)
				goto out;

			to_set &= ~FUSE_SET_ATTR_SIZE;
			if(to_set == 0)
				goto out;
		}
	}

	ASSERT(vp != NULL);

	vattr_t vattr = { 0 };

	if(to_set & FUSE_SET_ATTR_MODE) {
		vattr.va_mask |= AT_MODE;
		vattr.va_mode = attr->st_mode;
	}
	if(to_set & FUSE_SET_ATTR_UID) {
		vattr.va_mask |= AT_UID;
		vattr.va_uid = attr->st_uid;
	}
	if(to_set & FUSE_SET_ATTR_GID) {
		vattr.va_mask |= AT_GID;
		vattr.va_gid = attr->st_gid;
	}
	if(to_set & FUSE_SET_ATTR_SIZE) {
		vattr.va_mask |= AT_SIZE;
		vattr.va_size = attr->st_size;
	}
	if(to_set & FUSE_SET_ATTR_ATIME) {
		vattr.va_mask |= AT_ATIME;
		TIME_TO_TIMESTRUC(attr->st_atime, &vattr.va_atime);
	}
	if(to_set & FUSE_SET_ATTR_MTIME) {
		vattr.va_mask |= AT_MTIME;
		TIME_TO_TIMESTRUC(attr->st_mtime, &vattr.va_mtime);
	}

	int flags = (to_set & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME)) ? ATTR_UTIME : 0;
	error = VOP_SETATTR(vp, &vattr, flags, &cred, NULL);

out: ;
	struct stat stat_reply;

	if(!error)
		error = zfsfuse_stat(vp, &stat_reply, &cred);

	/* Do not release if vp was an opened inode */
	if(release)
		VN_RELE(vp);

	ZFS_EXIT(zfsvfs);

	if(!error)
		fuse_reply_attr(req, &stat_reply, 0.0);

	return error;
}
Пример #29
0
static int zfsfuse_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
{
	vnode_t *vp = ((file_info_t *)(uintptr_t) fi->fh)->vp;
	ASSERT(vp != NULL);
	ASSERT(VTOZ(vp) != NULL);
	ASSERT(VTOZ(vp)->z_id == ino);

	if(vp->v_type != VDIR)
		return ENOTDIR;

	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	char *outbuf = kmem_alloc(size, KM_NOSLEEP);
	if(outbuf == NULL)
		return ENOMEM;

	ZFS_ENTER(zfsvfs);

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	union {
		char buf[DIRENT64_RECLEN(MAXNAMELEN)];
		struct dirent64 dirent;
	} entry;

	struct stat fstat = { 0 };

	iovec_t iovec;
	uio_t uio;
	uio.uio_iov = &iovec;
	uio.uio_iovcnt = 1;
	uio.uio_segflg = UIO_SYSSPACE;
	uio.uio_fmode = 0;
	uio.uio_llimit = RLIM64_INFINITY;

	int eofp = 0;

	int outbuf_off = 0;
	int outbuf_resid = size;

	off_t next = off;

	int error;

	for(;;) {
		iovec.iov_base = entry.buf;
		iovec.iov_len = sizeof(entry.buf);
		uio.uio_resid = iovec.iov_len;
		uio.uio_loffset = next;

		error = VOP_READDIR(vp, &uio, &cred, &eofp, NULL, 0);
		if(error)
			goto out;

		/* No more directory entries */
		if(iovec.iov_base == entry.buf)
			break;

		fstat.st_ino = entry.dirent.d_ino;
		fstat.st_mode = 0;

		int dsize = fuse_dirent_size(strlen(entry.dirent.d_name));
		if(dsize > outbuf_resid)
			break;

		fuse_add_dirent(outbuf + outbuf_off, entry.dirent.d_name, &fstat, entry.dirent.d_off);

		outbuf_off += dsize;
		outbuf_resid -= dsize;
		next = entry.dirent.d_off;
	}

out:
	ZFS_EXIT(zfsvfs);

	if(!error)
		fuse_reply_buf(req, outbuf, outbuf_off);

	kmem_free(outbuf, size);

	return error;
}
Пример #30
0
static int zfsfuse_opencreate(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, int fflags, mode_t createmode, const char *name)
{
	if(name && strlen(name) >= MAXNAMELEN)
		return ENAMETOOLONG;

	vfs_t *vfs = (vfs_t *) fuse_req_userdata(req);
	zfsvfs_t *zfsvfs = vfs->vfs_data;

	ZFS_ENTER(zfsvfs);

	cred_t cred;
	zfsfuse_getcred(req, &cred);

	/* Map flags */
	int mode, flags;

	if(fflags & O_WRONLY) {
		mode = VWRITE;
		flags = FWRITE;
	} else if(fflags & O_RDWR) {
		mode = VREAD | VWRITE;
		flags = FREAD | FWRITE;
	} else {
		mode = VREAD;
		flags = FREAD;
	}

	if(fflags & O_CREAT)
		flags |= FCREAT;
	if(fflags & O_SYNC)
		flags |= FSYNC;
	if(fflags & O_DSYNC)
		flags |= FDSYNC;
	if(fflags & O_RSYNC)
		flags |= FRSYNC;
	if(fflags & O_APPEND)
		flags |= FAPPEND;
	if(fflags & O_LARGEFILE)
		flags |= FOFFMAX;
	if(fflags & O_NOFOLLOW)
		flags |= FNOFOLLOW;
	if(fflags & O_TRUNC)
		flags |= FTRUNC;
	if(fflags & O_EXCL)
		flags |= FEXCL;

	znode_t *znode;

	int error = zfs_zget(zfsvfs, ino, &znode, B_FALSE);
	if(error) {
		ZFS_EXIT(zfsvfs);
		/* If the inode we are trying to get was recently deleted
		   dnode_hold_impl will return EEXIST instead of ENOENT */
		return error == EEXIST ? ENOENT : error;
	}

	ASSERT(znode != NULL);
	vnode_t *vp = ZTOV(znode);
	ASSERT(vp != NULL);

	if (flags & FCREAT) {
		enum vcexcl excl;

		/*
		 * Wish to create a file.
		 */
		vattr_t vattr;
		vattr.va_type = VREG;
		vattr.va_mode = createmode;
		vattr.va_mask = AT_TYPE|AT_MODE;
		if (flags & FTRUNC) {
			vattr.va_size = 0;
			vattr.va_mask |= AT_SIZE;
		}
		if (flags & FEXCL)
			excl = EXCL;
		else
			excl = NONEXCL;

		vnode_t *new_vp;
		/* FIXME: check filesystem boundaries */
		error = VOP_CREATE(vp, (char *) name, &vattr, excl, mode, &new_vp, &cred, 0, NULL, NULL);

		if(error)
			goto out;

		VN_RELE(vp);
		vp = new_vp;
	} else {
		/*
		 * Get the attributes to check whether file is large.
		 * We do this only if the O_LARGEFILE flag is not set and
		 * only for regular files.
		 */
		if (!(flags & FOFFMAX) && (vp->v_type == VREG)) {
			vattr_t vattr;
			vattr.va_mask = AT_SIZE;
			if ((error = VOP_GETATTR(vp, &vattr, 0, &cred, NULL)))
				goto out;

			if (vattr.va_size > (u_offset_t) MAXOFF32_T) {
				/*
				 * Large File API - regular open fails
				 * if FOFFMAX flag is set in file mode
				 */
				error = EOVERFLOW;
				goto out;
			}
		}

		/*
		 * Check permissions.
		 */
		if (error = VOP_ACCESS(vp, mode, 0, &cred, NULL))
			goto out;
	}

	if ((flags & FNOFOLLOW) && vp->v_type == VLNK) {
		error = ELOOP;
		goto out;
	}

	vnode_t *old_vp = vp;

	error = VOP_OPEN(&vp, flags, &cred, NULL);

	ASSERT(old_vp == vp);

	if(error)
		goto out;

	struct fuse_entry_param e = { 0 };

	if(flags & FCREAT) {
		error = zfsfuse_stat(vp, &e.attr, &cred);
		if(error)
			goto out;
	}

	file_info_t *info = kmem_cache_alloc(file_info_cache, KM_NOSLEEP);
	if(info == NULL) {
		error = ENOMEM;
		goto out;
	}

	info->vp = vp;
	info->flags = flags;

	fi->fh = (uint64_t) (uintptr_t) info;
	fi->keep_cache = 1;

	if(flags & FCREAT) {
		e.attr_timeout = 0.0;
		e.entry_timeout = 0.0;
		e.ino = VTOZ(vp)->z_id;
		if(e.ino == 3)
			e.ino = 1;
		e.generation = VTOZ(vp)->z_phys->zp_gen;
	}

out:
	if(error) {
		ASSERT(vp->v_count > 0);
		VN_RELE(vp);
	}

	ZFS_EXIT(zfsvfs);

	if(!error) {
		if(!(flags & FCREAT))
			fuse_reply_open(req, fi);
		else
			fuse_reply_create(req, &e, fi);
	}
	return error;
}