diff --git a/sys/fs/fdescfs/fdesc_vfsops.c b/sys/fs/fdescfs/fdesc_vfsops.c --- a/sys/fs/fdescfs/fdesc_vfsops.c +++ b/sys/fs/fdescfs/fdesc_vfsops.c @@ -90,8 +90,7 @@ if (mp->mnt_flag & (MNT_UPDATE | MNT_ROOTFS)) return (EOPNOTSUPP); - fmp = malloc(sizeof(struct fdescmount), - M_FDESCMNT, M_WAITOK); /* XXX */ + fmp = malloc(sizeof(struct fdescmount), M_FDESCMNT, M_WAITOK); /* * We need to initialize a few bits of our local mount point struct to diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c --- a/sys/fs/fdescfs/fdesc_vnops.c +++ b/sys/fs/fdescfs/fdesc_vnops.c @@ -147,6 +147,7 @@ struct fdhashhead *fc; struct fdescnode *fd, *fd2; struct vnode *vp, *vp2; + enum vgetstate vgs; int error; fc = FD_NHASH(ix); @@ -166,9 +167,9 @@ if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) { /* Get reference to vnode in case it's being free'd */ vp = fd->fd_vnode; - VI_LOCK(vp); + vgs = vget_prep(vp); mtx_unlock(&fdesc_hashmtx); - if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) + if (vget_finish(vp, LK_EXCLUSIVE, vgs) != 0) goto loop; *vpp = vp; return (0); @@ -218,9 +219,9 @@ if (fd2->fd_ix == ix && fd2->fd_vnode->v_mount == mp) { /* Get reference to vnode in case it's being free'd */ vp2 = fd2->fd_vnode; - VI_LOCK(vp2); + vgs = vget_prep(vp2); mtx_unlock(&fdesc_hashmtx); - error = vget(vp2, LK_EXCLUSIVE | LK_INTERLOCK); + error = vget_finish(vp2, LK_EXCLUSIVE, vgs); /* Someone beat us, dec use count and wait for reclaim */ vgone(vp); vput(vp); @@ -290,7 +291,6 @@ int nlen = cnp->cn_namelen; u_int fd, fd1; int error; - bool fdropped; struct vnode *fvp; if ((cnp->cn_flags & ISLASTCN) && @@ -334,41 +334,34 @@ */ if ((error = fget(td, fd, &cap_no_rights, &fp)) != 0) goto bad; - fdropped = false; - /* Make sure we're not looking up the dvp itself. */ - if (VTOFDESC(dvp)->fd_ix != FD_DESC + fd) { - /* - * Unlock our root node (dvp) when doing this, since we might - * deadlock since the vnode might be locked by another thread - * and the root vnode lock will be obtained afterwards (in case - * we're looking up the fd of the root vnode), which will be the - * opposite lock order. Vhold the root vnode first so we don't - * lose it. - */ - arg.ftype = Fdesc; - arg.fd_fd = fd; - arg.ix = FD_DESC + fd; - arg.fp = fp; - arg.td = td; - arg.fdropped = fdropped; - error = vn_vget_ino_gen(dvp, fdesc_get_ino_alloc, &arg, - LK_EXCLUSIVE, &fvp); - fdropped = arg.fdropped; - } - - if (!fdropped) { + /* + * Make sure we do not deadlock looking up the dvp itself. + * + * Unlock our root node (dvp) when doing this, since we might + * deadlock since the vnode might be locked by another thread + * and the root vnode lock will be obtained afterwards (in case + * we're looking up the fd of the root vnode), which will be the + * opposite lock order. + */ + arg.ftype = Fdesc; + arg.fd_fd = fd; + arg.ix = FD_DESC + fd; + arg.fp = fp; + arg.td = td; + arg.fdropped = false; + error = vn_vget_ino_gen(dvp, fdesc_get_ino_alloc, &arg, + LK_EXCLUSIVE, &fvp); + + if (!arg.fdropped) { /* * In case we're holding the last reference to the file, the dvp * will be re-acquired. */ - vhold(dvp); VOP_UNLOCK(dvp); fdrop(fp, td); - fdropped = true; vn_lock(dvp, LK_RETRY | LK_EXCLUSIVE); - vdrop(dvp); fvp = dvp; if (error == 0 && VN_IS_DOOMED(dvp)) error = ENOENT;