From 1b362ad74b55b453bc0f5f659d62445a2ac7e3ba Mon Sep 17 00:00:00 2001 From: Taylor R Campbell Date: Mon, 7 Apr 2014 21:09:19 +0000 Subject: [PATCH 01/14] Make getnewvnode return with VI_CHANGING set. Callers must call either (1) ungetnewvnode, on failure before publishing the vnode; (2) vready_fail, on failure to load the vnode; (3) or vready, on success. vready_fail is a temporary marker for case (2) should it turn out to be unsafe to call vready in that case before calling vrele, but the current plan is to replace vready_fail/vrele by ungetnewvnode so that nobody ever gets partially loaded vnodes. Signature of getnewvnode is changed so that existing callers fail to compile. --- .../cddl/osnet/dist/uts/common/fs/zfs/zfs_znode.c | 9 ++++-- share/man/man9/vnode.9 | 33 +++++++++++++++++++++- sys/coda/coda_vnops.c | 5 +++- sys/fs/adosfs/advfsops.c | 7 ++++- sys/fs/cd9660/cd9660_vfsops.c | 10 ++++++- sys/fs/efs/efs_vfsops.c | 6 +++- sys/fs/filecorefs/filecore_vfsops.c | 5 +++- sys/fs/hfs/hfs_vfsops.c | 4 ++- sys/fs/msdosfs/msdosfs_denode.c | 4 ++- sys/fs/nilfs/nilfs_subr.c | 3 +- sys/fs/ntfs/ntfs_vfsops.c | 5 +++- sys/fs/ptyfs/ptyfs_subr.c | 3 +- sys/fs/puffs/puffs_node.c | 3 +- sys/fs/smbfs/smbfs_node.c | 3 +- sys/fs/sysvbfs/sysvbfs_vfsops.c | 4 ++- sys/fs/tmpfs/tmpfs_subr.c | 3 +- sys/fs/udf/udf_subr.c | 8 ++++-- sys/fs/union/union_subr.c | 3 +- sys/fs/unionfs/unionfs_subr.c | 3 +- sys/fs/v7fs/v7fs_vfsops.c | 4 ++- sys/kern/vfs_subr.c | 3 +- sys/kern/vfs_vnode.c | 25 ++++++++++++++-- sys/miscfs/fdesc/fdesc_vnops.c | 3 +- sys/miscfs/genfs/layer_subr.c | 3 +- sys/miscfs/kernfs/kernfs_subr.c | 7 ++++- sys/miscfs/procfs/procfs_subr.c | 3 +- sys/miscfs/syncfs/sync_vnops.c | 3 +- sys/nfs/nfs_node.c | 3 +- sys/rump/librump/rumpvfs/rumpfs.c | 3 +- sys/sys/vnode.h | 10 ++++++- sys/ufs/chfs/chfs_vfsops.c | 6 +++- sys/ufs/ext2fs/ext2fs_vfsops.c | 5 +++- sys/ufs/ffs/ffs_vfsops.c | 4 ++- sys/ufs/lfs/lfs_alloc.c | 3 +- sys/ufs/lfs/lfs_syscalls.c | 5 +++- sys/ufs/lfs/lfs_vfsops.c | 4 ++- sys/ufs/lfs/lfs_vnops.c | 2 +- sys/ufs/mfs/mfs_vfsops.c | 3 +- 38 files changed, 178 insertions(+), 42 deletions(-) diff --git a/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_znode.c b/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_znode.c index 5f15f3b..fe2185e 100644 --- a/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_znode.c +++ b/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_znode.c @@ -485,11 +485,12 @@ zfs_create_share_dir(zfsvfs_t *zfsvfs, dmu_tx_t *tx) vp = ZTOV(sharezp); error = getnewvnode(VT_ZFS, zfsvfs->z_parent->z_vfs, - zfs_vnodeop_p, NULL, &sharezp->z_vnode); + zfs_vnodeop_p, NULL, 0, &sharezp->z_vnode); if (error) { kmem_cache_free(znode_cache, sharezp); return error; } + vready(sharezp->z_vnode); vp->v_type = VDIR; VERIFY(0 == zfs_acl_ids_create(sharezp, IS_ROOT_NODE, &vattr, @@ -623,7 +624,7 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz) for (;;) { error = getnewvnode(VT_ZFS, zfsvfs->z_parent->z_vfs, - zfs_vnodeop_p, NULL, &zp->z_vnode); + zfs_vnodeop_p, NULL, 0, &zp->z_vnode); if (__predict_true(error == 0)) break; printf("WARNING: zfs_znode_alloc: unable to get vnode, " @@ -690,6 +691,7 @@ zfs_znode_alloc(zfsvfs_t *zfsvfs, dmu_buf_t *db, int blksz) mutex_exit(&zfsvfs->z_znodes_lock); VFS_HOLD(zfsvfs->z_vfs); + vready(vp); /* XXX not sure this is right */ return (zp); } @@ -1564,7 +1566,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) for (;;) { error = getnewvnode(VT_ZFS, NULL, zfs_vnodeop_p, - NULL, &rootzp->z_vnode); + NULL, 0, &rootzp->z_vnode); if (error == 0) break; printf("WARNING: zfs_create_fs: unable to get vnode, " @@ -1609,6 +1611,7 @@ zfs_create_fs(objset_t *os, cred_t *cr, nvlist_t *zplprops, dmu_tx_t *tx) dmu_buf_rele(rootzp->z_dbuf, NULL); rootzp->z_dbuf = NULL; + /* XXX Whisky tango foxtrot? */ ungetnewvnode(vp); kmem_cache_free(znode_cache, rootzp); diff --git a/share/man/man9/vnode.9 b/share/man/man9/vnode.9 index d48761e..5a110ab 100644 --- a/share/man/man9/vnode.9 +++ b/share/man/man9/vnode.9 @@ -27,7 +27,7 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd March 24, 2014 +.Dd April 9, 2014 .Dt VNODE 9 .Os .Sh NAME @@ -41,6 +41,7 @@ .Nm holdrele , .Nm getnewvnode , .Nm ungetnewvnode , +.Nm vready , .Nm vrecycle , .Nm vgone , .Nm vgonel , @@ -79,6 +80,8 @@ "kmutex_t *slock" "struct vnode **vpp" .Ft void .Fn ungetnewvnode "struct vnode *vp" +.Ft void +.Fn vready "struct vnode *vp" .Ft int .Fn vrecycle "struct vnode *vp" .Ft void @@ -344,6 +347,21 @@ When a user wants a new vnode for another file, .Fn getnewvnode is invoked to allocate a vnode and initialize it for the new file. .Pp +After initializing a new vnode, for example by loading the file's +on-disk data structures into memory, the caller must call +.Fn vready +to allow others to use the vnode, or +.Fn ungetnewvnode +to back out if anything went wrong and the vnode is unusable. +Until this time, the caller has exclusive access to the vnode in the +sense that other threads passing it to +.Fn vget +will block until +.Fn vready +or +.Fn ungetnewvnode +is called. +.Pp The type of object the vnode represents is recorded by .Em v_type . It is used by generic code to perform checks to ensure operations are @@ -587,6 +605,12 @@ is the mount point for the file system requested the new vnode. Before retrieving the new vnode, the file system is checked if it is busy (such as currently unmounting). An error is returned if the file system is unmounted. +Every successful call to +.Fn getnewvnode +must be followed either by +.Fn ungetnewvnode +or by +.Fn vready . .Pp The argument .Fa tag @@ -619,6 +643,13 @@ This function is needed for .Xr VFS_VGET 9 which may need to push back a vnode in case of a locking race condition. +.It Fn vready "vp" +Complete the operation of +.Fn getnewvnode +and wake any threads waiting for +.Fn vget +on +.Fa vp . .It Fn vrecycle "vp" Recycle the referenced vnode .Fa vp diff --git a/sys/coda/coda_vnops.c b/sys/coda/coda_vnops.c index 581c71b..33a327d 100644 --- a/sys/coda/coda_vnops.c +++ b/sys/coda/coda_vnops.c @@ -1835,14 +1835,17 @@ make_coda_node(CodaFid *fid, struct mount *fvsp, short type) cp = coda_alloc(); cp->c_fid = *fid; - error = getnewvnode(VT_CODA, fvsp, coda_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_CODA, fvsp, coda_vnodeop_p, NULL, 0, &vp); if (error) { + /* XXX Uh... This panic is obviously wrong. */ panic("%s: getnewvnode returned error %d", __func__, error); } vp->v_data = cp; vp->v_type = type; cp->c_vnode = vp; uvm_vnp_setsize(vp, 0); + vready(vp); + /* XXX Someone could beat us to it -- this code needs to retry. */ coda_save(cp); } else { diff --git a/sys/fs/adosfs/advfsops.c b/sys/fs/adosfs/advfsops.c index 099bb11..3fa8764 100644 --- a/sys/fs/adosfs/advfsops.c +++ b/sys/fs/adosfs/advfsops.c @@ -392,7 +392,7 @@ adosfs_vget(struct mount *mp, ino_t an, struct vnode **vpp) if ((*vpp = adosfs_ahashget(mp, an)) != NULL) return (0); - error = getnewvnode(VT_ADOSFS, mp, adosfs_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_ADOSFS, mp, adosfs_vnodeop_p, NULL, 0, &vp); if (error) return (error); @@ -410,6 +410,7 @@ adosfs_vget(struct mount *mp, ino_t an, struct vnode **vpp) if ((error = bread(amp->devvp, an * amp->bsize / DEV_BSIZE, amp->bsize, NOCRED, 0, &bp)) != 0) { + vready_fail(vp); vput(vp); return (error); } @@ -467,6 +468,7 @@ adosfs_vget(struct mount *mp, ino_t an, struct vnode **vpp) break; default: brelse(bp, 0); + vready_fail(vp); vput(vp); return (EINVAL); } @@ -487,6 +489,7 @@ adosfs_vget(struct mount *mp, ino_t an, struct vnode **vpp) (unsigned long long)an); #endif brelse(bp, 0); + vready_fail(vp); vput(vp); return (EINVAL); } @@ -530,6 +533,7 @@ adosfs_vget(struct mount *mp, ino_t an, struct vnode **vpp) error = bread(amp->devvp, ap->linkto * amp->bsize / DEV_BSIZE, amp->bsize, NOCRED, 0, &bp); if (error) { + vready_fail(vp); vput(vp); return (error); } @@ -587,6 +591,7 @@ adosfs_vget(struct mount *mp, ino_t an, struct vnode **vpp) *vpp = vp; brelse(bp, 0); uvm_vnp_setsize(vp, ap->fsize); + vready(vp); return (0); } diff --git a/sys/fs/cd9660/cd9660_vfsops.c b/sys/fs/cd9660/cd9660_vfsops.c index 2b01dc1..e8097ea 100644 --- a/sys/fs/cd9660/cd9660_vfsops.c +++ b/sys/fs/cd9660/cd9660_vfsops.c @@ -713,7 +713,7 @@ cd9660_vget_internal(struct mount *mp, ino_t ino, struct vnode **vpp, return (0); /* Allocate a new vnode/iso_node. */ - error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_ISOFS, mp, cd9660_vnodeop_p, NULL, 0, &vp); if (error) { *vpp = NULLVP; return (error); @@ -755,6 +755,7 @@ cd9660_vget_internal(struct mount *mp, ino_t ino, struct vnode **vpp, lbn = cd9660_lblkno(imp, ino); if (lbn >= imp->volume_space_size) { + vready_fail(vp); vput(vp); printf("fhtovp: lbn exceed volume space %d\n", lbn); return (ESTALE); @@ -762,6 +763,7 @@ cd9660_vget_internal(struct mount *mp, ino_t ino, struct vnode **vpp, off = cd9660_blkoff(imp, ino); if (off + ISO_DIRECTORY_RECORD_SIZE > imp->logical_block_size) { + vready_fail(vp); vput(vp); printf("fhtovp: crosses block boundary %d\n", off + ISO_DIRECTORY_RECORD_SIZE); @@ -772,6 +774,7 @@ cd9660_vget_internal(struct mount *mp, ino_t ino, struct vnode **vpp, lbn << (imp->im_bshift - DEV_BSHIFT), imp->logical_block_size, NOCRED, 0, &bp); if (error) { + vready_fail(vp); vput(vp); printf("fhtovp: bread error %d\n",error); return (error); @@ -780,6 +783,7 @@ cd9660_vget_internal(struct mount *mp, ino_t ino, struct vnode **vpp, if (off + isonum_711(isodir->length) > imp->logical_block_size) { + vready_fail(vp); vput(vp); if (bp != 0) brelse(bp, 0); @@ -792,6 +796,8 @@ cd9660_vget_internal(struct mount *mp, ino_t ino, struct vnode **vpp, #if 0 if (isonum_733(isodir->extent) + isonum_711(isodir->ext_attr_length) != ifhp->ifid_start) { + vready_fail(vp); + vput(vp); if (bp != 0) brelse(bp, 0); printf("fhtovp: file start miss %d vs %d\n", @@ -814,6 +820,7 @@ cd9660_vget_internal(struct mount *mp, ino_t ino, struct vnode **vpp, if (bp != 0) brelse(bp, 0); if ((error = cd9660_blkatoff(vp, (off_t)0, NULL, &bp)) != 0) { + vready_fail(vp); vput(vp); return (error); } @@ -889,6 +896,7 @@ cd9660_vget_internal(struct mount *mp, ino_t ino, struct vnode **vpp, * XXX need generation number? */ + vready(vp); *vpp = vp; return (0); } diff --git a/sys/fs/efs/efs_vfsops.c b/sys/fs/efs/efs_vfsops.c index fa5f470..339ee12 100644 --- a/sys/fs/efs/efs_vfsops.c +++ b/sys/fs/efs/efs_vfsops.c @@ -360,7 +360,7 @@ efs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) if (*vpp != NULL) return (0); - err = getnewvnode(VT_EFS, mp, efs_vnodeop_p, NULL, &vp); + err = getnewvnode(VT_EFS, mp, efs_vnodeop_p, NULL, 0, &vp); if (err) return (err); @@ -404,6 +404,7 @@ efs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) err = efs_read_inode(emp, ino, NULL, &eip->ei_di); if (err) { + vready_fail(vp); vput(vp); *vpp = NULL; return (err); @@ -414,6 +415,7 @@ efs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) if (ino == EFS_ROOTINO && !S_ISDIR(eip->ei_mode)) { printf("efs: root inode (%lu) is not a directory!\n", (ulong)EFS_ROOTINO); + vready_fail(vp); vput(vp); *vpp = NULL; return (EIO); @@ -451,12 +453,14 @@ efs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) default: printf("efs: invalid mode 0x%x in inode %lu on mount %s\n", eip->ei_mode, (ulong)ino, mp->mnt_stat.f_mntonname); + vready_fail(vp); vput(vp); *vpp = NULL; return (EIO); } uvm_vnp_setsize(vp, eip->ei_size); + vready(vp); *vpp = vp; KASSERT(VOP_ISLOCKED(vp)); diff --git a/sys/fs/filecorefs/filecore_vfsops.c b/sys/fs/filecorefs/filecore_vfsops.c index c105da1..e057ba4 100644 --- a/sys/fs/filecorefs/filecore_vfsops.c +++ b/sys/fs/filecorefs/filecore_vfsops.c @@ -569,7 +569,7 @@ filecore_vget(struct mount *mp, ino_t ino, struct vnode **vpp) return (0); /* Allocate a new vnode/filecore_node. */ - error = getnewvnode(VT_FILECORE, mp, filecore_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_FILECORE, mp, filecore_vnodeop_p, NULL, 0, &vp); if (error) { *vpp = NULLVP; return (error); @@ -605,6 +605,7 @@ filecore_vget(struct mount *mp, ino_t ino, struct vnode **vpp) /* Read in Data from Directory Entry */ if ((error = filecore_bread(fcmp, ino & FILECORE_INO_MASK, FILECORE_DIR_SIZE, NOCRED, &bp)) != 0) { + vready_fail(vp); vput(vp); *vpp = NULL; return (error); @@ -641,6 +642,7 @@ filecore_vget(struct mount *mp, ino_t ino, struct vnode **vpp) /* * Devices not supported. */ + vready_fail(vp); vput(vp); return (EOPNOTSUPP); case VLNK: @@ -660,6 +662,7 @@ filecore_vget(struct mount *mp, ino_t ino, struct vnode **vpp) */ uvm_vnp_setsize(vp, ip->i_size); + vready(vp); *vpp = vp; return (0); } diff --git a/sys/fs/hfs/hfs_vfsops.c b/sys/fs/hfs/hfs_vfsops.c index 013944f..814bf4b 100644 --- a/sys/fs/hfs/hfs_vfsops.c +++ b/sys/fs/hfs/hfs_vfsops.c @@ -544,7 +544,7 @@ hfs_vget_internal(struct mount *mp, ino_t ino, uint8_t fork, return 0; /* Allocate a new vnode/inode. */ - error = getnewvnode(VT_HFS, mp, hfs_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_HFS, mp, hfs_vnodeop_p, NULL, 0, &vp); if (error) { goto error; } @@ -595,6 +595,7 @@ hfs_vget_internal(struct mount *mp, ino_t ino, uint8_t fork, if (hfslib_find_catalog_record_with_cnid(&hmp->hm_vol, cnid, &rec, &key, &cbargs) != 0) { + vready_fail(vp); vput(vp); error = EBADF; goto error; @@ -632,6 +633,7 @@ hfs_vget_internal(struct mount *mp, ino_t ino, uint8_t fork, else uvm_vnp_setsize(vp, 0); /* no directly reading directories */ + vready(vp); *vpp = vp; return 0; diff --git a/sys/fs/msdosfs/msdosfs_denode.c b/sys/fs/msdosfs/msdosfs_denode.c index f1c7736..756411a 100644 --- a/sys/fs/msdosfs/msdosfs_denode.c +++ b/sys/fs/msdosfs/msdosfs_denode.c @@ -321,7 +321,7 @@ deget(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset, struct denode * copy it from the passed disk buffer. */ error = getnewvnode(VT_MSDOSFS, pmp->pm_mountp, msdosfs_vnodeop_p, - NULL, &nvp); + NULL, 0, &nvp); if (error) { *depp = 0; return (error); @@ -405,6 +405,7 @@ deget(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset, struct denode if (error) { ldep->de_devvp = NULL; ldep->de_Name[0] = SLOT_DELETED; + vready_fail(nvp); vput(nvp); return (error); } @@ -439,6 +440,7 @@ deget(struct msdosfsmount *pmp, u_long dirclust, u_long diroffset, struct denode vref(ldep->de_devvp); *depp = ldep; uvm_vnp_setsize(nvp, ldep->de_FileSize); + vready(nvp); return (0); } diff --git a/sys/fs/nilfs/nilfs_subr.c b/sys/fs/nilfs/nilfs_subr.c index a197918..190228a 100644 --- a/sys/fs/nilfs/nilfs_subr.c +++ b/sys/fs/nilfs/nilfs_subr.c @@ -809,7 +809,7 @@ nilfs_get_node_raw(struct nilfs_device *nilfsdev, struct nilfs_mount *ump, /* associate with mountpoint if present*/ mp = ump? ump->vfs_mountp : NULL; - error = getnewvnode(VT_NILFS, mp, vnodeops, NULL, &nvp); + error = getnewvnode(VT_NILFS, mp, vnodeops, NULL, 0, &nvp); if (error) return error; @@ -874,6 +874,7 @@ nilfs_get_node_raw(struct nilfs_device *nilfsdev, struct nilfs_mount *ump, nilfs_register_node(node); /* return node */ + vready(nvp); *nodep = node; return 0; } diff --git a/sys/fs/ntfs/ntfs_vfsops.c b/sys/fs/ntfs/ntfs_vfsops.c index 664d605..56efd03 100644 --- a/sys/fs/ntfs/ntfs_vfsops.c +++ b/sys/fs/ntfs/ntfs_vfsops.c @@ -792,7 +792,7 @@ loop: ntfs_ntput(ip); error = getnewvnode(VT_NTFS, ntmp->ntm_mountp, ntfs_vnodeop_p, - NULL, &vp); + NULL, 0, &vp); if(error) { ntfs_frele(fp); return (error); @@ -802,6 +802,7 @@ loop: if (error) { printf("ntfs_vget: ntfs_fget failed\n"); ntfs_ntput(ip); + ungetnewvnode(vp); return (error); } if (FTOV(fp)) { @@ -830,6 +831,7 @@ loop: if (lkflags & (LK_EXCLUSIVE | LK_SHARED)) { error = vn_lock(vp, lkflags); if (error) { + vready_fail(vp); vput(vp); return (error); } @@ -837,6 +839,7 @@ loop: uvm_vnp_setsize(vp, fp->f_size); /* XXX: mess, cf. ntfs_lookupfile() */ vref(ip->i_devvp); + vready(vp); *vpp = vp; return (0); } diff --git a/sys/fs/ptyfs/ptyfs_subr.c b/sys/fs/ptyfs/ptyfs_subr.c index 776333c..83dfbea 100644 --- a/sys/fs/ptyfs/ptyfs_subr.c +++ b/sys/fs/ptyfs/ptyfs_subr.c @@ -219,7 +219,7 @@ ptyfs_allocvp(struct mount *mp, struct vnode **vpp, ptyfstype type, int pty, if ((*vpp = ptyfs_used_get(type, pty, mp, LK_EXCLUSIVE)) != NULL) return 0; - error = getnewvnode(VT_PTYFS, mp, ptyfs_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_PTYFS, mp, ptyfs_vnodeop_p, NULL, 0, &vp); if (error) { *vpp = NULL; return error; @@ -254,6 +254,7 @@ ptyfs_allocvp(struct mount *mp, struct vnode **vpp, ptyfstype type, int pty, uvm_vnp_setsize(vp, 0); mutex_exit(&ptyfs_hashlock); + vready(vp); *vpp = vp; return 0; } diff --git a/sys/fs/puffs/puffs_node.c b/sys/fs/puffs/puffs_node.c index 7dfd083..728db39 100644 --- a/sys/fs/puffs/puffs_node.c +++ b/sys/fs/puffs/puffs_node.c @@ -93,7 +93,7 @@ puffs_getvnode(struct mount *mp, puffs_cookie_t ck, enum vtype type, goto bad; } - error = getnewvnode(VT_PUFFS, mp, puffs_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_PUFFS, mp, puffs_vnodeop_p, NULL, 0, &vp); if (error) { goto bad; } @@ -167,6 +167,7 @@ puffs_getvnode(struct mount *mp, puffs_cookie_t ck, enum vtype type, pnode->pn_serversize = vsize; genfs_node_init(vp, &puffs_genfsops); + vready(vp); *vpp = vp; DPRINTF(("new vnode at %p, pnode %p, cookie %p\n", vp, diff --git a/sys/fs/smbfs/smbfs_node.c b/sys/fs/smbfs/smbfs_node.c index 621167d..c2c46e1 100644 --- a/sys/fs/smbfs/smbfs_node.c +++ b/sys/fs/smbfs/smbfs_node.c @@ -170,7 +170,7 @@ allocnew: np = pool_get(&smbfs_node_pool, PR_WAITOK); memset(np, 0, sizeof(*np)); - error = getnewvnode(VT_SMBFS, mp, smbfs_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_SMBFS, mp, smbfs_vnodeop_p, NULL, 0, &vp); if (error) { pool_put(&smbfs_node_pool, np); return error; @@ -223,6 +223,7 @@ allocnew: uvm_vnp_setsize(vp, np->n_size); mutex_exit(&smp->sm_hashlock); + vready(vp); *vpp = vp; return 0; } diff --git a/sys/fs/sysvbfs/sysvbfs_vfsops.c b/sys/fs/sysvbfs/sysvbfs_vfsops.c index 4ea416b..4f4f76b 100644 --- a/sys/fs/sysvbfs/sysvbfs_vfsops.c +++ b/sys/fs/sysvbfs/sysvbfs_vfsops.c @@ -353,7 +353,7 @@ sysvbfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) mutex_exit(&mntvnode_lock); /* Allocate v-node. */ - error = getnewvnode(VT_SYSVBFS, mp, sysvbfs_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_SYSVBFS, mp, sysvbfs_vnodeop_p, NULL, 0, &vp); if (error) { DPRINTF("%s: getnewvnode error.\n", __func__); return error; @@ -366,6 +366,7 @@ sysvbfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) memset(vp->v_data, 0, sizeof(struct sysvbfs_node)); bnode = vp->v_data; mutex_enter(&mntvnode_lock); + /* XXX This is wrong! Gotta retry if someone beat us. */ LIST_INSERT_HEAD(&bmp->bnode_head, bnode, link); mutex_exit(&mntvnode_lock); bnode->vnode = vp; @@ -382,6 +383,7 @@ sysvbfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) genfs_node_init(vp, &sysvbfs_genfsops); uvm_vnp_setsize(vp, bfs_file_size(inode)); + vready(vp); *vpp = vp; return 0; diff --git a/sys/fs/tmpfs/tmpfs_subr.c b/sys/fs/tmpfs/tmpfs_subr.c index 3d94393..2dbecce 100644 --- a/sys/fs/tmpfs/tmpfs_subr.c +++ b/sys/fs/tmpfs/tmpfs_subr.c @@ -306,7 +306,7 @@ again: } else { slock = NULL; } - error = getnewvnode(VT_TMPFS, mp, tmpfs_vnodeop_p, slock, &vp); + error = getnewvnode(VT_TMPFS, mp, tmpfs_vnodeop_p, slock, 0, &vp); if (error) { mutex_exit(&node->tn_vlock); return error; @@ -343,6 +343,7 @@ again: mutex_exit(&node->tn_vlock); KASSERT(VOP_ISLOCKED(vp)); + vready(vp); *vpp = vp; return 0; } diff --git a/sys/fs/udf/udf_subr.c b/sys/fs/udf/udf_subr.c index 836b3ee..cbeb885 100644 --- a/sys/fs/udf/udf_subr.c +++ b/sys/fs/udf/udf_subr.c @@ -5325,7 +5325,8 @@ udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc, DPRINTF(NODE, ("\tget new vnode\n")); /* give it a vnode */ - error = getnewvnode(VT_UDF, ump->vfs_mountp, udf_vnodeop_p, NULL, &nvp); + error = getnewvnode(VT_UDF, ump->vfs_mountp, udf_vnodeop_p, NULL, 0, + &nvp); if (error) { pool_put(&udf_node_pool, udf_node); mutex_exit(&ump->get_node_lock); @@ -5618,6 +5619,7 @@ udf_get_node(struct udf_mount *ump, struct long_ad *node_icb_loc, /* TODO ext attr and streamdir udf_nodes */ + vready(nvp); *udf_noderes = udf_node; return 0; @@ -5778,7 +5780,7 @@ udf_create_node_raw(struct vnode *dvp, struct vnode **vpp, int udf_file_type, *vpp = NULL; /* allocate vnode */ - error = getnewvnode(VT_UDF, ump->vfs_mountp, vnodeops, NULL, &nvp); + error = getnewvnode(VT_UDF, ump->vfs_mountp, vnodeops, NULL, 0, &nvp); if (error) return error; @@ -5872,6 +5874,7 @@ udf_create_node_raw(struct vnode *dvp, struct vnode **vpp, int udf_file_type, /* recycle udf_node */ udf_dispose_node(udf_node); + vready_fail(nvp); vrele(nvp); *vpp = NULL; @@ -5882,6 +5885,7 @@ udf_create_node_raw(struct vnode *dvp, struct vnode **vpp, int udf_file_type, udf_adjust_filecount(udf_node, 1); /* return result */ + vready(nvp); *vpp = nvp; return 0; diff --git a/sys/fs/union/union_subr.c b/sys/fs/union/union_subr.c index b5157bf..8afdcca 100644 --- a/sys/fs/union/union_subr.c +++ b/sys/fs/union/union_subr.c @@ -471,7 +471,7 @@ found: */ vnode_t *svp = (uppervp != NULLVP) ? uppervp : lowervp; error = getnewvnode(VT_UNION, mp, union_vnodeop_p, - svp->v_interlock, vpp); + svp->v_interlock, 0, vpp); if (error) { if (uppervp) vrele(uppervp); @@ -554,6 +554,7 @@ found: if (docache) mutex_exit(&uhash_lock); + vready(*vpp); return (error); } diff --git a/sys/fs/unionfs/unionfs_subr.c b/sys/fs/unionfs/unionfs_subr.c index 6e82a55..0b077d1 100644 --- a/sys/fs/unionfs/unionfs_subr.c +++ b/sys/fs/unionfs/unionfs_subr.c @@ -97,7 +97,7 @@ unionfs_nodeget(struct mount *mp, struct vnode *uppervp, */ vnode_t *svp = (uppervp != NULLVP) ? uppervp : lowervp; error = getnewvnode(VT_UNION, mp, unionfs_vnodeop_p, - svp->v_interlock, &vp); + svp->v_interlock, 0, &vp); if (error != 0) { return (error); } @@ -128,6 +128,7 @@ unionfs_nodeget(struct mount *mp, struct vnode *uppervp, (lowervp != NULLVP && ump->um_lowervp == lowervp)) vp->v_vflag |= VV_ROOT; + vready(vp); *vpp = vp; return (0); diff --git a/sys/fs/v7fs/v7fs_vfsops.c b/sys/fs/v7fs/v7fs_vfsops.c index e8e95ee..227ec1c 100644 --- a/sys/fs/v7fs/v7fs_vfsops.c +++ b/sys/fs/v7fs/v7fs_vfsops.c @@ -459,7 +459,7 @@ retry: mutex_exit(&mntvnode_lock); /* Allocate v-node. */ - if ((error = getnewvnode(VT_V7FS, mp, v7fs_vnodeop_p, NULL, &vp))) { + if ((error = getnewvnode(VT_V7FS, mp, v7fs_vnodeop_p, NULL, 0, &vp))) { DPRINTF("getnewvnode error.\n"); return error; } @@ -471,6 +471,7 @@ retry: memset(vp->v_data, 0, sizeof(*v7fs_node)); v7fs_node = vp->v_data; mutex_enter(&mntvnode_lock); + /* XXX This is wrong! Gotta retry if someone beat us. */ LIST_INSERT_HEAD(&v7fsmount->v7fs_node_head, v7fs_node, link); mutex_exit(&mntvnode_lock); v7fs_node->vnode = vp; @@ -496,6 +497,7 @@ retry: } } + vready(vp); *vpp = vp; return 0; diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index c5d96e4..04a88bc 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -493,7 +493,7 @@ getdevvp(dev_t dev, vnode_t **vpp, enum vtype type) *vpp = NULL; return (0); } - error = getnewvnode(VT_NON, NULL, spec_vnodeop_p, NULL, &nvp); + error = getnewvnode(VT_NON, NULL, spec_vnodeop_p, NULL, 0, &nvp); if (error) { *vpp = NULL; return (error); @@ -503,6 +503,7 @@ getdevvp(dev_t dev, vnode_t **vpp, enum vtype type) vp->v_vflag |= VV_MPSAFE; uvm_vnp_setsize(vp, 0); spec_node_init(vp, dev); + vready(vp); *vpp = vp; return (0); } diff --git a/sys/kern/vfs_vnode.c b/sys/kern/vfs_vnode.c index 92a28f3..c4e3e9a 100644 --- a/sys/kern/vfs_vnode.c +++ b/sys/kern/vfs_vnode.c @@ -348,12 +348,14 @@ try_nextlist: */ int getnewvnode(enum vtagtype tag, struct mount *mp, int (**vops)(void *), - kmutex_t *slock, vnode_t **vpp) + kmutex_t *slock, int flags __diagused, vnode_t **vpp) { struct uvm_object *uobj __diagused; vnode_t *vp; int error = 0; + KASSERT(flags == 0); + if (mp != NULL) { /* * Mark filesystem busy while we are creating a vnode. @@ -401,6 +403,9 @@ getnewvnode(enum vtagtype tag, struct mount *mp, int (**vops)(void *), vp->v_iflag |= VI_LOCKSHARE; } + /* Mark the vnode changing until it's initialized. */ + vp->v_iflag |= VI_CHANGING; + /* Finally, move vnode into the mount queue. */ vfs_insmntque(vp, mp); @@ -415,6 +420,21 @@ getnewvnode(enum vtagtype tag, struct mount *mp, int (**vops)(void *), } /* + * Mark a vnode ready for consumption after getnewvnode, and wake any + * waiters in vget. + */ +void +vready(struct vnode *vp) +{ + + mutex_enter(vp->v_interlock); + KASSERT(ISSET(vp->v_iflag, VI_CHANGING)); + vp->v_iflag &= ~VI_CHANGING; + cv_broadcast(&vp->v_cv); + mutex_exit(vp->v_interlock); +} + +/* * This is really just the reverse of getnewvnode(). Needed for * VFS_VGET functions who may need to push back a vnode in case * of a locking race. @@ -428,8 +448,9 @@ ungetnewvnode(vnode_t *vp) KASSERT(vp->v_freelisthd == NULL); mutex_enter(vp->v_interlock); + KASSERT(ISSET(vp->v_iflag, VI_CHANGING)); vp->v_iflag |= VI_CLEAN; - vrelel(vp, 0); + vrelel(vp, VRELEL_CHANGING_SET); } /* diff --git a/sys/miscfs/fdesc/fdesc_vnops.c b/sys/miscfs/fdesc/fdesc_vnops.c index ca53bc1..dbccde0 100644 --- a/sys/miscfs/fdesc/fdesc_vnops.c +++ b/sys/miscfs/fdesc/fdesc_vnops.c @@ -224,7 +224,7 @@ loop: } mutex_exit(&fdcache_lock); - error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, NULL, vpp); + error = getnewvnode(VT_FDESC, mp, fdesc_vnodeop_p, NULL, 0, vpp); if (error) return error; @@ -254,6 +254,7 @@ loop: LIST_INSERT_HEAD(fc, fd, fd_hash); mutex_exit(&fdcache_lock); + vready(*vpp); return 0; } diff --git a/sys/miscfs/genfs/layer_subr.c b/sys/miscfs/genfs/layer_subr.c index 5c6bd36..b4c55d5 100644 --- a/sys/miscfs/genfs/layer_subr.c +++ b/sys/miscfs/genfs/layer_subr.c @@ -170,7 +170,7 @@ layer_node_alloc(struct mount *mp, struct vnode *lowervp, struct vnode **vpp) /* Get a new vnode and share its interlock with underlying vnode. */ error = getnewvnode(lmp->layerm_tag, mp, lmp->layerm_vnodeop_p, - lowervp->v_interlock, &vp); + lowervp->v_interlock, 0, &vp); if (error) { return error; } @@ -217,6 +217,7 @@ layer_node_alloc(struct mount *mp, struct vnode *lowervp, struct vnode **vpp) uvm_vnp_setsize(vp, 0); mutex_exit(&lmp->layerm_hashlock); + vready(vp); *vpp = vp; return 0; } diff --git a/sys/miscfs/kernfs/kernfs_subr.c b/sys/miscfs/kernfs/kernfs_subr.c index d893865..f998243 100644 --- a/sys/miscfs/kernfs/kernfs_subr.c +++ b/sys/miscfs/kernfs/kernfs_subr.c @@ -173,7 +173,11 @@ kernfs_allocvp(struct mount *mp, struct vnode **vpp, kfstype kfs_type, return (0); } - error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, NULL, &vp); + /* + * XXX This is wrong -- must call getnewvnode and malloc before + * taking kfs_hashlock. + */ + error = getnewvnode(VT_KERNFS, mp, kernfs_vnodeop_p, NULL, 0, &vp); if (error) { *vpp = NULL; mutex_exit(&kfs_hashlock); @@ -224,6 +228,7 @@ again: uvm_vnp_setsize(vp, 0); mutex_exit(&kfs_hashlock); + vready(vp); *vpp = vp; return (0); } diff --git a/sys/miscfs/procfs/procfs_subr.c b/sys/miscfs/procfs/procfs_subr.c index 1ae3469..df0cc79 100644 --- a/sys/miscfs/procfs/procfs_subr.c +++ b/sys/miscfs/procfs/procfs_subr.c @@ -169,7 +169,7 @@ procfs_allocvp(struct mount *mp, struct vnode **vpp, pid_t pid, if (*vpp != NULL) return (0); - error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_PROCFS, mp, procfs_vnodeop_p, NULL, 0, &vp); if (error) { *vpp = NULL; return (error); @@ -315,6 +315,7 @@ procfs_allocvp(struct mount *mp, struct vnode **vpp, pid_t pid, uvm_vnp_setsize(vp, 0); mutex_exit(&pfs_hashlock); + vready(vp); *vpp = vp; return (0); diff --git a/sys/miscfs/syncfs/sync_vnops.c b/sys/miscfs/syncfs/sync_vnops.c index d3dc91b..a5fa770 100644 --- a/sys/miscfs/syncfs/sync_vnops.c +++ b/sys/miscfs/syncfs/sync_vnops.c @@ -114,7 +114,7 @@ vfs_allocate_syncvnode(struct mount *mp) int error, vdelay; /* Allocate a new vnode */ - error = getnewvnode(VT_VFS, mp, sync_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_VFS, mp, sync_vnodeop_p, NULL, 0, &vp); if (error) { return error; } @@ -143,6 +143,7 @@ vfs_allocate_syncvnode(struct mount *mp) vn_syncer_add_to_worklist(vp, vdelay > 0 ? next % vdelay : 0); mutex_exit(vp->v_interlock); mp->mnt_syncer = vp; + vready(vp); return (0); } diff --git a/sys/nfs/nfs_node.c b/sys/nfs/nfs_node.c index 79c974a..a600eb6 100644 --- a/sys/nfs/nfs_node.c +++ b/sys/nfs/nfs_node.c @@ -186,7 +186,7 @@ loop: } rw_exit(&nmp->nm_rbtlock); - error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_NFS, mntp, nfsv2_vnodeop_p, NULL, 0, &vp); if (error) { *npp = 0; return (error); @@ -236,6 +236,7 @@ loop: (void)rb_tree_insert_node(&nmp->nm_rbtree, np); rw_exit(&nmp->nm_rbtlock); + vready(vp); *npp = np; return (0); } diff --git a/sys/rump/librump/rumpvfs/rumpfs.c b/sys/rump/librump/rumpvfs/rumpfs.c index bc52a45..b6caa22 100644 --- a/sys/rump/librump/rumpvfs/rumpfs.c +++ b/sys/rump/librump/rumpvfs/rumpfs.c @@ -580,7 +580,7 @@ makevnode(struct mount *mp, struct rumpfs_node *rn, struct vnode **vpp) vpops = rump_vnodeop_p; } - rv = getnewvnode(VT_RUMP, mp, vpops, NULL, &vp); + rv = getnewvnode(VT_RUMP, mp, vpops, NULL, 0, &vp); if (rv) return rv; @@ -597,6 +597,7 @@ makevnode(struct mount *mp, struct rumpfs_node *rn, struct vnode **vpp) rn->rn_vp = vp; mutex_exit(&reclock); + vready(vp); *vpp = vp; return 0; diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h index fe78f26..caa6015d 100644 --- a/sys/sys/vnode.h +++ b/sys/sys/vnode.h @@ -531,7 +531,15 @@ void vfs_vnode_sysinit(void); int bdevvp(dev_t, struct vnode **); int cdevvp(dev_t, struct vnode **); int getnewvnode(enum vtagtype, struct mount *, int (**)(void *), - kmutex_t *, struct vnode **); + kmutex_t *, int, struct vnode **); +void vready(struct vnode *); +/* + * vready_fail is a temporary variant of vready to back out from + * getnewvnode too late to call ungetnewvnode. It exists to mark the + * code whose error branches need to be rewritten, so that when we + * remove it, that code will fail to compile. + */ +#define vready_fail vready void ungetnewvnode(struct vnode *); int vaccess(enum vtype, mode_t, uid_t, gid_t, mode_t, kauth_cred_t); void vattr_null(struct vattr *); diff --git a/sys/ufs/chfs/chfs_vfsops.c b/sys/ufs/chfs/chfs_vfsops.c index 2dd7f81..955142c 100644 --- a/sys/ufs/chfs/chfs_vfsops.c +++ b/sys/ufs/chfs/chfs_vfsops.c @@ -472,7 +472,7 @@ retry: /* Allocate a new vnode/inode. */ if ((error = getnewvnode(VT_CHFS, - mp, chfs_vnodeop_p, NULL, &vp)) != 0) { + mp, chfs_vnodeop_p, NULL, 0, &vp)) != 0) { *vpp = NULL; return (error); } @@ -569,6 +569,7 @@ retry: (unsigned long long)ip->ino); error = chfs_read_inode(chmp, ip); if (error) { + vready_fail(vp); vput(vp); *vpp = NULL; mutex_exit(&chmp->chm_lock_mountfields); @@ -581,6 +582,7 @@ retry: (unsigned long long)ip->ino); error = chfs_read_inode_internal(chmp, ip); if (error) { + vready_fail(vp); vput(vp); *vpp = NULL; mutex_exit(&chmp->chm_lock_mountfields); @@ -613,6 +615,7 @@ retry: (unsigned long long)ip->ino); error = chfs_read_inode_internal(chmp, ip); if (error) { + vready_fail(vp); vput(vp); *vpp = NULL; mutex_exit(&chmp->chm_lock_mountfields); @@ -653,6 +656,7 @@ retry: vref(ip->devvp); uvm_vnp_setsize(vp, ip->size); + vready(vp); *vpp = vp; return 0; diff --git a/sys/ufs/ext2fs/ext2fs_vfsops.c b/sys/ufs/ext2fs/ext2fs_vfsops.c index 6369923..5b4d144 100644 --- a/sys/ufs/ext2fs/ext2fs_vfsops.c +++ b/sys/ufs/ext2fs/ext2fs_vfsops.c @@ -965,7 +965,7 @@ retry: return (0); /* Allocate a new vnode/inode. */ - error = getnewvnode(VT_EXT2FS, mp, ext2fs_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_EXT2FS, mp, ext2fs_vnodeop_p, NULL, 0, &vp); if (error) { *vpp = NULL; return (error); @@ -1015,6 +1015,7 @@ retry: * list by vput(). */ + vready_fail(vp); vput(vp); *vpp = NULL; return (error); @@ -1039,6 +1040,7 @@ retry: error = ext2fs_vinit(mp, ext2fs_specop_p, ext2fs_fifoop_p, &vp); if (error) { + vready_fail(vp); vput(vp); *vpp = NULL; return (error); @@ -1063,6 +1065,7 @@ retry: ip->i_flag |= IN_MODIFIED; } uvm_vnp_setsize(vp, ext2fs_size(ip)); + vready(vp); *vpp = vp; return (0); } diff --git a/sys/ufs/ffs/ffs_vfsops.c b/sys/ufs/ffs/ffs_vfsops.c index 98946de..a3cd05d 100644 --- a/sys/ufs/ffs/ffs_vfsops.c +++ b/sys/ufs/ffs/ffs_vfsops.c @@ -1747,7 +1747,7 @@ ffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) return (0); /* Allocate a new vnode/inode. */ - error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, NULL, 0, &vp); if (error) { *vpp = NULL; return (error); @@ -1812,6 +1812,7 @@ ffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) * list by vput(). */ + vready_fail(vp); vput(vp); *vpp = NULL; return (error); @@ -1849,6 +1850,7 @@ ffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) ip->i_gid = ip->i_ffs1_ogid; /* XXX */ } /* XXX */ uvm_vnp_setsize(vp, ip->i_size); + vready(vp); *vpp = vp; return (0); } diff --git a/sys/ufs/lfs/lfs_alloc.c b/sys/ufs/lfs/lfs_alloc.c index 07180d5..1d5b01d 100644 --- a/sys/ufs/lfs/lfs_alloc.c +++ b/sys/ufs/lfs/lfs_alloc.c @@ -300,9 +300,10 @@ lfs_ialloc(struct lfs *fs, struct vnode *pvp, ino_t new_ino, int new_gen, memset(ip->i_lfs_fragsize, 0, ULFS_NDADDR * sizeof(*ip->i_lfs_fragsize)); uvm_vnp_setsize(vp, 0); - lfs_mark_vnode(vp); genfs_node_init(vp, &lfs_genfsops); vref(ip->i_devvp); + vready(vp); + lfs_mark_vnode(vp); return (0); } diff --git a/sys/ufs/lfs/lfs_syscalls.c b/sys/ufs/lfs/lfs_syscalls.c index cf6ebc6..3349e05 100644 --- a/sys/ufs/lfs/lfs_syscalls.c +++ b/sys/ufs/lfs/lfs_syscalls.c @@ -1119,7 +1119,7 @@ lfs_fastvget(struct mount *mp, ino_t ino, daddr_t daddr, struct vnode **vpp, *vpp = NULL; return EDEADLK; } - error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, NULL, 0, &vp); if (error) { *vpp = NULL; return (error); @@ -1168,6 +1168,7 @@ lfs_fastvget(struct mount *mp, ino_t ino, daddr_t daddr, struct vnode **vpp, ulfs_ihashrem(ip); /* Unlock and discard unneeded inode. */ + vready_fail(vp); VOP_UNLOCK(vp); lfs_vunref(vp); *vpp = NULL; @@ -1191,6 +1192,7 @@ lfs_fastvget(struct mount *mp, ino_t ino, daddr_t daddr, struct vnode **vpp, ulfs_ihashrem(ip); /* Unlock and discard unneeded inode. */ + vready_fail(vp); VOP_UNLOCK(vp); lfs_vunref(vp); *vpp = NULL; @@ -1212,6 +1214,7 @@ lfs_fastvget(struct mount *mp, ino_t ino, daddr_t daddr, struct vnode **vpp, } lfs_vinit(mp, &vp); + vready(vp); *vpp = vp; KASSERT(VOP_ISLOCKED(vp)); diff --git a/sys/ufs/lfs/lfs_vfsops.c b/sys/ufs/lfs/lfs_vfsops.c index 70f00dd..adc78fd 100644 --- a/sys/ufs/lfs/lfs_vfsops.c +++ b/sys/ufs/lfs/lfs_vfsops.c @@ -1469,7 +1469,7 @@ retry: if ((*vpp = ulfs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) return (0); - error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, NULL, &vp); + error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, NULL, 0, &vp); if (error) { *vpp = NULL; return (error); @@ -1537,6 +1537,7 @@ retry: * still zero, it will be unlinked and returned to the free * list by vput(). */ + vready_fail(vp); vput(vp); *vpp = NULL; return (error); @@ -1596,6 +1597,7 @@ retry: lfs_vinit(mp, &vp); + vready(vp); *vpp = vp; KASSERT(VOP_ISLOCKED(vp)); diff --git a/sys/ufs/lfs/lfs_vnops.c b/sys/ufs/lfs/lfs_vnops.c index f026a43..fab2baf 100644 --- a/sys/ufs/lfs/lfs_vnops.c +++ b/sys/ufs/lfs/lfs_vnops.c @@ -495,7 +495,7 @@ lfs_set_dirop_create(struct vnode *dvp, struct vnode **vpp) if (vpp == NULL) { return lfs_set_dirop(dvp, NULL); } - error = getnewvnode(VT_LFS, dvp->v_mount, lfs_vnodeop_p, NULL, vpp); + error = getnewvnode(VT_LFS, dvp->v_mount, lfs_vnodeop_p, NULL, 0, vpp); if (error) { DLOG((DLOG_ALLOC, "lfs_set_dirop_create: dvp %p error %d\n", dvp, error)); diff --git a/sys/ufs/mfs/mfs_vfsops.c b/sys/ufs/mfs/mfs_vfsops.c index a048051..5812d29 100644 --- a/sys/ufs/mfs/mfs_vfsops.c +++ b/sys/ufs/mfs/mfs_vfsops.c @@ -304,7 +304,7 @@ mfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) return EINVAL; return (0); } - error = getnewvnode(VT_MFS, NULL, mfs_vnodeop_p, NULL, &devvp); + error = getnewvnode(VT_MFS, NULL, mfs_vnodeop_p, NULL, 0, &devvp); if (error) return (error); devvp->v_vflag |= VV_MPSAFE; @@ -321,6 +321,7 @@ mfs_mount(struct mount *mp, const char *path, void *data, size_t *data_len) cv_init(&mfsp->mfs_cv, "mfsidl"); mfsp->mfs_refcnt = 1; bufq_alloc(&mfsp->mfs_buflist, "fcfs", 0); + vready(devvp); if ((error = ffs_mountfs(devvp, mp, l)) != 0) { mfsp->mfs_shutdown = 1; vrele(devvp); -- 1.8.3.1