xref: /csrg-svn/sys/kern/vfs_cluster.c (revision 11841)
1 /*	vfs_cluster.c	4.42	83/04/04	*/
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 		goto loop;
603 	}
604 	splx(s);
605 	bp = dp->av_forw;
606 	notavail(bp);
607 	if (bp->b_flags & B_DELWRI) {
608 		bp->b_flags |= B_ASYNC;
609 		bwrite(bp);
610 		goto loop;
611 	}
612 	trace(TR_BRELSE, bp->b_dev, bp->b_blkno);
613 	bp->b_flags = B_BUSY;
614 	return (bp);
615 }
616 
617 /*
618  * Wait for I/O completion on the buffer; return errors
619  * to the user.
620  */
621 biowait(bp)
622 	register struct buf *bp;
623 {
624 	int s;
625 
626 	s = spl6();
627 	while ((bp->b_flags&B_DONE)==0)
628 		sleep((caddr_t)bp, PRIBIO);
629 	splx(s);
630 	if (u.u_error == 0)			/* XXX */
631 		u.u_error = geterror(bp);
632 }
633 
634 /*
635  * Mark I/O complete on a buffer. If the header
636  * indicates a dirty page push completion, the
637  * header is inserted into the ``cleaned'' list
638  * to be processed by the pageout daemon. Otherwise
639  * release it if I/O is asynchronous, and wake
640  * up anyone waiting for it.
641  */
642 biodone(bp)
643 	register struct buf *bp;
644 {
645 	register int s;
646 
647 	if (bp->b_flags & B_DONE)
648 		panic("dup biodone");
649 	bp->b_flags |= B_DONE;
650 	if (bp->b_flags & B_DIRTY) {
651 		if (bp->b_flags & B_ERROR)
652 			panic("IO err in push");
653 		s = spl6();
654 		bp->av_forw = bclnlist;
655 		bp->b_bcount = swsize[bp - swbuf];
656 		bp->b_pfcent = swpf[bp - swbuf];
657 		cnt.v_pgout++;
658 		cnt.v_pgpgout += bp->b_bcount / NBPG;
659 		bclnlist = bp;
660 		if (bswlist.b_flags & B_WANTED)
661 			wakeup((caddr_t)&proc[2]);
662 		splx(s);
663 		return;
664 	}
665 	if (bp->b_flags & B_CALL) {
666 		bp->b_flags &= ~B_CALL;
667 		(*bp->b_iodone)(bp);
668 		return;
669 	}
670 	if (bp->b_flags&B_ASYNC)
671 		brelse(bp);
672 	else {
673 		bp->b_flags &= ~B_WANTED;
674 		wakeup((caddr_t)bp);
675 	}
676 }
677 
678 /*
679  * Insure that no part of a specified block is in an incore buffer.
680  */
681 blkflush(dev, blkno, size)
682 	dev_t dev;
683 	daddr_t blkno;
684 	long size;
685 {
686 	register struct buf *ep;
687 	struct buf *dp;
688 	daddr_t start, last;
689 	int s;
690 
691 	start = blkno;
692 	last = start + (size / DEV_BSIZE) - 1;
693 	dp = BUFHASH(dev, blkno);
694 loop:
695 	for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
696 		if (ep->b_dev != dev || (ep->b_flags&B_INVAL))
697 			continue;
698 		/* look for overlap */
699 		if (ep->b_bcount == 0 || ep->b_blkno > last ||
700 		    ep->b_blkno + (ep->b_bcount / DEV_BSIZE) <= start)
701 			continue;
702 		s = spl6();
703 		if (ep->b_flags&B_BUSY) {
704 			ep->b_flags |= B_WANTED;
705 			sleep((caddr_t)ep, PRIBIO+1);
706 			splx(s);
707 			goto loop;
708 		}
709 		if (ep->b_flags & B_DELWRI) {
710 			splx(s);
711 			notavail(ep);
712 			bwrite(ep);
713 			goto loop;
714 		}
715 		splx(s);
716 	}
717 }
718 
719 /*
720  * make sure all write-behind blocks
721  * on dev (or NODEV for all)
722  * are flushed out.
723  * (from umount and update)
724  * (and temporarily pagein)
725  */
726 bflush(dev)
727 	dev_t dev;
728 {
729 	register struct buf *bp;
730 	register struct buf *flist;
731 	int s;
732 
733 loop:
734 	s = spl6();
735 	for (flist = bfreelist; flist < &bfreelist[BQ_EMPTY]; flist++)
736 	for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) {
737 		if ((bp->b_flags & B_DELWRI) == 0)
738 			continue;
739 		if (dev == NODEV || dev == bp->b_dev) {
740 			bp->b_flags |= B_ASYNC;
741 			notavail(bp);
742 			bwrite(bp);
743 			goto loop;
744 		}
745 	}
746 	splx(s);
747 }
748 
749 /*
750  * Pick up the device's error number and pass it to the user;
751  * if there is an error but the number is 0 set a generalized
752  * code.  Actually the latter is always true because devices
753  * don't yet return specific errors.
754  */
755 geterror(bp)
756 	register struct buf *bp;
757 {
758 	int error = 0;
759 
760 	if (bp->b_flags&B_ERROR)
761 		if ((error = bp->b_error)==0)
762 			return (EIO);
763 	return (error);
764 }
765 
766 /*
767  * Invalidate in core blocks belonging to closed or umounted filesystem
768  *
769  * This is not nicely done at all - the buffer ought to be removed from the
770  * hash chains & have its dev/blkno fields clobbered, but unfortunately we
771  * can't do that here, as it is quite possible that the block is still
772  * being used for i/o. Eventually, all disc drivers should be forced to
773  * have a close routine, which ought ensure that the queue is empty, then
774  * properly flush the queues. Until that happy day, this suffices for
775  * correctness.						... kre
776  */
777 binval(dev)
778 	dev_t dev;
779 {
780 	register struct buf *bp;
781 	register struct bufhd *hp;
782 #define dp ((struct buf *)hp)
783 
784 	for (hp = bufhash; hp < &bufhash[BUFHSZ]; hp++)
785 		for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
786 			if (bp->b_dev == dev)
787 				bp->b_flags |= B_INVAL;
788 }
789