Index: sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c =================================================================== --- sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -5375,9 +5375,6 @@ ASSERT(zp != NULL); - /* Destroy the vm object and flush associated pages. */ - vnode_destroy_vobject(vp); - /* * z_teardown_inactive_lock protects from a race with * zfs_znode_dmu_fini in zfsvfs_teardown during Index: sys/fs/cd9660/cd9660_node.c =================================================================== --- sys/fs/cd9660/cd9660_node.c +++ sys/fs/cd9660/cd9660_node.c @@ -91,10 +91,6 @@ { struct vnode *vp = ap->a_vp; - /* - * Destroy the vm object and flush associated pages. - */ - vnode_destroy_vobject(vp); /* * Remove the inode from its hash chain. */ Index: sys/fs/devfs/devfs_vnops.c =================================================================== --- sys/fs/devfs/devfs_vnops.c +++ sys/fs/devfs/devfs_vnops.c @@ -1428,7 +1428,6 @@ vp->v_data = NULL; } mtx_unlock(&devfs_de_interlock); - vnode_destroy_vobject(vp); return (0); } Index: sys/fs/ext2fs/ext2_inode.c =================================================================== --- sys/fs/ext2fs/ext2_inode.c +++ sys/fs/ext2fs/ext2_inode.c @@ -639,6 +639,5 @@ vfs_hash_remove(vp); free(vp->v_data, M_EXT2NODE); vp->v_data = 0; - vnode_destroy_vobject(vp); return (0); } Index: sys/fs/fuse/fuse_vnops.c =================================================================== --- sys/fs/fuse/fuse_vnops.c +++ sys/fs/fuse/fuse_vnops.c @@ -1537,7 +1537,6 @@ fuse_vnode_setparent(vp, NULL); cache_purge(vp); vfs_hash_remove(vp); - vnode_destroy_vobject(vp); fuse_vnode_destroy(vp); return 0; Index: sys/fs/msdosfs/msdosfs_denode.c =================================================================== --- sys/fs/msdosfs/msdosfs_denode.c +++ sys/fs/msdosfs/msdosfs_denode.c @@ -551,10 +551,6 @@ dep, dep->de_Name, dep->de_refcnt); #endif - /* - * Destroy the vm object and flush associated pages. - */ - vnode_destroy_vobject(vp); /* * Remove the denode from its hash chain. */ Index: sys/fs/nfsclient/nfs_clnode.c =================================================================== --- sys/fs/nfsclient/nfs_clnode.c +++ sys/fs/nfsclient/nfs_clnode.c @@ -296,11 +296,6 @@ ncl_releasesillyrename(vp, ap->a_td); mtx_unlock(&np->n_mtx); - /* - * Destroy the vm object and flush associated pages. - */ - vnode_destroy_vobject(vp); - if (NFS_ISV4(vp) && vp->v_type == VREG) /* * We can now safely close any remaining NFSv4 Opens for Index: sys/fs/smbfs/smbfs_node.c =================================================================== --- sys/fs/smbfs/smbfs_node.c +++ sys/fs/smbfs/smbfs_node.c @@ -272,10 +272,6 @@ KASSERT((np->n_flag & NOPEN) == 0, ("file not closed before reclaim")); - /* - * Destroy the vm object and flush associated pages. - */ - vnode_destroy_vobject(vp); dvp = (np->n_parent && (np->n_flag & NREFPARENT)) ? np->n_parent : NULL; Index: sys/fs/tmpfs/tmpfs_vnops.c =================================================================== --- sys/fs/tmpfs/tmpfs_vnops.c +++ sys/fs/tmpfs/tmpfs_vnops.c @@ -1296,8 +1296,6 @@ if (vp->v_type == VREG) tmpfs_destroy_vobject(vp, node->tn_reg.tn_aobj); - else - vnode_destroy_vobject(vp); vp->v_object = NULL; if (tmpfs_use_nc(vp)) cache_purge(vp); Index: sys/fs/udf/udf_vnops.c =================================================================== --- sys/fs/udf/udf_vnops.c +++ sys/fs/udf/udf_vnops.c @@ -1266,11 +1266,6 @@ vp = a->a_vp; unode = VTON(vp); - /* - * Destroy the vm object and flush associated pages. - */ - vnode_destroy_vobject(vp); - if (unode != NULL) { vfs_hash_remove(vp); Index: sys/kern/vfs_subr.c =================================================================== --- sys/kern/vfs_subr.c +++ sys/kern/vfs_subr.c @@ -3464,9 +3464,9 @@ vgonel(struct vnode *vp) { struct thread *td; - int oweinact; - int active; struct mount *mp; + vm_object_t object; + bool active, oweinact; ASSERT_VOP_ELOCKED(vp, "vgonel"); ASSERT_VI_LOCKED(vp, "vgonel"); @@ -3486,8 +3486,8 @@ * Check to see if the vnode is in use. If so, we have to call * VOP_CLOSE() and VOP_INACTIVE(). */ - active = vp->v_usecount; - oweinact = (vp->v_iflag & VI_OWEINACT); + active = vp->v_usecount > 0; + oweinact = (vp->v_iflag & VI_OWEINACT) != 0; VI_UNLOCK(vp); vfs_notify_upper(vp, VFS_NOTIFY_UPPER_RECLAIM); @@ -3526,13 +3526,21 @@ ("vp %p bufobj not invalidated", vp)); /* - * For VMIO bufobj, BO_DEAD is set in vm_object_terminate() - * after the object's page queue is flushed. + * For VMIO bufobj, BO_DEAD is set later, or in + * vm_object_terminate() after the object's page queue is + * flushed. */ - if (vp->v_bufobj.bo_object == NULL) + object = vp->v_bufobj.bo_object; + if (object == NULL) vp->v_bufobj.bo_flag |= BO_DEAD; BO_UNLOCK(&vp->v_bufobj); + /* + * Handle the VM part. Tmpfs handles v_object on its own. + */ + if (object != NULL && object->type == OBJT_VNODE) + vnode_destroy_vobject(vp); + /* * Reclaim the vnode. */ Index: sys/ufs/ffs/ffs_alloc.c =================================================================== --- sys/ufs/ffs/ffs_alloc.c +++ sys/ufs/ffs/ffs_alloc.c @@ -1137,10 +1137,15 @@ (allocfcn_t *)ffs_nodealloccg); if (ino == 0) goto noinodes; - error = ffs_vget(pvp->v_mount, ino, LK_EXCLUSIVE, vpp); + + /* + * Get rid of the cached old vnode, force allocation of a new vnode + * for this inode. + */ + error = ffs_vgetf(pvp->v_mount, ino, LK_EXCLUSIVE, vpp, FFSV_REPLACE); if (error) { error1 = ffs_vgetf(pvp->v_mount, ino, LK_EXCLUSIVE, vpp, - FFSV_FORCEINSMQ); + FFSV_FORCEINSMQ | FFSV_REPLACE); ffs_vfree(pvp, ino, mode); if (error1 == 0) { ip = VTOI(*vpp); @@ -1176,7 +1181,6 @@ ip->i_din2->di_birthtime = ts.tv_sec; ip->i_din2->di_birthnsec = ts.tv_nsec; } - ufs_prepare_reclaim(*vpp); ip->i_flag = 0; (*vpp)->v_vflag = 0; (*vpp)->v_type = VNON; Index: sys/ufs/ffs/ffs_extern.h =================================================================== --- sys/ufs/ffs/ffs_extern.h +++ sys/ufs/ffs/ffs_extern.h @@ -121,6 +121,7 @@ * Flags to ffs_vgetf */ #define FFSV_FORCEINSMQ 0x0001 +#define FFSV_REPLACE 0x0002 /* * Flags to ffs_reload Index: sys/ufs/ffs/ffs_vfsops.c =================================================================== --- sys/ufs/ffs/ffs_vfsops.c +++ sys/ufs/ffs/ffs_vfsops.c @@ -1671,9 +1671,17 @@ struct vnode *vp; int error; + MPASS((ffs_flags & FFSV_REPLACE) == 0 || (flags & LK_EXCLUSIVE) != 0); + error = vfs_hash_get(mp, ino, flags, curthread, vpp, NULL, NULL); - if (error || *vpp != NULL) + if (error != 0) return (error); + if (*vpp != NULL) { + if ((ffs_flags & FFSV_REPLACE) == 0) + return (0); + vgone(*vpp); + vput(*vpp); + } /* * We must promote to an exclusive lock for vnode creation. This @@ -1735,8 +1743,19 @@ } vp->v_vflag &= ~VV_FORCEINSMQ; error = vfs_hash_insert(vp, ino, flags, curthread, vpp, NULL, NULL); - if (error || *vpp != NULL) + if (error != 0) return (error); + if (*vpp != NULL) { + /* + * Calls from ffs_valloc() (i.e. FFSV_REPLACE set) + * operate on empty inode, which must not be found by + * other threads until fully filled. Vnode for empty + * inode must be not re-inserted on the hash by other + * thread, after removal by us at the beginning. + */ + MPASS((ffs_flags & FFSV_REPLACE) == 0); + return (0); + } /* Read in the disk contents for the inode, copy into the inode. */ error = bread(ump->um_devvp, fsbtodb(fs, ino_to_fsba(fs, ino)), Index: sys/ufs/ufs/ufs_inode.c =================================================================== --- sys/ufs/ufs/ufs_inode.c +++ sys/ufs/ufs/ufs_inode.c @@ -189,7 +189,6 @@ ip = VTOI(vp); - vnode_destroy_vobject(vp); #ifdef QUOTA for (i = 0; i < MAXQUOTAS; i++) { if (ip->i_dquot[i] != NODQUOT) { Index: sys/vm/vm_object.h =================================================================== --- sys/vm/vm_object.h +++ sys/vm/vm_object.h @@ -189,7 +189,6 @@ #define OBJ_TMPFS_DIRTY 0x0400 /* dirty tmpfs obj */ #define OBJ_COLORED 0x1000 /* pg_color is defined */ #define OBJ_ONEMAPPING 0x2000 /* One USE (a single, non-forked) mapping flag */ -#define OBJ_DISCONNECTWNT 0x4000 /* disconnect from vnode wanted */ #define OBJ_TMPFS 0x8000 /* has tmpfs vnode allocated */ /* Index: sys/vm/vnode_pager.c =================================================================== --- sys/vm/vnode_pager.c +++ sys/vm/vnode_pager.c @@ -147,17 +147,9 @@ if (!vn_isdisk(vp, NULL) && vn_canvmio(vp) == FALSE) return (0); - while ((object = vp->v_object) != NULL) { - VM_OBJECT_WLOCK(object); - if (!(object->flags & OBJ_DEAD)) { - VM_OBJECT_WUNLOCK(object); - return (0); - } - VOP_UNLOCK(vp, 0); - vm_object_set_flag(object, OBJ_DISCONNECTWNT); - VM_OBJECT_SLEEP(object, object, PDROP | PVM, "vodead", 0); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); - } + object = vp->v_object; + if (object != NULL) + return (0); if (size == 0) { if (vn_isdisk(vp, NULL)) { @@ -194,6 +186,7 @@ return; ASSERT_VOP_ELOCKED(vp, "vnode_destroy_vobject"); VM_OBJECT_WLOCK(obj); + MPASS(obj->type == OBJT_VNODE); umtx_shm_object_terminated(obj); if (obj->ref_count == 0) { /* @@ -223,9 +216,6 @@ * prevented new waiters from referencing the dying * object. */ - KASSERT((obj->flags & OBJ_DISCONNECTWNT) == 0, - ("OBJ_DISCONNECTWNT set obj %p flags %x", - obj, obj->flags)); vp->v_object = NULL; VM_OBJECT_WUNLOCK(obj); } @@ -243,8 +233,6 @@ /* * Allocate (or lookup) pager for a vnode. * Handle is a vnode pointer. - * - * MPSAFE */ vm_object_t vnode_pager_alloc(void *handle, vm_ooffset_t size, vm_prot_t prot, @@ -259,28 +247,18 @@ if (handle == NULL) return (NULL); - vp = (struct vnode *) handle; - - /* - * If the object is being terminated, wait for it to - * go away. - */ -retry: - while ((object = vp->v_object) != NULL) { - VM_OBJECT_WLOCK(object); - if ((object->flags & OBJ_DEAD) == 0) - break; - vm_object_set_flag(object, OBJ_DISCONNECTWNT); - VM_OBJECT_SLEEP(object, object, PDROP | PVM, "vadead", 0); - } - + vp = (struct vnode *)handle; + ASSERT_VOP_LOCKED(vp, "vnode_pager_alloc"); KASSERT(vp->v_usecount != 0, ("vnode_pager_alloc: no vnode reference")); +retry: + object = vp->v_object; if (object == NULL) { /* * Add an object of the appropriate size */ - object = vm_object_allocate(OBJT_VNODE, OFF_TO_IDX(round_page(size))); + object = vm_object_allocate(OBJT_VNODE, + OFF_TO_IDX(round_page(size))); object->un_pager.vnp.vnp_size = size; object->un_pager.vnp.writemappings = 0; @@ -290,7 +268,7 @@ VI_LOCK(vp); if (vp->v_object != NULL) { /* - * Object has been created while we were sleeping + * Object has been created while we were allocating. */ VI_UNLOCK(vp); VM_OBJECT_WLOCK(object); @@ -305,6 +283,7 @@ vp->v_object = object; VI_UNLOCK(vp); } else { + VM_OBJECT_WLOCK(object); object->ref_count++; #if VM_NRESERVLEVEL > 0 vm_object_color(object, 0); @@ -334,10 +313,6 @@ object->handle = NULL; object->type = OBJT_DEAD; - if (object->flags & OBJ_DISCONNECTWNT) { - vm_object_clear_flag(object, OBJ_DISCONNECTWNT); - wakeup(object); - } ASSERT_VOP_ELOCKED(vp, "vnode_pager_dealloc"); if (object->un_pager.vnp.writemappings > 0) { object->un_pager.vnp.writemappings = 0;