1*a74e29feSjoerg /* $NetBSD: vnode.c,v 1.16 2020/04/03 19:36:33 joerg Exp $ */
2ba10361aSperseant /*-
3ba10361aSperseant * Copyright (c) 2003 The NetBSD Foundation, Inc.
4ba10361aSperseant * All rights reserved.
5ba10361aSperseant *
6ba10361aSperseant * This code is derived from software contributed to The NetBSD Foundation
7ba10361aSperseant * by Konrad E. Schroder <perseant@hhhh.org>.
8ba10361aSperseant *
9ba10361aSperseant * Redistribution and use in source and binary forms, with or without
10ba10361aSperseant * modification, are permitted provided that the following conditions
11ba10361aSperseant * are met:
12ba10361aSperseant * 1. Redistributions of source code must retain the above copyright
13ba10361aSperseant * notice, this list of conditions and the following disclaimer.
14ba10361aSperseant * 2. Redistributions in binary form must reproduce the above copyright
15ba10361aSperseant * notice, this list of conditions and the following disclaimer in the
16ba10361aSperseant * documentation and/or other materials provided with the distribution.
17ba10361aSperseant *
18ba10361aSperseant * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
19ba10361aSperseant * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
20ba10361aSperseant * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
21ba10361aSperseant * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
22ba10361aSperseant * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23ba10361aSperseant * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24ba10361aSperseant * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25ba10361aSperseant * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26ba10361aSperseant * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27ba10361aSperseant * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28ba10361aSperseant * POSSIBILITY OF SUCH DAMAGE.
29ba10361aSperseant */
30ba10361aSperseant
31ba10361aSperseant #include <sys/types.h>
32ba10361aSperseant #include <sys/param.h>
33ba10361aSperseant #include <sys/time.h>
34ba10361aSperseant #include <sys/buf.h>
35ba10361aSperseant #include <sys/mount.h>
36ba10361aSperseant #include <sys/queue.h>
37ba10361aSperseant
38a4fc39c0Sdholland #define VU_DIROP 0x01000000 /* XXX XXX from sys/vnode.h */
39a4fc39c0Sdholland #define vnode uvnode
40ba10361aSperseant #include <ufs/lfs/lfs.h>
41c13a1250Sdholland #include <ufs/lfs/lfs_inode.h>
42ba10361aSperseant #undef vnode
43ba10361aSperseant
44ba10361aSperseant #include <assert.h>
45ba10361aSperseant #include <err.h>
46ba10361aSperseant #include <errno.h>
47ba10361aSperseant #include <stdarg.h>
48ba10361aSperseant #include <stdio.h>
49ba10361aSperseant #include <stdlib.h>
50ba10361aSperseant #include <string.h>
51ba10361aSperseant #include <unistd.h>
52b6479e9fSchristos #include <util.h>
53ba10361aSperseant
54ba10361aSperseant #include "bufcache.h"
55*a74e29feSjoerg #include "extern.h"
56709a4d5bSpooka #include "kernelops.h"
57ba10361aSperseant
58ba10361aSperseant struct uvnodelst vnodelist;
591d4cc6a1Sperseant struct uvnodelst getvnodelist[VNODE_HASH_MAX];
60ba10361aSperseant struct vgrlst vgrlist;
61ba10361aSperseant
62ba10361aSperseant int nvnodes;
63ba10361aSperseant
64ba10361aSperseant /* Convert between inode pointers and vnode pointers. */
65ba10361aSperseant #ifndef VTOI
66ba10361aSperseant #define VTOI(vp) ((struct inode *)(vp)->v_data)
67ba10361aSperseant #endif
68ba10361aSperseant
69ba10361aSperseant /*
70ba10361aSperseant * Raw device uvnode ops
71ba10361aSperseant */
72ba10361aSperseant
73ba10361aSperseant int
raw_vop_strategy(struct ubuf * bp)74ba10361aSperseant raw_vop_strategy(struct ubuf * bp)
75ba10361aSperseant {
76ba10361aSperseant if (bp->b_flags & B_READ) {
77709a4d5bSpooka return kops.ko_pread(bp->b_vp->v_fd, bp->b_data, bp->b_bcount,
7879748725Smlelstv bp->b_blkno * dev_bsize);
79ba10361aSperseant } else {
80709a4d5bSpooka return kops.ko_pwrite(bp->b_vp->v_fd, bp->b_data, bp->b_bcount,
8179748725Smlelstv bp->b_blkno * dev_bsize);
82ba10361aSperseant }
83ba10361aSperseant }
84ba10361aSperseant
85ba10361aSperseant int
raw_vop_bwrite(struct ubuf * bp)86ba10361aSperseant raw_vop_bwrite(struct ubuf * bp)
87ba10361aSperseant {
88ba10361aSperseant bp->b_flags &= ~(B_READ | B_DELWRI | B_DONE | B_ERROR);
89ba10361aSperseant raw_vop_strategy(bp);
90fe44973fSad brelse(bp, 0);
91ba10361aSperseant return 0;
92ba10361aSperseant }
93ba10361aSperseant
94ba10361aSperseant int
raw_vop_bmap(struct uvnode * vp,daddr_t lbn,daddr_t * daddrp)95ba10361aSperseant raw_vop_bmap(struct uvnode * vp, daddr_t lbn, daddr_t * daddrp)
96ba10361aSperseant {
97ba10361aSperseant *daddrp = lbn;
98ba10361aSperseant return 0;
99ba10361aSperseant }
100ba10361aSperseant
101ba10361aSperseant /* Register a fs-specific vget function */
102ba10361aSperseant void
register_vget(void * fs,struct uvnode * func (void *,ino_t))103ba10361aSperseant register_vget(void *fs, struct uvnode *func(void *, ino_t))
104ba10361aSperseant {
105ba10361aSperseant struct vget_reg *vgr;
106ba10361aSperseant
107b6479e9fSchristos vgr = emalloc(sizeof(*vgr));
108ba10361aSperseant vgr->vgr_fs = fs;
109ba10361aSperseant vgr->vgr_func = func;
110ba10361aSperseant LIST_INSERT_HEAD(&vgrlist, vgr, vgr_list);
111ba10361aSperseant }
112ba10361aSperseant
113ba10361aSperseant static struct uvnode *
VFS_VGET(void * fs,ino_t ino)114ba10361aSperseant VFS_VGET(void *fs, ino_t ino)
115ba10361aSperseant {
116ba10361aSperseant struct vget_reg *vgr;
117ba10361aSperseant
118ba10361aSperseant LIST_FOREACH(vgr, &vgrlist, vgr_list) {
119ba10361aSperseant if (vgr->vgr_fs == fs)
120ba10361aSperseant return vgr->vgr_func(fs, ino);
121ba10361aSperseant }
122ba10361aSperseant return NULL;
123ba10361aSperseant }
124ba10361aSperseant
125ba10361aSperseant void
vnode_destroy(struct uvnode * tossvp)126ba10361aSperseant vnode_destroy(struct uvnode *tossvp)
127ba10361aSperseant {
128ba10361aSperseant struct ubuf *bp;
129ba10361aSperseant
130ba10361aSperseant --nvnodes;
131ba10361aSperseant LIST_REMOVE(tossvp, v_getvnodes);
132ba10361aSperseant LIST_REMOVE(tossvp, v_mntvnodes);
1330794bfc8Schristos while ((bp = LIST_FIRST(&tossvp->v_dirtyblkhd)) != NULL) {
1340794bfc8Schristos LIST_REMOVE(bp, b_vnbufs);
135ba10361aSperseant bremfree(bp);
136ba10361aSperseant buf_destroy(bp);
137ba10361aSperseant }
1380794bfc8Schristos while ((bp = LIST_FIRST(&tossvp->v_cleanblkhd)) != NULL) {
1390794bfc8Schristos LIST_REMOVE(bp, b_vnbufs);
140ba10361aSperseant bremfree(bp);
141ba10361aSperseant buf_destroy(bp);
142ba10361aSperseant }
143ba10361aSperseant free(VTOI(tossvp)->inode_ext.lfs);
144c9cfc4bdSdholland free(VTOI(tossvp)->i_din);
145ba10361aSperseant memset(VTOI(tossvp), 0, sizeof(struct inode));
146ba10361aSperseant free(tossvp->v_data);
147ba10361aSperseant memset(tossvp, 0, sizeof(*tossvp));
148ba10361aSperseant free(tossvp);
149ba10361aSperseant }
150ba10361aSperseant
1511d4cc6a1Sperseant int hits, misses;
1521d4cc6a1Sperseant
153ba10361aSperseant /*
154ba10361aSperseant * Find a vnode in the cache; if not present, get it from the
155ba10361aSperseant * filesystem-specific vget routine.
156ba10361aSperseant */
157ba10361aSperseant struct uvnode *
vget(void * fs,ino_t ino)158ba10361aSperseant vget(void *fs, ino_t ino)
159ba10361aSperseant {
160ba10361aSperseant struct uvnode *vp, *tossvp;
1611d4cc6a1Sperseant int hash;
162ba10361aSperseant
163ba10361aSperseant /* Look in the uvnode cache */
164ba10361aSperseant tossvp = NULL;
1651d4cc6a1Sperseant hash = ((unsigned long)fs + ino) & (VNODE_HASH_MAX - 1);
1661d4cc6a1Sperseant LIST_FOREACH(vp, &getvnodelist[hash], v_getvnodes) {
167ba10361aSperseant if (vp->v_fs != fs)
168ba10361aSperseant continue;
169ba10361aSperseant if (VTOI(vp)->i_number == ino) {
1701d4cc6a1Sperseant /* Move to the front of the list */
171ba10361aSperseant LIST_REMOVE(vp, v_getvnodes);
1721d4cc6a1Sperseant LIST_INSERT_HEAD(&getvnodelist[hash], vp, v_getvnodes);
1731d4cc6a1Sperseant ++hits;
174ba10361aSperseant break;
175ba10361aSperseant }
176ba10361aSperseant if (LIST_EMPTY(&vp->v_dirtyblkhd) &&
177ba10361aSperseant vp->v_usecount == 0 &&
1787dad9f73Sad !(vp->v_uflag & VU_DIROP))
179ba10361aSperseant tossvp = vp;
180ba10361aSperseant }
181ba10361aSperseant /* Don't let vnode list grow arbitrarily */
182ba10361aSperseant if (nvnodes > VNODE_CACHE_SIZE && tossvp) {
183ba10361aSperseant vnode_destroy(tossvp);
184ba10361aSperseant }
185ba10361aSperseant if (vp)
186ba10361aSperseant return vp;
187ba10361aSperseant
1881d4cc6a1Sperseant ++misses;
189ba10361aSperseant return VFS_VGET(fs, ino);
190ba10361aSperseant }
191ba10361aSperseant
192ba10361aSperseant void
vfs_init(void)193ba10361aSperseant vfs_init(void)
194ba10361aSperseant {
1951d4cc6a1Sperseant int i;
1961d4cc6a1Sperseant
197ba10361aSperseant nvnodes = 0;
198ba10361aSperseant LIST_INIT(&vnodelist);
1991d4cc6a1Sperseant for (i = 0; i < VNODE_HASH_MAX; i++)
2001d4cc6a1Sperseant LIST_INIT(&getvnodelist[i]);
201ba10361aSperseant LIST_INIT(&vgrlist);
202ba10361aSperseant }
203