xref: /original-bsd/sys/kern/vfs_bio.c (revision 92d3de31)
1 /*	vfs_bio.c	4.44	83/05/02	*/
2 
3 #include "../machine/pte.h"
4 
5 #include "../h/param.h"
6 #include "../h/systm.h"
7 #include "../h/dir.h"
8 #include "../h/user.h"
9 #include "../h/buf.h"
10 #include "../h/conf.h"
11 #include "../h/proc.h"
12 #include "../h/seg.h"
13 #include "../h/vm.h"
14 #include "../h/trace.h"
15 
16 /*
17  * Read in (if necessary) the block and return a buffer pointer.
18  */
19 struct buf *
20 bread(dev, blkno, size)
21 	dev_t dev;
22 	daddr_t blkno;
23 	int size;
24 {
25 	register struct buf *bp;
26 
27 	if (size == 0)
28 		panic("bread: size 0");
29 	bp = getblk(dev, blkno, size);
30 	if (bp->b_flags&B_DONE) {
31 		trace(TR_BREADHIT, dev, blkno);
32 		return(bp);
33 	}
34 	bp->b_flags |= B_READ;
35 	if (bp->b_bcount > bp->b_bufsize)
36 		panic("bread");
37 	(*bdevsw[major(dev)].d_strategy)(bp);
38 	trace(TR_BREADMISS, dev, blkno);
39 	u.u_ru.ru_inblock++;		/* pay for read */
40 	biowait(bp);
41 	return(bp);
42 }
43 
44 /*
45  * Read in the block, like bread, but also start I/O on the
46  * read-ahead block (which is not allocated to the caller)
47  */
48 struct buf *
49 breada(dev, blkno, size, rablkno, rabsize)
50 	dev_t dev;
51 	daddr_t blkno; int size;
52 	daddr_t rablkno; int rabsize;
53 {
54 	register struct buf *bp, *rabp;
55 
56 	bp = NULL;
57 	/*
58 	 * If the block isn't in core, then allocate
59 	 * a buffer and initiate i/o (getblk checks
60 	 * for a cache hit).
61 	 */
62 	if (!incore(dev, blkno)) {
63 		bp = getblk(dev, blkno, size);
64 		if ((bp->b_flags&B_DONE) == 0) {
65 			bp->b_flags |= B_READ;
66 			if (bp->b_bcount > bp->b_bufsize)
67 				panic("breada");
68 			(*bdevsw[major(dev)].d_strategy)(bp);
69 			trace(TR_BREADMISS, dev, blkno);
70 			u.u_ru.ru_inblock++;		/* pay for read */
71 		} else
72 			trace(TR_BREADHIT, dev, blkno);
73 	}
74 
75 	/*
76 	 * If there's a read-ahead block, start i/o
77 	 * on it also (as above).
78 	 */
79 	if (rablkno && !incore(dev, rablkno)) {
80 		rabp = getblk(dev, rablkno, rabsize);
81 		if (rabp->b_flags & B_DONE) {
82 			brelse(rabp);
83 			trace(TR_BREADHITRA, dev, blkno);
84 		} else {
85 			rabp->b_flags |= B_READ|B_ASYNC;
86 			if (rabp->b_bcount > rabp->b_bufsize)
87 				panic("breadrabp");
88 			(*bdevsw[major(dev)].d_strategy)(rabp);
89 			trace(TR_BREADMISSRA, dev, rablock);
90 			u.u_ru.ru_inblock++;		/* pay in advance */
91 		}
92 	}
93 
94 	/*
95 	 * If block was in core, let bread get it.
96 	 * If block wasn't in core, then the read was started
97 	 * above, and just wait for it.
98 	 */
99 	if (bp == NULL)
100 		return (bread(dev, blkno, size));
101 	biowait(bp);
102 	return (bp);
103 }
104 
105 /*
106  * Write the buffer, waiting for completion.
107  * Then release the buffer.
108  */
109 bwrite(bp)
110 	register struct buf *bp;
111 {
112 	register flag;
113 
114 	flag = bp->b_flags;
115 	bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI);
116 	if ((flag&B_DELWRI) == 0)
117 		u.u_ru.ru_oublock++;		/* noone paid yet */
118 	trace(TR_BWRITE, bp->b_dev, bp->b_blkno);
119 	if (bp->b_bcount > bp->b_bufsize)
120 		panic("bwrite");
121 	(*bdevsw[major(bp->b_dev)].d_strategy)(bp);
122 
123 	/*
124 	 * If the write was synchronous, then await i/o completion.
125 	 * If the write was "delayed", then we put the buffer on
126 	 * the q of blocks awaiting i/o completion status.
127 	 */
128 	if ((flag&B_ASYNC) == 0) {
129 		biowait(bp);
130 		brelse(bp);
131 	} else if (flag & B_DELWRI)
132 		bp->b_flags |= B_AGE;
133 }
134 
135 /*
136  * Release the buffer, marking it so that if it is grabbed
137  * for another purpose it will be written out before being
138  * given up (e.g. when writing a partial block where it is
139  * assumed that another write for the same block will soon follow).
140  * This can't be done for magtape, since writes must be done
141  * in the same order as requested.
142  */
143 bdwrite(bp)
144 	register struct buf *bp;
145 {
146 	register int flags;
147 
148 	if ((bp->b_flags&B_DELWRI) == 0)
149 		u.u_ru.ru_oublock++;		/* noone paid yet */
150 	flags = bdevsw[major(bp->b_dev)].d_flags;
151 	if(flags & B_TAPE)
152 		bawrite(bp);
153 	else {
154 		bp->b_flags |= B_DELWRI | B_DONE;
155 		brelse(bp);
156 	}
157 }
158 
159 /*
160  * Release the buffer, start I/O on it, but don't wait for completion.
161  */
162 bawrite(bp)
163 	register struct buf *bp;
164 {
165 
166 	bp->b_flags |= B_ASYNC;
167 	bwrite(bp);
168 }
169 
170 /*
171  * Release the buffer, with no I/O implied.
172  */
173 brelse(bp)
174 	register struct buf *bp;
175 {
176 	register struct buf *flist;
177 	register s;
178 
179 	/*
180 	 * If someone's waiting for the buffer, or
181 	 * is waiting for a buffer wake 'em up.
182 	 */
183 	if (bp->b_flags&B_WANTED)
184 		wakeup((caddr_t)bp);
185 	if (bfreelist[0].b_flags&B_WANTED) {
186 		bfreelist[0].b_flags &= ~B_WANTED;
187 		wakeup((caddr_t)bfreelist);
188 	}
189 	if (bp->b_flags&B_ERROR)
190 		if (bp->b_flags & B_LOCKED)
191 			bp->b_flags &= ~B_ERROR;	/* try again later */
192 		else
193 			bp->b_dev = NODEV;  		/* no assoc */
194 
195 	/*
196 	 * Stick the buffer back on a free list.
197 	 */
198 	s = spl6();
199 	if (bp->b_bufsize <= 0) {
200 		/* block has no buffer ... put at front of unused buffer list */
201 		flist = &bfreelist[BQ_EMPTY];
202 		binsheadfree(bp, flist);
203 	} else if (bp->b_flags & (B_ERROR|B_INVAL)) {
204 		/* block has no info ... put at front of most free list */
205 		flist = &bfreelist[BQ_AGE];
206 		binsheadfree(bp, flist);
207 	} else {
208 		if (bp->b_flags & B_LOCKED)
209 			flist = &bfreelist[BQ_LOCKED];
210 		else if (bp->b_flags & B_AGE)
211 			flist = &bfreelist[BQ_AGE];
212 		else
213 			flist = &bfreelist[BQ_LRU];
214 		binstailfree(bp, flist);
215 	}
216 	bp->b_flags &= ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE);
217 	splx(s);
218 }
219 
220 /*
221  * See if the block is associated with some buffer
222  * (mainly to avoid getting hung up on a wait in breada)
223  */
224 incore(dev, blkno)
225 	dev_t dev;
226 	daddr_t blkno;
227 {
228 	register struct buf *bp;
229 	register struct buf *dp;
230 
231 	dp = BUFHASH(dev, blkno);
232 	for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
233 		if (bp->b_blkno == blkno && bp->b_dev == dev &&
234 		    (bp->b_flags & B_INVAL) == 0)
235 			return (1);
236 	return (0);
237 }
238 
239 struct buf *
240 baddr(dev, blkno, size)
241 	dev_t dev;
242 	daddr_t blkno;
243 	int size;
244 {
245 
246 	if (incore(dev, blkno))
247 		return (bread(dev, blkno, size));
248 	return (0);
249 }
250 
251 /*
252  * Assign a buffer for the given block.  If the appropriate
253  * block is already associated, return it; otherwise search
254  * for the oldest non-busy buffer and reassign it.
255  *
256  * We use splx here because this routine may be called
257  * on the interrupt stack during a dump, and we don't
258  * want to lower the ipl back to 0.
259  */
260 struct buf *
261 getblk(dev, blkno, size)
262 	dev_t dev;
263 	daddr_t blkno;
264 	int size;
265 {
266 	register struct buf *bp, *dp;
267 	int s;
268 
269 	if ((unsigned)blkno >= 1 << (sizeof(int)*NBBY-PGSHIFT))	/* XXX */
270 		blkno = 1 << ((sizeof(int)*NBBY-PGSHIFT) + 1);
271 	/*
272 	 * Search the cache for the block.  If we hit, but
273 	 * the buffer is in use for i/o, then we wait until
274 	 * the i/o has completed.
275 	 */
276 	dp = BUFHASH(dev, blkno);
277 loop:
278 	for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) {
279 		if (bp->b_blkno != blkno || bp->b_dev != dev ||
280 		    bp->b_flags&B_INVAL)
281 			continue;
282 		s = spl6();
283 		if (bp->b_flags&B_BUSY) {
284 			bp->b_flags |= B_WANTED;
285 			sleep((caddr_t)bp, PRIBIO+1);
286 			splx(s);
287 			goto loop;
288 		}
289 		splx(s);
290 		notavail(bp);
291 		if (brealloc(bp, size) == 0)
292 			goto loop;
293 		bp->b_flags |= B_CACHE;
294 		return(bp);
295 	}
296 	if (major(dev) >= nblkdev)
297 		panic("blkdev");
298 	bp = getnewbuf();
299 	bfree(bp);
300 	bremhash(bp);
301 	binshash(bp, dp);
302 	bp->b_dev = dev;
303 	bp->b_blkno = blkno;
304 	bp->b_error = 0;
305 	if (brealloc(bp, size) == 0)
306 		goto loop;
307 	return(bp);
308 }
309 
310 /*
311  * get an empty block,
312  * not assigned to any particular device
313  */
314 struct buf *
315 geteblk(size)
316 	int size;
317 {
318 	register struct buf *bp, *flist;
319 
320 loop:
321 	bp = getnewbuf();
322 	bp->b_flags |= B_INVAL;
323 	bfree(bp);
324 	bremhash(bp);
325 	flist = &bfreelist[BQ_AGE];
326 	binshash(bp, flist);
327 	bp->b_dev = (dev_t)NODEV;
328 	bp->b_error = 0;
329 	if (brealloc(bp, size) == 0)
330 		goto loop;
331 	return(bp);
332 }
333 
334 /*
335  * Allocate space associated with a buffer.
336  * If can't get space, buffer is released
337  */
338 brealloc(bp, size)
339 	register struct buf *bp;
340 	int size;
341 {
342 	daddr_t start, last;
343 	register struct buf *ep;
344 	struct buf *dp;
345 	int s;
346 
347 	/*
348 	 * First need to make sure that all overlaping previous I/O
349 	 * is dispatched with.
350 	 */
351 	if (size == bp->b_bcount)
352 		return (1);
353 	if (size < bp->b_bcount) {
354 		if (bp->b_flags & B_DELWRI) {
355 			bwrite(bp);
356 			return (0);
357 		}
358 		if (bp->b_flags & B_LOCKED)
359 			panic("brealloc");
360 		return (allocbuf(bp, size));
361 	}
362 	bp->b_flags &= ~B_DONE;
363 	if (bp->b_dev == NODEV)
364 		return (allocbuf(bp, size));
365 
366 	/*
367 	 * Search cache for any buffers that overlap the one that we
368 	 * are trying to allocate. Overlapping buffers must be marked
369 	 * invalid, after being written out if they are dirty. (indicated
370 	 * by B_DELWRI) A disk block must be mapped by at most one buffer
371 	 * at any point in time. Care must be taken to avoid deadlocking
372 	 * when two buffer are trying to get the same set of disk blocks.
373 	 */
374 	start = bp->b_blkno;
375 	last = start + (size / DEV_BSIZE) - 1;
376 	dp = BUFHASH(bp->b_dev, bp->b_blkno);
377 loop:
378 	for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
379 		if (ep == bp || ep->b_dev != bp->b_dev || (ep->b_flags&B_INVAL))
380 			continue;
381 		/* look for overlap */
382 		if (ep->b_bcount == 0 || ep->b_blkno > last ||
383 		    ep->b_blkno + (ep->b_bcount / DEV_BSIZE) <= start)
384 			continue;
385 		s = spl6();
386 		if (ep->b_flags&B_BUSY) {
387 			ep->b_flags |= B_WANTED;
388 			sleep((caddr_t)ep, PRIBIO+1);
389 			splx(s);
390 			goto loop;
391 		}
392 		splx(s);
393 		notavail(ep);
394 		if (ep->b_flags & B_DELWRI) {
395 			bwrite(ep);
396 			goto loop;
397 		}
398 		ep->b_flags |= B_INVAL;
399 		brelse(ep);
400 	}
401 	return (allocbuf(bp, size));
402 }
403 
404 /*
405  * Expand or contract the actual memory allocated to a buffer.
406  * If no memory is available, release buffer and take error exit
407  */
408 allocbuf(tp, size)
409 	register struct buf *tp;
410 	int size;
411 {
412 	register struct buf *bp, *ep;
413 	int sizealloc, take;
414 #ifdef sun
415 	register char *a;
416 	int osize;
417 #endif
418 
419 #ifndef sun
420 	sizealloc = roundup(size, CLBYTES);
421 #else
422 	sizealloc = roundup(size, BUFALLOCSIZE);
423 #endif
424 	/*
425 	 * Buffer size does not change
426 	 */
427 	if (sizealloc == tp->b_bufsize)
428 		goto out;
429 #ifndef sun
430 	/*
431 	 * Buffer size is shrinking.
432 	 * Place excess space in a buffer header taken from the
433 	 * BQ_EMPTY buffer list and placed on the "most free" list.
434 	 * If no extra buffer headers are available, leave the
435 	 * extra space in the present buffer.
436 	 */
437 	if (sizealloc < tp->b_bufsize) {
438 		ep = bfreelist[BQ_EMPTY].av_forw;
439 		if (ep == &bfreelist[BQ_EMPTY])
440 			goto out;
441 		notavail(ep);
442 		pagemove(tp->b_un.b_addr + sizealloc, ep->b_un.b_addr,
443 		    (int)tp->b_bufsize - sizealloc);
444 		ep->b_bufsize = tp->b_bufsize - sizealloc;
445 		tp->b_bufsize = sizealloc;
446 		ep->b_flags |= B_INVAL;
447 		ep->b_bcount = 0;
448 		brelse(ep);
449 		goto out;
450 	}
451 	/*
452 	 * More buffer space is needed. Get it out of buffers on
453 	 * the "most free" list, placing the empty headers on the
454 	 * BQ_EMPTY buffer header list.
455 	 */
456 	while (tp->b_bufsize < sizealloc) {
457 		take = sizealloc - tp->b_bufsize;
458 		bp = getnewbuf();
459 		if (take >= bp->b_bufsize)
460 			take = bp->b_bufsize;
461 		pagemove(&bp->b_un.b_addr[bp->b_bufsize - take],
462 		    &tp->b_un.b_addr[tp->b_bufsize], take);
463 		tp->b_bufsize += take;
464 		bp->b_bufsize = bp->b_bufsize - take;
465 		if (bp->b_bcount > bp->b_bufsize)
466 			bp->b_bcount = bp->b_bufsize;
467 		if (bp->b_bufsize <= 0) {
468 			bremhash(bp);
469 			binshash(bp, &bfreelist[BQ_EMPTY]);
470 			bp->b_dev = (dev_t)NODEV;
471 			bp->b_error = 0;
472 			bp->b_flags |= B_INVAL;
473 		}
474 		brelse(bp);
475 	}
476 #else
477 	/*
478 	 * Buffer size is shrinking
479 	 * Just put the tail end back in the map
480 	 */
481 	if (sizealloc < tp->b_bufsize) {
482 		rmfree(buffermap, (long)(tp->b_bufsize - sizealloc),
483 			(long)(tp->b_un.b_addr + sizealloc));
484 		tp->b_bufsize = sizealloc;
485 		goto out;
486 	}
487 	/*
488 	 * Buffer is being expanded or created
489 	 * If being expanded, attempt to get contiguous
490 	 * section, otherwise get a new chunk and copy.
491 	 * If no space, free up a buffer on the AGE list
492 	 * and try again.
493 	 */
494 	do {
495 		if ((osize = tp->b_bufsize)) {
496 			a = (char *)rmget(buffermap, (long)(sizealloc-osize),
497 				(long)(tp->b_un.b_addr + osize));
498 			if (a == 0) {
499 				a = (char *)rmalloc(buffermap, (long)sizealloc);
500 				if (a != 0) {
501 					bcopy(tp->b_un.b_addr, a, osize);
502 					rmfree(buffermap, (long)osize,
503 						(long)tp->b_un.b_addr);
504 					tp->b_un.b_addr = a;
505 				}
506 			}
507 		} else {
508 			a = (char *)rmalloc(buffermap, (long)sizealloc);
509 			if (a != 0)
510 				tp->b_un.b_addr = a;
511 		}
512 	} while (a == 0 && bfreemem());
513 	if (a == 0) {
514 		brelse(tp);
515 		return (0);
516 	}
517 	tp->b_bufsize = sizealloc;
518 #endif
519 out:
520 	tp->b_bcount = size;
521 	return (1);
522 }
523 
524 /*
525  * Release space associated with a buffer.
526  */
527 bfree(bp)
528 	struct buf *bp;
529 {
530 #ifdef sun
531 	if (bp->b_bufsize) {
532 		rmfree(buffermap, (long)bp->b_bufsize, (long)bp->b_un.b_addr);
533 		bp->b_bufsize = 0;
534 	}
535 #endif
536 	bp->b_bcount = 0;
537 }
538 
539 #ifdef sun
540 /*
541  * Attempt to free up buffer space by flushing
542  * something in the free list.
543  * Don't wait for something, that could cause deadlocks
544  * We start with BQ_AGE because we know BQ_EMPTY take no memory.
545  */
546 bfreemem()
547 {
548 	register struct buf *bp, *dp;
549 	int s;
550 
551 loop:
552 	s = spl6();
553 	for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--)
554 		if (dp->av_forw != dp)
555 			break;
556 	splx(s);
557 	if (dp == bfreelist) {		/* no free blocks */
558 		return (0);
559 	}
560 	bp = dp->av_forw;
561 	notavail(bp);
562 	if (bp->b_flags & B_DELWRI) {
563 		bp->b_flags |= B_ASYNC;
564 		bwrite(bp);
565 		goto loop;
566 	}
567 	trace(TR_BRELSE, bp->b_dev, bp->b_blkno);
568 	bp->b_flags = B_BUSY | B_INVAL;
569 	bfree(bp);
570 	bremhash(bp);
571 	binshash(bp, &bfreelist[BQ_EMPTY]);
572 	bp->b_dev = (dev_t)NODEV;
573 	bp->b_error = 0;
574 	brelse(bp);
575 	return (1);
576 }
577 #endif
578 
579 /*
580  * Find a buffer which is available for use.
581  * Select something from a free list.
582  * Preference is to AGE list, then LRU list.
583  */
584 struct buf *
585 getnewbuf()
586 {
587 	register struct buf *bp, *dp;
588 	int s;
589 
590 loop:
591 	s = spl6();
592 #ifndef sun
593 	for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--)
594 #else
595 	for (dp = &bfreelist[BQ_EMPTY]; dp > bfreelist; dp--)
596 #endif
597 		if (dp->av_forw != dp)
598 			break;
599 	if (dp == bfreelist) {		/* no free blocks */
600 		dp->b_flags |= B_WANTED;
601 		sleep((caddr_t)dp, PRIBIO+1);
602 		splx(s);
603 		goto loop;
604 	}
605 	splx(s);
606 	bp = dp->av_forw;
607 	notavail(bp);
608 	if (bp->b_flags & B_DELWRI) {
609 		bp->b_flags |= B_ASYNC;
610 		bwrite(bp);
611 		goto loop;
612 	}
613 	trace(TR_BRELSE, bp->b_dev, bp->b_blkno);
614 	bp->b_flags = B_BUSY;
615 	return (bp);
616 }
617 
618 /*
619  * Wait for I/O completion on the buffer; return errors
620  * to the user.
621  */
622 biowait(bp)
623 	register struct buf *bp;
624 {
625 	int s;
626 
627 	s = spl6();
628 	while ((bp->b_flags&B_DONE)==0)
629 		sleep((caddr_t)bp, PRIBIO);
630 	splx(s);
631 	if (u.u_error == 0)			/* XXX */
632 		u.u_error = geterror(bp);
633 }
634 
635 /*
636  * Mark I/O complete on a buffer. If the header
637  * indicates a dirty page push completion, the
638  * header is inserted into the ``cleaned'' list
639  * to be processed by the pageout daemon. Otherwise
640  * release it if I/O is asynchronous, and wake
641  * up anyone waiting for it.
642  */
643 biodone(bp)
644 	register struct buf *bp;
645 {
646 	register int s;
647 
648 	if (bp->b_flags & B_DONE)
649 		panic("dup biodone");
650 	bp->b_flags |= B_DONE;
651 	if (bp->b_flags & B_DIRTY) {
652 		if (bp->b_flags & B_ERROR)
653 			panic("IO err in push");
654 		s = spl6();
655 		bp->av_forw = bclnlist;
656 		bp->b_bcount = swsize[bp - swbuf];
657 		bp->b_pfcent = swpf[bp - swbuf];
658 		cnt.v_pgout++;
659 		cnt.v_pgpgout += bp->b_bcount / NBPG;
660 		bclnlist = bp;
661 		if (bswlist.b_flags & B_WANTED)
662 			wakeup((caddr_t)&proc[2]);
663 		splx(s);
664 		return;
665 	}
666 	if (bp->b_flags & B_CALL) {
667 		bp->b_flags &= ~B_CALL;
668 		(*bp->b_iodone)(bp);
669 		return;
670 	}
671 	if (bp->b_flags&B_ASYNC)
672 		brelse(bp);
673 	else {
674 		bp->b_flags &= ~B_WANTED;
675 		wakeup((caddr_t)bp);
676 	}
677 }
678 
679 /*
680  * Insure that no part of a specified block is in an incore buffer.
681  */
682 blkflush(dev, blkno, size)
683 	dev_t dev;
684 	daddr_t blkno;
685 	long size;
686 {
687 	register struct buf *ep;
688 	struct buf *dp;
689 	daddr_t start, last;
690 	int s;
691 
692 	start = blkno;
693 	last = start + (size / DEV_BSIZE) - 1;
694 	dp = BUFHASH(dev, blkno);
695 loop:
696 	for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
697 		if (ep->b_dev != dev || (ep->b_flags&B_INVAL))
698 			continue;
699 		/* look for overlap */
700 		if (ep->b_bcount == 0 || ep->b_blkno > last ||
701 		    ep->b_blkno + (ep->b_bcount / DEV_BSIZE) <= start)
702 			continue;
703 		s = spl6();
704 		if (ep->b_flags&B_BUSY) {
705 			ep->b_flags |= B_WANTED;
706 			sleep((caddr_t)ep, PRIBIO+1);
707 			splx(s);
708 			goto loop;
709 		}
710 		if (ep->b_flags & B_DELWRI) {
711 			splx(s);
712 			notavail(ep);
713 			bwrite(ep);
714 			goto loop;
715 		}
716 		splx(s);
717 	}
718 }
719 
720 /*
721  * make sure all write-behind blocks
722  * on dev (or NODEV for all)
723  * are flushed out.
724  * (from umount and update)
725  * (and temporarily pagein)
726  */
727 bflush(dev)
728 	dev_t dev;
729 {
730 	register struct buf *bp;
731 	register struct buf *flist;
732 	int s;
733 
734 loop:
735 	s = spl6();
736 	for (flist = bfreelist; flist < &bfreelist[BQ_EMPTY]; flist++)
737 	for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) {
738 		if ((bp->b_flags & B_DELWRI) == 0)
739 			continue;
740 		if (dev == NODEV || dev == bp->b_dev) {
741 			bp->b_flags |= B_ASYNC;
742 			notavail(bp);
743 			bwrite(bp);
744 			splx(s);
745 			goto loop;
746 		}
747 	}
748 	splx(s);
749 }
750 
751 /*
752  * Pick up the device's error number and pass it to the user;
753  * if there is an error but the number is 0 set a generalized
754  * code.  Actually the latter is always true because devices
755  * don't yet return specific errors.
756  */
757 geterror(bp)
758 	register struct buf *bp;
759 {
760 	int error = 0;
761 
762 	if (bp->b_flags&B_ERROR)
763 		if ((error = bp->b_error)==0)
764 			return (EIO);
765 	return (error);
766 }
767 
768 /*
769  * Invalidate in core blocks belonging to closed or umounted filesystem
770  *
771  * This is not nicely done at all - the buffer ought to be removed from the
772  * hash chains & have its dev/blkno fields clobbered, but unfortunately we
773  * can't do that here, as it is quite possible that the block is still
774  * being used for i/o. Eventually, all disc drivers should be forced to
775  * have a close routine, which ought ensure that the queue is empty, then
776  * properly flush the queues. Until that happy day, this suffices for
777  * correctness.						... kre
778  */
779 binval(dev)
780 	dev_t dev;
781 {
782 	register struct buf *bp;
783 	register struct bufhd *hp;
784 #define dp ((struct buf *)hp)
785 
786 	for (hp = bufhash; hp < &bufhash[BUFHSZ]; hp++)
787 		for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
788 			if (bp->b_dev == dev)
789 				bp->b_flags |= B_INVAL;
790 }
791