|
|
1.1.1.2 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1992 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: * vfs_bio.c,v 1.1.2.2 1993/08/07 01:56:01 cgd Exp ! 28: * ! 29: * (Mach) HISTORY ! 30: * Revision 2.3 92/07/08 16:19:50 mrt ! 31: * Added fourth arg, TRUE, to vm_allocate call in getnewbuf. ! 32: * [92/07/02 mrt] ! 33: * ! 34: * Revision 2.2 92/06/25 17:25:40 mrt ! 35: * Clear b_resid on release. No one cares once released. ! 36: * [ XXX -- this had to be squished; symlinks care -- cgd] ! 37: * [92/06/25 rwd] ! 38: * Set b_rcred before VOP_STRATEGY calls. [from Jolitz] ! 39: * ! 40: * Revision 2.1 92/04/21 17:12:36 rwd ! 41: * BSDSS ! 42: */ ! 43: 1.1 root 44: /* 45: * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 46: * All rights reserved. 47: * 48: * Redistribution and use in source and binary forms, with or without 49: * modification, are permitted provided that the following conditions 50: * are met: 51: * 1. Redistributions of source code must retain the above copyright 52: * notice, this list of conditions and the following disclaimer. 53: * 2. Redistributions in binary form must reproduce the above copyright 54: * notice, this list of conditions and the following disclaimer in the 55: * documentation and/or other materials provided with the distribution. 56: * 3. All advertising materials mentioning features or use of this software 57: * must display the following acknowledgement: 58: * This product includes software developed by the University of 59: * California, Berkeley and its contributors. 60: * 4. Neither the name of the University nor the names of its contributors 61: * may be used to endorse or promote products derived from this software 62: * without specific prior written permission. 63: * 64: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 65: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 66: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 67: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 68: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 69: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 70: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 71: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 72: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 73: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 74: * SUCH DAMAGE. 75: * 76: * from: @(#)vfs_bio.c 7.40 (Berkeley) 5/8/91 77: */ 78: 1.1.1.2 ! root 79: #include <sys/param.h> ! 80: #include <sys/proc.h> ! 81: #include <sys/buf.h> ! 82: #include <sys/vnode.h> ! 83: #include <sys/specdev.h> ! 84: #include <sys/mount.h> ! 85: #include <sys/trace.h> ! 86: #include <sys/resourcevar.h> ! 87: #include <vm/vm.h> ! 88: #include <vm/vm_param.h> ! 89: ! 90: int debug_bio = 0; ! 91: int freebufspace = 0; ! 92: int allocbufspace = 0; ! 93: extern int bufpages; ! 94: ! 95: static struct buf *getnewbuf __P((int)); ! 96: extern vm_map_t buffer_map; ! 97: ! 98: struct buf *buf; /* the buffer pool itself */ ! 99: char *buffers; ! 100: int nbuf; /* number of buffer headers */ ! 101: int bufpages; /* number of memory pages in the buffer pool */ ! 102: struct buf *swbuf; /* swap I/O headers (XXX go elsewhere?) */ ! 103: int nswbuf; ! 104: struct bufhd bufhash[BUFHSZ]; /* heads of hash lists */ ! 105: struct buf bfreelist[BQUEUES]; /* heads of available lists */ ! 106: struct buf bswlist; /* head of free swap header list */ ! 107: struct buf *bclnlist; /* head of cleaned page list */ 1.1 root 108: 109: /* 110: * Initialize buffers and hash links for buffers. 111: */ 1.1.1.2 ! root 112: void 1.1 root 113: bufinit() 114: { 1.1.1.2 ! root 115: struct bufhd *bh; ! 116: struct buf *bp; 1.1 root 117: 1.1.1.2 ! root 118: freebufspace = bufpages * NBPG; ! 119: ! 120: /* first, make a null hash table */ ! 121: for(bh = bufhash; bh < bufhash + BUFHSZ; bh++) { ! 122: bh->b_flags = 0; ! 123: bh->b_forw = (struct buf *)bh; ! 124: bh->b_back = (struct buf *)bh; ! 125: } ! 126: ! 127: /* next, make a null set of free lists */ ! 128: for(bp = bfreelist; bp < bfreelist + BQUEUES; bp++) { ! 129: bp->b_flags = 0; ! 130: bp->av_forw = bp; ! 131: bp->av_back = bp; ! 132: bp->b_forw = bp; ! 133: bp->b_back = bp; ! 134: ! 135: } ! 136: ! 137: /* finally, initialize each buffer header and stick on empty q */ ! 138: for(bp = buf; bp < buf + nbuf ; bp++) { ! 139: bp->b_flags = B_HEAD | B_INVAL; /* we're just an empty header */ ! 140: bp->b_dev = NODEV; ! 141: bp->b_rcred = bp->b_wcred = NOCRED; ! 142: bp->b_vp = 0; ! 143: binstailfree(bp, bfreelist + BQ_EMPTY); ! 144: binshash(bp, bfreelist + BQ_EMPTY); ! 145: } 1.1 root 146: } 147: 1.1.1.2 ! root 148: 1.1 root 149: /* 150: * Find the block in the buffer pool. 151: * If the buffer is not present, allocate a new buffer and load 152: * its contents according to the filesystem fill routine. 153: */ 1.1.1.2 ! root 154: int 1.1 root 155: bread(vp, blkno, size, cred, bpp) 156: struct vnode *vp; 157: daddr_t blkno; 158: int size; 159: struct ucred *cred; 160: struct buf **bpp; 161: { 1.1.1.2 ! root 162: struct buf *bp; ! 163: int rv = 0; 1.1 root 164: 1.1.1.2 ! root 165: bp = getblk (vp, blkno, size); ! 166: ! 167: /* if not found in cache, do some I/O */ ! 168: if ((bp->b_flags & B_CACHE) == 0 || (bp->b_flags & B_INVAL) != 0) { ! 169: bp->b_flags |= B_READ; ! 170: bp->b_flags &= ~(B_DONE|B_ERROR|B_INVAL); ! 171: if (cred != NOCRED && bp->b_rcred == NOCRED) { ! 172: crhold(cred); ! 173: bp->b_rcred = cred; ! 174: } ! 175: VOP_STRATEGY(bp); ! 176: rv = biowait (bp); ! 177: } ! 178: *bpp = bp; ! 179: ! 180: return (rv); 1.1 root 181: } 182: 183: /* 184: * Operates like bread, but also starts I/O on the specified 1.1.1.2 ! root 185: * read-ahead block. [See page 55 of Bach's Book] 1.1 root 186: */ 1.1.1.2 ! root 187: int 1.1 root 188: breada(vp, blkno, size, rablkno, rabsize, cred, bpp) 189: struct vnode *vp; 1.1.1.2 ! root 190: daddr_t blkno; ! 191: int size; ! 192: daddr_t rablkno; ! 193: int rabsize; 1.1 root 194: struct ucred *cred; 195: struct buf **bpp; 196: { 1.1.1.2 ! root 197: struct buf *bp, *rabp; ! 198: int rv = 0, needwait = 0; 1.1 root 199: 1.1.1.2 ! root 200: bp = getblk (vp, blkno, size); ! 201: ! 202: /* if not found in cache, do some I/O */ ! 203: if ((bp->b_flags & B_CACHE) == 0 || (bp->b_flags & B_INVAL) != 0) { ! 204: bp->b_flags |= B_READ; ! 205: bp->b_flags &= ~(B_DONE|B_ERROR|B_INVAL); ! 206: if (cred != NOCRED && bp->b_rcred == NOCRED) { ! 207: crhold(cred); ! 208: bp->b_rcred = cred; ! 209: } ! 210: VOP_STRATEGY(bp); ! 211: needwait++; ! 212: } ! 213: ! 214: rabp = getblk (vp, rablkno, rabsize); ! 215: ! 216: /* if not found in cache, do some I/O (overlapped with first) */ ! 217: if ((rabp->b_flags & B_CACHE) == 0 || (rabp->b_flags & B_INVAL) != 0) { ! 218: rabp->b_flags |= B_READ | B_ASYNC; ! 219: rabp->b_flags &= ~(B_DONE|B_ERROR|B_INVAL); ! 220: if (cred != NOCRED && bp->b_rcred == NOCRED) { ! 221: crhold(cred); ! 222: rabp->b_rcred = cred; ! 223: } ! 224: VOP_STRATEGY(rabp); ! 225: } else ! 226: brelse(rabp); ! 227: ! 228: /* wait for original I/O */ ! 229: if (needwait) ! 230: rv = biowait (bp); ! 231: ! 232: *bpp = bp; ! 233: return (rv); 1.1 root 234: } 235: 236: /* 237: * Synchronous write. 238: * Release buffer on completion. 239: */ 1.1.1.2 ! root 240: int 1.1 root 241: bwrite(bp) 242: register struct buf *bp; 243: { 1.1.1.2 ! root 244: int rv; 1.1 root 245: 1.1.1.2 ! root 246: if(bp->b_flags & B_INVAL) { ! 247: brelse(bp); ! 248: return (0); ! 249: } else { ! 250: int wasdelayed; ! 251: ! 252: if(!(bp->b_flags & B_BUSY)) ! 253: panic("bwrite: not busy"); ! 254: ! 255: wasdelayed = bp->b_flags & B_DELWRI; ! 256: bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_ASYNC|B_DELWRI); ! 257: if(wasdelayed) ! 258: reassignbuf(bp, bp->b_vp); ! 259: ! 260: bp->b_flags |= B_DIRTY; ! 261: bp->b_vp->v_numoutput++; ! 262: VOP_STRATEGY(bp); ! 263: rv = biowait(bp); ! 264: if (!rv) ! 265: bp->b_flags &= ~B_DIRTY; ! 266: brelse(bp); ! 267: return (rv); ! 268: } 1.1 root 269: } 270: 271: /* 272: * Delayed write. 273: * 274: * The buffer is marked dirty, but is not queued for I/O. 275: * This routine should be used when the buffer is expected 276: * to be modified again soon, typically a small write that 277: * partially fills a buffer. 278: * 279: * NB: magnetic tapes cannot be delayed; they must be 280: * written in the order that the writes are requested. 281: */ 1.1.1.2 ! root 282: void 1.1 root 283: bdwrite(bp) 284: register struct buf *bp; 285: { 286: 1.1.1.2 ! root 287: if(!(bp->b_flags & B_BUSY)) ! 288: panic("bdwrite: not busy"); ! 289: ! 290: if(bp->b_flags & B_INVAL) { ! 291: brelse(bp); ! 292: return; ! 293: } ! 294: if(bp->b_flags & B_TAPE) { ! 295: bwrite(bp); ! 296: return; ! 297: } ! 298: bp->b_flags &= ~(B_READ|B_DONE); ! 299: bp->b_flags |= B_DIRTY|B_DELWRI; ! 300: reassignbuf(bp, bp->b_vp); ! 301: brelse(bp); 1.1 root 302: return; 303: } 304: 305: /* 306: * Asynchronous write. 307: * Start I/O on a buffer, but do not wait for it to complete. 308: * The buffer is released when the I/O completes. 309: */ 1.1.1.2 ! root 310: void 1.1 root 311: bawrite(bp) 312: register struct buf *bp; 313: { 314: 1.1.1.2 ! root 315: if(!(bp->b_flags & B_BUSY)) ! 316: panic("bawrite: not busy"); ! 317: ! 318: if(bp->b_flags & B_INVAL) ! 319: brelse(bp); ! 320: else { ! 321: int wasdelayed; ! 322: ! 323: wasdelayed = bp->b_flags & B_DELWRI; ! 324: bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); ! 325: if(wasdelayed) ! 326: reassignbuf(bp, bp->b_vp); ! 327: ! 328: bp->b_flags |= B_DIRTY | B_ASYNC; ! 329: bp->b_vp->v_numoutput++; ! 330: VOP_STRATEGY(bp); ! 331: } 1.1 root 332: } 333: 334: /* 335: * Release a buffer. 336: * Even if the buffer is dirty, no I/O is started. 337: */ 1.1.1.2 ! root 338: void 1.1 root 339: brelse(bp) 340: register struct buf *bp; 341: { 1.1.1.2 ! root 342: int x; 1.1 root 343: 1.1.1.2 ! root 344: /* anyone need a "free" block? */ ! 345: x=splbio(); ! 346: if ((bfreelist + BQ_AGE)->b_flags & B_WANTED) { ! 347: (bfreelist + BQ_AGE) ->b_flags &= ~B_WANTED; ! 348: wakeup(bfreelist); ! 349: } ! 350: /* anyone need this very block? */ ! 351: if (bp->b_flags & B_WANTED) { ! 352: bp->b_flags &= ~B_WANTED; ! 353: wakeup(bp); ! 354: } ! 355: ! 356: if (bp->b_flags & (B_INVAL|B_ERROR)) { ! 357: bp->b_flags |= B_INVAL; ! 358: bp->b_flags &= ~(B_DELWRI|B_CACHE); ! 359: if(bp->b_vp) ! 360: brelvp(bp); ! 361: } ! 362: ! 363: /* enqueue */ ! 364: /* just an empty buffer head ... */ ! 365: /*if(bp->b_flags & B_HEAD) ! 366: binsheadfree(bp, bfreelist + BQ_EMPTY)*/ ! 367: /* buffers with junk contents */ ! 368: /*else*/ if(bp->b_flags & (B_ERROR|B_INVAL|B_NOCACHE)) ! 369: binsheadfree(bp, bfreelist + BQ_AGE) ! 370: /* buffers with stale but valid contents */ ! 371: else if(bp->b_flags & B_AGE) ! 372: binstailfree(bp, bfreelist + BQ_AGE) ! 373: /* buffers with valid and quite potentially reuseable contents */ ! 374: else ! 375: binstailfree(bp, bfreelist + BQ_LRU) ! 376: ! 377: /* unlock */ ! 378: bp->b_flags &= ~B_BUSY; ! 379: /* bp->b_resid = 0; XXX (cgd) -- actually, we need resid for symlinks */ ! 380: splx(x); ! 381: } ! 382: ! 383: /* ! 384: * Find a buffer which is available for use. ! 385: * If free memory for buffer space and an empty header from the empty list, ! 386: * use that. Otherwise, select something from a free list. ! 387: * Preference is to AGE list, then LRU list. ! 388: */ ! 389: static struct buf * ! 390: getnewbuf(sz) ! 391: int sz; ! 392: { ! 393: struct buf *bp; ! 394: int x, allocsize; ! 395: ! 396: x = splbio(); ! 397: allocsize = MAXBSIZE; /* XXX -- should be round_page(sz) */ ! 398: ! 399: start: ! 400: /* can we constitute a new buffer? */ ! 401: if (freebufspace >= allocsize ! 402: && bfreelist[BQ_EMPTY].av_forw != (struct buf *)bfreelist+BQ_EMPTY) { ! 403: caddr_t addr; ! 404: int kr; ! 405: ! 406: #if 0 ! 407: if ((kr = vm_allocate(buffer_map, (vm_offset_t *) &addr, (vm_size_t) allocsize, TRUE)) ! 408: != KERN_SUCCESS) goto tryfree; ! 409: #else ! 410: if (! (addr = (caddr_t) kmem_alloc (buffer_map, (vm_size_t) allocsize))) goto tryfree; ! 411: #endif ! 412: freebufspace -= allocsize; ! 413: allocbufspace += allocsize; ! 414: ! 415: bp = bfreelist[BQ_EMPTY].av_forw; ! 416: if (debug_bio) printf(" allocate bp: %x addr: %x (alloc)size: %x\n",bp, addr, allocsize); ! 417: bp->b_flags = B_BUSY | B_INVAL; ! 418: bremfree(bp); ! 419: bp->b_un.b_addr = (caddr_t) addr; ! 420: bp->b_bufsize = allocsize; ! 421: goto fillin; ! 422: } ! 423: ! 424: tryfree: ! 425: if (bfreelist[BQ_AGE].av_forw != (struct buf *)bfreelist+BQ_AGE) { ! 426: bp = bfreelist[BQ_AGE].av_forw; ! 427: bremfree(bp); ! 428: } else if (bfreelist[BQ_LRU].av_forw != (struct buf *)bfreelist+BQ_LRU) { ! 429: bp = bfreelist[BQ_LRU].av_forw; ! 430: bremfree(bp); ! 431: } else { ! 432: /* wait for a free buffer of any kind */ ! 433: (bfreelist + BQ_AGE)->b_flags |= B_WANTED; ! 434: tsleep(bfreelist, PRIBIO, "getnewbuf", 0); ! 435: splx(x); ! 436: return (0); ! 437: } ! 438: ! 439: /* if we are a delayed write, convert to an async write! */ ! 440: if (bp->b_flags & B_DELWRI) { ! 441: bp->b_flags |= B_BUSY; ! 442: bawrite (bp); ! 443: goto start; ! 444: } ! 445: ! 446: ! 447: if(bp->b_vp) ! 448: brelvp(bp); ! 449: ! 450: /* we are not free, nor do we contain interesting data */ ! 451: if (bp->b_rcred != NOCRED) ! 452: crfree(bp->b_rcred); ! 453: if (bp->b_wcred != NOCRED) ! 454: crfree(bp->b_wcred); ! 455: ! 456: bp->b_flags = B_BUSY; ! 457: fillin: ! 458: bremhash(bp); ! 459: splx(x); ! 460: bp->b_dev = NODEV; ! 461: bp->b_vp = NULL; ! 462: bp->b_blkno = bp->b_lblkno = 0; ! 463: bp->b_iodone = 0; ! 464: bp->b_error = 0; ! 465: bp->b_resid = 0; ! 466: bp->b_wcred = bp->b_rcred = NOCRED; ! 467: if (bp->b_bufsize != allocsize) ! 468: allocbuf(bp, allocsize); ! 469: bp->b_bcount = sz; ! 470: bp->b_dirtyoff = bp->b_dirtyend = 0; ! 471: return (bp); 1.1 root 472: } 473: 474: /* 475: * Check to see if a block is currently memory resident. 1.1.1.2 ! root 476: * This routine must be called at splbio(). If it is not, ! 477: * and you take a disk interrupt while in the while loop, ! 478: * you can loop forever. 1.1 root 479: */ 1.1.1.2 ! root 480: struct buf * 1.1 root 481: incore(vp, blkno) 482: struct vnode *vp; 483: daddr_t blkno; 484: { 1.1.1.2 ! root 485: struct buf *bh; ! 486: struct buf *bp; ! 487: ! 488: bh = BUFHASH(vp, blkno); 1.1 root 489: 1.1.1.2 ! root 490: /* Search hash chain */ ! 491: bp = bh->b_forw; ! 492: while (bp != (struct buf *) bh) { ! 493: /* hit */ ! 494: if (bp->b_lblkno == blkno && bp->b_vp == vp ! 495: && (bp->b_flags & B_INVAL) == 0) ! 496: return (bp); ! 497: bp = bp->b_forw; ! 498: } ! 499: ! 500: return(0); 1.1 root 501: } 502: 503: /* 1.1.1.2 ! root 504: * Get a block of requested size that is associated with ! 505: * a given vnode and block offset. If it is found in the ! 506: * block cache, mark it as having been found, make it busy ! 507: * and return it. Otherwise, return an empty block of the ! 508: * correct size. It is up to the caller to insure that the ! 509: * cached blocks be of the correct size. 1.1 root 510: */ 511: struct buf * 512: getblk(vp, blkno, size) 513: register struct vnode *vp; 514: daddr_t blkno; 515: int size; 516: { 1.1.1.2 ! root 517: struct buf *bp, *bh; ! 518: int x; 1.1 root 519: 1.1.1.2 ! root 520: x = splbio(); ! 521: start: ! 522: if (bp = incore(vp, blkno)) { ! 523: if (bp->b_flags & B_BUSY) { ! 524: bp->b_flags |= B_WANTED; ! 525: tsleep (bp, PRIBIO, "getblk", 0); ! 526: goto start; ! 527: } ! 528: bp->b_flags |= B_BUSY | B_CACHE; ! 529: bremfree(bp); ! 530: if (size > bp->b_bufsize) ! 531: panic("getblk: buffer too small"); /* XXX */ ! 532: /* if (bp->b_bufsize != size) allocbuf(bp, size); */ ! 533: } else { ! 534: splx(x); ! 535: if((bp = getnewbuf(size)) == NULL) { ! 536: x = splbio(); ! 537: goto start; ! 538: } ! 539: bp->b_blkno = bp->b_lblkno = blkno; ! 540: bgetvp(vp, bp); ! 541: x = splbio(); ! 542: bh = BUFHASH(vp, blkno); ! 543: binshash(bp, bh); ! 544: bp->b_flags = B_BUSY; ! 545: } ! 546: splx(x); ! 547: return (bp); 1.1 root 548: } 549: 550: /* 1.1.1.2 ! root 551: * Get an empty, disassociated buffer of given size. 1.1 root 552: */ 553: struct buf * 554: geteblk(size) 555: int size; 556: { 1.1.1.2 ! root 557: struct buf *bp; ! 558: int x; 1.1 root 559: 1.1.1.2 ! root 560: while ((bp = getnewbuf(size)) == 0) ! 561: ; ! 562: x = splbio(); ! 563: binshash(bp, bfreelist + BQ_AGE); ! 564: splx(x); 1.1 root 565: 1.1.1.2 ! root 566: return (bp); 1.1 root 567: } 568: 569: /* 1.1.1.2 ! root 570: * Exchange a buffer's underlying buffer storage for one of different ! 571: * size, taking care to maintain contents appropriately. When buffer ! 572: * increases in size, caller is responsible for filling out additional ! 573: * contents. When buffer shrinks in size, data is lost, so caller must ! 574: * first return it to backing store before shrinking the buffer, as ! 575: * no implied I/O will be done. 1.1 root 576: */ 1.1.1.2 ! root 577: void ! 578: allocbuf(bp, size) ! 579: register struct buf *bp; ! 580: int size; 1.1 root 581: { 1.1.1.2 ! root 582: vm_size_t current_size, desired_size; ! 583: vm_offset_t new_start; ! 584: int kr; ! 585: ! 586: current_size = bp->b_bufsize; ! 587: desired_size = MAXBSIZE; /* XXX (cgd) -- round_page(size) */ ! 588: ! 589: if (current_size < desired_size) { ! 590: /* ! 591: * Buffer is growing. ! 592: * If buffer already has data, allocate new area and copy ! 593: * old data to it. ! 594: */ ! 595: #if 0 ! 596: kr = vm_allocate(buffer_map, ! 597: &new_start, ! 598: desired_size, ! 599: TRUE); ! 600: if (kr != KERN_SUCCESS) ! 601: #else ! 602: new_start = kmem_alloc (buffer_map, desired_size); ! 603: if (! new_start) ! 604: #endif ! 605: panic("allocbuf: allocate",kr); ! 606: if (debug_bio) printf(" reallocate bp: %x addr: %x size: %x\n",bp, new_start, desired_size); ! 607: if (current_size) { ! 608: bcopy(bp->b_un.b_addr, ! 609: (caddr_t) new_start, ! 610: bp->b_bufsize); ! 611: #if 0 ! 612: kr = vm_deallocate(buffer_map, ! 613: (vm_offset_t)bp->b_un.b_addr, ! 614: current_size); ! 615: if (kr != KERN_SUCCESS) ! 616: panic("allocbuf: deallocate",kr); ! 617: #else ! 618: kmem_free (buffer_map, (vm_offset_t)bp->b_un.b_addr, current_size); ! 619: #endif ! 620: if (debug_bio) printf(" deallocate bp: %x addr: %x size: %x\n",bp, bp->b_un.b_addr,bp->b_bufsize); ! 621: } ! 622: bp->b_un.b_addr = (char *)new_start; ! 623: bp->b_bufsize = desired_size; ! 624: ! 625: /* adjust buffer cache's idea of memory allocated to buffer contents */ ! 626: freebufspace -= desired_size - current_size; ! 627: allocbufspace += desired_size - current_size; ! 628: } 1.1 root 629: 1.1.1.2 ! root 630: bp->b_bcount = size; 1.1 root 631: } 632: 633: /* 1.1.1.2 ! root 634: * Patiently await operations to complete on this buffer. ! 635: * When they do, extract error value and return it. 1.1 root 636: * Extract and return any errors associated with the I/O. 1.1.1.2 ! root 637: * If an invalid block, force it off the lookup hash chains. 1.1 root 638: */ 1.1.1.2 ! root 639: int 1.1 root 640: biowait(bp) 641: register struct buf *bp; 642: { 1.1.1.2 ! root 643: int x; 1.1 root 644: 1.1.1.2 ! root 645: x = splbio(); ! 646: while ((bp->b_flags & B_DONE) == 0) ! 647: tsleep((caddr_t)bp, PRIBIO, "biowait", 0); ! 648: if((bp->b_flags & B_ERROR) || bp->b_error) { ! 649: if ((bp->b_flags & B_INVAL) == 0) { ! 650: bp->b_flags |= B_INVAL; ! 651: /* XXX ! 652: * brelse() already puts buffers with B_ERROR set on the age queue ! 653: * and i believe it's wrong to let bp->b_error override B_ERROR ! 654: * but it certainly appears to work OK this way... ! 655: */ ! 656: bremhash(bp); ! 657: binshash(bp, bfreelist + BQ_AGE); ! 658: } ! 659: if (!bp->b_error) ! 660: bp->b_error = EIO; ! 661: else ! 662: bp->b_flags |= B_ERROR; ! 663: splx(x); ! 664: return (bp->b_error); ! 665: } else { ! 666: splx(x); ! 667: return (0); ! 668: } 1.1 root 669: } 670: 671: /* 1.1.1.2 ! root 672: * Finish up operations on a buffer, calling an optional ! 673: * function (if requested), and releasing the buffer if ! 674: * marked asynchronous. Then mark this buffer done so that ! 675: * others biowait()'ing for it will notice when they are ! 676: * woken up from sleep(). 1.1 root 677: */ 1.1.1.2 ! root 678: void 1.1 root 679: biodone(bp) 680: register struct buf *bp; 681: { 1.1.1.2 ! root 682: int x; 1.1 root 683: 1.1.1.2 ! root 684: x = splbio(); ! 685: if (bp->b_flags & B_CALL) (*bp->b_iodone)(bp); ! 686: bp->b_flags &= ~B_CALL; ! 687: if ((bp->b_flags & (B_READ|B_DIRTY)) == B_DIRTY) { ! 688: bp->b_flags &= ~B_DIRTY; ! 689: vwakeup(bp); ! 690: } ! 691: if (bp->b_flags & B_ASYNC) ! 692: brelse(bp); ! 693: bp->b_flags &= ~B_ASYNC; ! 694: bp->b_flags |= B_DONE; ! 695: wakeup(bp); ! 696: splx(x); 1.1 root 697: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.