1251877Speter/* $NetBSD: vnode.c,v 1.10 2009/08/06 00:51:55 pooka Exp $ */
2251877Speter/*-
3251877Speter * Copyright (c) 2003 The NetBSD Foundation, Inc.
4251877Speter * All rights reserved.
5251877Speter *
6251877Speter * This code is derived from software contributed to The NetBSD Foundation
7251877Speter * by Konrad E. Schroder <perseant@hhhh.org>.
8251877Speter *
9251877Speter * Redistribution and use in source and binary forms, with or without
10251877Speter * modification, are permitted provided that the following conditions
11251877Speter * are met:
12251877Speter * 1. Redistributions of source code must retain the above copyright
13251877Speter *    notice, this list of conditions and the following disclaimer.
14251877Speter * 2. Redistributions in binary form must reproduce the above copyright
15251877Speter *    notice, this list of conditions and the following disclaimer in the
16251877Speter *    documentation and/or other materials provided with the distribution.
17251877Speter *
18251877Speter * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19251877Speter * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20251877Speter * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21251877Speter * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22251877Speter * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23251877Speter * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24251877Speter * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25251877Speter * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26251877Speter * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27251877Speter * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28251877Speter * POSSIBILITY OF SUCH DAMAGE.
29251877Speter */
30251877Speter
31251877Speter#include <sys/types.h>
32251877Speter#include <sys/param.h>
33251877Speter#include <sys/time.h>
34251877Speter#include <sys/buf.h>
35251877Speter#include <sys/mount.h>
36251877Speter#include <sys/queue.h>
37251877Speter
38251877Speter#include <ufs/ufs/inode.h>
39251877Speter#include <ufs/ufs/ufsmount.h>
40251877Speter#define vnode uvnode
41251877Speter#include <ufs/lfs/lfs.h>
42251877Speter#undef vnode
43251877Speter
44251877Speter#include <assert.h>
45251877Speter#include <err.h>
46251877Speter#include <errno.h>
47251877Speter#include <stdarg.h>
48251877Speter#include <stdio.h>
49251877Speter#include <stdlib.h>
50251877Speter#include <string.h>
51251877Speter#include <unistd.h>
52251877Speter#include <util.h>
53251877Speter
54251877Speter#include "bufcache.h"
55251877Speter#include "vnode.h"
56251877Speter#include "kernelops.h"
57251877Speter
58251877Speterstruct uvnodelst vnodelist;
59251877Speterstruct uvnodelst getvnodelist[VNODE_HASH_MAX];
60251877Speterstruct vgrlst    vgrlist;
61251877Speter
62251877Speterint nvnodes;
63251877Speter
64251877Speter/* Convert between inode pointers and vnode pointers. */
65251877Speter#ifndef VTOI
66251877Speter#define	VTOI(vp)	((struct inode *)(vp)->v_data)
67251877Speter#endif
68251877Speter
69251877Speter/*
70251877Speter * Raw device uvnode ops
71251877Speter */
72251877Speter
73251877Speterint
74251877Speterraw_vop_strategy(struct ubuf * bp)
75251877Speter{
76251877Speter	if (bp->b_flags & B_READ) {
77251877Speter		return kops.ko_pread(bp->b_vp->v_fd, bp->b_data, bp->b_bcount,
78251877Speter		    bp->b_blkno * dev_bsize);
79251877Speter	} else {
80251877Speter		return kops.ko_pwrite(bp->b_vp->v_fd, bp->b_data, bp->b_bcount,
81251877Speter		    bp->b_blkno * dev_bsize);
82251877Speter	}
83251877Speter}
84251877Speter
85251877Speterint
86251877Speterraw_vop_bwrite(struct ubuf * bp)
87251877Speter{
88251877Speter	bp->b_flags &= ~(B_READ | B_DELWRI | B_DONE | B_ERROR);
89251877Speter	raw_vop_strategy(bp);
90251877Speter	brelse(bp, 0);
91251877Speter	return 0;
92251877Speter}
93251877Speter
94251877Speterint
95251877Speterraw_vop_bmap(struct uvnode * vp, daddr_t lbn, daddr_t * daddrp)
96251877Speter{
97251877Speter	*daddrp = lbn;
98251877Speter	return 0;
99251877Speter}
100251877Speter
101251877Speter/* Register a fs-specific vget function */
102251877Spetervoid
103251877Speterregister_vget(void *fs, struct uvnode *func(void *, ino_t))
104251877Speter{
105251877Speter	struct vget_reg *vgr;
106251877Speter
107251877Speter	vgr = emalloc(sizeof(*vgr));
108251877Speter	vgr->vgr_fs = fs;
109251877Speter	vgr->vgr_func = func;
110251877Speter	LIST_INSERT_HEAD(&vgrlist, vgr, vgr_list);
111251877Speter}
112251877Speter
113251877Speterstatic struct uvnode *
114251877SpeterVFS_VGET(void *fs, ino_t ino)
115251877Speter{
116251877Speter	struct vget_reg *vgr;
117251877Speter
118251877Speter	LIST_FOREACH(vgr, &vgrlist, vgr_list) {
119251877Speter		if (vgr->vgr_fs == fs)
120251877Speter			return vgr->vgr_func(fs, ino);
121251877Speter	}
122251877Speter	return NULL;
123251877Speter}
124251877Speter
125251877Spetervoid
126251877Spetervnode_destroy(struct uvnode *tossvp)
127251877Speter{
128251877Speter	struct ubuf *bp;
129251877Speter
130251877Speter	--nvnodes;
131251877Speter	LIST_REMOVE(tossvp, v_getvnodes);
132251877Speter	LIST_REMOVE(tossvp, v_mntvnodes);
133251877Speter	while ((bp = LIST_FIRST(&tossvp->v_dirtyblkhd)) != NULL) {
134251877Speter		LIST_REMOVE(bp, b_vnbufs);
135251877Speter		bremfree(bp);
136251877Speter		buf_destroy(bp);
137251877Speter	}
138251877Speter	while ((bp = LIST_FIRST(&tossvp->v_cleanblkhd)) != NULL) {
139251877Speter		LIST_REMOVE(bp, b_vnbufs);
140251877Speter		bremfree(bp);
141251877Speter		buf_destroy(bp);
142251877Speter	}
143251877Speter	free(VTOI(tossvp)->inode_ext.lfs);
144251877Speter	free(VTOI(tossvp)->i_din.ffs1_din);
145251877Speter	memset(VTOI(tossvp), 0, sizeof(struct inode));
146251877Speter	free(tossvp->v_data);
147251877Speter	memset(tossvp, 0, sizeof(*tossvp));
148251877Speter	free(tossvp);
149251877Speter}
150251877Speter
151251877Speterint hits, misses;
152251877Speter
153251877Speter/*
154251877Speter * Find a vnode in the cache; if not present, get it from the
155253895Speter * filesystem-specific vget routine.
156251877Speter */
157251877Speterstruct uvnode *
158251877Spetervget(void *fs, ino_t ino)
159251877Speter{
160251877Speter	struct uvnode *vp, *tossvp;
161251877Speter	int hash;
162251877Speter
163251877Speter	/* Look in the uvnode cache */
164251877Speter	tossvp = NULL;
165251877Speter	hash = ((unsigned long)fs + ino) & (VNODE_HASH_MAX - 1);
166251877Speter	LIST_FOREACH(vp, &getvnodelist[hash], v_getvnodes) {
167251877Speter		if (vp->v_fs != fs)
168251877Speter			continue;
169251877Speter		if (VTOI(vp)->i_number == ino) {
170251877Speter			/* Move to the front of the list */
171251877Speter			LIST_REMOVE(vp, v_getvnodes);
172251877Speter			LIST_INSERT_HEAD(&getvnodelist[hash], vp, v_getvnodes);
173251877Speter			++hits;
174251877Speter			break;
175251877Speter		}
176251877Speter		if (LIST_EMPTY(&vp->v_dirtyblkhd) &&
177		    vp->v_usecount == 0 &&
178		    !(vp->v_uflag & VU_DIROP))
179			tossvp = vp;
180	}
181	/* Don't let vnode list grow arbitrarily */
182	if (nvnodes > VNODE_CACHE_SIZE && tossvp) {
183		vnode_destroy(tossvp);
184	}
185	if (vp)
186		return vp;
187
188	++misses;
189	return VFS_VGET(fs, ino);
190}
191
192void
193vfs_init(void)
194{
195	int i;
196
197	nvnodes = 0;
198	LIST_INIT(&vnodelist);
199	for (i = 0; i < VNODE_HASH_MAX; i++)
200		LIST_INIT(&getvnodelist[i]);
201	LIST_INIT(&vgrlist);
202}
203