--- //depot/projects/smpng/sys/kern/vfs_syscalls.c 2012-06-04 18:27:32.000000000 0000 +++ //depot/user/jhb/ktrace/kern/vfs_syscalls.c 2012-06-05 21:00:18.000000000 0000 @@ -4484,17 +4484,12 @@ 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 @@ 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,45 @@ /* 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; + if (error) { + VFS_UNLOCK_GIANT(vfslocked); + return (error); } - 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); - } + error = falloc_noinstall(td, &nfp); + if (error) { + vput(vp); + VFS_UNLOCK_GIANT(vfslocked); + return (error); + } - /* - * end of vn_open code - */ + /* An extra reference on `nfp' has been held for us by falloc(). */ + fp = nfp; +#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()")); - 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); - } + vput(vp); +#if 0 + /* XXX: Open does this. */ + if (error == ERESTART) + error = EINTR; +#endif 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 = 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 +4563,22 @@ 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); + error = finstall(td, fp, &indx, fmode); +bad: + VFS_UNLOCK_GIANT(vfslocked); fdrop(fp, td); - VFS_UNLOCK_GIANT(vfslocked); td->td_retval[0] = indx; - return (0); - -bad: - vput(vp); -out: - VFS_UNLOCK_GIANT(vfslocked); return (error); } --- //depot/projects/smpng/sys/kern/vfs_vnops.c 2012-06-04 18:27:32.000000000 0000 +++ //depot/user/jhb/ktrace/kern/vfs_vnops.c 2012-06-05 21:00:18.000000000 0000 @@ -108,7 +108,8 @@ } /* - * 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 @@ 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 @@ 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 @@ #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); } /* --- //depot/projects/smpng/sys/sys/vnode.h 2012-06-04 18:27:32.000000000 0000 +++ //depot/user/jhb/ktrace/sys/vnode.h 2012-06-05 00:27:57.000000000 0000 @@ -654,6 +654,8 @@ 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,