Split the second half of vn_open_cred() (after a vnode has been found via

a lookup or created via VOP_CREATE()) into a new vn_open_vnode() function
and use this function in fhopen() instead of duplicating code from
vn_open_cred() directly.

Tested by:	pho
Reviewed by:	kib
MFC after:	2 weeks
This commit is contained in:
John Baldwin 2012-06-08 18:32:09 +00:00
parent 2ac58c1d79
commit 7ac1b61aac
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=236762
3 changed files with 84 additions and 159 deletions

View File

@ -4484,17 +4484,12 @@ sys_fhopen(td, uap)
int flags;
} */ *uap;
{
struct proc *p = td->td_proc;
struct mount *mp;
struct vnode *vp;
struct fhandle fhp;
struct vattr vat;
struct vattr *vap = &vat;
struct flock lf;
struct file *fp;
register struct filedesc *fdp = p->p_fd;
int fmode, error, type;
accmode_t accmode;
struct file *nfp;
int vfslocked;
int indx;
@ -4502,6 +4497,7 @@ sys_fhopen(td, uap)
error = priv_check(td, PRIV_VFS_FHOPEN);
if (error)
return (error);
indx = -1;
fmode = FFLAGS(uap->flags);
/* why not allow a non-read/write open for our lockd? */
if (((fmode & (FREAD | FWRITE)) == 0) || (fmode & O_CREAT))
@ -4517,109 +4513,40 @@ sys_fhopen(td, uap)
/* now give me my vnode, it gets returned to me locked */
error = VFS_FHTOVP(mp, &fhp.fh_fid, LK_EXCLUSIVE, &vp);
vfs_unbusy(mp);
if (error)
goto out;
/*
* from now on we have to make sure not
* to forget about the vnode
* any error that causes an abort must vput(vp)
* just set error = err and 'goto bad;'.
*/
/*
* from vn_open
*/
if (vp->v_type == VLNK) {
error = EMLINK;
goto bad;
}
if (vp->v_type == VSOCK) {
error = EOPNOTSUPP;
goto bad;
}
if (vp->v_type != VDIR && fmode & O_DIRECTORY) {
error = ENOTDIR;
goto bad;
}
accmode = 0;
if (fmode & (FWRITE | O_TRUNC)) {
if (vp->v_type == VDIR) {
error = EISDIR;
goto bad;
}
error = vn_writechk(vp);
if (error)
goto bad;
accmode |= VWRITE;
}
if (fmode & FREAD)
accmode |= VREAD;
if ((fmode & O_APPEND) && (fmode & FWRITE))
accmode |= VAPPEND;
#ifdef MAC
error = mac_vnode_check_open(td->td_ucred, vp, accmode);
if (error)
goto bad;
#endif
if (accmode) {
error = VOP_ACCESS(vp, accmode, td->td_ucred, td);
if (error)
goto bad;
}
if (fmode & O_TRUNC) {
vfs_ref(mp);
VOP_UNLOCK(vp, 0); /* XXX */
if ((error = vn_start_write(NULL, &mp, V_WAIT | PCATCH)) != 0) {
vrele(vp);
vfs_rel(mp);
goto out;
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); /* XXX */
vfs_rel(mp);
#ifdef MAC
/*
* We don't yet have fp->f_cred, so use td->td_ucred, which
* should be right.
*/
error = mac_vnode_check_write(td->td_ucred, td->td_ucred, vp);
if (error == 0) {
#endif
VATTR_NULL(vap);
vap->va_size = 0;
error = VOP_SETATTR(vp, vap, td->td_ucred);
#ifdef MAC
}
#endif
vn_finished_write(mp);
if (error)
goto bad;
}
error = VOP_OPEN(vp, fmode, td->td_ucred, td, NULL);
if (error)
goto bad;
if (fmode & FWRITE) {
vp->v_writecount++;
CTR3(KTR_VFS, "%s: vp %p v_writecount increased to %d",
__func__, vp, vp->v_writecount);
if (error) {
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
/*
* end of vn_open code
*/
error = falloc_noinstall(td, &nfp);
if (error) {
vput(vp);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
}
if ((error = falloc(td, &nfp, &indx, fmode)) != 0) {
if (fmode & FWRITE) {
vp->v_writecount--;
CTR3(KTR_VFS, "%s: vp %p v_writecount decreased to %d",
__func__, vp, vp->v_writecount);
}
goto bad;
}
/* An extra reference on `nfp' has been held for us by falloc(). */
fp = nfp;
nfp->f_vnode = vp;
finit(nfp, fmode & FMASK, DTYPE_VNODE, vp, &vnops);
#ifdef INVARIANTS
td->td_dupfd = -1;
#endif
error = vn_open_vnode(vp, fmode, td->td_ucred, td, fp);
if (error) {
KASSERT(fp->f_ops == &badfileops,
("VOP_OPEN in fhopen() set f_ops"));
KASSERT(td->td_dupfd < 0,
("fhopen() encountered fdopen()"));
vput(vp);
goto bad;
}
#ifdef INVARIANTS
td->td_dupfd = 0;
#endif
fp->f_vnode = vp;
fp->f_seqcount = 1;
finit(fp, fmode & FMASK, DTYPE_VNODE, vp, &vnops);
VOP_UNLOCK(vp, 0);
if (fmode & (O_EXLOCK | O_SHLOCK)) {
lf.l_whence = SEEK_SET;
lf.l_start = 0;
@ -4631,36 +4558,22 @@ sys_fhopen(td, uap)
type = F_FLOCK;
if ((fmode & FNONBLOCK) == 0)
type |= F_WAIT;
VOP_UNLOCK(vp, 0);
if ((error = VOP_ADVLOCK(vp, (caddr_t)fp, F_SETLK, &lf,
type)) != 0) {
/*
* The lock request failed. Normally close the
* descriptor but handle the case where someone might
* have dup()d or close()d it when we weren't looking.
*/
fdclose(fdp, fp, indx, td);
/*
* release our private reference
*/
fdrop(fp, td);
goto out;
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
type)) != 0)
goto bad;
atomic_set_int(&fp->f_flag, FHASLOCK);
}
if (fmode & O_TRUNC) {
error = fo_truncate(fp, 0, td->td_ucred, td);
if (error)
goto bad;
}
VOP_UNLOCK(vp, 0);
fdrop(fp, td);
VFS_UNLOCK_GIANT(vfslocked);
td->td_retval[0] = indx;
return (0);
error = finstall(td, fp, &indx, fmode);
bad:
vput(vp);
out:
VFS_UNLOCK_GIANT(vfslocked);
fdrop(fp, td);
td->td_retval[0] = indx;
return (error);
}

View File

@ -108,7 +108,8 @@ vn_open(ndp, flagp, cmode, fp)
}
/*
* Common code for vnode open operations.
* Common code for vnode open operations via a name lookup.
* Lookup the vnode and invoke VOP_CREATE if needed.
* Check permissions, and call the VOP_OPEN or VOP_CREATE routine.
*
* Note that this does NOT free nameidata for the successful case,
@ -124,7 +125,6 @@ vn_open_cred(struct nameidata *ndp, int *flagp, int cmode, u_int vn_open_flags,
struct vattr vat;
struct vattr *vap = &vat;
int fmode, error;
accmode_t accmode;
int vfslocked, mpsafe;
mpsafe = ndp->ni_cnd.cn_flags & MPSAFE;
@ -205,24 +205,44 @@ vn_open_cred(struct nameidata *ndp, int *flagp, int cmode, u_int vn_open_flags,
vfslocked = NDHASGIANT(ndp);
vp = ndp->ni_vp;
}
if (vp->v_type == VLNK) {
error = EMLINK;
error = vn_open_vnode(vp, fmode, cred, td, fp);
if (error)
goto bad;
}
if (vp->v_type == VSOCK) {
error = EOPNOTSUPP;
goto bad;
}
if (vp->v_type != VDIR && fmode & O_DIRECTORY) {
error = ENOTDIR;
goto bad;
}
*flagp = fmode;
if (!mpsafe)
VFS_UNLOCK_GIANT(vfslocked);
return (0);
bad:
NDFREE(ndp, NDF_ONLY_PNBUF);
vput(vp);
VFS_UNLOCK_GIANT(vfslocked);
*flagp = fmode;
ndp->ni_vp = NULL;
return (error);
}
/*
* Common code for vnode open operations once a vnode is located.
* Check permissions, and call the VOP_OPEN routine.
*/
int
vn_open_vnode(struct vnode *vp, int fmode, struct ucred *cred,
struct thread *td, struct file *fp)
{
accmode_t accmode;
int error;
VFS_ASSERT_GIANT(vp->v_mount);
if (vp->v_type == VLNK)
return (EMLINK);
if (vp->v_type == VSOCK)
return (EOPNOTSUPP);
if (vp->v_type != VDIR && fmode & O_DIRECTORY)
return (ENOTDIR);
accmode = 0;
if (fmode & (FWRITE | O_TRUNC)) {
if (vp->v_type == VDIR) {
error = EISDIR;
goto bad;
}
if (vp->v_type == VDIR)
return (EISDIR);
accmode |= VWRITE;
}
if (fmode & FREAD)
@ -234,40 +254,30 @@ vn_open_cred(struct nameidata *ndp, int *flagp, int cmode, u_int vn_open_flags,
#ifdef MAC
error = mac_vnode_check_open(cred, vp, accmode);
if (error)
goto bad;
return (error);
#endif
if ((fmode & O_CREAT) == 0) {
if (accmode & VWRITE) {
error = vn_writechk(vp);
if (error)
goto bad;
return (error);
}
if (accmode) {
error = VOP_ACCESS(vp, accmode, cred, td);
if (error)
goto bad;
return (error);
}
}
if ((error = VOP_OPEN(vp, fmode, cred, td, fp)) != 0)
goto bad;
return (error);
if (fmode & FWRITE) {
vp->v_writecount++;
CTR3(KTR_VFS, "%s: vp %p v_writecount increased to %d",
__func__, vp, vp->v_writecount);
}
*flagp = fmode;
ASSERT_VOP_LOCKED(vp, "vn_open_cred");
if (!mpsafe)
VFS_UNLOCK_GIANT(vfslocked);
ASSERT_VOP_LOCKED(vp, "vn_open_vnode");
return (0);
bad:
NDFREE(ndp, NDF_ONLY_PNBUF);
vput(vp);
VFS_UNLOCK_GIANT(vfslocked);
*flagp = fmode;
ndp->ni_vp = NULL;
return (error);
}
/*

View File

@ -654,6 +654,8 @@ int _vn_lock(struct vnode *vp, int flags, char *file, int line);
int vn_open(struct nameidata *ndp, int *flagp, int cmode, struct file *fp);
int vn_open_cred(struct nameidata *ndp, int *flagp, int cmode,
u_int vn_open_flags, struct ucred *cred, struct file *fp);
int vn_open_vnode(struct vnode *vp, int fmode, struct ucred *cred,
struct thread *td, struct file *fp);
void vn_pages_remove(struct vnode *vp, vm_pindex_t start, vm_pindex_t end);
int vn_pollrecord(struct vnode *vp, struct thread *p, int events);
int vn_rdwr(enum uio_rw rw, struct vnode *vp, void *base,