/*- * Copyright (c) 1982, 1986, 1989, 1993 * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph * Co. or Unix System Laboratories, Inc. and are reproduced herein with * the permission of UNIX System Laboratories, Inc. * * %sccs.include.redist.c% * * from: @(#)vfs_bio.c 8.6 (Berkeley) 1/11/94 */ #include #include #include #include #include #include #include #include #include /* * Definitions for the buffer hash lists. */ #define BUFHASH(dvp, lbn) \ (&bufhashtbl[((int)(dvp) / sizeof(*(dvp)) + (int)(lbn)) & bufhash]) LIST_HEAD(bufhashhdr, buf) *bufhashtbl, invalhash; u_long bufhash; /* * Insq/Remq for the buffer hash lists. */ #define binshash(bp, dp) LIST_INSERT_HEAD(dp, bp, b_hash) #define bremhash(bp) LIST_REMOVE(bp, b_hash) /* * Definitions for the buffer free lists. */ #define BQUEUES 4 /* number of free buffer queues */ #define BQ_LOCKED 0 /* super-blocks &c */ #define BQ_LRU 1 /* lru, useful buffers */ #define BQ_AGE 2 /* rubbish */ #define BQ_EMPTY 3 /* buffer headers with no memory */ TAILQ_HEAD(bqueues, buf) bufqueues[BQUEUES]; int needbuffer; /* * Insq/Remq for the buffer free lists. */ #define binsheadfree(bp, dp) TAILQ_INSERT_HEAD(dp, bp, b_freelist) #define binstailfree(bp, dp) TAILQ_INSERT_TAIL(dp, bp, b_freelist) void bremfree(bp) struct buf *bp; { struct bqueues *dp = NULL; /* * We only calculate the head of the freelist when removing * the last element of the list as that is the only time that * it is needed (e.g. to reset the tail pointer). * * NB: This makes an assumption about how tailq's are implemented. */ if (bp->b_freelist.tqe_next == NULL) { for (dp = bufqueues; dp < &bufqueues[BQUEUES]; dp++) if (dp->tqh_last == &bp->b_freelist.tqe_next) break; if (dp == &bufqueues[BQUEUES]) panic("bremfree: lost tail"); } TAILQ_REMOVE(dp, bp, b_freelist); } /* * Initialize buffers and hash links for buffers. */ void bufinit() { register struct buf *bp; struct bqueues *dp; register int i; int base, residual; for (dp = bufqueues; dp < &bufqueues[BQUEUES]; dp++) TAILQ_INIT(dp); bufhashtbl = hashinit(nbuf, M_CACHE, &bufhash); base = bufpages / nbuf; residual = bufpages % nbuf; for (i = 0; i < nbuf; i++) { bp = &buf[i]; bzero((char *)bp, sizeof *bp); bp->b_dev = NODEV; bp->b_rcred = NOCRED; bp->b_wcred = NOCRED; bp->b_vnbufs.le_next = NOLIST; bp->b_data = buffers + i * MAXBSIZE; if (i < residual) bp->b_bufsize = (base + 1) * CLBYTES; else bp->b_bufsize = base * CLBYTES; bp->b_flags = B_INVAL; dp = bp->b_bufsize ? &bufqueues[BQ_AGE] : &bufqueues[BQ_EMPTY]; binsheadfree(bp, dp); binshash(bp, &invalhash); } } bread(a1, a2, a3, a4, a5) struct vnode *a1; daddr_t a2; int a3; struct ucred *a4; struct buf **a5; { /* * Body deleted. */ return (EIO); } breadn(a1, a2, a3, a4, a5, a6, a7, a8) struct vnode *a1; daddr_t a2; int a3; daddr_t a4[]; int a5[]; int a6; struct ucred *a7; struct buf **a8; { /* * Body deleted. */ return (EIO); } bwrite(a1) struct buf *a1; { /* * Body deleted. */ return (EIO); } int vn_bwrite(ap) struct vop_bwrite_args *ap; { return (bwrite(ap->a_bp)); } bdwrite(a1) struct buf *a1; { /* * Body deleted. */ return; } bawrite(a1) struct buf *a1; { /* * Body deleted. */ return; } brelse(a1) struct buf *a1; { /* * Body deleted. */ return; } struct buf * incore(a1, a2) struct vnode *a1; daddr_t a2; { /* * Body deleted. */ return (0); } struct buf * getblk(a1, a2, a3, a4, a5) struct vnode *a1; daddr_t a2; int a3, a4, a5; { /* * Body deleted. */ return ((struct buf *)0); } struct buf * geteblk(a1) int a1; { /* * Body deleted. */ return ((struct buf *)0); } allocbuf(a1, a2) struct buf *a1; int a2; { /* * Body deleted. */ return (0); } struct buf * getnewbuf(a1, a2) int a1, a2; { /* * Body deleted. */ return ((struct buf *)0); } biowait(a1) struct buf *a1; { /* * Body deleted. */ return (EIO); } void biodone(a1) struct buf *a1; { /* * Body deleted. */ return; } int count_lock_queue() { /* * Body deleted. */ return (0); } #ifdef DIAGNOSTIC /* * Print out statistics on the current allocation of the buffer pool. * Can be enabled to print out on every ``sync'' by setting "syncprt" * in vfs_syscalls.c using sysctl. */ void vfs_bufstats() { int s, i, j, count; register struct buf *bp; register struct bqueues *dp; int counts[MAXBSIZE/CLBYTES+1]; static char *bname[BQUEUES] = { "LOCKED", "LRU", "AGE", "EMPTY" }; for (dp = bufqueues, i = 0; dp < &bufqueues[BQUEUES]; dp++, i++) { count = 0; for (j = 0; j <= MAXBSIZE/CLBYTES; j++) counts[j] = 0; s = splbio(); for (bp = dp->tqh_first; bp; bp = bp->b_freelist.tqe_next) { counts[bp->b_bufsize/CLBYTES]++; count++; } splx(s); printf("%s: total-%d", bname[i], count); for (j = 0; j <= MAXBSIZE/CLBYTES; j++) if (counts[j] != 0) printf(", %d-%d", j * CLBYTES, counts[j]); printf("\n"); } } #endif /* DIAGNOSTIC */