Module Name: src Committed By: hannken Date: Sun May 31 15:48:03 UTC 2015
Modified Files: src/sys/modules/lfs: Makefile src/sys/rump/fs/lib/liblfs: Makefile src/sys/ufs: files.ufs src/sys/ufs/lfs: lfs_alloc.c lfs_extern.h lfs_rfw.c lfs_segment.c lfs_syscalls.c lfs_vfsops.c lfs_vnops.c ulfs_extern.h ulfs_inode.c ulfs_lookup.c ulfs_vfsops.c ulfs_vnops.c ulfsmount.h Removed Files: src/sys/ufs/lfs: ulfs_ihash.c Log Message: Change lfs from hash table to vcache. - Change lfs_valloc() to return an inode number and version instead of a vnode and move lfs_ialloc() and lfs_vcreate() to new lfs_init_vnode(). - Add lfs_valloc_fixed() to allocate a known inode, used by kernel roll forward. - Remove lfs_*ref(), these functions cannot coexist with vcache and their commented behaviour is far away from their implementation. - Add the cleaner lwp and blockinfo to struct ulfsmount so lfs_loadvnode() may use hints from the cleaner. - Remove vnode locks from ulfs_lookup() like we did with ufs_lookup(). To generate a diff of this commit: cvs rdiff -u -r1.7 -r1.8 src/sys/modules/lfs/Makefile cvs rdiff -u -r1.11 -r1.12 src/sys/rump/fs/lib/liblfs/Makefile cvs rdiff -u -r1.39 -r1.40 src/sys/ufs/files.ufs cvs rdiff -u -r1.119 -r1.120 src/sys/ufs/lfs/lfs_alloc.c cvs rdiff -u -r1.104 -r1.105 src/sys/ufs/lfs/lfs_extern.h cvs rdiff -u -r1.19 -r1.20 src/sys/ufs/lfs/lfs_rfw.c cvs rdiff -u -r1.239 -r1.240 src/sys/ufs/lfs/lfs_segment.c cvs rdiff -u -r1.159 -r1.160 src/sys/ufs/lfs/lfs_syscalls.c cvs rdiff -u -r1.323 -r1.324 src/sys/ufs/lfs/lfs_vfsops.c cvs rdiff -u -r1.271 -r1.272 src/sys/ufs/lfs/lfs_vnops.c cvs rdiff -u -r1.14 -r1.15 src/sys/ufs/lfs/ulfs_extern.h cvs rdiff -u -r1.5 -r0 src/sys/ufs/lfs/ulfs_ihash.c cvs rdiff -u -r1.9 -r1.10 src/sys/ufs/lfs/ulfs_inode.c cvs rdiff -u -r1.23 -r1.24 src/sys/ufs/lfs/ulfs_lookup.c cvs rdiff -u -r1.8 -r1.9 src/sys/ufs/lfs/ulfs_vfsops.c cvs rdiff -u -r1.25 -r1.26 src/sys/ufs/lfs/ulfs_vnops.c cvs rdiff -u -r1.12 -r1.13 src/sys/ufs/lfs/ulfsmount.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/modules/lfs/Makefile diff -u src/sys/modules/lfs/Makefile:1.7 src/sys/modules/lfs/Makefile:1.8 --- src/sys/modules/lfs/Makefile:1.7 Fri May 16 09:34:03 2014 +++ src/sys/modules/lfs/Makefile Sun May 31 15:48:02 2015 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.7 2014/05/16 09:34:03 dholland Exp $ +# $NetBSD: Makefile,v 1.8 2015/05/31 15:48:02 hannken Exp $ .include "../Makefile.inc" @@ -13,7 +13,7 @@ SRCS= lfs_vfsops.c lfs_vnops.c lfs_subr. lfs_bio.c lfs_cksum.c lfs_debug.c lfs_inode.c lfs_pages.c \ lfs_segment.c lfs_rename.c lfs_syscalls.c lfs_itimes.c -SRCS+= ulfs_bmap.c ulfs_dirhash.c ulfs_ihash.c ulfs_inode.c ulfs_lookup.c \ +SRCS+= ulfs_bmap.c ulfs_dirhash.c ulfs_inode.c ulfs_lookup.c \ ulfs_snapshot.c ulfs_vfsops.c ulfs_vnops.c .include <bsd.kmodule.mk> Index: src/sys/rump/fs/lib/liblfs/Makefile diff -u src/sys/rump/fs/lib/liblfs/Makefile:1.11 src/sys/rump/fs/lib/liblfs/Makefile:1.12 --- src/sys/rump/fs/lib/liblfs/Makefile:1.11 Fri May 16 09:34:03 2014 +++ src/sys/rump/fs/lib/liblfs/Makefile Sun May 31 15:48:02 2015 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.11 2014/05/16 09:34:03 dholland Exp $ +# $NetBSD: Makefile,v 1.12 2015/05/31 15:48:02 hannken Exp $ # .PATH: ${.CURDIR}/../../../../ufs/lfs @@ -9,7 +9,7 @@ SRCS= lfs_alloc.c lfs_balloc.c lfs_bio.c lfs_inode.c lfs_itimes.c lfs_pages.c lfs_rename.c lfs_rfw.c \ lfs_segment.c lfs_subr.c lfs_syscalls.c lfs_vfsops.c lfs_vnops.c -SRCS+= ulfs_bmap.c ulfs_dirhash.c ulfs_extattr.c ulfs_ihash.c \ +SRCS+= ulfs_bmap.c ulfs_dirhash.c ulfs_extattr.c \ ulfs_inode.c ulfs_lookup.c ulfs_quota.c ulfs_quota1.c \ ulfs_quota2.c ulfs_quota1_subr.c ulfs_quota2_subr.c \ ulfs_snapshot.c ulfs_vfsops.c ulfs_vnops.c Index: src/sys/ufs/files.ufs diff -u src/sys/ufs/files.ufs:1.39 src/sys/ufs/files.ufs:1.40 --- src/sys/ufs/files.ufs:1.39 Sun Jan 11 17:29:57 2015 +++ src/sys/ufs/files.ufs Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -# $NetBSD: files.ufs,v 1.39 2015/01/11 17:29:57 hannken Exp $ +# $NetBSD: files.ufs,v 1.40 2015/05/31 15:48:03 hannken Exp $ deffs FFS deffs EXT2FS @@ -77,7 +77,6 @@ file ufs/lfs/lfs_vnops.c lfs file ufs/lfs/ulfs_bmap.c lfs file ufs/lfs/ulfs_dirhash.c lfs & lfs_dirhash file ufs/lfs/ulfs_extattr.c lfs & lfs_extattr -file ufs/lfs/ulfs_ihash.c lfs file ufs/lfs/ulfs_inode.c lfs file ufs/lfs/ulfs_lookup.c lfs file ufs/lfs/ulfs_quota.c lfs & (lfs_quota | lfs_quota2) Index: src/sys/ufs/lfs/lfs_alloc.c diff -u src/sys/ufs/lfs/lfs_alloc.c:1.119 src/sys/ufs/lfs/lfs_alloc.c:1.120 --- src/sys/ufs/lfs/lfs_alloc.c:1.119 Sun Jul 28 01:25:05 2013 +++ src/sys/ufs/lfs/lfs_alloc.c Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_alloc.c,v 1.119 2013/07/28 01:25:05 dholland Exp $ */ +/* $NetBSD: lfs_alloc.c,v 1.120 2015/05/31 15:48:03 hannken Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007 The NetBSD Foundation, Inc. @@ -60,7 +60,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.119 2013/07/28 01:25:05 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_alloc.c,v 1.120 2015/05/31 15:48:03 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_quota.h" @@ -191,14 +191,12 @@ lfs_extend_ifile(struct lfs *fs, kauth_c /* VOP_BWRITE 2i times */ int lfs_valloc(struct vnode *pvp, int mode, kauth_cred_t cred, - struct vnode **vpp) + ino_t *ino, int *gen) { struct lfs *fs; struct buf *bp, *cbp; struct ifile *ifp; - ino_t new_ino; int error; - int new_gen; CLEANERINFO *cip; fs = VTOI(pvp)->i_lfs; @@ -210,32 +208,32 @@ lfs_valloc(struct vnode *pvp, int mode, lfs_seglock(fs, SEGM_PROT); /* Get the head of the freelist. */ - LFS_GET_HEADFREE(fs, cip, cbp, &new_ino); - KASSERT(new_ino != LFS_UNUSED_INUM && new_ino != LFS_IFILE_INUM); + LFS_GET_HEADFREE(fs, cip, cbp, ino); + KASSERT(*ino != LFS_UNUSED_INUM && *ino != LFS_IFILE_INUM); - DLOG((DLOG_ALLOC, "lfs_valloc: allocate inode %lld\n", - (long long)new_ino)); + DLOG((DLOG_ALLOC, "lfs_valloc: allocate inode %" PRId64 "\n", + *ino)); /* * Remove the inode from the free list and write the new start * of the free list into the superblock. */ - CLR_BITMAP_FREE(fs, new_ino); - LFS_IENTRY(ifp, fs, new_ino, bp); + CLR_BITMAP_FREE(fs, *ino); + LFS_IENTRY(ifp, fs, *ino, bp); if (ifp->if_daddr != LFS_UNUSED_DADDR) - panic("lfs_valloc: inuse inode %llu on the free list", - (unsigned long long)new_ino); + panic("lfs_valloc: inuse inode %" PRId64 " on the free list", + *ino); LFS_PUT_HEADFREE(fs, cip, cbp, ifp->if_nextfree); - DLOG((DLOG_ALLOC, "lfs_valloc: headfree %lld -> %lld\n", - (long long)new_ino, (long long)ifp->if_nextfree)); + DLOG((DLOG_ALLOC, "lfs_valloc: headfree %" PRId64 " -> %u\n", + *ino, ifp->if_nextfree)); - new_gen = ifp->if_version; /* version was updated by vfree */ + *gen = ifp->if_version; /* version was updated by vfree */ brelse(bp, 0); /* Extend IFILE so that the next lfs_valloc will succeed. */ if (fs->lfs_freehd == LFS_UNUSED_INUM) { if ((error = lfs_extend_ifile(fs, cred)) != 0) { - LFS_PUT_HEADFREE(fs, cip, cbp, new_ino); + LFS_PUT_HEADFREE(fs, cip, cbp, *ino); lfs_segunlock(fs); return error; } @@ -253,94 +251,54 @@ lfs_valloc(struct vnode *pvp, int mode, lfs_segunlock(fs); - return lfs_ialloc(fs, pvp, new_ino, new_gen, vpp); + return 0; } /* - * Finish allocating a new inode, given an inode and generation number. + * Allocate a new inode with given inode number and version. */ int -lfs_ialloc(struct lfs *fs, struct vnode *pvp, ino_t new_ino, int new_gen, - struct vnode **vpp) +lfs_valloc_fixed(struct lfs *fs, ino_t ino, int vers) { - struct inode *ip; - struct vnode *vp; - - ASSERT_NO_SEGLOCK(fs); - - vp = *vpp; - mutex_enter(&ulfs_hashlock); - /* Create an inode to associate with the vnode. */ - lfs_vcreate(pvp->v_mount, new_ino, vp); - - ip = VTOI(vp); - mutex_enter(&lfs_lock); - LFS_SET_UINO(ip, IN_CHANGE); - mutex_exit(&lfs_lock); - /* on-disk structure has been zeroed out by lfs_vcreate */ - ip->i_din.ffs1_din->di_inumber = new_ino; - - /* Note no blocks yet */ - ip->i_lfs_hiblk = -1; + IFILE *ifp; + struct buf *bp, *cbp; + ino_t tino, oldnext; + CLEANERINFO *cip; - /* Set a new generation number for this inode. */ - if (new_gen) { - ip->i_gen = new_gen; - ip->i_ffs1_gen = new_gen; + /* If the Ifile is too short to contain this inum, extend it */ + while (VTOI(fs->lfs_ivnode)->i_size <= (ino / + fs->lfs_ifpb + fs->lfs_cleansz + fs->lfs_segtabsz) + << fs->lfs_bshift) { + lfs_extend_ifile(fs, NOCRED); } - /* Insert into the inode hash table. */ - ulfs_ihashins(ip); - mutex_exit(&ulfs_hashlock); - - ulfs_vinit(vp->v_mount, lfs_specop_p, lfs_fifoop_p, vpp); - vp = *vpp; - ip = VTOI(vp); - - 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); - return (0); -} - -/* Create a new vnode/inode pair and initialize what fields we can. */ -void -lfs_vcreate(struct mount *mp, ino_t ino, struct vnode *vp) -{ - struct inode *ip; - struct ulfs1_dinode *dp; - struct ulfsmount *ump; - - /* Get a pointer to the private mount structure. */ - ump = VFSTOULFS(mp); + LFS_IENTRY(ifp, fs, ino, bp); + oldnext = ifp->if_nextfree; + ifp->if_version = vers; + brelse(bp, 0); - ASSERT_NO_SEGLOCK(ump->um_lfs); + LFS_GET_HEADFREE(fs, cip, cbp, &ino); + if (ino) { + LFS_PUT_HEADFREE(fs, cip, cbp, oldnext); + } else { + tino = ino; + while (1) { + LFS_IENTRY(ifp, fs, tino, bp); + if (ifp->if_nextfree == ino || + ifp->if_nextfree == LFS_UNUSED_INUM) + break; + tino = ifp->if_nextfree; + brelse(bp, 0); + } + if (ifp->if_nextfree == LFS_UNUSED_INUM) { + brelse(bp, 0); + return ENOENT; + } + ifp->if_nextfree = oldnext; + LFS_BWRITE_LOG(bp); + } - /* Initialize the inode. */ - ip = pool_get(&lfs_inode_pool, PR_WAITOK); - memset(ip, 0, sizeof(*ip)); - dp = pool_get(&lfs_dinode_pool, PR_WAITOK); - memset(dp, 0, sizeof(*dp)); - ip->inode_ext.lfs = pool_get(&lfs_inoext_pool, PR_WAITOK); - memset(ip->inode_ext.lfs, 0, sizeof(*ip->inode_ext.lfs)); - vp->v_data = ip; - ip->i_din.ffs1_din = dp; - ip->i_ump = ump; - ip->i_vnode = vp; - ip->i_devvp = ump->um_devvp; - ip->i_dev = ump->um_dev; - ip->i_number = dp->di_inumber = ino; - ip->i_lfs = ump->um_lfs; - ip->i_lfs_effnblks = 0; - SPLAY_INIT(&ip->i_lfs_lbtree); - ip->i_lfs_nbtree = 0; - LIST_INIT(&ip->i_lfs_segdhd); -#if defined(LFS_QUOTA) || defined(LFS_QUOTA2) - ulfsquota_init(ip); -#endif + return 0; } #if 0 @@ -449,7 +407,7 @@ lfs_vfree(struct vnode *vp, ino_t ino, i wakeup(&fs->lfs_dirvcount); wakeup(&lfs_dirvcount); mutex_exit(&lfs_lock); - lfs_vunref(vp); + vrele(vp); /* * If this inode is not going to be written any more, any Index: src/sys/ufs/lfs/lfs_extern.h diff -u src/sys/ufs/lfs/lfs_extern.h:1.104 src/sys/ufs/lfs/lfs_extern.h:1.105 --- src/sys/ufs/lfs/lfs_extern.h:1.104 Sun May 31 15:45:18 2015 +++ src/sys/ufs/lfs/lfs_extern.h Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_extern.h,v 1.104 2015/05/31 15:45:18 hannken Exp $ */ +/* $NetBSD: lfs_extern.h,v 1.105 2015/05/31 15:48:03 hannken Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -122,12 +122,11 @@ extern kcondvar_t lfs_writing_cv; extern kcondvar_t locked_queue_cv; /* lfs_alloc.c */ -void lfs_vcreate(struct mount *, ino_t, struct vnode *); -int lfs_valloc(struct vnode *, int, kauth_cred_t, struct vnode **); +int lfs_valloc(struct vnode *, int, kauth_cred_t, ino_t *, int *); +int lfs_valloc_fixed(struct lfs *, ino_t, int); int lfs_vfree(struct vnode *, ino_t, int); void lfs_order_freelist(struct lfs *); int lfs_extend_ifile(struct lfs *, kauth_cred_t); -int lfs_ialloc(struct lfs *, struct vnode *, ino_t, int, struct vnode **); void lfs_orphan(struct lfs *, ino_t); /* lfs_balloc.c */ @@ -195,9 +194,6 @@ int lfs_match_indir(struct lfs *, struct int lfs_match_dindir(struct lfs *, struct buf *); int lfs_match_tindir(struct lfs *, struct buf *); void lfs_callback(struct buf *); -int lfs_vref(struct vnode *); -void lfs_vunref(struct vnode *); -void lfs_vunref_head(struct vnode *); void lfs_acquire_finfo(struct lfs *fs, ino_t, int); void lfs_release_finfo(struct lfs *fs); Index: src/sys/ufs/lfs/lfs_rfw.c diff -u src/sys/ufs/lfs/lfs_rfw.c:1.19 src/sys/ufs/lfs/lfs_rfw.c:1.20 --- src/sys/ufs/lfs/lfs_rfw.c:1.19 Sat Mar 28 19:24:05 2015 +++ src/sys/ufs/lfs/lfs_rfw.c Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_rfw.c,v 1.19 2015/03/28 19:24:05 maxv Exp $ */ +/* $NetBSD: lfs_rfw.c,v 1.20 2015/05/31 15:48:03 hannken Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: lfs_rfw.c,v 1.19 2015/03/28 19:24:05 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_rfw.c,v 1.20 2015/05/31 15:48:03 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_quota.h" @@ -101,13 +101,10 @@ int lfs_rf_valloc(struct lfs *fs, ino_t ino, int vers, struct lwp *l, struct vnode **vpp) { - IFILE *ifp; - struct buf *bp, *cbp; + struct vattr va; struct vnode *vp; struct inode *ip; - ino_t tino, oldnext; int error; - CLEANERINFO *cip; ASSERT_SEGLOCK(fs); /* XXX it doesn't, really */ @@ -138,70 +135,25 @@ lfs_rf_valloc(struct lfs *fs, ino_t ino, } } - /* - * The inode is not in use. Find it on the free list. - */ - /* If the Ifile is too short to contain this inum, extend it */ - while (VTOI(fs->lfs_ivnode)->i_size <= (ino / - fs->lfs_ifpb + fs->lfs_cleansz + fs->lfs_segtabsz) - << fs->lfs_bshift) { - lfs_extend_ifile(fs, NOCRED); - } - - LFS_IENTRY(ifp, fs, ino, bp); - oldnext = ifp->if_nextfree; - ifp->if_version = vers; - brelse(bp, 0); - - LFS_GET_HEADFREE(fs, cip, cbp, &ino); - if (ino) { - LFS_PUT_HEADFREE(fs, cip, cbp, oldnext); - } else { - tino = ino; - while (1) { - LFS_IENTRY(ifp, fs, tino, bp); - if (ifp->if_nextfree == ino || - ifp->if_nextfree == LFS_UNUSED_INUM) - break; - tino = ifp->if_nextfree; - brelse(bp, 0); - } - if (ifp->if_nextfree == LFS_UNUSED_INUM) { - brelse(bp, 0); - return ENOENT; - } - ifp->if_nextfree = oldnext; - LFS_BWRITE_LOG(bp); - } - - error = lfs_ialloc(fs, fs->lfs_ivnode, ino, vers, &vp); - if (error == 0) { - /* - * Make it VREG so we can put blocks on it. We will change - * this later if it turns out to be some other kind of file. - */ - ip = VTOI(vp); - ip->i_mode = ip->i_ffs1_mode = LFS_IFREG; - ip->i_nlink = ip->i_ffs1_nlink = 1; - ulfs_vinit(vp->v_mount, lfs_specop_p, lfs_fifoop_p, &vp); - ip = VTOI(vp); - - DLOG((DLOG_RF, "lfs_rf_valloc: ino %d vp %p\n", ino, vp)); - - /* The dirop-nature of this vnode is past */ - lfs_unmark_vnode(vp); - (void)lfs_vunref(vp); - vp->v_uflag &= ~VU_DIROP; - mutex_enter(&lfs_lock); - --lfs_dirvcount; - --fs->lfs_dirvcount; - TAILQ_REMOVE(&fs->lfs_dchainhd, ip, i_lfs_dchain); - wakeup(&lfs_dirvcount); - wakeup(&fs->lfs_dirvcount); - mutex_exit(&lfs_lock); + /* Not found, create as regular file. */ + vattr_null(&va); + va.va_type = VREG; + va.va_mode = 0; + va.va_fileid = ino; + va.va_gen = vers; + error = vcache_new(fs->lfs_ivnode->v_mount, NULL, &va, NOCRED, &vp); + if (error) + return error; + error = vn_lock(vp, LK_EXCLUSIVE); + if (error) { + vrele(vp); + *vpp = NULLVP; + return error; } + ip = VTOI(vp); + ip->i_nlink = ip->i_ffs1_nlink = 1; *vpp = vp; - return error; + return 0; } /* Index: src/sys/ufs/lfs/lfs_segment.c diff -u src/sys/ufs/lfs/lfs_segment.c:1.239 src/sys/ufs/lfs/lfs_segment.c:1.240 --- src/sys/ufs/lfs/lfs_segment.c:1.239 Sun May 31 15:44:31 2015 +++ src/sys/ufs/lfs/lfs_segment.c Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_segment.c,v 1.239 2015/05/31 15:44:31 hannken Exp $ */ +/* $NetBSD: lfs_segment.c,v 1.240 2015/05/31 15:48:03 hannken Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -60,7 +60,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.239 2015/05/31 15:44:31 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_segment.c,v 1.240 2015/05/31 15:48:03 hannken Exp $"); #define _VFS_VNODE_PRIVATE /* XXX: check for VI_MARKER, this has to go */ @@ -541,8 +541,8 @@ lfs_writevnodes(struct lfs *fs, struct m } mutex_exit(&mntvnode_lock); - if (lfs_vref(vp)) { - vndebug(vp,"vref"); + if (vget(vp, LK_NOWAIT, false /* !wait */)) { + vndebug(vp,"vget"); mutex_enter(&mntvnode_lock); continue; } @@ -558,7 +558,7 @@ lfs_writevnodes(struct lfs *fs, struct m if (ip->i_number != LFS_IFILE_INUM) { error = lfs_writefile(fs, sp, vp); if (error) { - lfs_vunref(vp); + vrele(vp); if (error == EAGAIN) { /* * This error from lfs_putpages @@ -599,9 +599,9 @@ lfs_writevnodes(struct lfs *fs, struct m } if (lfs_clean_vnhead && only_cleaning) - lfs_vunref_head(vp); + vrele(vp); else - lfs_vunref(vp); + vrele(vp); mutex_enter(&mntvnode_lock); } @@ -2756,79 +2756,6 @@ lfs_shellsort(struct buf **bp_array, int } /* - * Call vget with LK_NOWAIT. If we are the one who is dead, - * however, we must press on. Just fake success in that case. - */ -int -lfs_vref(struct vnode *vp) -{ - struct lfs *fs; - - KASSERT(mutex_owned(vp->v_interlock)); - - fs = VTOI(vp)->i_lfs; - - ASSERT_MAYBE_SEGLOCK(fs); - - /* - * If we return 1 here during a flush, we risk vinvalbuf() not - * being able to flush all of the pages from this vnode, which - * will cause it to panic. So, return 0 if a flush is in progress. - */ - if (IS_FLUSHING(VTOI(vp)->i_lfs, vp)) { - ++fs->lfs_flushvp_fakevref; - mutex_exit(vp->v_interlock); - return 0; - } - - return vget(vp, LK_NOWAIT, false /* !wait */); -} - -/* - * This is vrele except that we do not want to VOP_INACTIVE this vnode. We - * inline vrele here to avoid the vn_lock and VOP_INACTIVE call at the end. - */ -void -lfs_vunref(struct vnode *vp) -{ - struct lfs *fs; - - fs = VTOI(vp)->i_lfs; - ASSERT_MAYBE_SEGLOCK(fs); - - /* - * Analogous to lfs_vref, if the node is flushing, fake it. - */ - if (IS_FLUSHING(fs, vp) && fs->lfs_flushvp_fakevref) { - --fs->lfs_flushvp_fakevref; - return; - } - - /* does not call inactive XXX sure it does XXX */ - vrele(vp); -} - -/* - * We use this when we have vnodes that were loaded in solely for cleaning. - * There is no reason to believe that these vnodes will be referenced again - * soon, since the cleaning process is unrelated to normal filesystem - * activity. Putting cleaned vnodes at the tail of the list has the effect - * of flushing the vnode LRU. So, put vnodes that were loaded only for - * cleaning at the head of the list, instead. - */ -void -lfs_vunref_head(struct vnode *vp) -{ - - ASSERT_SEGLOCK(VTOI(vp)->i_lfs); - - /* does not call inactive XXX sure it does XXX, - inserts non-held vnode at head of freelist */ - vrele(vp); -} - - -/* * Set up an FINFO entry for a new file. The fip pointer is assumed to * point at uninitialized space. */ Index: src/sys/ufs/lfs/lfs_syscalls.c diff -u src/sys/ufs/lfs/lfs_syscalls.c:1.159 src/sys/ufs/lfs/lfs_syscalls.c:1.160 --- src/sys/ufs/lfs/lfs_syscalls.c:1.159 Sun May 31 15:45:18 2015 +++ src/sys/ufs/lfs/lfs_syscalls.c Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_syscalls.c,v 1.159 2015/05/31 15:45:18 hannken Exp $ */ +/* $NetBSD: lfs_syscalls.c,v 1.160 2015/05/31 15:48:03 hannken Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007, 2007, 2008 @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: lfs_syscalls.c,v 1.159 2015/05/31 15:45:18 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_syscalls.c,v 1.160 2015/05/31 15:48:03 hannken Exp $"); #ifndef LFS # define LFS /* for prototypes in syscallargs.h */ @@ -85,11 +85,9 @@ __KERNEL_RCSID(0, "$NetBSD: lfs_syscalls #include <ufs/lfs/lfs_kernel.h> #include <ufs/lfs/lfs_extern.h> +static int lfs_fastvget(struct mount *, ino_t, BLOCK_INFO *, int, + struct vnode **); struct buf *lfs_fakebuf(struct lfs *, struct vnode *, int, size_t, void *); -int lfs_fasthashget(dev_t, ino_t, struct vnode **); -int lfs_fastvget(struct mount *, ino_t, BLOCK_INFO *, int, struct vnode **); - -pid_t lfs_cleaner_pid = 0; /* * sys_lfs_markv: @@ -295,8 +293,7 @@ lfs_markv(struct proc *p, fsid_t *fsidp, * Finish the old file, if there was one. */ if (vp != NULL) { - VOP_UNLOCK(vp); - lfs_vunref(vp); + vput(vp); vp = NULL; numrefed--; } @@ -466,8 +463,7 @@ lfs_markv(struct proc *p, fsid_t *fsidp, * Finish the old file, if there was one */ if (vp != NULL) { - VOP_UNLOCK(vp); - lfs_vunref(vp); + vput(vp); vp = NULL; numrefed--; } @@ -512,8 +508,7 @@ err3: */ if (vp != NULL) { - VOP_UNLOCK(vp); - lfs_vunref(vp); + vput(vp); vp = NULL; --numrefed; } @@ -658,6 +653,7 @@ lfs_bmapv(struct proc *p, fsid_t *fsidp, struct inode *ip = NULL; struct lfs *fs; struct mount *mntp; + struct ulfsmount *ump; struct vnode *vp; ino_t lastino; daddr_t v_daddr; @@ -667,9 +663,14 @@ lfs_bmapv(struct proc *p, fsid_t *fsidp, if ((mntp = vfs_getvfs(fsidp)) == NULL) return (ENOENT); + ump = VFSTOULFS(mntp); if ((error = vfs_busy(mntp, NULL)) != 0) return (error); + if (ump->um_cleaner_thread == NULL) + ump->um_cleaner_thread = curlwp; + KASSERT(ump->um_cleaner_thread == curlwp); + cnt = blkcnt; fs = VFSTOULFS(mntp)->um_lfs; @@ -691,8 +692,7 @@ lfs_bmapv(struct proc *p, fsid_t *fsidp, * Finish the old file, if there was one. */ if (vp != NULL) { - VOP_UNLOCK(vp); - lfs_vunref(vp); + vput(vp); vp = NULL; numrefed--; } @@ -771,8 +771,7 @@ lfs_bmapv(struct proc *p, fsid_t *fsidp, * Finish the old file, if there was one. */ if (vp != NULL) { - VOP_UNLOCK(vp); - lfs_vunref(vp); + vput(vp); vp = NULL; numrefed--; } @@ -972,218 +971,36 @@ sys___lfs_segwait50(struct lwp *l, const } /* - * VFS_VGET call specialized for the cleaner. The cleaner already knows the - * daddr from the ifile, so don't look it up again. If the cleaner is + * VFS_VGET call specialized for the cleaner. If the cleaner is * processing IINFO structures, it may have the ondisk inode already, so * don't go retrieving it again. * - * we lfs_vref, and it is the caller's responsibility to lfs_vunref - * when finished. + * Return the vnode referenced and locked. */ -int -lfs_fasthashget(dev_t dev, ino_t ino, struct vnode **vpp) -{ - struct vnode *vp; - - mutex_enter(&ulfs_ihash_lock); - if ((vp = ulfs_ihashlookup(dev, ino)) != NULL) { - mutex_enter(vp->v_interlock); - mutex_exit(&ulfs_ihash_lock); - if (vdead_check(vp, VDEAD_NOWAIT) != 0) { - DLOG((DLOG_CLEAN, "lfs_fastvget: ino %d dead\n", - ino)); - lfs_stats.clean_vnlocked++; - mutex_exit(vp->v_interlock); - return EAGAIN; - } - if (lfs_vref(vp)) { - DLOG((DLOG_CLEAN, "lfs_fastvget: lfs_vref failed" - " for ino %d\n", ino)); - lfs_stats.clean_inlocked++; - return EAGAIN; - } - } else { - mutex_exit(&ulfs_ihash_lock); - } - *vpp = vp; - - return (0); -} - -int +static int lfs_fastvget(struct mount *mp, ino_t ino, BLOCK_INFO *blkp, int lk_flags, struct vnode **vpp) { - IFILE *ifp; - struct inode *ip; - struct ulfs1_dinode *dip, *dinp; - struct vnode *vp; struct ulfsmount *ump; - daddr_t daddr; - dev_t dev; - int error, retries; - struct buf *bp; - struct lfs *fs; + int error; ump = VFSTOULFS(mp); - dev = ump->um_dev; - fs = ump->um_lfs; - - /* - * Wait until the filesystem is fully mounted before allowing vget - * to complete. This prevents possible problems with roll-forward. - */ - mutex_enter(&lfs_lock); - while (fs->lfs_flags & LFS_NOTYET) { - mtsleep(&fs->lfs_flags, PRIBIO+1, "lfs_fnotyet", 0, - &lfs_lock); - } - mutex_exit(&lfs_lock); - - /* - * This is playing fast and loose. Someone may have the inode - * locked, in which case they are going to be distinctly unhappy - * if we trash something. - */ - - error = lfs_fasthashget(dev, ino, vpp); - if (error != 0) + ump->um_cleaner_hint = blkp; + error = vcache_get(mp, &ino, sizeof(ino), vpp); + ump->um_cleaner_hint = NULL; + if (error) return error; - else if (*vpp != NULL) { - error = vn_lock(*vpp, lk_flags); + error = vn_lock(*vpp, lk_flags); + if (error) { if (error == EBUSY) error = EAGAIN; - if (error) { - lfs_vunref(*vpp); - *vpp = NULL; - return error; - } - } - - if (blkp != NULL && blkp->bi_lbn == LFS_UNUSED_LBN) - dinp = blkp->bi_bp; - else - dinp = NULL; - - if (ino == LFS_IFILE_INUM) - daddr = fs->lfs_idaddr; - else { - LFS_IENTRY(ifp, fs, ino, bp); - daddr = ifp->if_daddr; - brelse(bp, 0); - } - if (daddr == LFS_UNUSED_DADDR) - return ENOENT; - - /* - * getnewvnode(9) will call vfs_busy, which will block if the - * filesystem is being unmounted; but umount(9) is waiting for - * us because we're already holding the fs busy. - * XXXMP - */ - if (mp->mnt_iflag & IMNT_UNMOUNT) { + vrele(*vpp); *vpp = NULL; - return EDEADLK; - } - error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, NULL, &vp); - if (error) { - *vpp = NULL; - return (error); - } - - mutex_enter(&ulfs_hashlock); - error = lfs_fasthashget(dev, ino, vpp); - if (error != 0 || *vpp != NULL) { - mutex_exit(&ulfs_hashlock); - ungetnewvnode(vp); - return (error); - } - - /* Allocate new vnode/inode. */ - lfs_vcreate(mp, ino, vp); - - /* - * Put it onto its hash chain and lock it so that other requests for - * this inode will block if they arrive while we are sleeping waiting - * for old data structures to be purged or for the contents of the - * disk portion of this inode to be read. - */ - ip = VTOI(vp); - ulfs_ihashins(ip); - mutex_exit(&ulfs_hashlock); - -#ifdef notyet - /* Not found in the cache => this vnode was loaded only for cleaning. */ - ip->i_lfs_iflags |= LFSI_BMAP; -#endif - - /* - * XXX - * This may not need to be here, logically it should go down with - * the i_devvp initialization. - * Ask Kirk. - */ - ip->i_lfs = fs; - - /* Read in the disk contents for the inode, copy into the inode. */ - if (dinp) { - error = copyin(dinp, ip->i_din.ffs1_din, sizeof (struct ulfs1_dinode)); - if (error) { - DLOG((DLOG_CLEAN, "lfs_fastvget: dinode copyin failed" - " for ino %d\n", ino)); - ulfs_ihashrem(ip); - - /* Unlock and discard unneeded inode. */ - VOP_UNLOCK(vp); - lfs_vunref(vp); - *vpp = NULL; - return (error); - } - if (ip->i_number != ino) - panic("lfs_fastvget: I was fed the wrong inode!"); - } else { - retries = 0; - again: - error = bread(ump->um_devvp, LFS_FSBTODB(fs, daddr), fs->lfs_ibsize, - 0, &bp); - if (error) { - DLOG((DLOG_CLEAN, "lfs_fastvget: bread failed (%d)\n", - error)); - /* - * The inode does not contain anything useful, so it - * would be misleading to leave it on its hash chain. - * Iput() will return it to the free list. - */ - ulfs_ihashrem(ip); - - /* Unlock and discard unneeded inode. */ - VOP_UNLOCK(vp); - lfs_vunref(vp); - *vpp = NULL; - return (error); - } - dip = lfs_ifind(ump->um_lfs, ino, bp); - if (dip == NULL) { - /* Assume write has not completed yet; try again */ - brelse(bp, BC_INVAL); - ++retries; - if (retries > LFS_IFIND_RETRIES) - panic("lfs_fastvget: dinode not found"); - DLOG((DLOG_CLEAN, "lfs_fastvget: dinode not found," - " retrying...\n")); - goto again; - } - *ip->i_din.ffs1_din = *dip; - brelse(bp, 0); + return error; } - lfs_vinit(mp, &vp); - *vpp = vp; - - KASSERT(VOP_ISLOCKED(vp)); - - return (0); + return 0; } /* Index: src/sys/ufs/lfs/lfs_vfsops.c diff -u src/sys/ufs/lfs/lfs_vfsops.c:1.323 src/sys/ufs/lfs/lfs_vfsops.c:1.324 --- src/sys/ufs/lfs/lfs_vfsops.c:1.323 Sun May 31 15:44:31 2015 +++ src/sys/ufs/lfs/lfs_vfsops.c Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_vfsops.c,v 1.323 2015/05/31 15:44:31 hannken Exp $ */ +/* $NetBSD: lfs_vfsops.c,v 1.324 2015/05/31 15:48:03 hannken Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003, 2007, 2007 @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.323 2015/05/31 15:44:31 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c,v 1.324 2015/05/31 15:48:03 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_lfs.h" @@ -101,6 +101,7 @@ __KERNEL_RCSID(0, "$NetBSD: lfs_vfsops.c #include <ufs/lfs/ulfs_quotacommon.h> #include <ufs/lfs/ulfs_inode.h> #include <ufs/lfs/ulfsmount.h> +#include <ufs/lfs/ulfs_bswap.h> #include <ufs/lfs/ulfs_extern.h> #include <uvm/uvm.h> @@ -151,6 +152,8 @@ struct vfsops lfs_vfsops = { .vfs_statvfs = lfs_statvfs, .vfs_sync = lfs_sync, .vfs_vget = lfs_vget, + .vfs_loadvnode = lfs_loadvnode, + .vfs_newvnode = lfs_newvnode, .vfs_fhtovp = lfs_fhtovp, .vfs_vptofh = lfs_vptofh, .vfs_init = lfs_init, @@ -983,6 +986,7 @@ lfs_mountfs(struct vnode *devvp, struct ump = kmem_zalloc(sizeof(*ump), KM_SLEEP); ump->um_lfs = fs; ump->um_fstype = ULFS1; + /* ump->um_cleaner_thread = NULL; */ if (sizeof(struct lfs) < LFS_SBPAD) { /* XXX why? */ brelse(bp, BC_INVAL); brelse(abp, BC_INVAL); @@ -1437,22 +1441,94 @@ lfs_sync(struct mount *mp, int waitfor, int lfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) { + int error; + + error = vcache_get(mp, &ino, sizeof(ino), vpp); + if (error) + return error; + error = vn_lock(*vpp, LK_EXCLUSIVE); + if (error) { + vrele(*vpp); + *vpp = NULL; + return error; + } + + return 0; +} + +/* + * Create a new vnode/inode pair and initialize what fields we can. + */ +static void +lfs_init_vnode(struct ulfsmount *ump, ino_t ino, struct vnode *vp) +{ + struct inode *ip; + struct ulfs1_dinode *dp; + + ASSERT_NO_SEGLOCK(ump->um_lfs); + + /* Initialize the inode. */ + ip = pool_get(&lfs_inode_pool, PR_WAITOK); + memset(ip, 0, sizeof(*ip)); + dp = pool_get(&lfs_dinode_pool, PR_WAITOK); + memset(dp, 0, sizeof(*dp)); + ip->inode_ext.lfs = pool_get(&lfs_inoext_pool, PR_WAITOK); + memset(ip->inode_ext.lfs, 0, sizeof(*ip->inode_ext.lfs)); + ip->i_din.ffs1_din = dp; + ip->i_ump = ump; + ip->i_vnode = vp; + ip->i_dev = ump->um_dev; + ip->i_number = dp->di_inumber = ino; + ip->i_lfs = ump->um_lfs; + ip->i_lfs_effnblks = 0; + SPLAY_INIT(&ip->i_lfs_lbtree); + ip->i_lfs_nbtree = 0; + LIST_INIT(&ip->i_lfs_segdhd); + + vp->v_tag = VT_LFS; + vp->v_op = lfs_vnodeop_p; + vp->v_data = ip; +} + +/* + * Undo lfs_init_vnode(). + */ +static void +lfs_deinit_vnode(struct ulfsmount *ump, struct vnode *vp) +{ + struct inode *ip = VTOI(vp); + + pool_put(&lfs_inoext_pool, ip->inode_ext.lfs); + pool_put(&lfs_dinode_pool, ip->i_din.ffs1_din); + pool_put(&lfs_inode_pool, ip); + vp->v_data = NULL; +} + +/* + * Read an inode from disk and initialize this vnode / inode pair. + * Caller assures no other thread will try to load this inode. + */ +int +lfs_loadvnode(struct mount *mp, struct vnode *vp, + const void *key, size_t key_len, const void **new_key) +{ struct lfs *fs; struct ulfs1_dinode *dip; struct inode *ip; struct buf *bp; struct ifile *ifp; - struct vnode *vp; struct ulfsmount *ump; + ino_t ino; daddr_t daddr; - dev_t dev; int error, retries; struct timespec ts; + KASSERT(key_len == sizeof(ino)); + memcpy(&ino, key, key_len); + memset(&ts, 0, sizeof ts); /* XXX gcc */ ump = VFSTOULFS(mp); - dev = ump->um_dev; fs = ump->um_lfs; /* @@ -1465,23 +1541,6 @@ lfs_vget(struct mount *mp, ino_t ino, st &lfs_lock); mutex_exit(&lfs_lock); -retry: - if ((*vpp = ulfs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) - return (0); - - error = getnewvnode(VT_LFS, mp, lfs_vnodeop_p, NULL, &vp); - if (error) { - *vpp = NULL; - return (error); - } - - mutex_enter(&ulfs_hashlock); - if (ulfs_ihashget(dev, ino, 0) != NULL) { - mutex_exit(&ulfs_hashlock); - ungetnewvnode(vp); - goto retry; - } - /* Translate the inode number to a disk address. */ if (ino == LFS_IFILE_INUM) daddr = fs->lfs_idaddr; @@ -1495,51 +1554,37 @@ retry: } brelse(bp, 0); - if (daddr == LFS_UNUSED_DADDR) { - *vpp = NULLVP; - mutex_exit(&ulfs_hashlock); - ungetnewvnode(vp); + if (daddr == LFS_UNUSED_DADDR) return (ENOENT); - } } /* Allocate/init new vnode/inode. */ - lfs_vcreate(mp, ino, vp); - - /* - * Put it onto its hash chain and lock it so that other requests for - * this inode will block if they arrive while we are sleeping waiting - * for old data structures to be purged or for the contents of the - * disk portion of this inode to be read. - */ + lfs_init_vnode(ump, ino, vp); ip = VTOI(vp); - ulfs_ihashins(ip); - mutex_exit(&ulfs_hashlock); - /* - * XXX - * This may not need to be here, logically it should go down with - * the i_devvp initialization. - * Ask Kirk. - */ - ip->i_lfs = ump->um_lfs; + /* If the cleaner supplied the inode, use it. */ + if (curlwp == ump->um_cleaner_thread && ump->um_cleaner_hint != NULL && + ump->um_cleaner_hint->bi_lbn == LFS_UNUSED_LBN) { + dip = ump->um_cleaner_hint->bi_bp; + error = copyin(dip, ip->i_din.ffs1_din, + sizeof(struct ulfs1_dinode)); + if (error) { + lfs_deinit_vnode(ump, vp); + return error; + } + KASSERT(ip->i_number == ino); + goto out; + } /* Read in the disk contents for the inode, copy into the inode. */ retries = 0; - again: +again: error = bread(ump->um_devvp, LFS_FSBTODB(fs, daddr), (fs->lfs_version == 1 ? fs->lfs_bsize : fs->lfs_ibsize), 0, &bp); if (error) { - /* - * The inode does not contain anything useful, so it would - * be misleading to leave it on its hash chain. With mode - * still zero, it will be unlinked and returned to the free - * list by vput(). - */ - vput(vp); - *vpp = NULL; - return (error); + lfs_deinit_vnode(ump, vp); + return error; } dip = lfs_ifind(fs, ino, bp); @@ -1547,48 +1592,53 @@ retry: /* Assume write has not completed yet; try again */ brelse(bp, BC_INVAL); ++retries; - if (retries > LFS_IFIND_RETRIES) { -#ifdef DEBUG - /* If the seglock is held look at the bpp to see - what is there anyway */ + if (retries <= LFS_IFIND_RETRIES) { mutex_enter(&lfs_lock); - if (fs->lfs_seglock > 0) { - struct buf **bpp; - struct ulfs1_dinode *dp; - int i; - - for (bpp = fs->lfs_sp->bpp; - bpp != fs->lfs_sp->cbpp; ++bpp) { - if ((*bpp)->b_vp == fs->lfs_ivnode && - bpp != fs->lfs_sp->bpp) { - /* Inode block */ - printf("lfs_vget: block 0x%" PRIx64 ": ", - (*bpp)->b_blkno); - dp = (struct ulfs1_dinode *)(*bpp)->b_data; - for (i = 0; i < LFS_INOPB(fs); i++) - if (dp[i].di_inumber) - printf("%d ", dp[i].di_inumber); - printf("\n"); - } - } - } + if (fs->lfs_iocount) { + DLOG((DLOG_VNODE, + "%s: dinode %d not found, retrying...\n", + __func__, ino)); + (void)mtsleep(&fs->lfs_iocount, PRIBIO + 1, + "lfs ifind", 1, &lfs_lock); + } else + retries = LFS_IFIND_RETRIES; mutex_exit(&lfs_lock); -#endif /* DEBUG */ - panic("lfs_vget: dinode not found"); + goto again; } +#ifdef DEBUG + /* If the seglock is held look at the bpp to see + what is there anyway */ mutex_enter(&lfs_lock); - if (fs->lfs_iocount) { - DLOG((DLOG_VNODE, "lfs_vget: dinode %d not found, retrying...\n", ino)); - (void)mtsleep(&fs->lfs_iocount, PRIBIO + 1, - "lfs ifind", 1, &lfs_lock); - } else - retries = LFS_IFIND_RETRIES; + if (fs->lfs_seglock > 0) { + struct buf **bpp; + struct ulfs1_dinode *dp; + int i; + + for (bpp = fs->lfs_sp->bpp; + bpp != fs->lfs_sp->cbpp; ++bpp) { + if ((*bpp)->b_vp == fs->lfs_ivnode && + bpp != fs->lfs_sp->bpp) { + /* Inode block */ + printf("%s: block 0x%" PRIx64 ": ", + __func__, (*bpp)->b_blkno); + dp = (struct ulfs1_dinode *) + (*bpp)->b_data; + for (i = 0; i < LFS_INOPB(fs); i++) + if (dp[i].di_inumber) + printf("%d ", + dp[i].di_inumber); + printf("\n"); + } + } + } mutex_exit(&lfs_lock); - goto again; +#endif /* DEBUG */ + panic("lfs_loadvnode: dinode not found"); } *ip->i_din.ffs1_din = *dip; brelse(bp, 0); +out: if (fs->lfs_version > 1) { ip->i_ffs1_atime = ts.tv_sec; ip->i_ffs1_atimensec = ts.tv_nsec; @@ -1596,11 +1646,107 @@ retry: lfs_vinit(mp, &vp); - *vpp = vp; + *new_key = &ip->i_number; + return 0; +} - KASSERT(VOP_ISLOCKED(vp)); +/* + * Create a new inode and initialize this vnode / inode pair. + */ +int +lfs_newvnode(struct mount *mp, struct vnode *dvp, struct vnode *vp, + struct vattr *vap, kauth_cred_t cred, + size_t *key_len, const void **new_key) +{ + ino_t ino; + struct inode *ip; + struct ulfsmount *ump; + struct lfs *fs; + int error, mode, gen; - return (0); + KASSERT(dvp != NULL || vap->va_fileid > 0); + KASSERT(dvp != NULL && dvp->v_mount == mp); + KASSERT(vap->va_type != VNON); + + *key_len = sizeof(ino); + ump = VFSTOULFS(mp); + fs = ump->um_lfs; + mode = MAKEIMODE(vap->va_type, vap->va_mode); + + /* + * Allocate fresh inode. With "dvp == NULL" take the inode number + * and version from "vap". + */ + if (dvp == NULL) { + ino = vap->va_fileid; + gen = vap->va_gen; + error = lfs_valloc_fixed(fs, ino, gen); + } else { + error = lfs_valloc(dvp, mode, cred, &ino, &gen); + } + if (error) + return error; + + /* Attach inode to vnode. */ + lfs_init_vnode(ump, ino, vp); + ip = VTOI(vp); + + mutex_enter(&lfs_lock); + LFS_SET_UINO(ip, IN_CHANGE); + mutex_exit(&lfs_lock); + + /* Note no blocks yet */ + ip->i_lfs_hiblk = -1; + + /* Set a new generation number for this inode. */ + ip->i_gen = gen; + ip->i_ffs1_gen = gen; + + memset(ip->i_lfs_fragsize, 0, + ULFS_NDADDR * sizeof(*ip->i_lfs_fragsize)); + + /* Set uid / gid. */ + if (cred == NOCRED || cred == FSCRED) { + ip->i_gid = 0; + ip->i_uid = 0; + } else { + ip->i_gid = VTOI(dvp)->i_gid; + ip->i_uid = kauth_cred_geteuid(cred); + } + DIP_ASSIGN(ip, gid, ip->i_gid); + DIP_ASSIGN(ip, uid, ip->i_uid); + +#if defined(LFS_QUOTA) || defined(LFS_QUOTA2) + error = lfs_chkiq(ip, 1, cred, 0); + if (error) { + lfs_vfree(dvp, ino, mode); + ffs_deinit_vnode(ump, vp); + + return error; + } +#endif + + /* Set type and finalize. */ + ip->i_flags = 0; + DIP_ASSIGN(ip, flags, 0); + ip->i_mode = mode; + DIP_ASSIGN(ip, mode, mode); + if (vap->va_rdev != VNOVAL) { + /* + * Want to be able to use this to make badblock + * inodes, so don't truncate the dev number. + */ + if (ump->um_fstype == ULFS1) + ip->i_ffs1_rdev = ulfs_rw32(vap->va_rdev, + ULFS_MPNEEDSWAP(ump)); + else + ip->i_ffs2_rdev = ulfs_rw64(vap->va_rdev, + ULFS_MPNEEDSWAP(ump)); + } + lfs_vinit(mp, &vp); + + *new_key = &ip->i_number; + return 0; } /* @@ -1610,11 +1756,7 @@ int lfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp) { struct lfid lfh; - struct buf *bp; - IFILE *ifp; - int32_t daddr; struct lfs *fs; - vnode_t *vp; if (fhp->fid_len != sizeof(struct lfid)) return EINVAL; @@ -1632,17 +1774,6 @@ lfs_fhtovp(struct mount *mp, struct fid fs->lfs_cleansz - fs->lfs_segtabsz) * fs->lfs_ifpb) return ESTALE; - mutex_enter(&ulfs_ihash_lock); - vp = ulfs_ihashlookup(VFSTOULFS(mp)->um_dev, lfh.lfid_ino); - mutex_exit(&ulfs_ihash_lock); - if (vp == NULL) { - LFS_IENTRY(ifp, fs, lfh.lfid_ino, bp); - daddr = ifp->if_daddr; - brelse(bp, 0); - if (daddr == LFS_UNUSED_DADDR) - return ESTALE; - } - return (ulfs_fhtovp(mp, &lfh.lfid_ufid, vpp)); } @@ -2038,7 +2169,7 @@ lfs_gop_write(struct vnode *vp, struct v /* * finish vnode/inode initialization. - * used by lfs_vget and lfs_fastvget. + * used by lfs_vget. */ void lfs_vinit(struct mount *mp, struct vnode **vpp) Index: src/sys/ufs/lfs/lfs_vnops.c diff -u src/sys/ufs/lfs/lfs_vnops.c:1.271 src/sys/ufs/lfs/lfs_vnops.c:1.272 --- src/sys/ufs/lfs/lfs_vnops.c:1.271 Mon Apr 20 23:03:09 2015 +++ src/sys/ufs/lfs/lfs_vnops.c Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: lfs_vnops.c,v 1.271 2015/04/20 23:03:09 riastradh Exp $ */ +/* $NetBSD: lfs_vnops.c,v 1.272 2015/05/31 15:48:03 hannken Exp $ */ /*- * Copyright (c) 1999, 2000, 2001, 2002, 2003 The NetBSD Foundation, Inc. @@ -125,7 +125,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.271 2015/04/20 23:03:09 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: lfs_vnops.c,v 1.272 2015/05/31 15:48:03 hannken Exp $"); #ifdef _KERNEL_OPT #include "opt_compat_netbsd.h" @@ -585,9 +585,7 @@ lfs_mark_vnode(struct vnode *vp) if (!(ip->i_flag & IN_ADIROP)) { if (!(vp->v_uflag & VU_DIROP)) { mutex_exit(&lfs_lock); - mutex_enter(vp->v_interlock); - if (lfs_vref(vp) != 0) - panic("lfs_mark_vnode: could not vref"); + vref(vp); mutex_enter(&lfs_lock); ++lfs_dirvcount; ++fs->lfs_dirvcount; @@ -638,6 +636,7 @@ lfs_symlink(void *v) KASSERT(vpp != NULL); KASSERT(*vpp == NULL); + KASSERT(ap->a_vap->va_type == VLNK); /* XXX should handle this material another way */ ulr = &VTOI(ap->a_dvp)->i_crap; @@ -649,31 +648,12 @@ lfs_symlink(void *v) return EROFS; } - /* - * Get a new vnode *before* adjusting the dirop count, to - * avoid a deadlock in getnewvnode(), if we have a stacked - * filesystem mounted on top of us. - * - * NB: this means we have to destroy the new vnode on error. - */ - - error = getnewvnode(VT_LFS, dvp->v_mount, lfs_vnodeop_p, NULL, vpp); - if (error) { - DLOG((DLOG_ALLOC, "lfs_mkdir: dvp %p error %d\n", dvp, error)); - return error; - } - KASSERT(*vpp != NULL); - error = lfs_set_dirop(dvp, NULL); - if (error) { - ungetnewvnode(*vpp); - *vpp = NULL; + if (error) return error; - } fstrans_start(dvp->v_mount, FSTRANS_SHARED); - error = ulfs_makeinode(LFS_IFLNK | ap->a_vap->va_mode, dvp, ulr, - vpp, ap->a_cnp); + error = ulfs_makeinode(ap->a_vap, dvp, ulr, vpp, ap->a_cnp); if (error) { goto out; } @@ -708,7 +688,6 @@ out: UNMARK_VNODE(*vpp); if (!((*vpp)->v_uflag & VU_DIROP)) { KASSERT(error != 0); - ungetnewvnode(*vpp); *vpp = NULL; } else { @@ -734,7 +713,6 @@ lfs_mknod(void *v) struct vattr *vap; struct inode *ip; int error; - struct mount *mp; ino_t ino; struct ulfs_lookup_results *ulr; @@ -755,38 +733,18 @@ lfs_mknod(void *v) return EROFS; } - /* - * Get a new vnode *before* adjusting the dirop count, to - * avoid a deadlock in getnewvnode(), if we have a stacked - * filesystem mounted on top of us. - * - * NB: this means we have to destroy the new vnode on error. - */ - - error = getnewvnode(VT_LFS, dvp->v_mount, lfs_vnodeop_p, NULL, vpp); - if (error) { - DLOG((DLOG_ALLOC, "lfs_mknod: dvp %p error %d\n", dvp, error)); - return error; - } - KASSERT(*vpp != NULL); - error = lfs_set_dirop(dvp, NULL); - if (error) { - ungetnewvnode(*vpp); - *vpp = NULL; + if (error) return error; - } fstrans_start(ap->a_dvp->v_mount, FSTRANS_SHARED); - error = ulfs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), - dvp, ulr, vpp, ap->a_cnp); + error = ulfs_makeinode(vap, dvp, ulr, vpp, ap->a_cnp); /* Either way we're done with the dirop at this point */ UNMARK_VNODE(dvp); UNMARK_VNODE(*vpp); if (!((*vpp)->v_uflag & VU_DIROP)) { KASSERT(error != 0); - ungetnewvnode(*vpp); *vpp = NULL; } else { @@ -808,23 +766,8 @@ lfs_mknod(void *v) VN_KNOTE(dvp, NOTE_WRITE); ip = VTOI(*vpp); - mp = (*vpp)->v_mount; ino = ip->i_number; ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; - if (vap->va_rdev != VNOVAL) { - struct ulfsmount *ump = ip->i_ump; - KASSERT(fs == ip->i_lfs); - /* - * Want to be able to use this to make badblock - * inodes, so don't truncate the dev number. - */ - if (ump->um_fstype == ULFS1) - ip->i_ffs1_rdev = ulfs_rw32(vap->va_rdev, - ULFS_MPNEEDSWAP(fs)); - else - ip->i_ffs2_rdev = ulfs_rw64(vap->va_rdev, - ULFS_MPNEEDSWAP(fs)); - } /* * Call fsync to write the vnode so that we don't have to deal with @@ -839,17 +782,6 @@ lfs_mknod(void *v) (unsigned long long)ino); /* return (error); */ } - /* - * Remove vnode so that it will be reloaded by VFS_VGET and - * checked to see if it is an alias of an existing entry in - * the inode cache. - */ - /* Used to be vput, but that causes us to call VOP_INACTIVE twice. */ - - (*vpp)->v_type = VNON; - VOP_UNLOCK(*vpp); - vgone(*vpp); - error = VFS_VGET(mp, ino, vpp); fstrans_done(ap->a_dvp->v_mount); if (error != 0) { @@ -895,29 +827,12 @@ lfs_create(void *v) return EROFS; } - /* - * Get a new vnode *before* adjusting the dirop count, to - * avoid a deadlock in getnewvnode(), if we have a stacked - * filesystem mounted on top of us. - * - * NB: this means we have to destroy the new vnode on error. - */ - - error = getnewvnode(VT_LFS, dvp->v_mount, lfs_vnodeop_p, NULL, vpp); - if (error) { - DLOG((DLOG_ALLOC, "lfs_create: dvp %p error %d\n", dvp,error)); - return error; - } error = lfs_set_dirop(dvp, NULL); - if (error) { - ungetnewvnode(*vpp); - *vpp = NULL; + if (error) return error; - } fstrans_start(dvp->v_mount, FSTRANS_SHARED); - error = ulfs_makeinode(MAKEIMODE(vap->va_type, vap->va_mode), - dvp, ulr, vpp, ap->a_cnp); + error = ulfs_makeinode(vap, dvp, ulr, vpp, ap->a_cnp); if (error) { fstrans_done(dvp->v_mount); goto out; @@ -932,7 +847,6 @@ out: UNMARK_VNODE(*vpp); if (!((*vpp)->v_uflag & VU_DIROP)) { KASSERT(error != 0); - ungetnewvnode(*vpp); *vpp = NULL; } else { @@ -963,7 +877,6 @@ lfs_mkdir(void *v) struct lfs_dirtemplate dirtemplate; struct lfs_direct *newdir; int dirblksiz; - int dmode; int error; dvp = ap->a_dvp; @@ -975,6 +888,7 @@ lfs_mkdir(void *v) dp = VTOI(dvp); ip = NULL; + KASSERT(vap->va_type == VDIR); KASSERT(vpp != NULL); KASSERT(*vpp == NULL); @@ -989,25 +903,9 @@ lfs_mkdir(void *v) } dirblksiz = fs->um_dirblksiz; - /* - * Get a new vnode *before* adjusting the dirop count, to - * avoid a deadlock in getnewvnode(), if we have a stacked - * filesystem mounted on top of us. - * - * NB: this means we have to destroy the new vnode on error. - */ - - error = getnewvnode(VT_LFS, dvp->v_mount, lfs_vnodeop_p, NULL, vpp); - if (error) { - DLOG((DLOG_ALLOC, "lfs_mkdir: dvp %p error %d\n", dvp, error)); - return error; - } error = lfs_set_dirop(dvp, NULL); - if (error) { - ungetnewvnode(*vpp); - *vpp = NULL; + if (error) return error; - } fstrans_start(dvp->v_mount, FSTRANS_SHARED); @@ -1016,35 +914,26 @@ lfs_mkdir(void *v) goto out; } - dmode = vap->va_mode & ACCESSPERMS; - dmode |= LFS_IFDIR; /* * Must simulate part of ulfs_makeinode here to acquire the inode, * but not have it entered in the parent directory. The entry is * made later after writing "." and ".." entries. */ - if ((error = lfs_valloc(dvp, dmode, cnp->cn_cred, vpp)) != 0) + error = vcache_new(dvp->v_mount, dvp, vap, cnp->cn_cred, ap->a_vpp); + if (error) goto out; - tvp = *vpp; - ip = VTOI(tvp); - - ip->i_uid = kauth_cred_geteuid(cnp->cn_cred); - DIP_ASSIGN(ip, uid, ip->i_uid); - ip->i_gid = dp->i_gid; - DIP_ASSIGN(ip, gid, ip->i_gid); -#if defined(LFS_QUOTA) || defined(LFS_QUOTA2) - if ((error = lfs_chkiq(ip, 1, cnp->cn_cred, 0))) { - lfs_vfree(tvp, ip->i_number, dmode); - fstrans_done(dvp->v_mount); - vput(tvp); - goto out2; + error = vn_lock(*ap->a_vpp, LK_EXCLUSIVE); + if (error) { + vrele(*ap->a_vpp); + *ap->a_vpp = NULL; + goto out; } -#endif + + tvp = *ap->a_vpp; + lfs_mark_vnode(tvp); + ip = VTOI(tvp); ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; - ip->i_mode = dmode; - DIP_ASSIGN(ip, mode, dmode); - tvp->v_type = VDIR; /* Rest init'd in getnewvnode(). */ ip->i_nlink = 2; DIP_ASSIGN(ip, nlink, 2); if (cnp->cn_flags & ISWHITEOUT) { @@ -1136,7 +1025,6 @@ out2: UNMARK_VNODE(*vpp); if (!((*vpp)->v_uflag & VU_DIROP)) { KASSERT(error != 0); - ungetnewvnode(*vpp); *vpp = NULL; } else { @@ -1815,12 +1703,12 @@ lfs_flush_pchain(struct lfs *fs) mutex_exit(vp->v_interlock); continue; } - if (lfs_vref(vp)) + if (vget(vp, LK_NOWAIT, false /* !wait */)) continue; mutex_exit(&lfs_lock); if (vn_lock(vp, LK_EXCLUSIVE | LK_NOWAIT | LK_RETRY) != 0) { - lfs_vunref(vp); + vrele(vp); mutex_enter(&lfs_lock); continue; } @@ -1836,7 +1724,7 @@ lfs_flush_pchain(struct lfs *fs) error2 = lfs_writeinode(fs, sp, ip); VOP_UNLOCK(vp); - lfs_vunref(vp); + vrele(vp); if (error == EAGAIN || error2 == EAGAIN) { lfs_writeseg(fs, sp); @@ -2098,16 +1986,14 @@ segwait_common: wakeup(&fs->lfs_wrappass); /* Wait for the log to wrap, if asked */ if (*(int *)ap->a_data) { - mutex_enter(ap->a_vp->v_interlock); - if (lfs_vref(ap->a_vp) != 0) - panic("LFCNWRAPPASS: lfs_vref failed"); + vref(ap->a_vp); VTOI(ap->a_vp)->i_lfs_iflags |= LFSI_WRAPWAIT; log(LOG_NOTICE, "LFCNPASS waiting for log wrap\n"); error = mtsleep(&fs->lfs_nowrap, PCATCH | PUSER, "segwrap", 0, &lfs_lock); log(LOG_NOTICE, "LFCNPASS done waiting\n"); VTOI(ap->a_vp)->i_lfs_iflags &= ~LFSI_WRAPWAIT; - lfs_vunref(ap->a_vp); + vrele(ap->a_vp); } mutex_exit(&lfs_lock); return error; Index: src/sys/ufs/lfs/ulfs_extern.h diff -u src/sys/ufs/lfs/ulfs_extern.h:1.14 src/sys/ufs/lfs/ulfs_extern.h:1.15 --- src/sys/ufs/lfs/ulfs_extern.h:1.14 Fri Mar 27 17:27:56 2015 +++ src/sys/ufs/lfs/ulfs_extern.h Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: ulfs_extern.h,v 1.14 2015/03/27 17:27:56 riastradh Exp $ */ +/* $NetBSD: ulfs_extern.h,v 1.15 2015/05/31 15:48:03 hannken Exp $ */ /* from NetBSD: ufs_extern.h,v 1.72 2012/05/09 00:21:18 riastradh Exp */ /*- @@ -105,15 +105,6 @@ int ulfs_bmaparray(struct vnode *, daddr int *, int *, ulfs_issequential_callback_t); int ulfs_getlbns(struct vnode *, daddr_t, struct indir *, int *); -/* ulfs_ihash.c */ -void ulfs_ihashinit(void); -void ulfs_ihashreinit(void); -void ulfs_ihashdone(void); -struct vnode *ulfs_ihashlookup(dev_t, ino_t); -struct vnode *ulfs_ihashget(dev_t, ino_t, int); -void ulfs_ihashins(struct inode *); -void ulfs_ihashrem(struct inode *); - /* ulfs_inode.c */ int ulfs_reclaim(struct vnode *); int ulfs_balloc_range(struct vnode *, off_t, off_t, kauth_cred_t, int); @@ -166,7 +157,8 @@ int ulfs_fhtovp(struct mount *, struct u /* ulfs_vnops.c */ void ulfs_vinit(struct mount *, int (**)(void *), int (**)(void *), struct vnode **); -int ulfs_makeinode(int, struct vnode *, const struct ulfs_lookup_results *, +int ulfs_makeinode(struct vattr *vap, struct vnode *, + const struct ulfs_lookup_results *, struct vnode **, struct componentname *); int ulfs_gop_alloc(struct vnode *, off_t, off_t, int, kauth_cred_t); void ulfs_gop_markupdate(struct vnode *, int); @@ -181,7 +173,4 @@ void ulfs_snapgone(struct inode *); __END_DECLS -extern kmutex_t ulfs_ihash_lock; -extern kmutex_t ulfs_hashlock; - #endif /* !_UFS_LFS_ULFS_EXTERN_H_ */ Index: src/sys/ufs/lfs/ulfs_inode.c diff -u src/sys/ufs/lfs/ulfs_inode.c:1.9 src/sys/ufs/lfs/ulfs_inode.c:1.10 --- src/sys/ufs/lfs/ulfs_inode.c:1.9 Sun Jul 28 00:37:07 2013 +++ src/sys/ufs/lfs/ulfs_inode.c Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: ulfs_inode.c,v 1.9 2013/07/28 00:37:07 dholland Exp $ */ +/* $NetBSD: ulfs_inode.c,v 1.10 2015/05/31 15:48:03 hannken Exp $ */ /* from NetBSD: ufs_inode.c,v 1.89 2013/01/22 09:39:18 dholland Exp */ /* @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ulfs_inode.c,v 1.9 2013/07/28 00:37:07 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ulfs_inode.c,v 1.10 2015/05/31 15:48:03 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_lfs.h" @@ -150,9 +150,9 @@ ulfs_reclaim(struct vnode *vp) lfs_update(vp, NULL, NULL, UPDATE_CLOSE); /* - * Remove the inode from its hash chain. + * Remove the inode from the vnode cache. */ - ulfs_ihashrem(ip); + vcache_remove(vp->v_mount, &ip->i_number, sizeof(ip->i_number)); if (ip->i_devvp) { vrele(ip->i_devvp); Index: src/sys/ufs/lfs/ulfs_lookup.c diff -u src/sys/ufs/lfs/ulfs_lookup.c:1.23 src/sys/ufs/lfs/ulfs_lookup.c:1.24 --- src/sys/ufs/lfs/ulfs_lookup.c:1.23 Sat Mar 28 17:23:42 2015 +++ src/sys/ufs/lfs/ulfs_lookup.c Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: ulfs_lookup.c,v 1.23 2015/03/28 17:23:42 maxv Exp $ */ +/* $NetBSD: ulfs_lookup.c,v 1.24 2015/05/31 15:48:03 hannken Exp $ */ /* from NetBSD: ufs_lookup.c,v 1.122 2013/01/22 09:39:18 dholland Exp */ /* @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ulfs_lookup.c,v 1.23 2015/03/28 17:23:42 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ulfs_lookup.c,v 1.24 2015/05/31 15:48:03 hannken Exp $"); #ifdef _KERNEL_OPT #include "opt_lfs.h" @@ -138,8 +138,7 @@ ulfs_lookup(void *v) int numdirpasses; /* strategy for directory search */ doff_t endsearch; /* offset to end directory search */ doff_t prevoff; /* previous value of ulr_offset */ - struct vnode *pdp; /* saved dp during symlink work */ - struct vnode *tdp; /* returned by VFS_VGET */ + struct vnode *tdp; /* returned by vcache_get */ doff_t enduseful; /* pointer past last used dir slot. used for directory truncation. */ u_long bmask; /* block offset mask */ @@ -566,11 +565,8 @@ found: vref(vdp); tdp = vdp; } else { - if (flags & ISDOTDOT) - VOP_UNLOCK(vdp); /* race to get the inode */ - error = VFS_VGET(vdp->v_mount, foundino, &tdp); - if (flags & ISDOTDOT) - vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY); + error = vcache_get(vdp->v_mount, + &foundino, sizeof(foundino), &tdp); if (error) goto out; } @@ -579,10 +575,7 @@ found: */ error = VOP_ACCESS(vdp, VWRITE, cred); if (error) { - if (dp->i_number == foundino) - vrele(tdp); - else - vput(tdp); + vrele(tdp); goto out; } /* @@ -596,10 +589,7 @@ found: tdp, vdp, genfs_can_sticky(cred, dp->i_uid, VTOI(tdp)->i_uid)); if (error) { - if (dp->i_number == foundino) - vrele(tdp); - else - vput(tdp); + vrele(tdp); error = EPERM; goto out; } @@ -627,11 +617,8 @@ found: error = EISDIR; goto out; } - if (flags & ISDOTDOT) - VOP_UNLOCK(vdp); /* race to get the inode */ - error = VFS_VGET(vdp->v_mount, foundino, &tdp); - if (flags & ISDOTDOT) - vn_lock(vdp, LK_EXCLUSIVE | LK_RETRY); + error = vcache_get(vdp->v_mount, + &foundino, sizeof(foundino), &tdp); if (error) goto out; *vpp = tdp; @@ -639,39 +626,12 @@ found: goto out; } - /* - * Step through the translation in the name. We do not `vput' the - * directory because we may need it again if a symbolic link - * is relative to the current directory. Instead we save it - * unlocked as "pdp". We must get the target inode before unlocking - * the directory to insure that the inode will not be removed - * before we get it. We prevent deadlock by always fetching - * inodes from the root, moving down the directory tree. Thus - * when following backward pointers ".." we must unlock the - * parent directory before getting the requested directory. - * There is a potential race condition here if both the current - * and parent directories are removed before the VFS_VGET for the - * inode associated with ".." returns. We hope that this occurs - * infrequently since we cannot avoid this race condition without - * implementing a sophisticated deadlock detection algorithm. - * Note also that this simple deadlock detection scheme will not - * work if the file system has any hard links other than ".." - * that point backwards in the directory structure. - */ - pdp = vdp; - if (flags & ISDOTDOT) { - VOP_UNLOCK(pdp); /* race to get the inode */ - error = VFS_VGET(vdp->v_mount, foundino, &tdp); - vn_lock(pdp, LK_EXCLUSIVE | LK_RETRY); - if (error) { - goto out; - } - *vpp = tdp; - } else if (dp->i_number == foundino) { + if (dp->i_number == foundino) { vref(vdp); /* we want ourself, ie "." */ *vpp = vdp; } else { - error = VFS_VGET(vdp->v_mount, foundino, &tdp); + error = vcache_get(vdp->v_mount, + &foundino, sizeof(foundino), &tdp); if (error) goto out; *vpp = tdp; @@ -684,8 +644,6 @@ found: error = 0; out: - if (error == 0 && *vpp != vdp) - VOP_UNLOCK(*vpp); fstrans_done(vdp->v_mount); return error; } Index: src/sys/ufs/lfs/ulfs_vfsops.c diff -u src/sys/ufs/lfs/ulfs_vfsops.c:1.8 src/sys/ufs/lfs/ulfs_vfsops.c:1.9 --- src/sys/ufs/lfs/ulfs_vfsops.c:1.8 Sat Jun 8 02:12:56 2013 +++ src/sys/ufs/lfs/ulfs_vfsops.c Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: ulfs_vfsops.c,v 1.8 2013/06/08 02:12:56 dholland Exp $ */ +/* $NetBSD: ulfs_vfsops.c,v 1.9 2015/05/31 15:48:03 hannken Exp $ */ /* from NetBSD: ufs_vfsops.c,v 1.52 2013/01/22 09:39:18 dholland Exp */ /* @@ -38,7 +38,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ulfs_vfsops.c,v 1.8 2013/06/08 02:12:56 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ulfs_vfsops.c,v 1.9 2015/05/31 15:48:03 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_lfs.h" @@ -221,6 +221,8 @@ ulfs_fhtovp(struct mount *mp, struct ulf int error; if ((error = VFS_VGET(mp, ufhp->ufid_ino, &nvp)) != 0) { + if (error == ENOENT) + error = ESTALE; *vpp = NULLVP; return (error); } @@ -247,7 +249,6 @@ ulfs_init(void) ulfs_direct_cache = pool_cache_init(sizeof(struct lfs_direct), 0, 0, 0, "ulfsdir", NULL, IPL_NONE, NULL, NULL, NULL); - ulfs_ihashinit(); #if defined(LFS_QUOTA) || defined(LFS_QUOTA2) lfs_dqinit(); #endif @@ -262,7 +263,7 @@ ulfs_init(void) void ulfs_reinit(void) { - ulfs_ihashreinit(); + #if defined(LFS_QUOTA) || defined(LFS_QUOTA2) lfs_dqreinit(); #endif @@ -277,7 +278,6 @@ ulfs_done(void) if (--ulfs_initcount > 0) return; - ulfs_ihashdone(); #if defined(LFS_QUOTA) || defined(LFS_QUOTA2) lfs_dqdone(); #endif Index: src/sys/ufs/lfs/ulfs_vnops.c diff -u src/sys/ufs/lfs/ulfs_vnops.c:1.25 src/sys/ufs/lfs/ulfs_vnops.c:1.26 --- src/sys/ufs/lfs/ulfs_vnops.c:1.25 Mon Apr 20 23:03:09 2015 +++ src/sys/ufs/lfs/ulfs_vnops.c Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: ulfs_vnops.c,v 1.25 2015/04/20 23:03:09 riastradh Exp $ */ +/* $NetBSD: ulfs_vnops.c,v 1.26 2015/05/31 15:48:03 hannken Exp $ */ /* from NetBSD: ufs_vnops.c,v 1.213 2013/06/08 05:47:02 kardel Exp */ /*- @@ -67,7 +67,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ulfs_vnops.c,v 1.25 2015/04/20 23:03:09 riastradh Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ulfs_vnops.c,v 1.26 2015/05/31 15:48:03 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_lfs.h" @@ -1174,39 +1174,27 @@ ulfs_vinit(struct mount *mntp, int (**sp * Allocate a new inode. */ int -ulfs_makeinode(int mode, struct vnode *dvp, const struct ulfs_lookup_results *ulr, +ulfs_makeinode(struct vattr *vap, struct vnode *dvp, + const struct ulfs_lookup_results *ulr, struct vnode **vpp, struct componentname *cnp) { - struct inode *ip, *pdir; + struct inode *ip; struct lfs_direct *newdir; struct vnode *tvp; int error; - pdir = VTOI(dvp); - - if ((mode & LFS_IFMT) == 0) - mode |= LFS_IFREG; - - if ((error = lfs_valloc(dvp, mode, cnp->cn_cred, vpp)) != 0) { - return (error); + error = vcache_new(dvp->v_mount, dvp, vap, cnp->cn_cred, &tvp); + if (error) + return error; + error = vn_lock(tvp, LK_EXCLUSIVE); + if (error) { + vrele(tvp); + return error; } - tvp = *vpp; + lfs_mark_vnode(tvp); + *vpp = tvp; ip = VTOI(tvp); - ip->i_gid = pdir->i_gid; - DIP_ASSIGN(ip, gid, ip->i_gid); - ip->i_uid = kauth_cred_geteuid(cnp->cn_cred); - DIP_ASSIGN(ip, uid, ip->i_uid); -#if defined(LFS_QUOTA) || defined(LFS_QUOTA2) - if ((error = lfs_chkiq(ip, 1, cnp->cn_cred, 0))) { - lfs_vfree(tvp, ip->i_number, mode); - vput(tvp); - return (error); - } -#endif ip->i_flag |= IN_ACCESS | IN_CHANGE | IN_UPDATE; - ip->i_mode = mode; - DIP_ASSIGN(ip, mode, mode); - tvp->v_type = IFTOVT(mode); /* Rest init'd in getnewvnode(). */ ip->i_nlink = 1; DIP_ASSIGN(ip, nlink, 1); @@ -1214,7 +1202,7 @@ ulfs_makeinode(int mode, struct vnode *d if (ip->i_mode & ISGID) { error = kauth_authorize_vnode(cnp->cn_cred, KAUTH_VNODE_WRITE_SECURITY, tvp, NULL, genfs_can_chmod(tvp->v_type, cnp->cn_cred, ip->i_uid, - ip->i_gid, mode)); + ip->i_gid, MAKEIMODE(vap->va_type, vap->va_mode))); if (error) { ip->i_mode &= ~ISGID; DIP_ASSIGN(ip, mode, ip->i_mode); @@ -1250,7 +1238,6 @@ ulfs_makeinode(int mode, struct vnode *d ip->i_flag |= IN_CHANGE; /* If IN_ADIROP, account for it */ lfs_unmark_vnode(tvp); - tvp->v_type = VNON; /* explodes later if VBLK */ vput(tvp); return (error); } Index: src/sys/ufs/lfs/ulfsmount.h diff -u src/sys/ufs/lfs/ulfsmount.h:1.12 src/sys/ufs/lfs/ulfsmount.h:1.13 --- src/sys/ufs/lfs/ulfsmount.h:1.12 Sun Jul 28 01:10:49 2013 +++ src/sys/ufs/lfs/ulfsmount.h Sun May 31 15:48:03 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: ulfsmount.h,v 1.12 2013/07/28 01:10:49 dholland Exp $ */ +/* $NetBSD: ulfsmount.h,v 1.13 2015/05/31 15:48:03 hannken Exp $ */ /* from NetBSD: ufsmount.h,v 1.39 2012/10/19 17:09:08 drochner Exp */ /* @@ -73,6 +73,11 @@ struct ulfsmount { /* Extended attribute information. */ struct ulfs_extattr_per_mount um_extattr; + /* Cleaner lwp, set on first bmapv syscall. */ + struct lwp *um_cleaner_thread; + + /* Hint from cleaner, only valid if curlwp == um_cleaner_thread. */ + BLOCK_INFO *um_cleaner_hint; /* Quota-related material. */ struct vnode *um_quotas[ULFS_MAXQUOTAS]; /* quota files */ kauth_cred_t um_cred[ULFS_MAXQUOTAS]; /* quota file access cred */