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