|
|
1.1 root 1: /* bio.c 4.21 81/05/08 */
2:
3: #include "../h/param.h"
4: #include "../h/systm.h"
5: #include "../h/dir.h"
6: #include "../h/user.h"
7: #include "../h/buf.h"
8: #include "../h/conf.h"
9: #include "../h/proc.h"
10: #include "../h/seg.h"
11: #include "../machine/pte.h"
12: #include "../h/vm.h"
13: #include "../h/trace.h"
14: #include "../h/share.h"
15:
16: /*
17: * The following several routines allocate and free
18: * buffers with various side effects. In general the
19: * arguments to an allocate routine are a device and
20: * a block number, and the value is a pointer to
21: * to the buffer header; the buffer is marked "busy"
22: * so that no one else can touch it. If the block was
23: * already in core, no I/O need be done; if it is
24: * already busy, the process waits until it becomes free.
25: * The following routines allocate a buffer:
26: * getblk
27: * bread
28: * breada
29: * baddr (if it is incore)
30: * Eventually the buffer must be released, possibly with the
31: * side effect of writing it out, by using one of
32: * bwrite
33: * bdwrite
34: * bawrite
35: * brelse
36: */
37:
38: struct buf bfreelist[BQUEUES];
39: struct buf bswlist, *bclnlist;
40:
41: #define BUFHSZ 63
42: struct bufhd bufhash[BUFHSZ];
43: #define BUFHASH(dev, dblkno) \
44: ((struct buf *)&bufhash[((int)(dev)+(int)(dblkno)) % BUFHSZ])
45:
46: /*
47: * Initialize hash links for buffers.
48: */
49: bhinit()
50: {
51: register int i;
52: register struct bufhd *bp;
53:
54: for (bp = bufhash, i = 0; i < BUFHSZ; i++, bp++)
55: bp->b_forw = bp->b_back = (struct buf *)bp;
56: }
57:
58: /* #define DISKMON 1 */
59:
60: #ifdef DISKMON
61: struct {
62: long ndwrite; /* bdwrite, not real io */
63: long nread; /* someone's waiting for this one */
64: long nreada; /* readahead from disk */
65: long ncache; /* blocks found in cache, so not read */
66: long nwrite; /* acutally written */
67: long bufcount[64];
68: } io_info;
69: #endif
70:
71: /*
72: * Swap IO headers -
73: * They contain the necessary information for the swap I/O.
74: * At any given time, a swap header can be in three
75: * different lists. When free it is in the free list,
76: * when allocated and the I/O queued, it is on the swap
77: * device list, and finally, if the operation was a dirty
78: * page push, when the I/O completes, it is inserted
79: * in a list of cleaned pages to be processed by the pageout daemon.
80: */
81: struct buf *swbuf;
82: short *swsize; /* CAN WE JUST USE B_BCOUNT? */
83: int *swpf;
84:
85:
86: #ifndef UNFAST
87: #define notavail(bp) \
88: { \
89: int s = spl6(); \
90: (bp)->av_back->av_forw = (bp)->av_forw; \
91: (bp)->av_forw->av_back = (bp)->av_back; \
92: (bp)->b_flags |= B_BUSY; \
93: splx(s); \
94: }
95: #endif
96:
97: /*
98: * Read in (if necessary) the block and return a buffer pointer.
99: */
100: struct buf *
101: bread(dev, blkno)
102: dev_t dev;
103: daddr_t blkno;
104: {
105: register struct buf *bp;
106:
107: bp = getblk(dev, blkno);
108: if (bp->b_flags&B_DONE) {
109: #ifdef DISKMON
110: io_info.ncache++;
111: #endif
112: return(bp);
113: }
114: bp->b_flags |= B_READ;
115: bp->b_bcount = BSIZE(dev);
116: (*bdevsw[major(dev)].d_strategy)(bp);
117: #ifdef DISKMON
118: io_info.nread++;
119: #endif
120: u.u_vm.vm_inblk++; /* pay for read */
121: u.u_procp->p_lnode->kl_cost += shconsts.sc_bio;
122: shconsts.sc_bioc++;
123: iowait(bp);
124: return(bp);
125: }
126:
127: /*
128: * Read in the block, like bread, but also start I/O on the
129: * read-ahead block (which is not allocated to the caller)
130: */
131: struct buf *
132: breada(dev, blkno, rablkno)
133: dev_t dev;
134: daddr_t blkno, rablkno;
135: {
136: register struct buf *bp, *rabp;
137:
138: bp = NULL;
139: if (!incore(dev, blkno)) {
140: bp = getblk(dev, blkno);
141: if ((bp->b_flags&B_DONE) == 0) {
142: bp->b_flags |= B_READ;
143: bp->b_bcount = BSIZE(dev);
144: (*bdevsw[major(dev)].d_strategy)(bp);
145: #ifdef DISKMON
146: io_info.nread++;
147: #endif
148: u.u_vm.vm_inblk++; /* pay for read */
149: u.u_procp->p_lnode->kl_cost += shconsts.sc_bio;
150: shconsts.sc_bioc++;
151: }
152: }
153: if (rablkno && !incore(dev, rablkno)) {
154: rabp = getblk(dev, rablkno);
155: if (rabp->b_flags & B_DONE) {
156: brelse(rabp);
157: } else {
158: rabp->b_flags |= B_READ|B_ASYNC;
159: rabp->b_bcount = BSIZE(dev);
160: (*bdevsw[major(dev)].d_strategy)(rabp);
161: #ifdef DISKMON
162: io_info.nreada++;
163: #endif
164: u.u_vm.vm_inblk++; /* pay in advance */
165: u.u_procp->p_lnode->kl_cost += shconsts.sc_bio;
166: shconsts.sc_bioc++;
167: }
168: }
169: if(bp == NULL)
170: return(bread(dev, blkno));
171: iowait(bp);
172: return(bp);
173: }
174:
175: /*
176: * Write the buffer, waiting for completion.
177: * Then release the buffer.
178: */
179: bwrite(bp)
180: register struct buf *bp;
181: {
182: register flag;
183:
184: flag = bp->b_flags;
185: bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI | B_AGE);
186: bp->b_bcount = BSIZE(bp->b_dev);
187: #ifdef DISKMON
188: io_info.nwrite++;
189: #endif
190: u.u_procp->p_lnode->kl_cost += shconsts.sc_bio;
191: shconsts.sc_bioc++;
192: if ((flag&B_DELWRI) == 0)
193: u.u_vm.vm_oublk++; /* noone paid yet */
194: (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
195: if ((flag&B_ASYNC) == 0) {
196: iowait(bp);
197: brelse(bp);
198: } else if (flag & B_DELWRI)
199: bp->b_flags |= B_AGE;
200: else
201: geterror(bp);
202: }
203:
204: /*
205: * Release the buffer, marking it so that if it is grabbed
206: * for another purpose it will be written out before being
207: * given up (e.g. when writing a partial block where it is
208: * assumed that another write for the same block will soon follow).
209: * This can't be done for magtape, since writes must be done
210: * in the same order as requested.
211: */
212: bdwrite(bp)
213: register struct buf *bp;
214: {
215: register int flags;
216:
217: if ((bp->b_flags&B_DELWRI) == 0)
218: u.u_vm.vm_oublk++; /* noone paid yet */
219: flags = bdevsw[major(bp->b_dev)].d_flags;
220: if(flags & B_TAPE)
221: bawrite(bp);
222: else {
223: #ifdef DISKMON
224: io_info.ndwrite++;
225: #endif
226: u.u_procp->p_lnode->kl_cost += shconsts.sc_bio;
227: shconsts.sc_bioc++;
228: bp->b_flags |= B_DELWRI | B_DONE;
229: brelse(bp);
230: }
231: }
232:
233: /*
234: * Release the buffer, start I/O on it, but don't wait for completion.
235: */
236: bawrite(bp)
237: register struct buf *bp;
238: {
239:
240: bp->b_flags |= B_ASYNC;
241: bwrite(bp);
242: }
243:
244: /*
245: * release the buffer, with no I/O implied.
246: */
247: brelse(bp)
248: register struct buf *bp;
249: {
250: register struct buf *flist;
251: register s;
252:
253: if (bp->b_flags&B_WANTED)
254: wakeup((caddr_t)bp);
255: if (bfreelist[0].b_flags&B_WANTED) {
256: bfreelist[0].b_flags &= ~B_WANTED;
257: wakeup((caddr_t)bfreelist);
258: }
259: if (bp->b_flags&B_ERROR)
260: if (bp->b_flags & B_LOCKED)
261: bp->b_flags &= ~B_ERROR; /* try again later */
262: else
263: bp->b_dev = NODEV; /* no assoc */
264: s = spl6();
265: if (bp->b_flags & (B_ERROR|B_INVAL)) {
266: /* block has no info ... put at front of most free list */
267: flist = &bfreelist[BQUEUES-1];
268: flist->av_forw->av_back = bp;
269: bp->av_forw = flist->av_forw;
270: flist->av_forw = bp;
271: bp->av_back = flist;
272: } else {
273: if (bp->b_flags & B_LOCKED)
274: flist = &bfreelist[BQ_LOCKED];
275: else if (bp->b_flags & B_AGE)
276: flist = &bfreelist[BQ_AGE];
277: else
278: flist = &bfreelist[BQ_LRU];
279: flist->av_back->av_forw = bp;
280: bp->av_back = flist->av_back;
281: flist->av_back = bp;
282: bp->av_forw = flist;
283: }
284: bp->b_flags &= ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE);
285: splx(s);
286: }
287:
288: /*
289: * See if the block is associated with some buffer
290: * (mainly to avoid getting hung up on a wait in breada)
291: */
292: incore(dev, blkno)
293: dev_t dev;
294: daddr_t blkno;
295: {
296: register struct buf *bp;
297: register struct buf *dp;
298: register int dblkno = fsbtodb(dev, blkno);
299:
300: dp = BUFHASH(dev, dblkno);
301: for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
302: if (bp->b_blkno == dblkno && bp->b_dev == dev &&
303: !(bp->b_flags & B_INVAL))
304: return (1);
305: return (0);
306: }
307:
308: struct buf *
309: baddr(dev, blkno)
310: dev_t dev;
311: daddr_t blkno;
312: {
313:
314: if (incore(dev, blkno))
315: return (bread(dev, blkno));
316: return (0);
317: }
318:
319: /*
320: * Assign a buffer for the given block. If the appropriate
321: * block is already associated, return it; otherwise search
322: * for the oldest non-busy buffer and reassign it.
323: */
324: struct buf *
325: getblk(dev, blkno)
326: dev_t dev;
327: daddr_t blkno;
328: {
329: register struct buf *bp, *dp, *ep;
330: register int dblkno = fsbtodb(dev, blkno);
331: #ifdef DISKMON
332: register int i;
333: #endif
334:
335: if ((unsigned)blkno >= 1 << (sizeof(int)*NBBY-PGSHIFT))
336: blkno = 1 << ((sizeof(int)*NBBY-PGSHIFT) + 1);
337: dblkno = fsbtodb(dev, blkno);
338: dp = BUFHASH(dev, dblkno);
339: loop:
340: (void) spl0();
341: for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) {
342: if (bp->b_blkno != dblkno || bp->b_dev != dev ||
343: bp->b_flags&B_INVAL)
344: continue;
345: (void) spl6();
346: if (bp->b_flags&B_BUSY) {
347: bp->b_flags |= B_WANTED;
348: sleep((caddr_t)bp, PRIBIO+1);
349: goto loop;
350: }
351: (void) spl0();
352: #ifdef DISKMON
353: i = 0;
354: dp = bp->av_forw;
355: while ((dp->b_flags & B_HEAD) == 0) {
356: i++;
357: dp = dp->av_forw;
358: }
359: if (i<64)
360: io_info.bufcount[i]++;
361: #endif
362: notavail(bp);
363: bp->b_flags |= B_CACHE;
364: return(bp);
365: }
366: if (major(dev) >= nblkdev)
367: panic("blkdev");
368: (void) spl6();
369: for (ep = &bfreelist[BQUEUES-1]; ep > bfreelist; ep--)
370: if (ep->av_forw != ep)
371: break;
372: if (ep == bfreelist) { /* no free blocks at all */
373: ep->b_flags |= B_WANTED;
374: sleep((caddr_t)ep, PRIBIO+1);
375: goto loop;
376: }
377: (void) spl0();
378: bp = ep->av_forw;
379: notavail(bp);
380: if (bp->b_flags & B_DELWRI) {
381: bp->b_flags |= B_ASYNC;
382: bwrite(bp);
383: goto loop;
384: }
385: bp->b_flags = B_BUSY | (u.u_procp->p_usrpri << B_PRISHIFT);
386: bp->b_back->b_forw = bp->b_forw;
387: bp->b_forw->b_back = bp->b_back;
388: bp->b_forw = dp->b_forw;
389: bp->b_back = dp;
390: dp->b_forw->b_back = bp;
391: dp->b_forw = bp;
392: bp->b_dev = dev;
393: bp->b_blkno = dblkno;
394: return(bp);
395: }
396:
397: /*
398: * get an empty block,
399: * not assigned to any particular device
400: */
401: struct buf *
402: geteblk()
403: {
404: register struct buf *bp, *dp;
405: register int s;
406:
407: loop:
408: s = spl6();
409: for (dp = &bfreelist[BQUEUES-1]; dp > bfreelist; dp--)
410: if (dp->av_forw != dp)
411: break;
412: if (dp == bfreelist) { /* no free blocks */
413: dp->b_flags |= B_WANTED;
414: sleep((caddr_t)dp, PRIBIO+1);
415: goto loop;
416: }
417: (void) splx(s);
418: bp = dp->av_forw;
419: notavail(bp);
420: if (bp->b_flags & B_DELWRI) {
421: bp->b_flags |= B_ASYNC;
422: bwrite(bp);
423: goto loop;
424: }
425: bp->b_flags = B_BUSY | B_INVAL | (u.u_procp->p_usrpri << B_PRISHIFT);
426: bp->b_back->b_forw = bp->b_forw;
427: bp->b_forw->b_back = bp->b_back;
428: bp->b_forw = dp->b_forw;
429: bp->b_back = dp;
430: dp->b_forw->b_back = bp;
431: dp->b_forw = bp;
432: bp->b_dev = (dev_t)NODEV;
433: return(bp);
434: }
435:
436: /*
437: * Wait for I/O completion on the buffer; return errors
438: * to the user.
439: */
440: iowait(bp)
441: register struct buf *bp;
442: {
443:
444: (void) spl6();
445: while ((bp->b_flags&B_DONE)==0)
446: sleep((caddr_t)bp, PRIBIO);
447: (void) spl0();
448: geterror(bp);
449: }
450:
451: #ifdef UNFAST
452: /*
453: * Unlink a buffer from the available list and mark it busy.
454: * (internal interface)
455: */
456: notavail(bp)
457: register struct buf *bp;
458: {
459: register s;
460:
461: s = spl6();
462: bp->av_back->av_forw = bp->av_forw;
463: bp->av_forw->av_back = bp->av_back;
464: bp->b_flags |= B_BUSY;
465: splx(s);
466: }
467: #endif
468:
469: /*
470: * Mark I/O complete on a buffer. If the header
471: * indicates a dirty page push completion, the
472: * header is inserted into the ``cleaned'' list
473: * to be processed by the pageout daemon. Otherwise
474: * release it if I/O is asynchronous, and wake
475: * up anyone waiting for it.
476: */
477: iodone(bp)
478: register struct buf *bp;
479: {
480: register int s;
481:
482: if (bp->b_flags & B_DONE)
483: panic("dup iodone");
484: bp->b_flags |= B_DONE;
485: if (bp->b_flags & B_DIRTY) {
486: if (bp->b_flags & B_ERROR)
487: panic("IO err in push");
488: s = spl6();
489: bp->av_forw = bclnlist;
490: bp->b_bcount = swsize[bp - swbuf];
491: bp->b_pfcent = swpf[bp - swbuf];
492: cnt.v_pgout++;
493: cnt.v_pgpgout += bp->b_bcount / NBPG;
494: bclnlist = bp;
495: if (bswlist.b_flags & B_WANTED)
496: wakeup((caddr_t)&proc[2]);
497: splx(s);
498: return;
499: }
500: if (bp->b_flags&B_ASYNC)
501: brelse(bp);
502: else {
503: bp->b_flags &= ~B_WANTED;
504: wakeup((caddr_t)bp);
505: }
506: }
507:
508: /*
509: * Zero the core associated with a buffer.
510: */
511: clrbuf(bp)
512: struct buf *bp;
513: {
514: register *p;
515: register c;
516:
517: p = bp->b_un.b_words;
518: c = BUFSIZE/sizeof(int);
519: do
520: *p++ = 0;
521: while (--c);
522: bp->b_resid = 0;
523: }
524:
525: /*
526: * swap I/O -
527: *
528: * If the flag indicates a dirty page push initiated
529: * by the pageout daemon, we map the page into the i th
530: * virtual page of process 2 (the daemon itself) where i is
531: * the index of the swap header that has been allocated.
532: * We simply initialize the header and queue the I/O but
533: * do not wait for completion. When the I/O completes,
534: * iodone() will link the header to a list of cleaned
535: * pages to be processed by the pageout daemon.
536: */
537: swap(p, dblkno, addr, nbytes, rdflg, flag, dev, pfcent)
538: struct proc *p;
539: swblk_t dblkno;
540: caddr_t addr;
541: int flag, nbytes;
542: dev_t dev;
543: unsigned pfcent;
544: {
545: register struct buf *bp;
546: register int c;
547: int p2dp;
548: register struct pte *dpte, *vpte;
549: int s;
550:
551: s = spl6();
552: while (bswlist.av_forw == NULL) {
553: bswlist.b_flags |= B_WANTED;
554: sleep((caddr_t)&bswlist, PSWP+1);
555: }
556: bp = bswlist.av_forw;
557: bswlist.av_forw = bp->av_forw;
558: (void) splx(s);
559:
560: bp->b_flags = B_BUSY | B_PHYS | rdflg | flag;
561: if ((bp->b_flags & (B_DIRTY|B_PGIN)) == 0)
562: if (rdflg == B_READ)
563: sum.v_pswpin += btoc(nbytes);
564: else
565: sum.v_pswpout += btoc(nbytes);
566: bp->b_proc = p;
567: if (flag & B_DIRTY) {
568: p2dp = ((bp - swbuf) * CLSIZE) * KLMAX;
569: dpte = dptopte(&proc[2], p2dp);
570: vpte = vtopte(p, btop(addr));
571: for (c = 0; c < nbytes; c += NBPG) {
572: if (vpte->pg_pfnum == 0 || vpte->pg_fod)
573: panic("swap bad pte");
574: *dpte++ = *vpte++;
575: }
576: bp->b_un.b_addr = (caddr_t)ctob(dptov(&proc[2], p2dp));
577: } else
578: bp->b_un.b_addr = addr;
579: while (nbytes > 0) {
580: bp->b_bcount = nbytes;
581: bp->b_blkno = dblkno;
582: bp->b_dev = dev;
583: minphys(bp);
584: c = bp->b_bcount;
585: if (flag & B_DIRTY) {
586: swpf[bp - swbuf] = pfcent;
587: swsize[bp - swbuf] = nbytes;
588: }
589: physstrat(bp, bdevsw[major(dev)].d_strategy, PSWP);
590: if (flag & B_DIRTY) {
591: if (c < nbytes)
592: panic("big push");
593: return;
594: }
595: bp->b_un.b_addr += c;
596: bp->b_flags &= ~B_DONE;
597: if (bp->b_flags & B_ERROR) {
598: if ((flag & (B_UAREA|B_PAGET)) || rdflg == B_WRITE)
599: panic("hard IO err in swap");
600: swkill(p, (char *)0);
601: }
602: nbytes -= c;
603: dblkno += c >> 9;
604: }
605: s = spl6();
606: bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS|B_PAGET|B_UAREA|B_DIRTY);
607: bp->av_forw = bswlist.av_forw;
608: bswlist.av_forw = bp;
609: if (bswlist.b_flags & B_WANTED) {
610: bswlist.b_flags &= ~B_WANTED;
611: wakeup((caddr_t)&bswlist);
612: wakeup((caddr_t)&proc[2]);
613: }
614: (void) splx(s);
615: }
616:
617: /*
618: * If rout == 0 then killed on swap error, else
619: * rout is the name of the routine where we ran out of
620: * swap space.
621: */
622: swkill(p, rout)
623: struct proc *p;
624: char *rout;
625: {
626: char *mesg;
627:
628: printf("pid %d: ", p->p_pid);
629: if (rout)
630: printf(mesg = "killed due to no swap space\n");
631: else
632: printf(mesg = "killed on swap error\n");
633: uprintf("sorry, pid %d was %s", p->p_pid, mesg);
634: /*
635: * To be sure no looping (e.g. in vmsched trying to
636: * swap out) mark process locked in core (as though
637: * done by user) after killing it so noone will try
638: * to swap it out.
639: */
640: psignal(p, SIGKILL);
641: p->p_flag |= SULOCK;
642: }
643:
644: /*
645: * make sure all write-behind blocks
646: * on dev (or NODEV for all)
647: * are flushed out.
648: * (from umount and update)
649: */
650: bflush(dev)
651: dev_t dev;
652: {
653: register struct buf *bp;
654: register struct buf *flist;
655:
656: loop:
657: spl6();
658: trace(TR_BFIN, dev, 1);
659: for (flist = bfreelist; flist < &bfreelist[BQUEUES]; flist++)
660: for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) {
661: if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) {
662: bp->b_flags |= B_ASYNC;
663: notavail(bp);
664: bwrite(bp);
665: goto loop;
666: }
667: }
668: trace(TR_BFOUT, s, 1);
669: (void) spl0();
670: }
671:
672: /*
673: * Raw I/O. The arguments are
674: * The strategy routine for the device
675: * A buffer, which will always be a special buffer
676: * header owned exclusively by the device for this purpose
677: * The device number
678: * Read/write flag
679: * Essentially all the work is computing physical addresses and
680: * validating them.
681: * If the user has the proper access privilidges, the process is
682: * marked 'delayed unlock' and the pages involved in the I/O are
683: * faulted and locked. After the completion of the I/O, the above pages
684: * are unlocked.
685: */
686: physio(strat, bp, dev, rw, mincnt)
687: int (*strat)();
688: register struct buf *bp;
689: unsigned (*mincnt)();
690: {
691: register int c;
692: char *a;
693: register int s;
694:
695: if (useracc(u.u_base,u.u_count,rw==B_READ?B_WRITE:B_READ) == NULL) {
696: u.u_error = EFAULT;
697: return;
698: }
699: s = spl6();
700: while (bp->b_flags&B_BUSY) {
701: bp->b_flags |= B_WANTED;
702: /*sleep((caddr_t)bp, PRIBIO+1);*/
703: switch(tsleep((caddr_t)bp, PRIBIO+1, 20)) {
704: case TS_OK:
705: continue;
706: case TS_SIG: /* can't happen at PRIBIO+1*/
707: continue;
708: case TS_TIME:
709: u.u_error = EIO;
710: (void) splx(s);
711: return;
712: }
713: }
714: (void) splx(s);
715: bp->b_error = 0;
716: bp->b_proc = u.u_procp;
717: bp->b_un.b_addr = u.u_base;
718: while (u.u_count != 0) {
719: bp->b_flags = B_BUSY | B_PHYS | rw | (u.u_procp->p_usrpri << B_PRISHIFT);
720: bp->b_dev = dev;
721: bp->b_blkno = fsbtodb(dev, u.u_offset >> PGSHIFT);
722: bp->b_bcount = u.u_count;
723: (*mincnt)(bp);
724: c = bp->b_bcount;
725: u.u_procp->p_flag |= SPHYSIO;
726: vslock(a = bp->b_un.b_addr, c);
727: physstrat(bp, strat, PRIBIO);
728: spl6();
729: vsunlock(a, c, rw);
730: u.u_procp->p_flag &= ~SPHYSIO;
731: if (bp->b_flags&B_WANTED)
732: wakeup((caddr_t)bp);
733: (void) splx(s);
734: bp->b_un.b_addr += c;
735: u.u_count -= c;
736: u.u_offset += c;
737: if (bp->b_flags&B_ERROR)
738: break;
739: }
740: bp->b_flags &= ~(B_BUSY|B_WANTED|B_PHYS);
741: u.u_count = bp->b_resid;
742: geterror(bp);
743: }
744:
745: /*ARGSUSED*/
746: unsigned
747: minphys(bp)
748: struct buf *bp;
749: {
750:
751: if (bp->b_bcount > 56 * 1024)
752: bp->b_bcount = 56 * 1024;
753: }
754:
755: /*
756: * Pick up the device's error number and pass it to the user;
757: * if there is an error but the number is 0 set a generalized
758: * code. Actually the latter is always true because devices
759: * don't yet return specific errors.
760: */
761: geterror(bp)
762: register struct buf *bp;
763: {
764:
765: if (bp->b_flags&B_ERROR)
766: if ((u.u_error = bp->b_error)==0)
767: u.u_error = EIO;
768: }
769:
770: /*
771: * Invalidate in core blocks belonging to closed or umounted filesystem
772: *
773: * This is not nicely done at all - the buffer ought to be removed from the
774: * hash chains & have its dev/blkno fields clobbered, but unfortunately we
775: * can't do that here, as it is quite possible that the block is still
776: * being used for i/o. Eventually, all disc drivers should be forced to
777: * have a close routine, which ought ensure that the queue is empty, then
778: * properly flush the queues. Until that happy day, this suffices for
779: * correctness. ... kre
780: */
781: binval(dev)
782: dev_t dev;
783: {
784: register struct buf *bp;
785: register struct bufhd *hp;
786: #define dp ((struct buf *)hp)
787:
788: for (hp = bufhash; hp < &bufhash[BUFHSZ]; hp++)
789: for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
790: if (bp->b_dev == dev)
791: bp->b_flags |= B_INVAL;
792: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.