X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/4c05b581c07ca671261303f2e20bfd01425117cc..84baaab36073dd5d55807ec0c2f16fbd545b7219:/usr/src/sys/kern/vfs_cluster.c diff --git a/usr/src/sys/kern/vfs_cluster.c b/usr/src/sys/kern/vfs_cluster.c index 37ad963dbd..02c6db1047 100644 --- a/usr/src/sys/kern/vfs_cluster.c +++ b/usr/src/sys/kern/vfs_cluster.c @@ -1,4 +1,4 @@ -/* vfs_cluster.c 4.14 %G% */ +/* vfs_cluster.c 4.33 82/06/07 */ #include "../h/param.h" #include "../h/systm.h" @@ -12,115 +12,27 @@ #include "../h/vm.h" #include "../h/trace.h" -/* - * The following several routines allocate and free - * buffers with various side effects. In general the - * arguments to an allocate routine are a device and - * a block number, and the value is a pointer to - * to the buffer header; the buffer is marked "busy" - * so that no one else can touch it. If the block was - * already in core, no I/O need be done; if it is - * already busy, the process waits until it becomes free. - * The following routines allocate a buffer: - * getblk - * bread - * breada - * baddr (if it is incore) - * Eventually the buffer must be released, possibly with the - * side effect of writing it out, by using one of - * bwrite - * bdwrite - * bawrite - * brelse - */ - -#define BUFHSZ 63 -struct bufhd bufhash[BUFHSZ]; -#define BUFHASH(dev, dblkno) \ - ((struct buf *)&bufhash[((int)(dev)+(int)(dblkno)) % BUFHSZ]) - -/* - * Initialize hash links for buffers. - */ -bhinit() -{ - register int i; - register struct bufhd *bp; - - for (bp = bufhash, i = 0; i < BUFHSZ; i++, bp++) - bp->b_forw = bp->b_back = (struct buf *)bp; -} - -/* #define DISKMON 1 */ - -#ifdef DISKMON -struct { - int nbuf; - long nread; - long nreada; - long ncache; - long nwrite; - long bufcount[64]; -} io_info; -#endif - -/* - * Swap IO headers - - * They contain the necessary information for the swap I/O. - * At any given time, a swap header can be in three - * different lists. When free it is in the free list, - * when allocated and the I/O queued, it is on the swap - * device list, and finally, if the operation was a dirty - * page push, when the I/O completes, it is inserted - * in a list of cleaned pages to be processed by the pageout daemon. - */ -struct buf *swbuf; -short *swsize; /* CAN WE JUST USE B_BCOUNT? */ -int *swpf; - - -#ifndef UNFAST -#define notavail(bp) \ -{ \ - int s = spl6(); \ - (bp)->av_back->av_forw = (bp)->av_forw; \ - (bp)->av_forw->av_back = (bp)->av_back; \ - (bp)->b_flags |= B_BUSY; \ - splx(s); \ -} -#endif - /* * Read in (if necessary) the block and return a buffer pointer. */ struct buf * -bread(dev, blkno) -dev_t dev; -daddr_t blkno; +bread(dev, blkno, size) + dev_t dev; + daddr_t blkno; + int size; { register struct buf *bp; - bp = getblk(dev, blkno); + bp = getblk(dev, blkno, size); if (bp->b_flags&B_DONE) { -#ifdef EPAWNJ - trace(TR_BREAD|TR_HIT, dev, blkno); -#endif -#ifdef DISKMON - io_info.ncache++; -#endif + trace(TR_BREADHIT, dev, blkno); return(bp); } bp->b_flags |= B_READ; - bp->b_bcount = BSIZE; (*bdevsw[major(dev)].d_strategy)(bp); -#ifdef EPAWNJ - trace(TR_BREAD|TR_MISS, dev, blkno); -#endif -#ifdef DISKMON - io_info.nread++; -#endif + trace(TR_BREADMISS, dev, blkno); u.u_vm.vm_inblk++; /* pay for read */ - iowait(bp); + biowait(bp); return(bp); } @@ -129,56 +41,56 @@ daddr_t blkno; * read-ahead block (which is not allocated to the caller) */ struct buf * -breada(dev, blkno, rablkno) -dev_t dev; -daddr_t blkno, rablkno; +breada(dev, blkno, size, rablkno, rasize) + dev_t dev; + daddr_t blkno; int size; + daddr_t rablkno; int rasize; { register struct buf *bp, *rabp; bp = NULL; + /* + * If the block isn't in core, then allocate + * a buffer and initiate i/o (getblk checks + * for a cache hit). + */ if (!incore(dev, blkno)) { - bp = getblk(dev, blkno); + bp = getblk(dev, blkno, size); if ((bp->b_flags&B_DONE) == 0) { bp->b_flags |= B_READ; - bp->b_bcount = BSIZE; (*bdevsw[major(dev)].d_strategy)(bp); -#ifdef EPAWNJ - trace(TR_BREAD|TR_MISS, dev, blkno); -#endif -#ifdef DISKMON - io_info.nread++; -#endif + trace(TR_BREADMISS, dev, blkno); u.u_vm.vm_inblk++; /* pay for read */ - } -#ifdef EPAWNJ - else - trace(TR_BREAD|TR_HIT, dev, blkno); -#endif + } else + trace(TR_BREADHIT, dev, blkno); } + + /* + * If there's a read-ahead block, start i/o + * on it also (as above). + */ if (rablkno && !incore(dev, rablkno)) { - rabp = getblk(dev, rablkno); + rabp = getblk(dev, rablkno, rasize); if (rabp->b_flags & B_DONE) { brelse(rabp); -#ifdef EPAWNJ - trace(TR_BREAD|TR_HIT|TR_RA, dev, blkno); -#endif + trace(TR_BREADHITRA, dev, blkno); } else { rabp->b_flags |= B_READ|B_ASYNC; - rabp->b_bcount = BSIZE; (*bdevsw[major(dev)].d_strategy)(rabp); -#ifdef EPAWNJ - trace(TR_BREAD|TR_MISS|TR_RA, dev, rablock); -#endif -#ifdef DISKMON - io_info.nreada++; -#endif + trace(TR_BREADMISSRA, dev, rablock); u.u_vm.vm_inblk++; /* pay in advance */ } } - if(bp == NULL) - return(bread(dev, blkno)); - iowait(bp); - return(bp); + + /* + * If block was in core, let bread get it. + * If block wasn't in core, then the read was started + * above, and just wait for it. + */ + if (bp == NULL) + return (bread(dev, blkno, size)); + biowait(bp); + return (bp); } /* @@ -186,24 +98,26 @@ daddr_t blkno, rablkno; * Then release the buffer. */ bwrite(bp) -register struct buf *bp; + register struct buf *bp; { register flag; flag = bp->b_flags; bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI | B_AGE); - bp->b_bcount = BSIZE; -#ifdef DISKMON - io_info.nwrite++; -#endif if ((flag&B_DELWRI) == 0) u.u_vm.vm_oublk++; /* noone paid yet */ -#ifdef EPAWNJ - trace(TR_BWRITE, bp->b_dev, dbtofsb(bp->b_blkno)); -#endif + trace(TR_BWRITE, bp->b_dev, bp->b_blkno); (*bdevsw[major(bp->b_dev)].d_strategy)(bp); + + /* + * If the write was synchronous, then await i/o completion. + * If the write was "delayed", then we put the buffer on + * the q of blocks awaiting i/o completion status. + * Otherwise, the i/o must be finished and we check for + * an error. + */ if ((flag&B_ASYNC) == 0) { - iowait(bp); + biowait(bp); brelse(bp); } else if (flag & B_DELWRI) bp->b_flags |= B_AGE; @@ -220,7 +134,7 @@ register struct buf *bp; * in the same order as requested. */ bdwrite(bp) -register struct buf *bp; + register struct buf *bp; { register int flags; @@ -239,7 +153,7 @@ register struct buf *bp; * Release the buffer, start I/O on it, but don't wait for completion. */ bawrite(bp) -register struct buf *bp; + register struct buf *bp; { bp->b_flags |= B_ASYNC; @@ -247,14 +161,18 @@ register struct buf *bp; } /* - * release the buffer, with no I/O implied. + * Release the buffer, with no I/O implied. */ brelse(bp) -register struct buf *bp; + register struct buf *bp; { register struct buf *flist; register s; + /* + * If someone's waiting for the buffer, or + * is waiting for a buffer wake 'em up. + */ if (bp->b_flags&B_WANTED) wakeup((caddr_t)bp); if (bfreelist[0].b_flags&B_WANTED) { @@ -266,14 +184,15 @@ register struct buf *bp; bp->b_flags &= ~B_ERROR; /* try again later */ else bp->b_dev = NODEV; /* no assoc */ + + /* + * Stick the buffer back on a free list. + */ s = spl6(); if (bp->b_flags & (B_ERROR|B_INVAL)) { /* block has no info ... put at front of most free list */ flist = &bfreelist[BQUEUES-1]; - flist->av_forw->av_back = bp; - bp->av_forw = flist->av_forw; - flist->av_forw = bp; - bp->av_back = flist; + binsheadfree(bp, flist); } else { if (bp->b_flags & B_LOCKED) flist = &bfreelist[BQ_LOCKED]; @@ -281,10 +200,7 @@ register struct buf *bp; flist = &bfreelist[BQ_AGE]; else flist = &bfreelist[BQ_LRU]; - flist->av_back->av_forw = bp; - bp->av_back = flist->av_back; - flist->av_back = bp; - bp->av_forw = flist; + binstailfree(bp, flist); } bp->b_flags &= ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE); splx(s); @@ -295,29 +211,29 @@ register struct buf *bp; * (mainly to avoid getting hung up on a wait in breada) */ incore(dev, blkno) -dev_t dev; -daddr_t blkno; + dev_t dev; + daddr_t blkno; { register struct buf *bp; register struct buf *dp; - register int dblkno = fsbtodb(blkno); - dp = BUFHASH(dev, dblkno); + dp = BUFHASH(dev, blkno); for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) - if (bp->b_blkno == dblkno && bp->b_dev == dev && - !(bp->b_flags & B_INVAL)) + if (bp->b_blkno == blkno && bp->b_dev == dev && + (bp->b_flags & B_INVAL) == 0) return (1); return (0); } struct buf * -baddr(dev, blkno) -dev_t dev; -daddr_t blkno; +baddr(dev, blkno, size) + dev_t dev; + daddr_t blkno; + int size; { if (incore(dev, blkno)) - return (bread(dev, blkno)); + return (bread(dev, blkno, size)); return (0); } @@ -325,61 +241,63 @@ daddr_t blkno; * Assign a buffer for the given block. If the appropriate * block is already associated, return it; otherwise search * for the oldest non-busy buffer and reassign it. + * + * We use splx here because this routine may be called + * on the interrupt stack during a dump, and we don't + * want to lower the ipl back to 0. */ struct buf * -getblk(dev, blkno) -dev_t dev; -daddr_t blkno; +getblk(dev, blkno, size) + dev_t dev; + daddr_t blkno; + int size; { register struct buf *bp, *dp, *ep; - register int dblkno = fsbtodb(blkno); -#ifdef DISKMON - register int i; -#endif + int s; if ((unsigned)blkno >= 1 << (sizeof(int)*NBBY-PGSHIFT)) blkno = 1 << ((sizeof(int)*NBBY-PGSHIFT) + 1); - dblkno = fsbtodb(blkno); - dp = BUFHASH(dev, dblkno); - loop: - (void) spl0(); + /* + * Search the cache for the block. If we hit, but + * the buffer is in use for i/o, then we wait until + * the i/o has completed. + */ + dp = BUFHASH(dev, blkno); +loop: for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) { - if (bp->b_blkno != dblkno || bp->b_dev != dev || + if (bp->b_blkno != blkno || bp->b_dev != dev || bp->b_flags&B_INVAL) continue; - (void) spl6(); + s = spl6(); if (bp->b_flags&B_BUSY) { bp->b_flags |= B_WANTED; sleep((caddr_t)bp, PRIBIO+1); + splx(s); goto loop; } - (void) spl0(); -#ifdef DISKMON - i = 0; - dp = bp->av_forw; - while ((dp->b_flags & B_HEAD) == 0) { - i++; - dp = dp->av_forw; - } - if (i<64) - io_info.bufcount[i]++; -#endif + splx(s); notavail(bp); + brealloc(bp, size); bp->b_flags |= B_CACHE; return(bp); } if (major(dev) >= nblkdev) panic("blkdev"); - (void) spl6(); + /* + * Not found in the cache, select something from + * a free list. Preference is to LRU list, then AGE list. + */ + s = spl6(); for (ep = &bfreelist[BQUEUES-1]; ep > bfreelist; ep--) if (ep->av_forw != ep) break; if (ep == bfreelist) { /* no free blocks at all */ ep->b_flags |= B_WANTED; sleep((caddr_t)ep, PRIBIO+1); + splx(s); goto loop; } - (void) spl0(); + splx(s); bp = ep->av_forw; notavail(bp); if (bp->b_flags & B_DELWRI) { @@ -387,18 +305,14 @@ daddr_t blkno; bwrite(bp); goto loop; } -#ifdef EPAWNJ - trace(TR_BRELSE, bp->b_dev, dbtofsb(bp->b_blkno)); -#endif + trace(TR_BRELSE, bp->b_dev, bp->b_blkno); bp->b_flags = B_BUSY; - bp->b_back->b_forw = bp->b_forw; - bp->b_forw->b_back = bp->b_back; - bp->b_forw = dp->b_forw; - bp->b_back = dp; - dp->b_forw->b_back = bp; - dp->b_forw = bp; + bfree(bp); + bremhash(bp); + binshash(bp, dp); bp->b_dev = dev; - bp->b_blkno = dblkno; + bp->b_blkno = blkno; + brealloc(bp, size); return(bp); } @@ -407,12 +321,14 @@ daddr_t blkno; * not assigned to any particular device */ struct buf * -geteblk() +geteblk(size) + int size; { register struct buf *bp, *dp; + int s; loop: - (void) spl6(); + s = spl6(); for (dp = &bfreelist[BQUEUES-1]; dp > bfreelist; dp--) if (dp->av_forw != dp) break; @@ -421,7 +337,7 @@ loop: sleep((caddr_t)dp, PRIBIO+1); goto loop; } - (void) spl0(); + splx(s); bp = dp->av_forw; notavail(bp); if (bp->b_flags & B_DELWRI) { @@ -429,52 +345,109 @@ loop: bwrite(bp); goto loop; } -#ifdef EPAWNJ - trace(TR_BRELSE, bp->b_dev, dbtofsb(bp->b_blkno)); -#endif + trace(TR_BRELSE, bp->b_dev, bp->b_blkno); bp->b_flags = B_BUSY|B_INVAL; - bp->b_back->b_forw = bp->b_forw; - bp->b_forw->b_back = bp->b_back; - bp->b_forw = dp->b_forw; - bp->b_back = dp; - dp->b_forw->b_back = bp; - dp->b_forw = bp; + bfree(bp); + bremhash(bp); + binshash(bp, dp); bp->b_dev = (dev_t)NODEV; + brealloc(bp, size); return(bp); } /* - * Wait for I/O completion on the buffer; return errors - * to the user. + * Allocate space associated with a buffer. */ -iowait(bp) -register struct buf *bp; +brealloc(bp, size) + register struct buf *bp; + int size; { + daddr_t start, last; + register struct buf *ep; + struct buf *dp; + int s; - (void) spl6(); - while ((bp->b_flags&B_DONE)==0) - sleep((caddr_t)bp, PRIBIO); - (void) spl0(); - geterror(bp); + /* + * First need to make sure that all overlaping previous I/O + * is dispatched with. + */ + if (size == bp->b_bcount) + return; + if (size < bp->b_bcount || bp->b_dev == NODEV) + goto allocit; + + start = bp->b_blkno + (bp->b_bcount / DEV_BSIZE); + last = bp->b_blkno + (size / DEV_BSIZE) - 1; + if (bp->b_bcount == 0) { + start++; + if (start == last) + goto allocit; + } + dp = BUFHASH(bp->b_dev, bp->b_blkno); +loop: + for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) { + if (ep->b_blkno < start || ep->b_blkno > last || + ep->b_dev != bp->b_dev || ep->b_flags&B_INVAL) + continue; + s = spl6(); + if (ep->b_flags&B_BUSY) { + ep->b_flags |= B_WANTED; + sleep((caddr_t)ep, PRIBIO+1); + (void) splx(s); + goto loop; + } + (void) splx(s); + /* + * What we would really like to do is kill this + * I/O since it is now useless. We cannot do that + * so we force it to complete, so that it cannot + * over-write our useful data later. + */ + if (ep->b_flags & B_DELWRI) { + notavail(ep); + ep->b_flags |= B_ASYNC; + bwrite(ep); + goto loop; + } + } +allocit: + /* + * Here the buffer is already available, so all we + * need to do is set the size. Someday a better memory + * management scheme will be implemented. + */ + bp->b_bcount = size; } -#ifdef UNFAST /* - * Unlink a buffer from the available list and mark it busy. - * (internal interface) + * Release space associated with a buffer. */ -notavail(bp) -register struct buf *bp; +bfree(bp) + struct buf *bp; { - register s; + /* + * Here the buffer does not change, so all we + * need to do is set the size. Someday a better memory + * management scheme will be implemented. + */ + bp->b_bcount = 0; +} + +/* + * Wait for I/O completion on the buffer; return errors + * to the user. + */ +biowait(bp) + register struct buf *bp; +{ + int s; s = spl6(); - bp->av_back->av_forw = bp->av_forw; - bp->av_forw->av_back = bp->av_back; - bp->b_flags |= B_BUSY; + while ((bp->b_flags&B_DONE)==0) + sleep((caddr_t)bp, PRIBIO); splx(s); + geterror(bp); } -#endif /* * Mark I/O complete on a buffer. If the header @@ -484,22 +457,23 @@ register struct buf *bp; * release it if I/O is asynchronous, and wake * up anyone waiting for it. */ -iodone(bp) -register struct buf *bp; +biodone(bp) + register struct buf *bp; { register int s; if (bp->b_flags & B_DONE) - panic("dup iodone"); + panic("dup biodone"); bp->b_flags |= B_DONE; if (bp->b_flags & B_DIRTY) { if (bp->b_flags & B_ERROR) panic("IO err in push"); s = spl6(); - cnt.v_pgout++; bp->av_forw = bclnlist; bp->b_bcount = swsize[bp - swbuf]; bp->b_pfcent = swpf[bp - swbuf]; + cnt.v_pgout++; + cnt.v_pgpgout += bp->b_bcount / NBPG; bclnlist = bp; if (bswlist.b_flags & B_WANTED) wakeup((caddr_t)&proc[2]); @@ -514,237 +488,34 @@ register struct buf *bp; } } -/* - * Zero the core associated with a buffer. - */ -clrbuf(bp) -struct buf *bp; -{ - register *p; - register c; - - p = bp->b_un.b_words; - c = BSIZE/sizeof(int); - do - *p++ = 0; - while (--c); - bp->b_resid = 0; -} - -/* - * swap I/O - - * - * If the flag indicates a dirty page push initiated - * by the pageout daemon, we map the page into the i th - * virtual page of process 2 (the daemon itself) where i is - * the index of the swap header that has been allocated. - * We simply initialize the header and queue the I/O but - * do not wait for completion. When the I/O completes, - * iodone() will link the header to a list of cleaned - * pages to be processed by the pageout daemon. - */ -swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent) - struct proc *p; - swblk_t dblkno; - caddr_t addr; - int flag, nbytes; - dev_t dev; - unsigned pfcent; -{ - register struct buf *bp; - register int c; - int p2dp; - register struct pte *dpte, *vpte; - - (void) spl6(); - while (bswlist.av_forw == NULL) { - bswlist.b_flags |= B_WANTED; - sleep((caddr_t)&bswlist, PSWP+1); - } - bp = bswlist.av_forw; - bswlist.av_forw = bp->av_forw; - (void) spl0(); - - bp->b_flags = B_BUSY | B_PHYS | rdflg | flag; - if ((bp->b_flags & (B_DIRTY|B_PGIN)) == 0) - if (rdflg == B_READ) - sum.v_pswpin += btoc(nbytes); - else - sum.v_pswpout += btoc(nbytes); - bp->b_proc = p; - if (flag & B_DIRTY) { - p2dp = ((bp - swbuf) * CLSIZE) * KLMAX; - dpte = dptopte(&proc[2], p2dp); - vpte = vtopte(p, btop(addr)); - for (c = 0; c < nbytes; c += NBPG) { - if (vpte->pg_pfnum == 0 || vpte->pg_fod) - panic("swap bad pte"); - *dpte++ = *vpte++; - } - bp->b_un.b_addr = (caddr_t)ctob(p2dp); - } else - bp->b_un.b_addr = addr; - while (nbytes > 0) { - c = imin(ctob(120), nbytes); - bp->b_bcount = c; - bp->b_blkno = dblkno; - bp->b_dev = dev; - if (flag & B_DIRTY) { - swpf[bp - swbuf] = pfcent; - swsize[bp - swbuf] = nbytes; - } - (*bdevsw[major(dev)].d_strategy)(bp); - if (flag & B_DIRTY) { - if (c < nbytes) - panic("big push"); - return; - } - (void) spl6(); - while((bp->b_flags&B_DONE)==0) - sleep((caddr_t)bp, PSWP); - (void) spl0(); - bp->b_un.b_addr += c; - bp->b_flags &= ~B_DONE; - if (bp->b_flags & B_ERROR) { - if ((flag & (B_UAREA|B_PAGET)) || rdflg == B_WRITE) - panic("hard IO err in swap"); - swkill(p, (char *)0); - } - nbytes -= c; - dblkno += btoc(c); - } - (void) spl6(); - bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY); - bp->av_forw = bswlist.av_forw; - bswlist.av_forw = bp; - if (bswlist.b_flags & B_WANTED) { - bswlist.b_flags &= ~B_WANTED; - wakeup((caddr_t)&bswlist); - wakeup((caddr_t)&proc[2]); - } - (void) spl0(); -} - -/* - * If rout == 0 then killed on swap error, else - * rout is the name of the routine where we ran out of - * swap space. - */ -swkill(p, rout) - struct proc *p; - char *rout; -{ - - printf("%d: ", p->p_pid); - if (rout) - printf("out of swap space in %s\n", rout); - else - printf("killed on swap error\n"); - /* - * To be sure no looping (e.g. in vmsched trying to - * swap out) mark process locked in core (as though - * done by user) after killing it so noone will try - * to swap it out. - */ - psignal(p, SIGKILL); - p->p_flag |= SULOCK; -} - /* * make sure all write-behind blocks * on dev (or NODEV for all) * are flushed out. * (from umount and update) + * (and temporarily pagein) */ bflush(dev) -dev_t dev; + dev_t dev; { register struct buf *bp; register struct buf *flist; + int s; loop: - (void) spl6(); + s = spl6(); for (flist = bfreelist; flist < &bfreelist[BQUEUES]; flist++) for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) { - if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) { + if ((bp->b_flags & B_DELWRI) == 0) + continue; + if (dev == NODEV || dev == bp->b_dev) { bp->b_flags |= B_ASYNC; notavail(bp); bwrite(bp); goto loop; } } - (void) spl0(); -} - -/* - * Raw I/O. The arguments are - * The strategy routine for the device - * A buffer, which will always be a special buffer - * header owned exclusively by the device for this purpose - * The device number - * Read/write flag - * Essentially all the work is computing physical addresses and - * validating them. - * If the user has the proper access privilidges, the process is - * marked 'delayed unlock' and the pages involved in the I/O are - * faulted and locked. After the completion of the I/O, the above pages - * are unlocked. - */ -physio(strat, bp, dev, rw, mincnt) -int (*strat)(); -register struct buf *bp; -unsigned (*mincnt)(); -{ - register int c; - char *a; - - if (useracc(u.u_base,u.u_count,rw==B_READ?B_WRITE:B_READ) == NULL) { - u.u_error = EFAULT; - return; - } - (void) spl6(); - while (bp->b_flags&B_BUSY) { - bp->b_flags |= B_WANTED; - sleep((caddr_t)bp, PRIBIO+1); - } - bp->b_error = 0; - bp->b_proc = u.u_procp; - bp->b_un.b_addr = u.u_base; - while (u.u_count != 0 && bp->b_error==0) { - bp->b_flags = B_BUSY | B_PHYS | rw; - bp->b_dev = dev; - bp->b_blkno = u.u_offset >> PGSHIFT; - bp->b_bcount = u.u_count; - (*mincnt)(bp); - c = bp->b_bcount; - u.u_procp->p_flag |= SPHYSIO; - vslock(a = bp->b_un.b_addr, c); - (*strat)(bp); - (void) spl6(); - while ((bp->b_flags&B_DONE) == 0) - sleep((caddr_t)bp, PRIBIO); - vsunlock(a, c, rw); - u.u_procp->p_flag &= ~SPHYSIO; - if (bp->b_flags&B_WANTED) - wakeup((caddr_t)bp); - (void) spl0(); - bp->b_un.b_addr += c; - u.u_count -= c; - u.u_offset += c; - } - bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS); - u.u_count = bp->b_resid; - geterror(bp); -} - -/*ARGSUSED*/ -unsigned -minphys(bp) -struct buf *bp; -{ - - if (bp->b_bcount > 60 * 1024) - bp->b_bcount = 60 * 1024; + splx(s); } /* @@ -754,7 +525,7 @@ struct buf *bp; * don't yet return specific errors. */ geterror(bp) -register struct buf *bp; + register struct buf *bp; { if (bp->b_flags&B_ERROR) @@ -774,7 +545,7 @@ register struct buf *bp; * correctness. ... kre */ binval(dev) -dev_t dev; + dev_t dev; { register struct buf *bp; register struct bufhd *hp;