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:
parent
2ac58c1d79
commit
7ac1b61aac
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=236762
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user