예제 #1
0
static int
auto_rmdir(
	vnode_t *dvp,
	char *nm,
	vnode_t *cdir,
	cred_t *cred,
	caller_context_t *ct,
	int flags)
{
	vnode_t *newvp;
	int error;

	AUTOFS_DPRINT((4, "auto_rmdir: vp=%p nm=%s\n", (void *)dvp, nm));

	if (error = auto_trigger_mount(dvp, cred, &newvp))
		goto done;

	if (newvp != NULL) {
		/*
		 * Node is now mounted on.
		 */
		if (vn_is_readonly(newvp))
			error = EROFS;
		else
			error = VOP_RMDIR(newvp, nm, cdir, cred, ct, flags);
		VN_RELE(newvp);
	} else
		error = ENOSYS;

done:
	AUTOFS_DPRINT((5, "auto_rmdir: error=%d\n", error));
	return (error);
}
예제 #2
0
/*ARGSUSED4*/
static int
auto_setattr(
	vnode_t *vp,
	struct vattr *vap,
	int flags,
	cred_t *cred,
	caller_context_t *ct)
{
	vnode_t *newvp;
	int error;

	AUTOFS_DPRINT((4, "auto_setattr vp %p\n", (void *)vp));

	if (error = auto_trigger_mount(vp, cred, &newvp))
		goto done;

	if (newvp != NULL) {
		/*
		 * Node is mounted on.
		 */
		if (vn_is_readonly(newvp))
			error = EROFS;
		else
			error = VOP_SETATTR(newvp, vap, flags, cred, ct);
		VN_RELE(newvp);
	} else
		error = ENOSYS;

done:
	AUTOFS_DPRINT((5, "auto_setattr: error=%d\n", error));
	return (error);
}
예제 #3
0
파일: ufs_xattr.c 프로젝트: andreiw/polaris
/*
 * Unhook an attribute directory from a parent file/dir
 * Only do so, if we are the only user of the vnode.
 */
void
ufs_unhook_shadow(struct inode *ip, struct inode *sip)
{
	struct vnode		*datavp = ITOV(ip);
	struct vnode		*dirvp = ITOV(sip);
	int			hno;
	kmutex_t		*ihm;

	ASSERT(RW_WRITE_HELD(&sip->i_contents));
	ASSERT(RW_WRITE_HELD(&ip->i_contents));

	if (vn_is_readonly(ITOV(ip)))
		return;

	if (ip->i_ufsvfs == NULL || sip->i_ufsvfs == NULL)
		return;

	hno = INOHASH(ip->i_number);
	ihm = &ih_lock[hno];
	mutex_enter(ihm);

	mutex_enter(&datavp->v_lock);
	mutex_enter(&dirvp->v_lock);

	if (dirvp->v_count != 1 && datavp->v_count != 1) {
		mutex_exit(&dirvp->v_lock);
		mutex_exit(&datavp->v_lock);
		mutex_exit(ihm);
		return;
	}

	/*
	 * Delete shadow from ip
	 */

	sip->i_nlink -= 2;
	ufs_setreclaim(sip);
	TRANS_INODE(sip->i_ufsvfs, sip);
	sip->i_flag |= ICHG;
	sip->i_seq++;
	ITIMES_NOLOCK(sip);

	/*
	 * Update src file
	 */
	ip->i_oeftflag = 0;
	TRANS_INODE(ip->i_ufsvfs, ip);
	ip->i_flag |= ICHG;
	ip->i_seq++;
	ufs_iupdat(ip, 1);
	mutex_exit(&dirvp->v_lock);
	mutex_exit(&datavp->v_lock);
	mutex_exit(ihm);
}
예제 #4
0
static int
auto_link(
	vnode_t *tdvp,
	vnode_t *svp,
	char *nm,
	cred_t *cred,
	caller_context_t *ct,
	int flags)
{
	vnode_t *newvp;
	int error;

	AUTOFS_DPRINT((4, "auto_link tdvp %p svp %p nm %s\n", (void *)tdvp,
	    (void *)svp, nm));

	if (error = auto_trigger_mount(tdvp, cred, &newvp))
		goto done;

	if (newvp == NULL) {
		/*
		 * an autonode can not be a link to another node
		 */
		error = ENOSYS;
		goto done;
	}

	if (vn_is_readonly(newvp)) {
		error = EROFS;
		VN_RELE(newvp);
		goto done;
	}

	if (vn_matchops(svp, auto_vnodeops)) {
		/*
		 * source vp can't be an autonode
		 */
		error = ENOSYS;
		VN_RELE(newvp);
		goto done;
	}

	error = VOP_LINK(newvp, svp, nm, cred, ct, flags);
	VN_RELE(newvp);

done:
	AUTOFS_DPRINT((5, "auto_link error=%d\n", error));
	return (error);
}
예제 #5
0
/* ARGSUSED */
void
acl2_setacl(SETACL2args *args, SETACL2res *resp, struct exportinfo *exi,
	struct svc_req *req, cred_t *cr)
{
	int error;
	vnode_t *vp;
	vattr_t va;

	vp = nfs_fhtovp(&args->fh, exi);
	if (vp == NULL) {
		resp->status = NFSERR_STALE;
		return;
	}

	if (rdonly(exi, req) || vn_is_readonly(vp)) {
		VN_RELE(vp);
		resp->status = NFSERR_ROFS;
		return;
	}

	(void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);
	error = VOP_SETSECATTR(vp, &args->acl, 0, cr);
	if (error) {
		VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
		VN_RELE(vp);
		resp->status = puterrno(error);
		return;
	}

	va.va_mask = AT_ALL;
	error = rfs4_delegated_getattr(vp, &va, 0, cr);

	VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
	VN_RELE(vp);

	/* check for overflowed values */
	if (!error) {
		error = vattr_to_nattr(&va, &resp->resok.attr);
	}
	if (error) {
		resp->status = puterrno(error);
		return;
	}

	resp->status = NFS_OK;
}
예제 #6
0
static int
auto_create(
	vnode_t *dvp,
	char *nm,
	vattr_t *va,
	vcexcl_t excl,
	int mode,
	vnode_t **vpp,
	cred_t *cred,
	int flag,
	caller_context_t *ct,
	vsecattr_t *vsecp)
{
	vnode_t *newvp;
	int error;

	AUTOFS_DPRINT((4, "auto_create dvp %p nm %s\n", (void *)dvp, nm));

	if (error = auto_trigger_mount(dvp, cred, &newvp))
		goto done;

	if (newvp != NULL) {
		/*
		 * Node is now mounted on.
		 */
		if (vn_is_readonly(newvp))
			error = EROFS;
		else
			error = VOP_CREATE(newvp, nm, va, excl,
			    mode, vpp, cred, flag, ct, vsecp);
		VN_RELE(newvp);
	} else
		error = ENOSYS;

done:
	AUTOFS_DPRINT((5, "auto_create: error=%d\n", error));
	return (error);
}
예제 #7
0
static int
auto_symlink(
	vnode_t *dvp,
	char *lnknm,		/* new entry */
	vattr_t *tva,
	char *tnm,		/* existing entry */
	cred_t *cred,
	caller_context_t *ct,
	int flags)
{
	vnode_t *newvp;
	int error;

	AUTOFS_DPRINT((4, "auto_symlink: dvp=%p lnknm=%s tnm=%s\n",
	    (void *)dvp, lnknm, tnm));

	if (error = auto_trigger_mount(dvp, cred, &newvp))
		goto done;

	if (newvp != NULL) {
		/*
		 * Node is mounted on.
		 */
		if (vn_is_readonly(newvp))
			error = EROFS;
		else
			error = VOP_SYMLINK(newvp, lnknm, tva, tnm, cred,
			    ct, flags);
		VN_RELE(newvp);
	} else
		error = ENOSYS;

done:
	AUTOFS_DPRINT((5, "auto_symlink: error=%d\n", error));
	return (error);
}
예제 #8
0
static int
auto_rename(
	vnode_t *odvp,
	char *onm,
	vnode_t *ndvp,
	char *nnm,
	cred_t *cr,
	caller_context_t *ct,
	int flags)
{
	vnode_t *o_newvp, *n_newvp;
	int error;

	AUTOFS_DPRINT((4, "auto_rename odvp %p onm %s to ndvp %p nnm %s\n",
	    (void *)odvp, onm, (void *)ndvp, nnm));

	/*
	 * we know odvp is an autonode, otherwise this function
	 * could not have ever been called.
	 */
	ASSERT(vn_matchops(odvp, auto_vnodeops));

	if (error = auto_trigger_mount(odvp, cr, &o_newvp))
		goto done;

	if (o_newvp == NULL) {
		/*
		 * can't rename an autonode
		 */
		error = ENOSYS;
		goto done;
	}

	if (vn_matchops(ndvp, auto_vnodeops)) {
		/*
		 * directory is AUTOFS, need to trigger the
		 * mount of the real filesystem.
		 */
		if (error = auto_trigger_mount(ndvp, cr, &n_newvp)) {
			VN_RELE(o_newvp);
			goto done;
		}

		if (n_newvp == NULL) {
			/*
			 * target can't be an autonode
			 */
			error = ENOSYS;
			VN_RELE(o_newvp);
			goto done;
		}
	} else {
		/*
		 * destination directory mount had been
		 * triggered prior to the call to this function.
		 */
		n_newvp = ndvp;
	}

	ASSERT(!vn_matchops(n_newvp, auto_vnodeops));

	if (vn_is_readonly(n_newvp)) {
		error = EROFS;
		VN_RELE(o_newvp);
		if (n_newvp != ndvp)
			VN_RELE(n_newvp);
		goto done;
	}

	error = VOP_RENAME(o_newvp, onm, n_newvp, nnm, cr, ct, flags);
	VN_RELE(o_newvp);
	if (n_newvp != ndvp)
		VN_RELE(n_newvp);

done:
	AUTOFS_DPRINT((5, "auto_rename error=%d\n", error));
	return (error);
}
예제 #9
0
static int
cfutimesat(int fd, char *fname, int nmflag, vattr_t *vap, int flags, int follow)
{
	file_t *fp;
	vnode_t *startvp, *vp;
	int error;
	char startchar;

	if (fd == AT_FDCWD && fname == NULL)
		return (set_errno(EFAULT));

	if (nmflag == 1 || (nmflag == 2 && fname != NULL)) {
		if (copyin(fname, &startchar, sizeof (char)))
			return (set_errno(EFAULT));
	} else {
		startchar = '\0';
	}

	if (fd == AT_FDCWD) {
		startvp = NULL;
	} else {
		/*
		 * is this absolute path?
		 */
		if (startchar != '/') {
			if ((fp = getf(fd)) == NULL)
				return (set_errno(EBADF));
			startvp = fp->f_vnode;
			VN_HOLD(startvp);
			releasef(fd);
		} else {
			startvp = NULL;
		}
	}

	if ((nmflag == 1) || ((nmflag == 2) && (fname != NULL))) {
		if (AU_AUDITING() && startvp != NULL)
			audit_setfsat_path(1);
		if ((error = lookupnameat(fname, UIO_USERSPACE,
		    follow, NULLVPP, &vp, startvp)) != 0) {
			if (startvp != NULL)
				VN_RELE(startvp);
			return (set_errno(error));
		}
	} else {
		vp = startvp;
		VN_HOLD(vp);
	}

	if (startvp != NULL) {
		VN_RELE(startvp);
	}

	if (vn_is_readonly(vp)) {
		error = EROFS;
	} else {
		error = VOP_SETATTR(vp, vap, flags, CRED(), NULL);
	}

	VN_RELE(vp);
	if (error != 0)
		return (set_errno(error));
	return (0);
}
예제 #10
0
/* ARGSUSED */
void
acl3_setacl(SETACL3args *args, SETACL3res *resp, struct exportinfo *exi,
	struct svc_req *req, cred_t *cr)
{
	int error;
	vnode_t *vp;
	vattr_t *vap;
	vattr_t va;

	vap = NULL;

	vp = nfs3_fhtovp(&args->fh, exi);
	if (vp == NULL) {
		error = ESTALE;
		goto out1;
	}

	(void) VOP_RWLOCK(vp, V_WRITELOCK_TRUE, NULL);

#ifdef DEBUG
	if (rfs3_do_post_op_attr) {
		va.va_mask = AT_ALL;
		vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
	} else
		vap = NULL;
#else
	va.va_mask = AT_ALL;
	vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
#endif

	if (rdonly(exi, req) || vn_is_readonly(vp)) {
		resp->status = NFS3ERR_ROFS;
		goto out1;
	}

	error = VOP_SETSECATTR(vp, &args->acl, 0, cr);

#ifdef DEBUG
	if (rfs3_do_post_op_attr) {
		va.va_mask = AT_ALL;
		vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
	} else
		vap = NULL;
#else
	va.va_mask = AT_ALL;
	vap = rfs4_delegated_getattr(vp, &va, 0, cr) ? NULL : &va;
#endif

	if (error)
		goto out;

	VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
	VN_RELE(vp);

	resp->status = NFS3_OK;
	vattr_to_post_op_attr(vap, &resp->resok.attr);
	return;

out:
	if (curthread->t_flag & T_WOULDBLOCK) {
		curthread->t_flag &= ~T_WOULDBLOCK;
		resp->status = NFS3ERR_JUKEBOX;
	} else
		resp->status = puterrno3(error);
out1:
	if (vp != NULL) {
		VOP_RWUNLOCK(vp, V_WRITELOCK_TRUE, NULL);
		VN_RELE(vp);
	}
	vattr_to_post_op_attr(vap, &resp->resfail.attr);
}
예제 #11
0
파일: chown.c 프로젝트: andreiw/polaris
/*
 * nmflag has the following values
 *
 * 1 - Always do lookup.  i.e. chown, lchown.
 * 2 - Name is optional i.e. fchownat
 * 0 - Don't lookup name, vp is in file_p. i.e. fchown
 *
 */
int
cfchownat(int fd, char *name, int nmflag, uid_t uid, gid_t gid, int flags)
{
	vnode_t		*startvp, *vp;
	file_t 		*filefp;
	struct vattr 	vattr;
	int 		error = 0;
	char 		startchar;

	if (uid < -1 || uid > MAXUID || gid < -1 || gid > MAXUID)
		return (set_errno(EINVAL));
	vattr.va_uid = uid;
	vattr.va_gid = gid;
	vattr.va_mask = 0;
	if (vattr.va_uid != -1)
		vattr.va_mask |= AT_UID;
	if (vattr.va_gid != -1)
		vattr.va_mask |= AT_GID;


	if (fd == AT_FDCWD && name == NULL)
		return (set_errno(EFAULT));

	if (nmflag == 1 || (nmflag == 2 && name != NULL)) {
		if (copyin(name, &startchar, sizeof (char)))
			return (set_errno(EFAULT));
	} else
		startchar = '\0';


	if (fd == AT_FDCWD)
		startvp = NULL;
	else {
		/*
		 * only get fd if not doing absolute lookup
		 */
		if (startchar != '/' || nmflag == 0) {
			if ((filefp = getf(fd)) == NULL) {
				return (set_errno(EBADF));
			}
			startvp = filefp->f_vnode;
			VN_HOLD(startvp);
			releasef(fd);
		} else {
			startvp = NULL;
		}
	}

#if C2_AUDIT
	if ((nmflag == 2) && audit_active)
		audit_setfsat_path(1);
#endif /* C2_AUDIT */

	/*
	 * Do lookups for chown, lchown and fchownat when name not NULL
	 */
	if ((nmflag == 2 && name != NULL) || nmflag == 1) {
		if (error = lookupnameat(name, UIO_USERSPACE,
		    (flags == AT_SYMLINK_NOFOLLOW) ?
		    NO_FOLLOW : FOLLOW,
		    NULLVPP, &vp, startvp)) {
			if (startvp != NULL)
				VN_RELE(startvp);
			return (set_errno(error));
		}
	} else {
		vp = startvp;
		ASSERT(vp);
		VN_HOLD(vp);
	}

	if (vn_is_readonly(vp)) {
		error = EROFS;
	} else {
		error = VOP_SETATTR(vp, &vattr, 0, CRED(), NULL);
	}

	if (startvp != NULL)
		VN_RELE(startvp);
	if (vp != NULL)
		VN_RELE(vp);

	if (error != 0)
		return (set_errno(error));
	else
		return (error);
}
예제 #12
0
/*
 * Flush all vnodes in this (or every) vfs.
 * Used by nfs_sync and by nfs_unmount.
 */
void
r4flush(struct vfs *vfsp, cred_t *cr)
{
	int index;
	rnode4_t *rp;
	vnode_t *vp, **vplist;
	long num, cnt;

	/*
	 * Check to see whether there is anything to do.
	 */
	num = rnode4_new;
	if (num == 0)
		return;

	/*
	 * Allocate a slot for all currently active rnodes on the
	 * supposition that they all may need flushing.
	 */
	vplist = kmem_alloc(num * sizeof (*vplist), KM_SLEEP);
	cnt = 0;

	/*
	 * Walk the hash queues looking for rnodes with page
	 * lists associated with them.  Make a list of these
	 * files.
	 */
	for (index = 0; index < rtable4size; index++) {
		rw_enter(&rtable4[index].r_lock, RW_READER);
		for (rp = rtable4[index].r_hashf;
		    rp != (rnode4_t *)(&rtable4[index]);
		    rp = rp->r_hashf) {
			vp = RTOV4(rp);
			/*
			 * Don't bother sync'ing a vp if it
			 * is part of virtual swap device or
			 * if VFS is read-only
			 */
			if (IS_SWAPVP(vp) || vn_is_readonly(vp))
				continue;
			/*
			 * If flushing all mounted file systems or
			 * the vnode belongs to this vfs, has pages
			 * and is marked as either dirty or mmap'd,
			 * hold and add this vnode to the list of
			 * vnodes to flush.
			 */
			if ((vfsp == NULL || vp->v_vfsp == vfsp) &&
			    nfs4_has_pages(vp) &&
			    ((rp->r_flags & R4DIRTY) || rp->r_mapcnt > 0)) {
				VN_HOLD(vp);
				vplist[cnt++] = vp;
				if (cnt == num) {
					rw_exit(&rtable4[index].r_lock);
					goto toomany;
				}
			}
		}
		rw_exit(&rtable4[index].r_lock);
	}
toomany:

	/*
	 * Flush and release all of the files on the list.
	 */
	while (cnt-- > 0) {
		vp = vplist[cnt];
		(void) VOP_PUTPAGE(vp, (u_offset_t)0, 0, B_ASYNC, cr, NULL);
		VN_RELE(vp);
	}

	/*
	 * Free the space allocated to hold the list.
	 */
	kmem_free(vplist, num * sizeof (*vplist));
}