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 */