Change chfs from hashlist to vcache.

This commit is contained in:
hannken 2015-01-11 17:29:57 +00:00
parent bf7db7c8e6
commit ba1d531e8e
8 changed files with 62 additions and 295 deletions

View File

@ -1,4 +1,4 @@
# $NetBSD: Makefile,v 1.3 2012/04/12 15:31:01 ttoth Exp $
# $NetBSD: Makefile,v 1.4 2015/01/11 17:29:57 hannken Exp $
.include "../Makefile.inc"
@ -7,7 +7,7 @@
CPPFLAGS+= -DDIAGNOSTIC -DDEBUG -DLOCKDEBUG
KMOD= chfs
SRCS= ebh.c chfs_wbuf.c chfs_vnode_cache.c chfs_ihash.c
SRCS= ebh.c chfs_wbuf.c chfs_vnode_cache.c
SRCS+= chfs_gc.c
SRCS+= chfs_vnode.c chfs_erase.c chfs_write.c chfs_readinode.c
SRCS+= chfs_build.c chfs_scan.c chfs_nodeops.c chfs_malloc.c

View File

@ -1,4 +1,4 @@
/* $NetBSD: chfs.h,v 1.8 2012/10/19 12:44:39 ttoth Exp $ */
/* $NetBSD: chfs.h,v 1.9 2015/01/11 17:29:57 hannken Exp $ */
/*-
* Copyright (c) 2010 Department of Software Engineering,
@ -571,18 +571,6 @@ int chfs_read_data(struct chfs_mount*, struct vnode *,
/* chfs_erase.c */
int chfs_remap_leb(struct chfs_mount *);
/* chfs_ihash.c */
void chfs_ihashinit(void);
void chfs_ihashreinit(void);
void chfs_ihashdone(void);
struct vnode *chfs_ihashlookup(dev_t, ino_t);
struct vnode *chfs_ihashget(dev_t, ino_t, int);
void chfs_ihashins(struct chfs_inode *);
void chfs_ihashrem(struct chfs_inode *);
extern kmutex_t chfs_ihash_lock;
extern kmutex_t chfs_hashlock;
/* chfs_gc.c */
void chfs_gc_trigger(struct chfs_mount *);
int chfs_gc_thread_should_wake(struct chfs_mount *);

View File

@ -1,214 +0,0 @@
/* $NetBSD: chfs_ihash.c,v 1.3 2014/02/27 16:51:39 hannken Exp $ */
/*-
* Copyright (c) 2010 Department of Software Engineering,
* University of Szeged, Hungary
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
* by the Department of Software Engineering, University of Szeged, Hungary
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include "chfs.h"
/*
* Structures associated with inode cacheing.
*/
static LIST_HEAD(ihashhead, chfs_inode) *chfs_ihashtbl;
static u_long chfs_ihash; /* size of hash table - 1 */
#define INOHASH(device, inum) (((device) + (inum)) & chfs_ihash)
kmutex_t chfs_ihash_lock;
kmutex_t chfs_hashlock;
/*
* Initialize inode hash table.
*/
void
chfs_ihashinit(void)
{
dbg("initing\n");
mutex_init(&chfs_hashlock, MUTEX_DEFAULT, IPL_NONE);
mutex_init(&chfs_ihash_lock, MUTEX_DEFAULT, IPL_NONE);
chfs_ihashtbl = hashinit(desiredvnodes,
HASH_LIST, true, &chfs_ihash);
}
/*
* Reinitialize inode hash table.
*/
void
chfs_ihashreinit(void)
{
struct chfs_inode *ip;
struct ihashhead *oldhash, *hash;
u_long oldmask, mask, val;
int i;
dbg("reiniting\n");
hash = hashinit(desiredvnodes, HASH_LIST, true, &mask);
mutex_enter(&chfs_ihash_lock);
oldhash = chfs_ihashtbl;
oldmask = chfs_ihash;
chfs_ihashtbl = hash;
chfs_ihash = mask;
for (i = 0; i <= oldmask; i++) {
while ((ip = LIST_FIRST(&oldhash[i])) != NULL) {
LIST_REMOVE(ip, hash_entry);
val = INOHASH(ip->dev, ip->ino);
LIST_INSERT_HEAD(&hash[val], ip, hash_entry);
}
}
mutex_exit(&chfs_ihash_lock);
hashdone(oldhash, HASH_LIST, oldmask);
}
/*
* Free inode hash table.
*/
void
chfs_ihashdone(void)
{
dbg("destroying\n");
hashdone(chfs_ihashtbl, HASH_LIST, chfs_ihash);
mutex_destroy(&chfs_hashlock);
mutex_destroy(&chfs_ihash_lock);
}
/*
* Use the device/inum pair to find the incore inode, and return a pointer
* to it. If it is in core, return it, even if it is locked.
*/
struct vnode *
chfs_ihashlookup(dev_t dev, ino_t inum)
{
struct chfs_inode *ip;
struct ihashhead *ipp;
dbg("dev: %ju, inum: %ju\n", (uintmax_t )dev, (uintmax_t )inum);
KASSERT(mutex_owned(&chfs_ihash_lock));
ipp = &chfs_ihashtbl[INOHASH(dev, inum)];
LIST_FOREACH(ip, ipp, hash_entry) {
if (inum == ip->ino && dev == ip->dev) {
break;
}
}
if (ip) {
return (ITOV(ip));
}
return (NULLVP);
}
/*
* Use the device/inum pair to find the incore inode, and return a pointer
* to it. If it is in core, but locked, wait for it.
*/
struct vnode *
chfs_ihashget(dev_t dev, ino_t inum, int flags)
{
struct ihashhead *ipp;
struct chfs_inode *ip;
struct vnode *vp;
dbg("search for ino\n");
loop:
mutex_enter(&chfs_ihash_lock);
ipp = &chfs_ihashtbl[INOHASH(dev, inum)];
dbg("ipp: %p, chfs_ihashtbl: %p, ihash: %lu\n",
ipp, chfs_ihashtbl, chfs_ihash);
LIST_FOREACH(ip, ipp, hash_entry) {
dbg("ip: %p\n", ip);
if (inum == ip->ino && dev == ip->dev) {
vp = ITOV(ip);
KASSERT(vp != NULL);
if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE) {
mutex_exit(&chfs_ihash_lock);
goto loop;
}
/*
if (VOP_ISLOCKED(vp))
dbg("locked\n");
else
dbg("isn't locked\n");
*/
if (flags == 0) {
mutex_exit(&chfs_ihash_lock);
} else {
mutex_enter(vp->v_interlock);
mutex_exit(&chfs_ihash_lock);
if (vget(vp, flags)) {
goto loop;
}
}
return (vp);
}
}
mutex_exit(&chfs_ihash_lock);
return (NULL);
}
/*
* Insert the inode into the hash table, and return it locked.
*/
void
chfs_ihashins(struct chfs_inode *ip)
{
struct ihashhead *ipp;
int error __diagused;
dbg("ip: %p\n", ip);
KASSERT(mutex_owned(&chfs_hashlock));
/* lock the inode, then put it on the appropriate hash list */
error = VOP_LOCK(ITOV(ip), LK_EXCLUSIVE);
KASSERT(error == 0);
mutex_enter(&chfs_ihash_lock);
ipp = &chfs_ihashtbl[INOHASH(ip->dev, ip->ino)];
LIST_INSERT_HEAD(ipp, ip, hash_entry);
mutex_exit(&chfs_ihash_lock);
}
/*
* Remove the inode from the hash table.
*/
void
chfs_ihashrem(struct chfs_inode *ip)
{
dbg("ip: %p\n", ip);
mutex_enter(&chfs_ihash_lock);
LIST_REMOVE(ip, hash_entry);
mutex_exit(&chfs_ihash_lock);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: chfs_inode.h,v 1.9 2014/05/26 19:16:39 dholland Exp $ */
/* $NetBSD: chfs_inode.h,v 1.10 2015/01/11 17:29:57 hannken Exp $ */
/*-
* Copyright (c) 2010 Department of Software Engineering,
@ -77,8 +77,6 @@ struct chfs_inode
struct genfs_node gnode;
kmutex_t inode_lock; /* lock the fields of chfs_inode */
LIST_ENTRY(chfs_inode) hash_entry; /* hash chain */
struct ufsmount *ump; /* ufs mount - TODO we should remove it */
struct chfs_mount *chmp; /* chfs mount point - TODO we should remove it */

View File

@ -1,4 +1,4 @@
/* $NetBSD: chfs_vfsops.c,v 1.14 2014/11/09 18:23:28 maxv Exp $ */
/* $NetBSD: chfs_vfsops.c,v 1.15 2015/01/11 17:29:57 hannken Exp $ */
/*-
* Copyright (c) 2010 Department of Software Engineering,
@ -70,6 +70,8 @@ MODULE(MODULE_CLASS_VFS, chfs, "flash");
static int chfs_mount(struct mount *, const char *, void *, size_t *);
static int chfs_unmount(struct mount *, int);
static int chfs_root(struct mount *, struct vnode **);
static int chfs_loadvnode(struct mount *, struct vnode *,
const void *, size_t, const void **);
static int chfs_vget(struct mount *, ino_t, struct vnode **);
static int chfs_fhtovp(struct mount *, struct fid *, struct vnode **);
static int chfs_vptofh(struct vnode *, struct fid *, size_t *);
@ -447,71 +449,49 @@ chfs_root(struct mount *mp, struct vnode **vpp)
extern rb_tree_ops_t frag_rbtree_ops;
static int
chfs_vget(struct mount *mp, ino_t ino, struct vnode **vpp)
chfs_loadvnode(struct mount *mp, struct vnode *vp,
const void *key, size_t key_len, const void **new_key)
{
struct chfs_mount *chmp;
struct chfs_inode *ip;
struct ufsmount *ump;
struct vnode *vp;
dev_t dev;
int error;
struct chfs_vnode_cache* chvc = NULL;
struct chfs_node_ref* nref = NULL;
struct buf *bp;
ino_t ino;
KASSERT(key_len == sizeof(ino));
memcpy(&ino, key, key_len);
dbg("vget() | ino: %llu\n", (unsigned long long)ino);
ump = VFSTOUFS(mp);
dev = ump->um_dev;
retry:
if (!vpp) {
vpp = kmem_alloc(sizeof(struct vnode*), KM_SLEEP);
}
/* Get node from inode hash. */
if ((*vpp = chfs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) {
return 0;
}
/* Allocate a new vnode/inode. */
if ((error = getnewvnode(VT_CHFS,
mp, chfs_vnodeop_p, NULL, &vp)) != 0) {
*vpp = NULL;
return (error);
}
ip = pool_get(&chfs_inode_pool, PR_WAITOK);
mutex_enter(&chfs_hashlock);
if ((*vpp = chfs_ihashget(dev, ino, LK_EXCLUSIVE)) != NULL) {
mutex_exit(&chfs_hashlock);
ungetnewvnode(vp);
pool_put(&chfs_inode_pool, ip);
goto retry;
}
vp->v_vflag |= VV_LOCKSWORK;
/* Initialize vnode/inode. */
memset(ip, 0, sizeof(*ip));
vp->v_data = ip;
ip->vp = vp;
ip->ch_type = VTTOCHT(vp->v_type);
ip->ump = ump;
ip->chmp = chmp = ump->um_chfs;
ip->dev = dev;
ip->ino = ino;
vp->v_mount = mp;
genfs_node_init(vp, &chfs_genfsops);
rb_tree_init(&ip->fragtree, &frag_rbtree_ops);
chfs_ihashins(ip);
mutex_exit(&chfs_hashlock);
vp->v_tag = VT_CHFS;
vp->v_op = chfs_vnodeop_p;
vp->v_vflag |= VV_LOCKSWORK;
if (ino == CHFS_ROOTINO)
vp->v_vflag |= VV_ROOT;
vp->v_data = ip;
/* Set root inode. */
if (ino == CHFS_ROOTINO) {
dbg("SETROOT\n");
vp->v_vflag |= VV_ROOT;
vp->v_type = VDIR;
ip->ch_type = CHT_DIR;
ip->mode = IFMT | IEXEC | IWRITE | IREAD;
@ -553,6 +533,7 @@ retry:
mutex_enter(&chmp->chm_lock_mountfields);
/* Initialize type specific things. */
error = 0;
switch (ip->ch_type) {
case CHT_DIR:
/* Read every dirent. */
@ -571,24 +552,14 @@ retry:
dbg("read_inode_internal | ino: %llu\n",
(unsigned long long)ip->ino);
error = chfs_read_inode(chmp, ip);
if (error) {
vput(vp);
*vpp = NULL;
mutex_exit(&chmp->chm_lock_mountfields);
return (error);
}
break;
case CHT_LNK:
/* Collect data. */
dbg("read_inode_internal | ino: %llu\n",
(unsigned long long)ip->ino);
error = chfs_read_inode_internal(chmp, ip);
if (error) {
vput(vp);
*vpp = NULL;
mutex_exit(&chmp->chm_lock_mountfields);
return (error);
}
if (error)
break;
/* Set link. */
dbg("size: %llu\n", (unsigned long long)ip->size);
@ -615,12 +586,8 @@ retry:
dbg("read_inode_internal | ino: %llu\n",
(unsigned long long)ip->ino);
error = chfs_read_inode_internal(chmp, ip);
if (error) {
vput(vp);
*vpp = NULL;
mutex_exit(&chmp->chm_lock_mountfields);
return (error);
}
if (error)
break;
/* Set device. */
bp = getiobuf(vp, true);
@ -648,21 +615,52 @@ retry:
break;
}
mutex_exit(&chmp->chm_lock_mountfields);
if (error) {
vp->v_data = NULL;
KASSERT(TAILQ_FIRST(&ip->dents) == NULL);
pool_put(&chfs_inode_pool, ip);
return error;
}
}
/* Finish inode initalization. */
ip->ch_type = VTTOCHT(vp->v_type);
ip->devvp = ump->um_devvp;
vref(ip->devvp);
genfs_node_init(vp, &chfs_genfsops);
uvm_vnp_setsize(vp, ip->size);
*vpp = vp;
*new_key = &ip->ino;
return 0;
}
/* --------------------------------------------------------------------- */
static int
chfs_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;
}
/* --------------------------------------------------------------------- */
static int
chfs_fhtovp(struct mount *mp, struct fid *fhp, struct vnode **vpp)
{
@ -735,7 +733,6 @@ chfs_init(void)
{
/* Initialize pools and inode hash. */
chfs_alloc_pool_caches();
chfs_ihashinit();
pool_init(&chfs_inode_pool, sizeof(struct chfs_inode), 0, 0, 0,
"chfsinopl", &pool_allocator_nointr, IPL_NONE);
ufs_init();
@ -746,7 +743,6 @@ chfs_init(void)
static void
chfs_reinit(void)
{
chfs_ihashreinit();
ufs_reinit();
}
@ -756,7 +752,6 @@ static void
chfs_done(void)
{
ufs_done();
chfs_ihashdone();
pool_destroy(&chfs_inode_pool);
chfs_destroy_pool_caches();
}
@ -798,6 +793,7 @@ struct vfsops chfs_vfsops = {
.vfs_statvfs = chfs_statvfs,
.vfs_sync = chfs_sync,
.vfs_vget = chfs_vget,
.vfs_loadvnode = chfs_loadvnode,
.vfs_fhtovp = chfs_fhtovp,
.vfs_vptofh = chfs_vptofh,
.vfs_init = chfs_init,

View File

@ -1,4 +1,4 @@
/* $NetBSD: chfs_vnode.c,v 1.13 2015/01/11 17:28:22 hannken Exp $ */
/* $NetBSD: chfs_vnode.c,v 1.14 2015/01/11 17:29:57 hannken Exp $ */
/*-
* Copyright (c) 2010 Department of Software Engineering,
@ -244,7 +244,7 @@ chfs_makeinode(int mode, struct vnode *dvp, struct vnode **vpp,
ip->target = NULL;
ip->mode = mode;
vp->v_type = type; /* Rest init'd in getnewvnode(). */
vp->v_type = type; /* Rest init'd in chfs_loadvnode(). */
ip->ch_type = VTTOCHT(vp->v_type);
/* authorize setting SGID if needed */

View File

@ -1,4 +1,4 @@
/* $NetBSD: chfs_vnops.c,v 1.23 2015/01/11 17:27:54 hannken Exp $ */
/* $NetBSD: chfs_vnops.c,v 1.24 2015/01/11 17:29:57 hannken Exp $ */
/*-
* Copyright (c) 2010 Department of Software Engineering,
@ -1514,11 +1514,11 @@ chfs_reclaim(void *v)
}
cache_purge(vp);
vcache_remove(vp->v_mount, &ip->ino, sizeof(ip->ino));
if (ip->devvp) {
vrele(ip->devvp);
ip->devvp = 0;
}
chfs_ihashrem(ip);
genfs_node_destroy(vp);
pool_put(&chfs_inode_pool, vp->v_data);

View File

@ -1,4 +1,4 @@
# $NetBSD: files.ufs,v 1.38 2014/11/16 16:01:39 manu Exp $
# $NetBSD: files.ufs,v 1.39 2015/01/11 17:29:57 hannken Exp $
deffs FFS
deffs EXT2FS
@ -28,7 +28,6 @@ file ufs/ext2fs/ext2fs_vnops.c ext2fs
define chfs: vfs, ffs
file ufs/chfs/ebh.c chfs
file ufs/chfs/chfs_ihash.c chfs
file ufs/chfs/chfs_scan.c chfs
file ufs/chfs/chfs_write.c chfs
file ufs/chfs/chfs_vnode_cache.c chfs