Home | History | Annotate | Line # | Download | only in fsck_lfs
vnode.c revision 1.8.8.1
      1 /* $NetBSD: vnode.c,v 1.8.8.1 2008/06/02 13:21:21 mjf 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 #include <ufs/ufs/inode.h>
     39 #include <ufs/ufs/ufsmount.h>
     40 #define vnode uvnode
     41 #include <ufs/lfs/lfs.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 "vnode.h"
     56 
     57 struct uvnodelst vnodelist;
     58 struct uvnodelst getvnodelist[VNODE_HASH_MAX];
     59 struct vgrlst    vgrlist;
     60 
     61 int nvnodes;
     62 
     63 /* Convert between inode pointers and vnode pointers. */
     64 #ifndef VTOI
     65 #define	VTOI(vp)	((struct inode *)(vp)->v_data)
     66 #endif
     67 
     68 /*
     69  * Raw device uvnode ops
     70  */
     71 
     72 int
     73 raw_vop_strategy(struct ubuf * bp)
     74 {
     75 	if (bp->b_flags & B_READ) {
     76 		return pread(bp->b_vp->v_fd, bp->b_data, bp->b_bcount,
     77 		    dbtob(bp->b_blkno));
     78 	} else {
     79 		return pwrite(bp->b_vp->v_fd, bp->b_data, bp->b_bcount,
     80 		    dbtob(bp->b_blkno));
     81 	}
     82 }
     83 
     84 int
     85 raw_vop_bwrite(struct ubuf * bp)
     86 {
     87 	bp->b_flags &= ~(B_READ | B_DELWRI | B_DONE | B_ERROR);
     88 	raw_vop_strategy(bp);
     89 	brelse(bp, 0);
     90 	return 0;
     91 }
     92 
     93 int
     94 raw_vop_bmap(struct uvnode * vp, daddr_t lbn, daddr_t * daddrp)
     95 {
     96 	*daddrp = lbn;
     97 	return 0;
     98 }
     99 
    100 /* Register a fs-specific vget function */
    101 void
    102 register_vget(void *fs, struct uvnode *func(void *, ino_t))
    103 {
    104 	struct vget_reg *vgr;
    105 
    106 	vgr = emalloc(sizeof(*vgr));
    107 	vgr->vgr_fs = fs;
    108 	vgr->vgr_func = func;
    109 	LIST_INSERT_HEAD(&vgrlist, vgr, vgr_list);
    110 }
    111 
    112 static struct uvnode *
    113 VFS_VGET(void *fs, ino_t ino)
    114 {
    115 	struct vget_reg *vgr;
    116 
    117 	LIST_FOREACH(vgr, &vgrlist, vgr_list) {
    118 		if (vgr->vgr_fs == fs)
    119 			return vgr->vgr_func(fs, ino);
    120 	}
    121 	return NULL;
    122 }
    123 
    124 void
    125 vnode_destroy(struct uvnode *tossvp)
    126 {
    127 	struct ubuf *bp;
    128 
    129 	--nvnodes;
    130 	LIST_REMOVE(tossvp, v_getvnodes);
    131 	LIST_REMOVE(tossvp, v_mntvnodes);
    132 	while ((bp = LIST_FIRST(&tossvp->v_dirtyblkhd)) != NULL) {
    133 		LIST_REMOVE(bp, b_vnbufs);
    134 		bremfree(bp);
    135 		buf_destroy(bp);
    136 	}
    137 	while ((bp = LIST_FIRST(&tossvp->v_cleanblkhd)) != NULL) {
    138 		LIST_REMOVE(bp, b_vnbufs);
    139 		bremfree(bp);
    140 		buf_destroy(bp);
    141 	}
    142 	free(VTOI(tossvp)->inode_ext.lfs);
    143 	free(VTOI(tossvp)->i_din.ffs1_din);
    144 	memset(VTOI(tossvp), 0, sizeof(struct inode));
    145 	free(tossvp->v_data);
    146 	memset(tossvp, 0, sizeof(*tossvp));
    147 	free(tossvp);
    148 }
    149 
    150 int hits, misses;
    151 
    152 /*
    153  * Find a vnode in the cache; if not present, get it from the
    154  * filesystem-specific vget routine.
    155  */
    156 struct uvnode *
    157 vget(void *fs, ino_t ino)
    158 {
    159 	struct uvnode *vp, *tossvp;
    160 	int hash;
    161 
    162 	/* Look in the uvnode cache */
    163 	tossvp = NULL;
    164 	hash = ((unsigned long)fs + ino) & (VNODE_HASH_MAX - 1);
    165 	LIST_FOREACH(vp, &getvnodelist[hash], v_getvnodes) {
    166 		if (vp->v_fs != fs)
    167 			continue;
    168 		if (VTOI(vp)->i_number == ino) {
    169 			/* Move to the front of the list */
    170 			LIST_REMOVE(vp, v_getvnodes);
    171 			LIST_INSERT_HEAD(&getvnodelist[hash], vp, v_getvnodes);
    172 			++hits;
    173 			break;
    174 		}
    175 		if (LIST_EMPTY(&vp->v_dirtyblkhd) &&
    176 		    vp->v_usecount == 0 &&
    177 		    !(vp->v_uflag & VU_DIROP))
    178 			tossvp = vp;
    179 	}
    180 	/* Don't let vnode list grow arbitrarily */
    181 	if (nvnodes > VNODE_CACHE_SIZE && tossvp) {
    182 		vnode_destroy(tossvp);
    183 	}
    184 	if (vp)
    185 		return vp;
    186 
    187 	++misses;
    188 	return VFS_VGET(fs, ino);
    189 }
    190 
    191 void
    192 vfs_init(void)
    193 {
    194 	int i;
    195 
    196 	nvnodes = 0;
    197 	LIST_INIT(&vnodelist);
    198 	for (i = 0; i < VNODE_HASH_MAX; i++)
    199 		LIST_INIT(&getvnodelist[i]);
    200 	LIST_INIT(&vgrlist);
    201 }
    202