Module Name: src Committed By: hannken Date: Thu May 8 08:21:53 UTC 2014
Modified Files: src/sys/kern: init_sysctl.c vfs_vnode.c src/sys/modules/ffs: Makefile src/sys/rump/fs/lib/libffs: Makefile src/sys/sys: mount.h param.h vnode.h src/sys/ufs: files.ufs src/sys/ufs/ext2fs: ext2fs_lookup.c ext2fs_vfsops.c src/sys/ufs/ffs: ffs_vfsops.c src/sys/ufs/mfs: mfs_vfsops.c src/sys/ufs/ufs: inode.h ufs_extern.h ufs_inode.c ufs_lookup.c ufs_vfsops.c src/usr.bin/vmstat: vmstat.c Removed Files: src/sys/ufs/ufs: ufs_ihash.c Log Message: Add a global vnode cache: - vcache_get() retrieves a referenced and initialised vnode / fs node pair. - vcache_remove() removes a vnode / fs node pair from the cache. On cache miss vcache_get() calls new vfs operation vfs_loadvnode() to initialise a vnode / fs node pair. This call is guaranteed exclusive, no other thread will try to load this vnode / fs node pair. Convert ufs/ext2fs, ufs/ffs and ufs/mfs to use this interface. Remove now unused ufs/ufs_ihash Discussed on tech-kern. Welcome to 6.99.41 To generate a diff of this commit: cvs rdiff -u -r1.202 -r1.203 src/sys/kern/init_sysctl.c cvs rdiff -u -r1.35 -r1.36 src/sys/kern/vfs_vnode.c cvs rdiff -u -r1.8 -r1.9 src/sys/modules/ffs/Makefile cvs rdiff -u -r1.14 -r1.15 src/sys/rump/fs/lib/libffs/Makefile cvs rdiff -u -r1.212 -r1.213 src/sys/sys/mount.h cvs rdiff -u -r1.450 -r1.451 src/sys/sys/param.h cvs rdiff -u -r1.246 -r1.247 src/sys/sys/vnode.h cvs rdiff -u -r1.34 -r1.35 src/sys/ufs/files.ufs cvs rdiff -u -r1.74 -r1.75 src/sys/ufs/ext2fs/ext2fs_lookup.c cvs rdiff -u -r1.180 -r1.181 src/sys/ufs/ext2fs/ext2fs_vfsops.c cvs rdiff -u -r1.297 -r1.298 src/sys/ufs/ffs/ffs_vfsops.c cvs rdiff -u -r1.107 -r1.108 src/sys/ufs/mfs/mfs_vfsops.c cvs rdiff -u -r1.65 -r1.66 src/sys/ufs/ufs/inode.h cvs rdiff -u -r1.73 -r1.74 src/sys/ufs/ufs/ufs_extern.h cvs rdiff -u -r1.32 -r0 src/sys/ufs/ufs/ufs_ihash.c cvs rdiff -u -r1.89 -r1.90 src/sys/ufs/ufs/ufs_inode.c cvs rdiff -u -r1.129 -r1.130 src/sys/ufs/ufs/ufs_lookup.c cvs rdiff -u -r1.52 -r1.53 src/sys/ufs/ufs/ufs_vfsops.c cvs rdiff -u -r1.191 -r1.192 src/usr.bin/vmstat/vmstat.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/init_sysctl.c diff -u src/sys/kern/init_sysctl.c:1.202 src/sys/kern/init_sysctl.c:1.203 --- src/sys/kern/init_sysctl.c:1.202 Mon Mar 24 20:07:41 2014 +++ src/sys/kern/init_sysctl.c Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: init_sysctl.c,v 1.202 2014/03/24 20:07:41 christos Exp $ */ +/* $NetBSD: init_sysctl.c,v 1.203 2014/05/08 08:21:53 hannken Exp $ */ /*- * Copyright (c) 2003, 2007, 2008, 2009 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.202 2014/03/24 20:07:41 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: init_sysctl.c,v 1.203 2014/05/08 08:21:53 hannken Exp $"); #include "opt_sysv.h" #include "opt_compat_netbsd.h" @@ -854,12 +854,10 @@ sysctl_kern_maxvnodes(SYSCTLFN_ARGS) old_vnodes = desiredvnodes; desiredvnodes = new_vnodes; - if (new_vnodes < old_vnodes) { - error = vfs_drainvnodes(new_vnodes); - if (error) { - desiredvnodes = old_vnodes; - return (error); - } + error = vfs_drainvnodes(new_vnodes); + if (error) { + desiredvnodes = old_vnodes; + return (error); } vfs_reinit(); nchreinit(); Index: src/sys/kern/vfs_vnode.c diff -u src/sys/kern/vfs_vnode.c:1.35 src/sys/kern/vfs_vnode.c:1.36 --- src/sys/kern/vfs_vnode.c:1.35 Mon Mar 24 13:42:40 2014 +++ src/sys/kern/vfs_vnode.c Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: vfs_vnode.c,v 1.35 2014/03/24 13:42:40 hannken Exp $ */ +/* $NetBSD: vfs_vnode.c,v 1.36 2014/05/08 08:21:53 hannken Exp $ */ /*- * Copyright (c) 1997-2011 The NetBSD Foundation, Inc. @@ -116,7 +116,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.35 2014/03/24 13:42:40 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c,v 1.36 2014/05/08 08:21:53 hannken Exp $"); #define _VFS_VNODE_PRIVATE @@ -127,6 +127,7 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c, #include <sys/buf.h> #include <sys/conf.h> #include <sys/device.h> +#include <sys/hash.h> #include <sys/kauth.h> #include <sys/kmem.h> #include <sys/kthread.h> @@ -147,6 +148,17 @@ __KERNEL_RCSID(0, "$NetBSD: vfs_vnode.c, #define VRELEL_ASYNC_RELE 0x0001 /* Always defer to vrele thread. */ #define VRELEL_CHANGING_SET 0x0002 /* VI_CHANGING set by caller. */ +struct vcache_key { + struct mount *vk_mount; + const void *vk_key; + size_t vk_key_len; +}; +struct vcache_node { + SLIST_ENTRY(vcache_node) vn_hash; + struct vnode *vn_vnode; + struct vcache_key vn_key; +}; + u_int numvnodes __cacheline_aligned; static pool_cache_t vnode_cache __read_mostly; @@ -169,7 +181,16 @@ static lwp_t * vrele_lwp __cacheline_a static int vrele_pending __cacheline_aligned; static int vrele_gen __cacheline_aligned; +static struct { + kmutex_t lock; + u_long hashmask; + SLIST_HEAD(hashhead, vcache_node) *hashtab; + pool_cache_t pool; +} vcache __cacheline_aligned; + static int cleanvnode(void); +static void vcache_init(void); +static void vcache_reinit(void); static void vclean(vnode_t *); static void vrelel(vnode_t *, int); static void vdrain_thread(void *); @@ -200,6 +221,8 @@ vfs_vnode_sysinit(void) TAILQ_INIT(&vnode_hold_list); TAILQ_INIT(&vrele_list); + vcache_init(); + mutex_init(&vrele_lock, MUTEX_DEFAULT, IPL_NONE); cv_init(&vdrain_cv, "vdrain"); cv_init(&vrele_cv, "vrele"); @@ -236,10 +259,20 @@ vnalloc(struct mount *mp) vp->v_mount = mp; vp->v_type = VBAD; vp->v_iflag = VI_MARKER; - } else { - rw_init(&vp->v_lock); + return vp; } + mutex_enter(&vnode_free_list_lock); + numvnodes++; + if (numvnodes > desiredvnodes + desiredvnodes / 10) + cv_signal(&vdrain_cv); + mutex_exit(&vnode_free_list_lock); + + rw_init(&vp->v_lock); + vp->v_usecount = 1; + vp->v_type = VNON; + vp->v_size = vp->v_writesize = VSIZENOTSET; + return vp; } @@ -367,29 +400,21 @@ getnewvnode(enum vtagtype tag, struct mo vp = NULL; /* Allocate a new vnode. */ - mutex_enter(&vnode_free_list_lock); - numvnodes++; - if (numvnodes > desiredvnodes + desiredvnodes / 10) - cv_signal(&vdrain_cv); - mutex_exit(&vnode_free_list_lock); vp = vnalloc(NULL); KASSERT(vp->v_freelisthd == NULL); KASSERT(LIST_EMPTY(&vp->v_nclist)); KASSERT(LIST_EMPTY(&vp->v_dnclist)); + KASSERT(vp->v_data == NULL); /* Initialize vnode. */ - vp->v_usecount = 1; - vp->v_type = VNON; vp->v_tag = tag; vp->v_op = vops; - vp->v_data = NULL; uobj = &vp->v_uobj; KASSERT(uobj->pgops == &uvm_vnodeops); KASSERT(uobj->uo_npages == 0); KASSERT(TAILQ_FIRST(&uobj->memq) == NULL); - vp->v_size = vp->v_writesize = VSIZENOTSET; /* Share the vnode_t::v_interlock, if requested. */ if (slock) { @@ -1120,6 +1145,208 @@ vgone(vnode_t *vp) vrelel(vp, VRELEL_CHANGING_SET); } +static inline uint32_t +vcache_hash(const struct vcache_key *key) +{ + uint32_t hash = HASH32_BUF_INIT; + + hash = hash32_buf(&key->vk_mount, sizeof(struct mount *), hash); + hash = hash32_buf(key->vk_key, key->vk_key_len, hash); + return hash; +} + +static void +vcache_init(void) +{ + + vcache.pool = pool_cache_init(sizeof(struct vcache_node), 0, 0, 0, + "vcachepl", NULL, IPL_NONE, NULL, NULL, NULL); + KASSERT(vcache.pool != NULL); + mutex_init(&vcache.lock, MUTEX_DEFAULT, IPL_NONE); + vcache.hashtab = hashinit(desiredvnodes, HASH_SLIST, true, + &vcache.hashmask); +} + +static void +vcache_reinit(void) +{ + int i; + uint32_t hash; + u_long oldmask, newmask; + struct hashhead *oldtab, *newtab; + struct vcache_node *node; + + newtab = hashinit(desiredvnodes, HASH_SLIST, true, &newmask); + mutex_enter(&vcache.lock); + oldtab = vcache.hashtab; + oldmask = vcache.hashmask; + vcache.hashtab = newtab; + vcache.hashmask = newmask; + for (i = 0; i <= oldmask; i++) { + while ((node = SLIST_FIRST(&oldtab[i])) != NULL) { + SLIST_REMOVE(&oldtab[i], node, vcache_node, vn_hash); + hash = vcache_hash(&node->vn_key); + SLIST_INSERT_HEAD(&newtab[hash & vcache.hashmask], + node, vn_hash); + } + } + mutex_exit(&vcache.lock); + hashdone(oldtab, HASH_SLIST, oldmask); +} + +static inline struct vcache_node * +vcache_hash_lookup(const struct vcache_key *key, uint32_t hash) +{ + struct hashhead *hashp; + struct vcache_node *node; + + KASSERT(mutex_owned(&vcache.lock)); + + hashp = &vcache.hashtab[hash & vcache.hashmask]; + SLIST_FOREACH(node, hashp, vn_hash) { + if (key->vk_mount != node->vn_key.vk_mount) + continue; + if (key->vk_key_len != node->vn_key.vk_key_len) + continue; + if (memcmp(key->vk_key, node->vn_key.vk_key, key->vk_key_len)) + continue; + return node; + } + return NULL; +} + +/* + * Get a vnode / fs node pair by key and return it referenced through vpp. + */ +int +vcache_get(struct mount *mp, const void *key, size_t key_len, + struct vnode **vpp) +{ + int error; + uint32_t hash; + const void *new_key; + struct vnode *vp; + struct vcache_key vcache_key; + struct vcache_node *node, *new_node; + + new_key = NULL; + *vpp = NULL; + + vcache_key.vk_mount = mp; + vcache_key.vk_key = key; + vcache_key.vk_key_len = key_len; + hash = vcache_hash(&vcache_key); + +again: + mutex_enter(&vcache.lock); + node = vcache_hash_lookup(&vcache_key, hash); + + /* If found, take a reference or retry. */ + if (__predict_true(node != NULL && node->vn_vnode != NULL)) { + vp = node->vn_vnode; + mutex_enter(vp->v_interlock); + mutex_exit(&vcache.lock); + error = vget(vp, 0); + if (error == ENOENT) + goto again; + if (error == 0) + *vpp = vp; + KASSERT((error != 0) == (*vpp == NULL)); + return error; + } + + /* If another thread loads this node, wait and retry. */ + if (node != NULL) { + KASSERT(node->vn_vnode == NULL); + mutex_exit(&vcache.lock); + kpause("vcache", false, mstohz(20), NULL); + goto again; + } + mutex_exit(&vcache.lock); + + /* Allocate and initialize a new vcache / vnode pair. */ + error = vfs_busy(mp, NULL); + if (error) + return error; + new_node = pool_cache_get(vcache.pool, PR_WAITOK); + new_node->vn_vnode = NULL; + new_node->vn_key = vcache_key; + vp = vnalloc(NULL); + mutex_enter(&vcache.lock); + node = vcache_hash_lookup(&vcache_key, hash); + if (node == NULL) { + SLIST_INSERT_HEAD(&vcache.hashtab[hash & vcache.hashmask], + new_node, vn_hash); + node = new_node; + } + mutex_exit(&vcache.lock); + + /* If another thread beat us inserting this node, retry. */ + if (node != new_node) { + pool_cache_put(vcache.pool, new_node); + KASSERT(vp->v_usecount == 1); + vp->v_usecount = 0; + vnfree(vp); + vfs_unbusy(mp, false, NULL); + goto again; + } + + /* Load the fs node. Exclusive as new_node->vn_vnode is NULL. */ + error = VFS_LOADVNODE(mp, vp, key, key_len, &new_key); + if (error) { + mutex_enter(&vcache.lock); + SLIST_REMOVE(&vcache.hashtab[hash & vcache.hashmask], + new_node, vcache_node, vn_hash); + mutex_exit(&vcache.lock); + pool_cache_put(vcache.pool, new_node); + KASSERT(vp->v_usecount == 1); + vp->v_usecount = 0; + vnfree(vp); + vfs_unbusy(mp, false, NULL); + KASSERT(*vpp == NULL); + return error; + } + KASSERT(new_key != NULL); + KASSERT(memcmp(key, new_key, key_len) == 0); + KASSERT(vp->v_op != NULL); + vfs_insmntque(vp, mp); + if ((mp->mnt_iflag & IMNT_MPSAFE) != 0) + vp->v_vflag |= VV_MPSAFE; + vfs_unbusy(mp, true, NULL); + + /* Finished loading, finalize node. */ + mutex_enter(&vcache.lock); + new_node->vn_key.vk_key = new_key; + new_node->vn_vnode = vp; + mutex_exit(&vcache.lock); + *vpp = vp; + return 0; +} + +/* + * Remove a vnode / fs node pair from the cache. + */ +void +vcache_remove(struct mount *mp, const void *key, size_t key_len) +{ + uint32_t hash; + struct vcache_key vcache_key; + struct vcache_node *node; + + vcache_key.vk_mount = mp; + vcache_key.vk_key = key; + vcache_key.vk_key_len = key_len; + hash = vcache_hash(&vcache_key); + + mutex_enter(&vcache.lock); + node = vcache_hash_lookup(&vcache_key, hash); + KASSERT(node != NULL); + SLIST_REMOVE(&vcache.hashtab[hash & vcache.hashmask], + node, vcache_node, vn_hash); + mutex_exit(&vcache.lock); + pool_cache_put(vcache.pool, node); +} + /* * Update outstanding I/O count and do wakeup if requested. */ @@ -1196,6 +1423,8 @@ vfs_drainvnodes(long target) mutex_exit(&vnode_free_list_lock); + vcache_reinit(); + return 0; } Index: src/sys/modules/ffs/Makefile diff -u src/sys/modules/ffs/Makefile:1.8 src/sys/modules/ffs/Makefile:1.9 --- src/sys/modules/ffs/Makefile:1.8 Thu May 10 07:51:34 2012 +++ src/sys/modules/ffs/Makefile Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.8 2012/05/10 07:51:34 riastradh Exp $ +# $NetBSD: Makefile,v 1.9 2014/05/08 08:21:53 hannken Exp $ .include "../Makefile.inc" @@ -10,7 +10,7 @@ CPPFLAGS+= -DUFS_DIRHASH -DFFS_EI - CWARNFLAGS.clang= -Wno-conversion .PATH: ${S}/ufs/ufs -SRCS= ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_ihash.c ufs_inode.c \ +SRCS= ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_inode.c \ ufs_lookup.c ufs_quota.c ufs_quota1.c ufs_quota2.c ufs_rename.c \ ufs_vfsops.c ufs_vnops.c ufs_wapbl.c quota2_subr.c Index: src/sys/rump/fs/lib/libffs/Makefile diff -u src/sys/rump/fs/lib/libffs/Makefile:1.14 src/sys/rump/fs/lib/libffs/Makefile:1.15 --- src/sys/rump/fs/lib/libffs/Makefile:1.14 Wed May 9 00:21:17 2012 +++ src/sys/rump/fs/lib/libffs/Makefile Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.14 2012/05/09 00:21:17 riastradh Exp $ +# $NetBSD: Makefile,v 1.15 2014/05/08 08:21:53 hannken Exp $ # .PATH: ${.CURDIR}/../../../../ufs/ffs ${.CURDIR}/../../../../ufs/ufs @@ -9,7 +9,7 @@ SRCS= ffs_alloc.c ffs_appleufs.c ffs_bal ffs_snapshot.c ffs_subr.c ffs_tables.c ffs_vfsops.c ffs_vnops.c \ ffs_wapbl.c ffs_quota2.c -SRCS+= ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_ihash.c ufs_inode.c \ +SRCS+= ufs_bmap.c ufs_dirhash.c ufs_extattr.c ufs_inode.c \ ufs_lookup.c ufs_rename.c ufs_vfsops.c ufs_vnops.c ufs_wapbl.c \ ufs_quota.c ufs_quota2.c quota2_subr.c Index: src/sys/sys/mount.h diff -u src/sys/sys/mount.h:1.212 src/sys/sys/mount.h:1.213 --- src/sys/sys/mount.h:1.212 Wed Mar 5 09:37:29 2014 +++ src/sys/sys/mount.h Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: mount.h,v 1.212 2014/03/05 09:37:29 hannken Exp $ */ +/* $NetBSD: mount.h,v 1.213 2014/05/08 08:21:53 hannken Exp $ */ /* * Copyright (c) 1989, 1991, 1993 @@ -220,6 +220,8 @@ struct vfsops { int (*vfs_statvfs) (struct mount *, struct statvfs *); int (*vfs_sync) (struct mount *, int, struct kauth_cred *); int (*vfs_vget) (struct mount *, ino_t, struct vnode **); + int (*vfs_loadvnode) (struct mount *, struct vnode *, + const void *, size_t, const void **); int (*vfs_fhtovp) (struct mount *, struct fid *, struct vnode **); int (*vfs_vptofh) (struct vnode *, struct fid *, size_t *); @@ -242,6 +244,8 @@ struct vfsops { /* XXX vget is actually file system internal. */ #define VFS_VGET(MP, INO, VPP) (*(MP)->mnt_op->vfs_vget)(MP, INO, VPP) +#define VFS_LOADVNODE(MP, VP, KEY, KEY_LEN, NEW_KEY) \ + (*(MP)->mnt_op->vfs_loadvnode)(MP, VP, KEY, KEY_LEN, NEW_KEY) #define VFS_RENAMELOCK_ENTER(MP) (*(MP)->mnt_op->vfs_renamelock_enter)(MP) #define VFS_RENAMELOCK_EXIT(MP) (*(MP)->mnt_op->vfs_renamelock_exit)(MP) @@ -281,6 +285,8 @@ int fsname##_quotactl(struct mount *, st int fsname##_statvfs(struct mount *, struct statvfs *); \ int fsname##_sync(struct mount *, int, struct kauth_cred *); \ int fsname##_vget(struct mount *, ino_t, struct vnode **); \ +int fsname##_loadvnode(struct mount *, struct vnode *, \ + const void *, size_t, const void **); \ int fsname##_fhtovp(struct mount *, struct fid *, struct vnode **); \ int fsname##_vptofh(struct vnode *, struct fid *, size_t *); \ void fsname##_init(void); \ Index: src/sys/sys/param.h diff -u src/sys/sys/param.h:1.450 src/sys/sys/param.h:1.451 --- src/sys/sys/param.h:1.450 Fri Apr 4 18:11:58 2014 +++ src/sys/sys/param.h Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: param.h,v 1.450 2014/04/04 18:11:58 christos Exp $ */ +/* $NetBSD: param.h,v 1.451 2014/05/08 08:21:53 hannken Exp $ */ /*- * Copyright (c) 1982, 1986, 1989, 1993 @@ -63,7 +63,7 @@ * 2.99.9 (299000900) */ -#define __NetBSD_Version__ 699004000 /* NetBSD 6.99.40 */ +#define __NetBSD_Version__ 699004100 /* NetBSD 6.99.41 */ #define __NetBSD_Prereq__(M,m,p) (((((M) * 100000000) + \ (m) * 1000000) + (p) * 100) <= __NetBSD_Version__) Index: src/sys/sys/vnode.h diff -u src/sys/sys/vnode.h:1.246 src/sys/sys/vnode.h:1.247 --- src/sys/sys/vnode.h:1.246 Mon Mar 24 13:42:40 2014 +++ src/sys/sys/vnode.h Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: vnode.h,v 1.246 2014/03/24 13:42:40 hannken Exp $ */ +/* $NetBSD: vnode.h,v 1.247 2014/05/08 08:21:53 hannken Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -556,6 +556,8 @@ struct vnode * vnalloc(struct mount *); void vnfree(struct vnode *); void vremfree(struct vnode *); +int vcache_get(struct mount *, const void *, size_t, struct vnode **); +void vcache_remove(struct mount *, const void *, size_t); /* see vnsubr(9) */ int vn_bwrite(void *); Index: src/sys/ufs/files.ufs diff -u src/sys/ufs/files.ufs:1.34 src/sys/ufs/files.ufs:1.35 --- src/sys/ufs/files.ufs:1.34 Tue Mar 18 18:20:44 2014 +++ src/sys/ufs/files.ufs Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -# $NetBSD: files.ufs,v 1.34 2014/03/18 18:20:44 riastradh Exp $ +# $NetBSD: files.ufs,v 1.35 2014/05/08 08:21:53 hannken Exp $ deffs FFS deffs EXT2FS @@ -94,7 +94,6 @@ file ufs/mfs/mfs_miniroot.c file ufs/ufs/ufs_bmap.c ffs | mfs | ext2fs | chfs file ufs/ufs/ufs_dirhash.c (ffs | mfs | ext2fs | chfs) & ufs_dirhash file ufs/ufs/ufs_extattr.c (ffs | mfs) & ufs_extattr -file ufs/ufs/ufs_ihash.c ffs | mfs | ext2fs file ufs/ufs/ufs_inode.c ffs | mfs | ext2fs file ufs/ufs/ufs_lookup.c ffs | mfs | ext2fs | chfs file ufs/ufs/ufs_quota.c (quota | quota2) & (ffs | mfs | ext2fs | chfs) Index: src/sys/ufs/ext2fs/ext2fs_lookup.c diff -u src/sys/ufs/ext2fs/ext2fs_lookup.c:1.74 src/sys/ufs/ext2fs/ext2fs_lookup.c:1.75 --- src/sys/ufs/ext2fs/ext2fs_lookup.c:1.74 Fri Feb 7 15:29:23 2014 +++ src/sys/ufs/ext2fs/ext2fs_lookup.c Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_lookup.c,v 1.74 2014/02/07 15:29:23 hannken Exp $ */ +/* $NetBSD: ext2fs_lookup.c,v 1.75 2014/05/08 08:21:53 hannken Exp $ */ /* * Modified for NetBSD 1.2E @@ -48,7 +48,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ext2fs_lookup.c,v 1.74 2014/02/07 15:29:23 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_lookup.c,v 1.75 2014/05/08 08:21:53 hannken Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -279,8 +279,7 @@ ext2fs_lookup(void *v) int numdirpasses; /* strategy for directory search */ doff_t endsearch; /* offset to end directory search */ doff_t prevoff; /* prev entry dp->i_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 */ u_long bmask; /* block offset mask */ int namlen, error; @@ -594,11 +593,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) return (error); } @@ -606,10 +602,7 @@ found: * Write access to directory required to delete files. */ if ((error = VOP_ACCESS(vdp, VWRITE, cred)) != 0) { - if (dp->i_number == foundino) - vrele(tdp); - else - vput(tdp); + vrele(tdp); return (error); } /* @@ -623,15 +616,10 @@ 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); return (EPERM); } } - if (tdp != vdp) - VOP_UNLOCK(tdp); *vpp = tdp; return (0); } @@ -652,52 +640,20 @@ found: */ if (dp->i_number == foundino) return (EISDIR); - 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) return (error); - if (tdp != vdp) - VOP_UNLOCK(tdp); *vpp = tdp; return (0); } - /* - * 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) { - return (error); - } - *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) return (error); *vpp = tdp; @@ -707,8 +663,6 @@ found: * Insert name into cache if appropriate. */ cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags); - if (*vpp != vdp) - VOP_UNLOCK(*vpp); return 0; } Index: src/sys/ufs/ext2fs/ext2fs_vfsops.c diff -u src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.180 src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.181 --- src/sys/ufs/ext2fs/ext2fs_vfsops.c:1.180 Wed Apr 16 18:55:19 2014 +++ src/sys/ufs/ext2fs/ext2fs_vfsops.c Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ext2fs_vfsops.c,v 1.180 2014/04/16 18:55:19 maxv Exp $ */ +/* $NetBSD: ext2fs_vfsops.c,v 1.181 2014/05/08 08:21:53 hannken Exp $ */ /* * Copyright (c) 1989, 1991, 1993, 1994 @@ -60,7 +60,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.180 2014/04/16 18:55:19 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ext2fs_vfsops.c,v 1.181 2014/05/08 08:21:53 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_compat_netbsd.h" @@ -130,7 +130,8 @@ struct vfsops ext2fs_vfsops = { .vfs_quotactl = ufs_quotactl, .vfs_statvfs = ext2fs_statvfs, .vfs_sync = ext2fs_sync, - .vfs_vget = ext2fs_vget, + .vfs_vget = ufs_vget, + .vfs_loadvnode = ext2fs_loadvnode, .vfs_fhtovp = ext2fs_fhtovp, .vfs_vptofh = ext2fs_vptofh, .vfs_init = ext2fs_init, @@ -943,84 +944,52 @@ ext2fs_sync(struct mount *mp, int waitfo } /* - * Look up a EXT2FS dinode number to find its incore vnode, otherwise read it - * in from disk. If it is in core, wait for the lock bit to clear, then - * return the inode locked. Detection and handling of mount points must be - * done by the calling routine. + * Read an inode from disk and initialize this vnode / inode pair. + * Caller assures no other thread will try to load this inode. */ int -ext2fs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) +ext2fs_loadvnode(struct mount *mp, struct vnode *vp, + const void *key, size_t key_len, const void **new_key) { + ino_t ino; struct m_ext2fs *fs; struct inode *ip; struct ufsmount *ump; struct buf *bp; - struct vnode *vp; dev_t dev; int error; void *cp; + KASSERT(key_len == sizeof(ino)); + memcpy(&ino, key, key_len); ump = VFSTOUFS(mp); dev = ump->um_dev; -retry: - if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) - return (0); - - /* Allocate a new vnode/inode. */ - error = getnewvnode(VT_EXT2FS, mp, ext2fs_vnodeop_p, NULL, &vp); - if (error) { - *vpp = NULL; - return (error); - } - ip = pool_get(&ext2fs_inode_pool, PR_WAITOK); - - mutex_enter(&ufs_hashlock); - if ((*vpp = ufs_ihashget(dev, ino, 0)) != NULL) { - mutex_exit(&ufs_hashlock); - ungetnewvnode(vp); - pool_put(&ext2fs_inode_pool, ip); - goto retry; - } + fs = ump->um_e2fs; - vp->v_vflag |= VV_LOCKSWORK; + /* Read in the disk contents for the inode, copy into the inode. */ + error = bread(ump->um_devvp, EXT2_FSBTODB(fs, ino_to_fsba(fs, ino)), + (int)fs->e2fs_bsize, NOCRED, 0, &bp); + if (error) + return error; + /* Allocate and initialize inode. */ + ip = pool_get(&ext2fs_inode_pool, PR_WAITOK); memset(ip, 0, sizeof(struct inode)); + vp->v_tag = VT_EXT2FS; + vp->v_op = ext2fs_vnodeop_p; + vp->v_vflag |= VV_LOCKSWORK; vp->v_data = ip; ip->i_vnode = vp; ip->i_ump = ump; - ip->i_e2fs = fs = ump->um_e2fs; + ip->i_e2fs = fs; ip->i_dev = dev; ip->i_number = ino; ip->i_e2fs_last_lblk = 0; ip->i_e2fs_last_blk = 0; - genfs_node_init(vp, &ext2fs_genfsops); - - /* - * 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. - */ - - ufs_ihashins(ip); - mutex_exit(&ufs_hashlock); - /* Read in the disk contents for the inode, copy into the inode. */ - error = bread(ump->um_devvp, EXT2_FSBTODB(fs, ino_to_fsba(fs, ino)), - (int)fs->e2fs_bsize, NOCRED, 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(). - */ + /* Initialize genfs node. */ + genfs_node_init(vp, &ext2fs_genfsops); - vput(vp); - *vpp = NULL; - return (error); - } cp = (char *)bp->b_data + (ino_to_fsbo(fs, ino) * EXT2_DINODE_SIZE(fs)); ip->i_din.e2fs_din = pool_get(&ext2fs_dinode_pool, PR_WAITOK); e2fs_iload((struct ext2fs_dinode *)cp, ip->i_din.e2fs_din); @@ -1035,20 +1004,10 @@ retry: memset(ip->i_e2fs_blocks, 0, sizeof(ip->i_e2fs_blocks)); } - /* - * Initialize the vnode from the inode, check for aliases. - */ - - error = ext2fs_vinit(mp, ext2fs_specop_p, ext2fs_fifoop_p, &vp); - if (error) { - vput(vp); - *vpp = NULL; - return (error); - } - /* - * Finish inode initialization now that aliasing has been resolved. - */ + /* Initialize the vnode from the inode. */ + ext2fs_vinit(mp, ext2fs_specop_p, ext2fs_fifoop_p, &vp); + /* Finish inode initialization. */ ip->i_devvp = ump->um_devvp; vref(ip->i_devvp); @@ -1065,8 +1024,8 @@ retry: ip->i_flag |= IN_MODIFIED; } uvm_vnp_setsize(vp, ext2fs_size(ip)); - *vpp = vp; - return (0); + *new_key = &ip->i_number; + return 0; } /* Index: src/sys/ufs/ffs/ffs_vfsops.c diff -u src/sys/ufs/ffs/ffs_vfsops.c:1.297 src/sys/ufs/ffs/ffs_vfsops.c:1.298 --- src/sys/ufs/ffs/ffs_vfsops.c:1.297 Wed Apr 16 18:55:19 2014 +++ src/sys/ufs/ffs/ffs_vfsops.c Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ffs_vfsops.c,v 1.297 2014/04/16 18:55:19 maxv Exp $ */ +/* $NetBSD: ffs_vfsops.c,v 1.298 2014/05/08 08:21:53 hannken Exp $ */ /*- * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.297 2014/04/16 18:55:19 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ffs_vfsops.c,v 1.298 2014/05/08 08:21:53 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_ffs.h" @@ -141,7 +141,8 @@ struct vfsops ffs_vfsops = { .vfs_quotactl = ufs_quotactl, .vfs_statvfs = ffs_statvfs, .vfs_sync = ffs_sync, - .vfs_vget = ffs_vget, + .vfs_vget = ufs_vget, + .vfs_loadvnode = ffs_loadvnode, .vfs_fhtovp = ffs_fhtovp, .vfs_vptofh = ffs_vptofh, .vfs_init = ffs_init, @@ -1725,99 +1726,52 @@ ffs_sync(struct mount *mp, int waitfor, } /* - * Look up a FFS dinode number to find its incore vnode, otherwise read it - * in from disk. If it is in core, wait for the lock bit to clear, then - * return the inode locked. Detection and handling of mount points must be - * done by the calling routine. + * Read an inode from disk and initialize this vnode / inode pair. + * Caller assures no other thread will try to load this inode. */ int -ffs_vget(struct mount *mp, ino_t ino, struct vnode **vpp) +ffs_loadvnode(struct mount *mp, struct vnode *vp, + const void *key, size_t key_len, const void **new_key) { + ino_t ino; struct fs *fs; struct inode *ip; struct ufsmount *ump; struct buf *bp; - struct vnode *vp; dev_t dev; int error; + KASSERT(key_len == sizeof(ino)); + memcpy(&ino, key, key_len); ump = VFSTOUFS(mp); dev = ump->um_dev; + fs = ump->um_fs; - retry: - if ((*vpp = ufs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) - return (0); + /* Read in the disk contents for the inode. */ + error = bread(ump->um_devvp, FFS_FSBTODB(fs, ino_to_fsba(fs, ino)), + (int)fs->fs_bsize, NOCRED, 0, &bp); + if (error) + return error; - /* Allocate a new vnode/inode. */ - error = getnewvnode(VT_UFS, mp, ffs_vnodeop_p, NULL, &vp); - if (error) { - *vpp = NULL; - return (error); - } + /* Allocate and initialize inode. */ ip = pool_cache_get(ffs_inode_cache, PR_WAITOK); - - /* - * If someone beat us to it, put back the freshly allocated - * vnode/inode pair and retry. - */ - mutex_enter(&ufs_hashlock); - if (ufs_ihashget(dev, ino, 0) != NULL) { - mutex_exit(&ufs_hashlock); - ungetnewvnode(vp); - pool_cache_put(ffs_inode_cache, ip); - goto retry; - } - - vp->v_vflag |= VV_LOCKSWORK; - - /* - * XXX MFS ends up here, too, to allocate an inode. Should we - * XXX create another pool for MFS inodes? - */ - memset(ip, 0, sizeof(struct inode)); + vp->v_tag = VT_UFS; + vp->v_op = ffs_vnodeop_p; + vp->v_vflag |= VV_LOCKSWORK; vp->v_data = ip; ip->i_vnode = vp; ip->i_ump = ump; - ip->i_fs = fs = ump->um_fs; + ip->i_fs = fs; ip->i_dev = dev; ip->i_number = ino; #if defined(QUOTA) || defined(QUOTA2) ufsquota_init(ip); #endif - /* - * Initialize genfs node, we might proceed to destroy it in - * error branches. - */ + /* Initialize genfs node. */ genfs_node_init(vp, &ffs_genfsops); - /* - * 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. - */ - - ufs_ihashins(ip); - mutex_exit(&ufs_hashlock); - - /* Read in the disk contents for the inode, copy into the inode. */ - error = bread(ump->um_devvp, FFS_FSBTODB(fs, ino_to_fsba(fs, ino)), - (int)fs->fs_bsize, NOCRED, 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); - } if (ip->i_ump->um_fstype == UFS1) ip->i_din.ffs1_din = pool_cache_get(ffs_dinode1_cache, PR_WAITOK); @@ -1827,17 +1781,10 @@ ffs_vget(struct mount *mp, ino_t ino, st ffs_load_inode(bp, ip, fs, ino); brelse(bp, 0); - /* - * Initialize the vnode from the inode, check for aliases. - * Note that the underlying vnode may have changed. - */ - + /* Initialize the vnode from the inode. */ ufs_vinit(mp, ffs_specop_p, ffs_fifoop_p, &vp); - /* - * Finish inode initialization now that aliasing has been resolved. - */ - + /* Finish inode initialization. */ ip->i_devvp = ump->um_devvp; vref(ip->i_devvp); @@ -1851,8 +1798,8 @@ ffs_vget(struct mount *mp, ino_t ino, st ip->i_gid = ip->i_ffs1_ogid; /* XXX */ } /* XXX */ uvm_vnp_setsize(vp, ip->i_size); - *vpp = vp; - return (0); + *new_key = &ip->i_number; + return 0; } /* Index: src/sys/ufs/mfs/mfs_vfsops.c diff -u src/sys/ufs/mfs/mfs_vfsops.c:1.107 src/sys/ufs/mfs/mfs_vfsops.c:1.108 --- src/sys/ufs/mfs/mfs_vfsops.c:1.107 Wed Apr 16 18:55:19 2014 +++ src/sys/ufs/mfs/mfs_vfsops.c Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: mfs_vfsops.c,v 1.107 2014/04/16 18:55:19 maxv Exp $ */ +/* $NetBSD: mfs_vfsops.c,v 1.108 2014/05/08 08:21:53 hannken Exp $ */ /* * Copyright (c) 1989, 1990, 1993, 1994 @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mfs_vfsops.c,v 1.107 2014/04/16 18:55:19 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mfs_vfsops.c,v 1.108 2014/05/08 08:21:53 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_compat_netbsd.h" @@ -99,7 +99,8 @@ struct vfsops mfs_vfsops = { .vfs_quotactl = ufs_quotactl, .vfs_statvfs = mfs_statvfs, .vfs_sync = ffs_sync, - .vfs_vget = ffs_vget, + .vfs_vget = ufs_vget, + .vfs_loadvnode = ffs_loadvnode, .vfs_fhtovp = ffs_fhtovp, .vfs_vptofh = ffs_vptofh, .vfs_init = mfs_init, Index: src/sys/ufs/ufs/inode.h diff -u src/sys/ufs/ufs/inode.h:1.65 src/sys/ufs/ufs/inode.h:1.66 --- src/sys/ufs/ufs/inode.h:1.65 Sun Jun 9 17:55:46 2013 +++ src/sys/ufs/ufs/inode.h Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: inode.h,v 1.65 2013/06/09 17:55:46 dholland Exp $ */ +/* $NetBSD: inode.h,v 1.66 2014/05/08 08:21:53 hannken Exp $ */ /* * Copyright (c) 1982, 1989, 1993 @@ -93,7 +93,6 @@ struct lfs_inode_ext; */ struct inode { struct genfs_node i_gnode; - LIST_ENTRY(inode) i_hash;/* Hash chain. */ TAILQ_ENTRY(inode) i_nextsnap; /* snapshot file list. */ struct vnode *i_vnode; /* Vnode associated with this inode. */ struct ufsmount *i_ump; /* Mount point associated with this inode. */ Index: src/sys/ufs/ufs/ufs_extern.h diff -u src/sys/ufs/ufs/ufs_extern.h:1.73 src/sys/ufs/ufs/ufs_extern.h:1.74 --- src/sys/ufs/ufs/ufs_extern.h:1.73 Sun Jun 16 13:33:30 2013 +++ src/sys/ufs/ufs/ufs_extern.h Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_extern.h,v 1.73 2013/06/16 13:33:30 hannken Exp $ */ +/* $NetBSD: ufs_extern.h,v 1.74 2014/05/08 08:21:53 hannken Exp $ */ /*- * Copyright (c) 1991, 1993, 1994 @@ -108,15 +108,6 @@ int ufs_bmaparray(struct vnode *, daddr_ int *, int *, ufs_issequential_callback_t); int ufs_getlbns(struct vnode *, daddr_t, struct indir *, int *); -/* ufs_ihash.c */ -void ufs_ihashinit(void); -void ufs_ihashreinit(void); -void ufs_ihashdone(void); -struct vnode *ufs_ihashlookup(dev_t, ino_t); -struct vnode *ufs_ihashget(dev_t, ino_t, int); -void ufs_ihashins(struct inode *); -void ufs_ihashrem(struct inode *); - /* ufs_inode.c */ int ufs_reclaim(struct vnode *); int ufs_balloc_range(struct vnode *, off_t, off_t, kauth_cred_t, int); @@ -188,6 +179,7 @@ void ufs_reinit(void); void ufs_done(void); int ufs_start(struct mount *, int); int ufs_root(struct mount *, struct vnode **); +int ufs_vget(struct mount *, ino_t, struct vnode **); int ufs_quotactl(struct mount *, struct quotactl_args *); int ufs_fhtovp(struct mount *, struct ufid *, struct vnode **); @@ -201,7 +193,6 @@ void ufs_gop_markupdate(struct vnode *, __END_DECLS -extern kmutex_t ufs_ihash_lock; extern kmutex_t ufs_hashlock; #endif /* !_UFS_UFS_EXTERN_H_ */ Index: src/sys/ufs/ufs/ufs_inode.c diff -u src/sys/ufs/ufs/ufs_inode.c:1.89 src/sys/ufs/ufs/ufs_inode.c:1.90 --- src/sys/ufs/ufs/ufs_inode.c:1.89 Tue Jan 22 09:39:18 2013 +++ src/sys/ufs/ufs/ufs_inode.c Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_inode.c,v 1.89 2013/01/22 09:39:18 dholland Exp $ */ +/* $NetBSD: ufs_inode.c,v 1.90 2014/05/08 08:21:53 hannken Exp $ */ /* * Copyright (c) 1991, 1993 @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.89 2013/01/22 09:39:18 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ufs_inode.c,v 1.90 2014/05/08 08:21:53 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_ffs.h" @@ -191,9 +191,9 @@ ufs_reclaim(struct vnode *vp) UFS_UPDATE(vp, NULL, NULL, UPDATE_CLOSE); /* - * Remove the inode from its hash chain. + * Remove the inode from the vnode cache. */ - ufs_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/ufs/ufs_lookup.c diff -u src/sys/ufs/ufs/ufs_lookup.c:1.129 src/sys/ufs/ufs/ufs_lookup.c:1.130 --- src/sys/ufs/ufs/ufs_lookup.c:1.129 Fri Feb 7 15:29:23 2014 +++ src/sys/ufs/ufs/ufs_lookup.c Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_lookup.c,v 1.129 2014/02/07 15:29:23 hannken Exp $ */ +/* $NetBSD: ufs_lookup.c,v 1.130 2014/05/08 08:21:53 hannken Exp $ */ /* * Copyright (c) 1989, 1993 @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ufs_lookup.c,v 1.129 2014/02/07 15:29:23 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ufs_lookup.c,v 1.130 2014/05/08 08:21:53 hannken Exp $"); #ifdef _KERNEL_OPT #include "opt_ffs.h" @@ -137,8 +137,7 @@ ufs_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/ufs/ufs_vfsops.c diff -u src/sys/ufs/ufs/ufs_vfsops.c:1.52 src/sys/ufs/ufs/ufs_vfsops.c:1.53 --- src/sys/ufs/ufs/ufs_vfsops.c:1.52 Tue Jan 22 09:39:18 2013 +++ src/sys/ufs/ufs/ufs_vfsops.c Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ufs_vfsops.c,v 1.52 2013/01/22 09:39:18 dholland Exp $ */ +/* $NetBSD: ufs_vfsops.c,v 1.53 2014/05/08 08:21:53 hannken Exp $ */ /* * Copyright (c) 1991, 1993, 1994 @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ufs_vfsops.c,v 1.52 2013/01/22 09:39:18 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ufs_vfsops.c,v 1.53 2014/05/08 08:21:53 hannken Exp $"); #if defined(_KERNEL_OPT) #include "opt_ffs.h" @@ -97,6 +97,26 @@ ufs_root(struct mount *mp, struct vnode } /* + * Look up and return a vnode/inode pair by inode number. + */ +int +ufs_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; +} + +/* * Do operations associated with quotas */ int @@ -245,7 +265,6 @@ ufs_init(void) ufs_direct_cache = pool_cache_init(sizeof(struct direct), 0, 0, 0, "ufsdir", NULL, IPL_NONE, NULL, NULL, NULL); - ufs_ihashinit(); #if defined(QUOTA) || defined(QUOTA2) dqinit(); #endif @@ -260,7 +279,6 @@ ufs_init(void) void ufs_reinit(void) { - ufs_ihashreinit(); #if defined(QUOTA) || defined(QUOTA2) dqreinit(); #endif @@ -275,7 +293,6 @@ ufs_done(void) if (--ufs_initcount > 0) return; - ufs_ihashdone(); #if defined(QUOTA) || defined(QUOTA2) dqdone(); #endif Index: src/usr.bin/vmstat/vmstat.c diff -u src/usr.bin/vmstat/vmstat.c:1.191 src/usr.bin/vmstat/vmstat.c:1.192 --- src/usr.bin/vmstat/vmstat.c:1.191 Wed Feb 19 20:42:14 2014 +++ src/usr.bin/vmstat/vmstat.c Thu May 8 08:21:53 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: vmstat.c,v 1.191 2014/02/19 20:42:14 dsl Exp $ */ +/* $NetBSD: vmstat.c,v 1.192 2014/05/08 08:21:53 hannken Exp $ */ /*- * Copyright (c) 1998, 2000, 2001, 2007 The NetBSD Foundation, Inc. @@ -70,7 +70,7 @@ __COPYRIGHT("@(#) Copyright (c) 1980, 19 #if 0 static char sccsid[] = "@(#)vmstat.c 8.2 (Berkeley) 3/1/95"; #else -__RCSID("$NetBSD: vmstat.c,v 1.191 2014/02/19 20:42:14 dsl Exp $"); +__RCSID("$NetBSD: vmstat.c,v 1.192 2014/05/08 08:21:53 hannken Exp $"); #endif #endif /* not lint */ @@ -1470,10 +1470,6 @@ struct kernel_hash { X_BUFHASH, X_BUFHASHTBL, HASH_LIST, offsetof(struct buf, b_hash) }, { - "inode cache (ihash)", - X_IHASH, X_IHASHTBL, - HASH_LIST, offsetof(struct inode, i_hash) - }, { "ipv4 address -> interface hash", X_IFADDRHASH, X_IFADDRHASHTBL, HASH_LIST, offsetof(struct in_ifaddr, ia_hash),