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),