示例#1
0
int
fusefs_getattr(void *v)
{
	struct vop_getattr_args *ap = v;
	struct vnode *vp = ap->a_vp;
	struct fusefs_mnt *fmp;
	struct vattr *vap = ap->a_vap;
	struct proc *p = curproc;
	struct fusefs_node *ip;
	struct fusebuf *fbuf;
	int error = 0;

	ip = VTOI(vp);
	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;

	if (!fmp->sess_init)
		goto fake;

	fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_GETATTR, p);

	error = fb_queue(fmp->dev, fbuf);
	if (error) {
		fb_delete(fbuf);
		return (error);
	}

	update_vattr(fmp->mp, &fbuf->fb_vattr);
	memcpy(vap, &fbuf->fb_vattr, sizeof(*vap));
	fb_delete(fbuf);
	return (error);
fake:
	bzero(vap, sizeof(*vap));
	vap->va_type = vp->v_type;
	return (0);
}
示例#2
0
int
fusefs_getattr(void *v)
{
	struct vop_getattr_args *ap = v;
	struct vnode *vp = ap->a_vp;
	struct fusefs_mnt *fmp;
	struct vattr *vap = ap->a_vap;
	struct proc *p = ap->a_p;
	struct fusefs_node *ip;
	struct fusebuf *fbuf;
	int error = 0;

	DPRINTF("fusefs_getattr\n");

	ip = VTOI(vp);
	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;

	if (!fmp->sess_init)
		goto fake;

	fbuf = fb_setup(0, ip->ufs_ino.i_number, FBT_GETATTR, p);

	error = fb_queue(fmp->dev, fbuf);
	if (error) {
		DPRINTF("getattr error\n");
		pool_put(&fusefs_fbuf_pool, fbuf);
		return (error);
	}

	/* check if we got a response */
	if (fbuf->fb_len == 0) {
		pool_put(&fusefs_fbuf_pool, fbuf);
		goto fake;
	}

	update_vattr(fmp->mp, &fbuf->fb_vattr);
	memcpy(vap, &fbuf->fb_vattr, sizeof(*vap));
	memcpy(&ip->cached_attrs, vap, sizeof(*vap));
	pool_put(&fusefs_fbuf_pool, fbuf);
	return (error);
fake:
	bzero(vap, sizeof(*vap));
	vap->va_type = vp->v_type;
	return (0);
}
示例#3
0
int
fusefs_setattr(void *v)
{
	struct vop_setattr_args *ap = v;
	struct vattr *vap = ap->a_vap;
	struct vnode *vp = ap->a_vp;
	struct fusefs_node *ip = VTOI(vp);
	struct proc *p = curproc;
	struct fusefs_mnt *fmp;
	struct fusebuf *fbuf;
	struct fb_io *io;
	int error = 0;

	fmp = (struct fusefs_mnt *)ip->ufs_ino.i_ump;
	/*
	 * Check for unsettable attributes.
	 */
	if ((vap->va_type != VNON) || (vap->va_nlink != VNOVAL) ||
	    (vap->va_fsid != VNOVAL) || (vap->va_fileid != VNOVAL) ||
	    (vap->va_blocksize != VNOVAL) || (vap->va_rdev != VNOVAL) ||
	    ((int)vap->va_bytes != VNOVAL) || (vap->va_gen != VNOVAL))
		return (EINVAL);

	if (!fmp->sess_init || (fmp->undef_op & UNDEF_SETATTR))
		return (ENXIO);

	fbuf = fb_setup(sizeof(*io), ip->ufs_ino.i_number, FBT_SETATTR, p);
	io = fbtod(fbuf, struct fb_io *);
	io->fi_flags = 0;

	if (vap->va_uid != (uid_t)VNOVAL) {
		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
			error = EROFS;
			goto out;
		}
		fbuf->fb_vattr.va_uid = vap->va_uid;
		io->fi_flags |= FUSE_FATTR_UID;
	}

	if (vap->va_gid != (gid_t)VNOVAL) {
		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
			error = EROFS;
			goto out;
		}
		fbuf->fb_vattr.va_gid = vap->va_gid;
		io->fi_flags |= FUSE_FATTR_GID;
	}

	if (vap->va_size != VNOVAL) {
		switch (vp->v_type) {
		case VDIR:
			error = EISDIR;
			goto out;
		case VLNK:
		case VREG:
			if (vp->v_mount->mnt_flag & MNT_RDONLY) {
				error = EROFS;
				goto out;
			}
			break;
		default:
			break;
		}

		fbuf->fb_vattr.va_size = vap->va_size;
		io->fi_flags |= FUSE_FATTR_SIZE;
	}

	if (vap->va_atime.tv_sec != VNOVAL) {
		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
			error = EROFS;
			goto out;
		}
		fbuf->fb_vattr.va_atime.tv_sec = vap->va_atime.tv_sec;
		fbuf->fb_vattr.va_atime.tv_nsec = vap->va_atime.tv_nsec;
		io->fi_flags |= FUSE_FATTR_ATIME;
	}

	if (vap->va_mtime.tv_sec != VNOVAL) {
		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
			error = EROFS;
			goto out;
		}
		fbuf->fb_vattr.va_mtime.tv_sec = vap->va_mtime.tv_sec;
		fbuf->fb_vattr.va_mtime.tv_nsec = vap->va_mtime.tv_nsec;
		io->fi_flags |= FUSE_FATTR_MTIME;
	}

	if (vap->va_mode != (mode_t)VNOVAL) {
		if (vp->v_mount->mnt_flag & MNT_RDONLY) {
			error = EROFS;
			goto out;
		}
		fbuf->fb_vattr.va_mode = vap->va_mode & ALLPERMS;
		io->fi_flags |= FUSE_FATTR_MODE;
	}

	if (!io->fi_flags) {
		goto out;
	}

	if (io->fi_flags & FUSE_FATTR_SIZE && vp->v_type == VDIR) {
		error = EISDIR;
		goto out;
	}

	error = fb_queue(fmp->dev, fbuf);

	if (error) {
		if (error == ENOSYS)
			fmp->undef_op |= UNDEF_SETATTR;
		goto out;
	}

	update_vattr(fmp->mp, &fbuf->fb_vattr);
	memcpy(vap, &fbuf->fb_vattr, sizeof(*vap));
	VN_KNOTE(ap->a_vp, NOTE_ATTRIB);

out:
	fb_delete(fbuf);
	return (error);
}
示例#4
0
int
fusefs_lookup(void *v)
{
	struct vop_lookup_args *ap = v;
	struct vnode *vdp;	/* vnode for directory being searched */
	struct fusefs_node *dp;	/* inode for directory being searched */
	struct fusefs_mnt *fmp;	/* file system that directory is in */
	int lockparent;		/* 1 => lockparent flag is set */
	struct vnode *tdp;	/* returned by VOP_VGET */
	struct fusebuf *fbuf = NULL;
	struct vnode **vpp = ap->a_vpp;
	struct componentname *cnp = ap->a_cnp;
	struct proc *p = cnp->cn_proc;
	struct ucred *cred = cnp->cn_cred;
	int flags;
	int nameiop = cnp->cn_nameiop;
	int wantparent;
	int error = 0;
	uint64_t nid;

	flags = cnp->cn_flags;
	*vpp = NULL;
	vdp = ap->a_dvp;
	dp = VTOI(vdp);
	fmp = (struct fusefs_mnt *)dp->ufs_ino.i_ump;
	lockparent = flags & LOCKPARENT;
	wantparent = flags & (LOCKPARENT | WANTPARENT);

	DPRINTF("lookup path %s\n", cnp->cn_pnbuf);
	DPRINTF("lookup file %s\n", cnp->cn_nameptr);

	if ((error = VOP_ACCESS(vdp, VEXEC, cred, cnp->cn_proc)) != 0)
		return (error);

	if ((flags & ISLASTCN) && (vdp->v_mount->mnt_flag & MNT_RDONLY) &&
	    (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME))
		return (EROFS);

	if ((error = cache_lookup(vdp, vpp, cnp)) >= 0)
		return (error);

	if (flags & ISDOTDOT) {
		/* got ".." */
		nid = dp->parent;
		if (nid == 0)
			return (ENOENT);
	} else if (cnp->cn_namelen == 1 && *(cnp->cn_nameptr) == '.') {
		nid = dp->ufs_ino.i_number;
	} else {
		/* got a real entry */
		fbuf = fb_setup(FUSEFDSIZE + cnp->cn_namelen + 1,
		    dp->ufs_ino.i_number, FBT_LOOKUP, p);

		memcpy(fbuf->fb_dat, cnp->cn_nameptr, cnp->cn_namelen);
		fbuf->fb_dat[cnp->cn_namelen] = '\0';

		error = fb_queue(fmp->dev, fbuf);

		/* tsleep return */
		if (error == EWOULDBLOCK)
			goto out;

		if (error) {
			if ((nameiop == CREATE || nameiop == RENAME) &&
			    (flags & ISLASTCN)) {
				if (vdp->v_mount->mnt_flag & MNT_RDONLY)
					return (EROFS);

				cnp->cn_flags |= SAVENAME;

				if (!lockparent) {
					VOP_UNLOCK(vdp, 0, p);
					cnp->cn_flags |= PDIRUNLOCK;
				}

				error = EJUSTRETURN;
				goto out;
			}

			error = ENOENT;
			goto out;
		}

		nid = fbuf->fb_vattr.va_fileid;
	}

	if (nameiop == DELETE && (flags & ISLASTCN)) {
		/*
		 * Write access to directory required to delete files.
		 */
		error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc);
		if (error != 0) {
			if (fbuf)
				pool_put(&fusefs_fbuf_pool, fbuf);
			return (error);
		}

		cnp->cn_flags |= SAVENAME;
	}

	if (nameiop == RENAME && wantparent && (flags & ISLASTCN)) {
		/*
		 * Write access to directory required to delete files.
		 */
		if ((error = VOP_ACCESS(vdp, VWRITE, cred, cnp->cn_proc)) != 0)
			return (error);

		if (nid == VTOI(vdp)->ufs_ino.i_number) {
			error = EISDIR;
			goto out;
		}

		error = VFS_VGET(fmp->mp, nid, &tdp);
		if (error)
			goto out;

		tdp->v_type = IFTOVT(fbuf->fb_vattr.va_mode);
		VTOI(tdp)->vtype = tdp->v_type;
		*vpp = tdp;
		cnp->cn_flags |= SAVENAME;

		goto out;
	}

	if (flags & ISDOTDOT) {
		VOP_UNLOCK(vdp, 0, p);	/* race to get the inode */
		cnp->cn_flags |= PDIRUNLOCK;

		error = VFS_VGET(fmp->mp, nid, &tdp);

		if (error) {
			if (vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY, p) == 0)
				cnp->cn_flags &= ~PDIRUNLOCK;

			return (error);
		}

		if (lockparent && (flags & ISLASTCN)) {
			if ((error = vn_lock(vdp, LK_EXCLUSIVE, p))) {
				vput(tdp);
				return (error);
			}
			cnp->cn_flags &= ~PDIRUNLOCK;
		}
		*vpp = tdp;

	} else if (nid == dp->ufs_ino.i_number) {
		vref(vdp);
		*vpp = vdp;
		error = 0;
	} else {
		error = VFS_VGET(fmp->mp, nid, &tdp);

		if (!error) {
			tdp->v_type = IFTOVT(fbuf->fb_vattr.va_mode);
			VTOI(tdp)->vtype = tdp->v_type;
		}

		update_vattr(fmp->mp, &fbuf->fb_vattr);
		memcpy(&(VTOI(tdp)->cached_attrs), &fbuf->fb_vattr,
		    sizeof(struct vattr));

		if (error) {
			if (fbuf)
				pool_put(&fusefs_fbuf_pool, fbuf);
			return (error);
		}

		if (vdp != NULL && vdp->v_type == VDIR)
			VTOI(tdp)->parent = dp->ufs_ino.i_number;

		if (!lockparent || !(flags & ISLASTCN)) {
			VOP_UNLOCK(vdp, 0, p);
			cnp->cn_flags |= PDIRUNLOCK;
		}

		*vpp = tdp;
	}

out:
	if ((cnp->cn_flags & MAKEENTRY) && nameiop != CREATE &&
	    nameiop != DELETE)
		cache_enter(vdp, *vpp, cnp);

	if (fbuf)
		pool_put(&fusefs_fbuf_pool, fbuf);
	return (error);
}