Index: kern/tty_cons.c =================================================================== RCS file: /usr/local/arch/ncvs/src/sys/kern/tty_cons.c,v retrieving revision 1.138 diff -u -r1.138 tty_cons.c --- kern/tty_cons.c 6 Nov 2006 13:42:01 -0000 1.138 +++ kern/tty_cons.c 16 Apr 2007 09:58:03 -0000 @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -390,6 +391,7 @@ struct vnode *vp; struct cdev *dev; struct cdevsw *csw; + struct filedesc *fdp; int error; if ((vp = cnd->cnd_vp) != NULL) { @@ -406,8 +408,11 @@ vn_close(vp, openflag, td->td_ucred, td); } snprintf(path, sizeof(path), "/dev/%s", cnd->cnd_cn->cn_name); - NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, path, td); + NDINIT(&nd, LOOKUP | FDLOCKED, FOLLOW, UIO_SYSSPACE, path, td); + fdp = td->td_proc->p_fd; + FILEDESC_SLOCK(fdp); error = vn_open(&nd, &openflag, 0, -1); + FILEDESC_SUNLOCK(fdp); if (error == 0) { NDFREE(&nd, NDF_ONLY_PNBUF); VOP_UNLOCK(nd.ni_vp, 0, td); Index: kern/vfs_lookup.c =================================================================== RCS file: /usr/local/arch/ncvs/src/sys/kern/vfs_lookup.c,v retrieving revision 1.100 diff -u -r1.100 vfs_lookup.c --- kern/vfs_lookup.c 4 Apr 2007 09:11:33 -0000 1.100 +++ kern/vfs_lookup.c 16 Apr 2007 09:58:03 -0000 @@ -188,14 +188,16 @@ /* * Get starting point for the translation. */ - FILEDESC_SLOCK(fdp); + if (!(cnp->cn_flags & FDLOCKED)) + FILEDESC_SLOCK(fdp); ndp->ni_rootdir = fdp->fd_rdir; ndp->ni_topdir = fdp->fd_jdir; dp = fdp->fd_cdir; vfslocked = VFS_LOCK_GIANT(dp->v_mount); VREF(dp); - FILEDESC_SUNLOCK(fdp); + if (!(cnp->cn_flags & FDLOCKED)) + FILEDESC_SUNLOCK(fdp); for (;;) { /* * Check if root directory should replace current directory. Index: kern/vfs_syscalls.c =================================================================== RCS file: /usr/local/arch/ncvs/src/sys/kern/vfs_syscalls.c,v retrieving revision 1.437 diff -u -r1.437 vfs_syscalls.c --- kern/vfs_syscalls.c 5 Apr 2007 21:10:53 -0000 1.437 +++ kern/vfs_syscalls.c 16 Apr 2007 09:58:03 -0000 @@ -984,7 +984,15 @@ cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT; NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1 | MPSAFE, pathseg, path, td); td->td_dupfd = -1; /* XXX check for fdopen */ + FILEDESC_SLOCK(fdp); + if (fp != fdp->fd_ofiles[indx]) { + FILEDESC_SUNLOCK(fdp); + fdrop(fp, td); + td->td_retval[0] = indx; + return (0); + } error = vn_open(&nd, &flags, cmode, indx); + FILEDESC_SUNLOCK(fdp); if (error) { /* * If the vn_open replaced the method vector, something Index: kern/vfs_vnops.c =================================================================== RCS file: /usr/local/arch/ncvs/src/sys/kern/vfs_vnops.c,v retrieving revision 1.248 diff -u -r1.248 vfs_vnops.c --- kern/vfs_vnops.c 12 Feb 2007 22:53:01 -0000 1.248 +++ kern/vfs_vnops.c 16 Apr 2007 09:58:03 -0000 @@ -113,9 +113,10 @@ struct vattr vat; struct vattr *vap = &vat; int mode, fmode, error; - int vfslocked, mpsafe; + int vfslocked, mpsafe, fdlocked; mpsafe = ndp->ni_cnd.cn_flags & MPSAFE; + fdlocked = (fdidx != -1) || (ndp->ni_cnd.cn_flags & FDLOCKED); restart: vfslocked = 0; fmode = *flagp; @@ -123,6 +124,8 @@ ndp->ni_cnd.cn_nameiop = CREATE; ndp->ni_cnd.cn_flags = ISOPEN | LOCKPARENT | LOCKLEAF | MPSAFE | AUDITVNODE1; + if (fdlocked) + ndp->ni_cnd.cn_flags |= FDLOCKED; if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0) ndp->ni_cnd.cn_flags |= FOLLOW; bwillwrite(); @@ -184,6 +187,8 @@ ndp->ni_cnd.cn_flags = ISOPEN | ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKSHARED | LOCKLEAF | MPSAFE | AUDITVNODE1; + if (fdlocked) + ndp->ni_cnd.cn_flags |= FDLOCKED; if ((error = namei(ndp)) != 0) return (error); if (!mpsafe) Index: sys/namei.h =================================================================== RCS file: /usr/local/arch/ncvs/src/sys/sys/namei.h,v retrieving revision 1.48 diff -u -r1.48 namei.h --- sys/namei.h 5 Feb 2006 15:42:01 -0000 1.48 +++ sys/namei.h 16 Apr 2007 09:58:03 -0000 @@ -105,6 +105,7 @@ #define WANTPARENT 0x0010 /* want parent vnode returned unlocked */ #define NOCACHE 0x0020 /* name must not be left in cache */ #define FOLLOW 0x0040 /* follow symbolic links */ +#define FDLOCKED 0x0080 /* filedesc already locked */ #define LOCKSHARED 0x0100 /* Shared lock leaf */ #define NOFOLLOW 0x0000 /* do not follow symbolic links (pseudo) */ #define MODMASK 0x01fc /* mask of operational modifiers */ Index: fs/devfs/devfs_vnops.c =================================================================== RCS file: /usr/local/arch/ncvs/src/sys/fs/devfs/devfs_vnops.c,v retrieving revision 1.143 diff -u -r1.143 devfs_vnops.c --- fs/devfs/devfs_vnops.c 4 Apr 2007 09:11:32 -0000 1.143 +++ fs/devfs/devfs_vnops.c 16 Apr 2007 09:58:03 -0000 @@ -734,6 +738,7 @@ struct thread *td = ap->a_td; struct vnode *vp = ap->a_vp; struct cdev *dev = vp->v_rdev; + struct filedesc *fdp = td->td_proc->p_fd; struct file *fp; int error; struct cdevsw *dsw; @@ -758,6 +763,9 @@ VOP_UNLOCK(vp, 0, td); + fp = fdp->fd_ofiles[ap->a_fdidx]; + FILEDESC_SUNLOCK(fdp); + if(!(dsw->d_flags & D_NEEDGIANT)) { DROP_GIANT(); if (dsw->d_fdopen != NULL) @@ -772,6 +780,7 @@ error = dsw->d_open(dev, ap->a_mode, S_IFCHR, td); } + FILEDESC_SLOCK(fdp); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); dev_relthread(dev); @@ -786,13 +795,8 @@ if(ap->a_fdidx < 0) return (error); #endif - /* - * This is a pretty disgustingly long chain, but I am not - * sure there is any better way. Passing the fdidx into - * VOP_OPEN() offers us more information than just passing - * the file *. - */ - fp = ap->a_td->td_proc->p_fd->fd_ofiles[ap->a_fdidx]; + if (fp != fdp->fd_ofiles[ap->a_fdidx]) + return (EBADF); FILE_LOCK(fp); KASSERT(fp->f_ops == &badfileops, ("Could not vnode bypass device on fdops %p", fp->f_ops));