1 /*- 2 * Copyright (c) 1990 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * William Jolitz. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)ufs_machdep.c 5.2 (Berkeley) 05/09/91 11 */ 12 13 #include "../machine/pte.h" 14 15 #include "../h/param.h" 16 #include "../h/systm.h" 17 #include "../h/dir.h" 18 #include "../h/user.h" 19 #include "../h/buf.h" 20 #include "../h/conf.h" 21 #include "../h/proc.h" 22 #include "../h/seg.h" 23 #include "../h/vm.h" 24 25 /* 26 * Machine dependent handling of the buffer cache. 27 */ 28 29 /* 30 * Expand or contract the actual memory allocated to a buffer. 31 * If no memory is available, release buffer and take error exit 32 */ 33 allocbuf(tp, size) 34 register struct buf *tp; 35 int size; 36 { 37 register struct buf *bp, *ep; 38 int sizealloc, take; 39 40 sizealloc = roundup(size, CLBYTES); 41 /* 42 * Buffer size does not change 43 */ 44 if (sizealloc == tp->b_bufsize) 45 goto out; 46 /* 47 * Buffer size is shrinking. 48 * Place excess space in a buffer header taken from the 49 * BQ_EMPTY buffer list and placed on the "most free" list. 50 * If no extra buffer headers are available, leave the 51 * extra space in the present buffer. 52 */ 53 if (sizealloc < tp->b_bufsize) { 54 ep = bfreelist[BQ_EMPTY].av_forw; 55 if (ep == &bfreelist[BQ_EMPTY]) 56 goto out; 57 notavail(ep); 58 pagemove(tp->b_un.b_addr + sizealloc, ep->b_un.b_addr, 59 (int)tp->b_bufsize - sizealloc); 60 ep->b_bufsize = tp->b_bufsize - sizealloc; 61 tp->b_bufsize = sizealloc; 62 ep->b_flags |= B_INVAL; 63 ep->b_bcount = 0; 64 brelse(ep); 65 goto out; 66 } 67 /* 68 * More buffer space is needed. Get it out of buffers on 69 * the "most free" list, placing the empty headers on the 70 * BQ_EMPTY buffer header list. 71 */ 72 while (tp->b_bufsize < sizealloc) { 73 take = sizealloc - tp->b_bufsize; 74 bp = getnewbuf(); 75 if (take >= bp->b_bufsize) 76 take = bp->b_bufsize; 77 pagemove(&bp->b_un.b_addr[bp->b_bufsize - take], 78 &tp->b_un.b_addr[tp->b_bufsize], take); 79 tp->b_bufsize += take; 80 bp->b_bufsize = bp->b_bufsize - take; 81 if (bp->b_bcount > bp->b_bufsize) 82 bp->b_bcount = bp->b_bufsize; 83 if (bp->b_bufsize <= 0) { 84 bremhash(bp); 85 binshash(bp, &bfreelist[BQ_EMPTY]); 86 bp->b_dev = (dev_t)NODEV; 87 bp->b_error = 0; 88 bp->b_flags |= B_INVAL; 89 } 90 brelse(bp); 91 } 92 out: 93 tp->b_bcount = size; 94 return (1); 95 } 96 97 /* 98 * Release space associated with a buffer. 99 */ 100 bfree(bp) 101 struct buf *bp; 102 { 103 104 bp->b_bcount = 0; 105 } 106