pseudofs_vncache.c revision 75295
175295Sdes/*-
275295Sdes * Copyright (c) 2001 Dag-Erling Co�dan Sm�rgrav
375295Sdes * All rights reserved.
475295Sdes *
575295Sdes * Redistribution and use in source and binary forms, with or without
675295Sdes * modification, are permitted provided that the following conditions
775295Sdes * are met:
875295Sdes * 1. Redistributions of source code must retain the above copyright
975295Sdes *    notice, this list of conditions and the following disclaimer
1075295Sdes *    in this position and unchanged.
1175295Sdes * 2. Redistributions in binary form must reproduce the above copyright
1275295Sdes *    notice, this list of conditions and the following disclaimer in the
1375295Sdes *    documentation and/or other materials provided with the distribution.
1475295Sdes * 3. The name of the author may not be used to endorse or promote products
1575295Sdes *    derived from this software without specific prior written permission.
1675295Sdes *
1775295Sdes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1875295Sdes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1975295Sdes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2075295Sdes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2175295Sdes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2275295Sdes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2375295Sdes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2475295Sdes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2575295Sdes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2675295Sdes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2775295Sdes *
2875295Sdes *      $FreeBSD: head/sys/fs/pseudofs/pseudofs_vncache.c 75295 2001-04-07 19:51:12Z des $
2975295Sdes */
3075295Sdes
3175295Sdes#include <sys/param.h>
3275295Sdes#include <sys/kernel.h>
3375295Sdes#include <sys/systm.h>
3475295Sdes#include <sys/malloc.h>
3575295Sdes#include <sys/mount.h>
3675295Sdes#include <sys/sbuf.h>
3775295Sdes#include <sys/sysctl.h>
3875295Sdes#include <sys/vnode.h>
3975295Sdes
4075295Sdes#include <fs/pseudofs/pseudofs.h>
4175295Sdes#include <fs/pseudofs/pseudofs_internal.h>
4275295Sdes
4375295Sdesstatic MALLOC_DEFINE(M_PFSVNCACHE, "pseudofs_vncache", "pseudofs vnode cache");
4475295Sdes
4575295Sdesstatic struct mtx pfs_vncache_mutex;
4675295Sdes
4775295Sdesstruct pfs_vnode {
4875295Sdes	struct vnode		*pv_vnode;
4975295Sdes	struct pfs_vnode	*pv_next;
5075295Sdes} *pfs_vncache;
5175295Sdes
5275295SdesSYSCTL_NODE(_vfs_pfs, OID_AUTO, vncache, CTLFLAG_RW, 0,
5375295Sdes    "pseudofs vnode cache");
5475295Sdes
5575295Sdesstatic int pfs_vncache_hits;
5675295SdesSYSCTL_INT(_vfs_pfs_vncache, OID_AUTO, hits, CTLFLAG_RD, &pfs_vncache_hits, 0,
5775295Sdes    "number of cache hits since initialization");
5875295Sdes
5975295Sdesstatic int pfs_vncache_misses;
6075295SdesSYSCTL_INT(_vfs_pfs_vncache, OID_AUTO, misses, CTLFLAG_RD, &pfs_vncache_misses, 0,
6175295Sdes    "number of cache misses since initialization");
6275295Sdes
6375295Sdesextern vop_t **pfs_vnodeop_p;
6475295Sdes
6575295Sdes/*
6675295Sdes * Initialize vnode cache
6775295Sdes */
6875295Sdesvoid
6975295Sdespfs_vncache_load(void)
7075295Sdes{
7175295Sdes	mtx_init(&pfs_vncache_mutex, "pseudofs_vncache", MTX_DEF);
7275295Sdes}
7375295Sdes
7475295Sdes/*
7575295Sdes * Tear down vnode cache
7675295Sdes */
7775295Sdesvoid
7875295Sdespfs_vncache_unload(void)
7975295Sdes{
8075295Sdes	mtx_destroy(&pfs_vncache_mutex);
8175295Sdes}
8275295Sdes
8375295Sdes/*
8475295Sdes * Allocate a vnode
8575295Sdes */
8675295Sdesint
8775295Sdespfs_vncache_alloc(struct mount *mp, struct vnode **vpp, struct pfs_node *pn)
8875295Sdes{
8975295Sdes	struct pfs_vnode *pv;
9075295Sdes	int error;
9175295Sdes
9275295Sdes	mtx_lock(&pfs_vncache_mutex);
9375295Sdes
9475295Sdes	/* see if the vnode is in the cache */
9575295Sdes	for (pv = pfs_vncache; pv; pv = pv->pv_next)
9675295Sdes		if (pv->pv_vnode->v_data == pn)
9775295Sdes			if (vget(pv->pv_vnode, 0, curproc) == 0) {
9875295Sdes				++pfs_vncache_hits;
9975295Sdes				*vpp = pv->pv_vnode;
10075295Sdes				mtx_unlock(&pfs_vncache_mutex);
10175295Sdes				return (0);
10275295Sdes			}
10375295Sdes	++pfs_vncache_misses;
10475295Sdes
10575295Sdes	/* nope, get a new one */
10675295Sdes	MALLOC(pv, struct pfs_vnode *, sizeof *pv, M_PFSVNCACHE, M_WAITOK);
10775295Sdes	error = getnewvnode(VT_PSEUDOFS, mp, pfs_vnodeop_p, vpp);
10875295Sdes	if (error) {
10975295Sdes		mtx_unlock(&pfs_vncache_mutex);
11075295Sdes		return (error);
11175295Sdes	}
11275295Sdes	(*vpp)->v_data = pn;
11375295Sdes	switch (pn->pn_type) {
11475295Sdes	case pfstype_root:
11575295Sdes		(*vpp)->v_flag = VROOT;
11675295Sdes#if 0
11775295Sdes		printf("root vnode allocated\n");
11875295Sdes#endif
11975295Sdes	case pfstype_dir:
12075295Sdes	case pfstype_this:
12175295Sdes	case pfstype_parent:
12275295Sdes		(*vpp)->v_type = VDIR;
12375295Sdes		break;
12475295Sdes	case pfstype_file:
12575295Sdes		(*vpp)->v_type = VREG;
12675295Sdes		break;
12775295Sdes	case pfstype_symlink:
12875295Sdes		(*vpp)->v_type = VLNK;
12975295Sdes		break;
13075295Sdes	default:
13175295Sdes		panic("%s has unexpected type: %d", pn->pn_name, pn->pn_type);
13275295Sdes	}
13375295Sdes	pv->pv_vnode = *vpp;
13475295Sdes	pv->pv_next = pfs_vncache;
13575295Sdes	pfs_vncache = pv;
13675295Sdes	mtx_unlock(&pfs_vncache_mutex);
13775295Sdes	return (0);
13875295Sdes}
13975295Sdes
14075295Sdes/*
14175295Sdes * Free a vnode
14275295Sdes */
14375295Sdesint
14475295Sdespfs_vncache_free(struct vnode *vp)
14575295Sdes{
14675295Sdes	struct pfs_vnode *prev, *pv;
14775295Sdes
14875295Sdes	mtx_lock(&pfs_vncache_mutex);
14975295Sdes	for (prev = NULL, pv = pfs_vncache; pv; prev = pv, pv = pv->pv_next)
15075295Sdes		if (pv->pv_vnode == vp)
15175295Sdes			break;
15275295Sdes	if (!pv)
15375295Sdes		printf("pfs_vncache_free(): not in cache\n"); /* it should be! */
15475295Sdes#if 0
15575295Sdes	if (vp->v_data == ((struct pfs_info *)vp->v_mount->mnt_data)->pi_root)
15675295Sdes		printf("root vnode reclaimed\n");
15775295Sdes#endif
15875295Sdes	vp->v_data = NULL;
15975295Sdes	if (pv) {
16075295Sdes		if (prev)
16175295Sdes			prev->pv_next = pv->pv_next;
16275295Sdes		else
16375295Sdes			pfs_vncache = pv->pv_next;
16475295Sdes		FREE(pv, M_PFSVNCACHE);
16575295Sdes	}
16675295Sdes	mtx_unlock(&pfs_vncache_mutex);
16775295Sdes	return (0);
16875295Sdes}
169