speed-ups using the new constants
[unix-history] / usr / src / sys / kern / vfs_cluster.c
CommitLineData
f844ee62 1/* vfs_cluster.c 4.41 82/12/19 */
961945a8
SL
2
3#include "../machine/pte.h"
663dbc72
BJ
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"
663dbc72 13#include "../h/vm.h"
973ecc4f 14#include "../h/trace.h"
663dbc72 15
663dbc72
BJ
16/*
17 * Read in (if necessary) the block and return a buffer pointer.
18 */
19struct buf *
ad30fb67
KM
20bread(dev, blkno, size)
21 dev_t dev;
22 daddr_t blkno;
23 int size;
663dbc72
BJ
24{
25 register struct buf *bp;
26
4f083fd7
SL
27 if (size == 0)
28 panic("bread: size 0");
ad30fb67 29 bp = getblk(dev, blkno, size);
663dbc72 30 if (bp->b_flags&B_DONE) {
15f77b9b 31 trace(TR_BREADHIT, dev, blkno);
663dbc72
BJ
32 return(bp);
33 }
34 bp->b_flags |= B_READ;
4f083fd7
SL
35 if (bp->b_bcount > bp->b_bufsize)
36 panic("bread");
663dbc72 37 (*bdevsw[major(dev)].d_strategy)(bp);
15f77b9b 38 trace(TR_BREADMISS, dev, blkno);
fb99a9a1 39 u.u_ru.ru_inblock++; /* pay for read */
3efdd860 40 biowait(bp);
663dbc72
BJ
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 */
48struct buf *
a8d3bf7f 49breada(dev, blkno, size, rablkno, rabsize)
ad30fb67 50 dev_t dev;
84baaab3 51 daddr_t blkno; int size;
a8d3bf7f 52 daddr_t rablkno; int rabsize;
663dbc72
BJ
53{
54 register struct buf *bp, *rabp;
55
56 bp = NULL;
3efdd860
KM
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 */
663dbc72 62 if (!incore(dev, blkno)) {
ad30fb67 63 bp = getblk(dev, blkno, size);
663dbc72
BJ
64 if ((bp->b_flags&B_DONE) == 0) {
65 bp->b_flags |= B_READ;
4f083fd7
SL
66 if (bp->b_bcount > bp->b_bufsize)
67 panic("breada");
663dbc72 68 (*bdevsw[major(dev)].d_strategy)(bp);
15f77b9b 69 trace(TR_BREADMISS, dev, blkno);
fb99a9a1 70 u.u_ru.ru_inblock++; /* pay for read */
3efdd860 71 } else
15f77b9b 72 trace(TR_BREADHIT, dev, blkno);
663dbc72 73 }
3efdd860
KM
74
75 /*
76 * If there's a read-ahead block, start i/o
77 * on it also (as above).
78 */
663dbc72 79 if (rablkno && !incore(dev, rablkno)) {
a8d3bf7f 80 rabp = getblk(dev, rablkno, rabsize);
973ecc4f 81 if (rabp->b_flags & B_DONE) {
663dbc72 82 brelse(rabp);
15f77b9b 83 trace(TR_BREADHITRA, dev, blkno);
973ecc4f 84 } else {
663dbc72 85 rabp->b_flags |= B_READ|B_ASYNC;
4f083fd7
SL
86 if (rabp->b_bcount > rabp->b_bufsize)
87 panic("breadrabp");
663dbc72 88 (*bdevsw[major(dev)].d_strategy)(rabp);
15f77b9b 89 trace(TR_BREADMISSRA, dev, rablock);
fb99a9a1 90 u.u_ru.ru_inblock++; /* pay in advance */
663dbc72
BJ
91 }
92 }
3efdd860
KM
93
94 /*
84baaab3
KM
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.
3efdd860 98 */
84baaab3
KM
99 if (bp == NULL)
100 return (bread(dev, blkno, size));
3efdd860 101 biowait(bp);
84baaab3 102 return (bp);
663dbc72
BJ
103}
104
105/*
106 * Write the buffer, waiting for completion.
107 * Then release the buffer.
108 */
109bwrite(bp)
3efdd860 110 register struct buf *bp;
663dbc72
BJ
111{
112 register flag;
113
114 flag = bp->b_flags;
f844ee62 115 bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI);
663dbc72 116 if ((flag&B_DELWRI) == 0)
fb99a9a1 117 u.u_ru.ru_oublock++; /* noone paid yet */
53f9ca20 118 trace(TR_BWRITE, bp->b_dev, bp->b_blkno);
4f083fd7
SL
119 if (bp->b_bcount > bp->b_bufsize)
120 panic("bwrite");
663dbc72 121 (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
3efdd860
KM
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.
3efdd860 127 */
663dbc72 128 if ((flag&B_ASYNC) == 0) {
3efdd860 129 biowait(bp);
663dbc72
BJ
130 brelse(bp);
131 } else if (flag & B_DELWRI)
132 bp->b_flags |= B_AGE;
663dbc72
BJ
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 */
143bdwrite(bp)
3efdd860 144 register struct buf *bp;
663dbc72 145{
e1e57888 146 register int flags;
663dbc72
BJ
147
148 if ((bp->b_flags&B_DELWRI) == 0)
fb99a9a1 149 u.u_ru.ru_oublock++; /* noone paid yet */
e1e57888
RE
150 flags = bdevsw[major(bp->b_dev)].d_flags;
151 if(flags & B_TAPE)
663dbc72
BJ
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 */
162bawrite(bp)
3efdd860 163 register struct buf *bp;
663dbc72
BJ
164{
165
166 bp->b_flags |= B_ASYNC;
167 bwrite(bp);
168}
169
170/*
3efdd860 171 * Release the buffer, with no I/O implied.
663dbc72
BJ
172 */
173brelse(bp)
3efdd860 174 register struct buf *bp;
663dbc72 175{
46387ee3 176 register struct buf *flist;
663dbc72
BJ
177 register s;
178
3efdd860
KM
179 /*
180 * If someone's waiting for the buffer, or
181 * is waiting for a buffer wake 'em up.
182 */
663dbc72
BJ
183 if (bp->b_flags&B_WANTED)
184 wakeup((caddr_t)bp);
46387ee3
BJ
185 if (bfreelist[0].b_flags&B_WANTED) {
186 bfreelist[0].b_flags &= ~B_WANTED;
187 wakeup((caddr_t)bfreelist);
663dbc72 188 }
60a71525
BJ
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 */
3efdd860
KM
194
195 /*
196 * Stick the buffer back on a free list.
197 */
663dbc72 198 s = spl6();
4f083fd7
SL
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)) {
46387ee3 204 /* block has no info ... put at front of most free list */
4f083fd7 205 flist = &bfreelist[BQ_AGE];
3efdd860 206 binsheadfree(bp, flist);
663dbc72 207 } else {
46387ee3
BJ
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];
3efdd860 214 binstailfree(bp, flist);
663dbc72
BJ
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 */
224incore(dev, blkno)
3efdd860
KM
225 dev_t dev;
226 daddr_t blkno;
663dbc72
BJ
227{
228 register struct buf *bp;
46387ee3 229 register struct buf *dp;
663dbc72 230
ad30fb67 231 dp = BUFHASH(dev, blkno);
46387ee3 232 for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
ad30fb67 233 if (bp->b_blkno == blkno && bp->b_dev == dev &&
3efdd860 234 (bp->b_flags & B_INVAL) == 0)
5603d07d 235 return (1);
5603d07d 236 return (0);
663dbc72
BJ
237}
238
239struct buf *
ad30fb67
KM
240baddr(dev, blkno, size)
241 dev_t dev;
242 daddr_t blkno;
243 int size;
663dbc72
BJ
244{
245
246 if (incore(dev, blkno))
ad30fb67 247 return (bread(dev, blkno, size));
663dbc72
BJ
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.
23900030
BJ
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.
663dbc72
BJ
259 */
260struct buf *
ad30fb67
KM
261getblk(dev, blkno, size)
262 dev_t dev;
263 daddr_t blkno;
264 int size;
663dbc72 265{
4f083fd7 266 register struct buf *bp, *dp;
23900030 267 int s;
663dbc72 268
961945a8 269 if ((unsigned)blkno >= 1 << (sizeof(int)*NBBY-PGSHIFT)) /* XXX */
01659974 270 blkno = 1 << ((sizeof(int)*NBBY-PGSHIFT) + 1);
3efdd860
KM
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 */
ad30fb67 276 dp = BUFHASH(dev, blkno);
3efdd860 277loop:
46387ee3 278 for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) {
ad30fb67 279 if (bp->b_blkno != blkno || bp->b_dev != dev ||
46387ee3 280 bp->b_flags&B_INVAL)
663dbc72 281 continue;
23900030 282 s = spl6();
663dbc72
BJ
283 if (bp->b_flags&B_BUSY) {
284 bp->b_flags |= B_WANTED;
285 sleep((caddr_t)bp, PRIBIO+1);
23900030 286 splx(s);
663dbc72
BJ
287 goto loop;
288 }
23900030 289 splx(s);
663dbc72 290 notavail(bp);
9d6d37ce
BJ
291 if (brealloc(bp, size) == 0)
292 goto loop;
663dbc72
BJ
293 bp->b_flags |= B_CACHE;
294 return(bp);
295 }
5603d07d
BJ
296 if (major(dev) >= nblkdev)
297 panic("blkdev");
4f083fd7 298 bp = getnewbuf();
ad30fb67 299 bfree(bp);
3efdd860
KM
300 bremhash(bp);
301 binshash(bp, dp);
663dbc72 302 bp->b_dev = dev;
ad30fb67 303 bp->b_blkno = blkno;
4f083fd7 304 bp->b_error = 0;
9d6d37ce
BJ
305 if (brealloc(bp, size) == 0)
306 goto loop;
663dbc72
BJ
307 return(bp);
308}
309
310/*
311 * get an empty block,
312 * not assigned to any particular device
313 */
314struct buf *
ad30fb67
KM
315geteblk(size)
316 int size;
663dbc72 317{
4f083fd7 318 register struct buf *bp, *flist;
663dbc72
BJ
319
320loop:
4f083fd7
SL
321 bp = getnewbuf();
322 bp->b_flags |= B_INVAL;
3efdd860
KM
323 bfree(bp);
324 bremhash(bp);
4f083fd7
SL
325 flist = &bfreelist[BQ_AGE];
326 binshash(bp, flist);
663dbc72 327 bp->b_dev = (dev_t)NODEV;
4f083fd7 328 bp->b_error = 0;
9d6d37ce
BJ
329 if (brealloc(bp, size) == 0)
330 goto loop;
663dbc72
BJ
331 return(bp);
332}
333
ad30fb67
KM
334/*
335 * Allocate space associated with a buffer.
961945a8 336 * If can't get space, buffer is released
ad30fb67
KM
337 */
338brealloc(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)
9d6d37ce
BJ
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");
961945a8 360 return (allocbuf(bp, size));
ad30fb67 361 }
9d6d37ce 362 bp->b_flags &= ~B_DONE;
961945a8
SL
363 if (bp->b_dev == NODEV)
364 return (allocbuf(bp, size));
9d6d37ce
BJ
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;
ad30fb67
KM
376 dp = BUFHASH(bp->b_dev, bp->b_blkno);
377loop:
ad30fb67 378 for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
9d6d37ce
BJ
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)
ad30fb67
KM
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);
4f083fd7 389 splx(s);
ad30fb67
KM
390 goto loop;
391 }
4f083fd7 392 splx(s);
9d6d37ce 393 notavail(ep);
ad30fb67 394 if (ep->b_flags & B_DELWRI) {
ad30fb67
KM
395 bwrite(ep);
396 goto loop;
397 }
9d6d37ce
BJ
398 ep->b_flags |= B_INVAL;
399 brelse(ep);
ad30fb67 400 }
961945a8 401 return (allocbuf(bp, size));
4f083fd7
SL
402}
403
404/*
405 * Expand or contract the actual memory allocated to a buffer.
961945a8 406 * If no memory is available, release buffer and take error exit
4f083fd7
SL
407 */
408allocbuf(tp, size)
409 register struct buf *tp;
410 int size;
411{
412 register struct buf *bp, *ep;
413 int sizealloc, take;
961945a8
SL
414#ifdef sun
415 register char *a;
416 int osize;
417#endif
4f083fd7 418
961945a8 419#ifndef sun
4f083fd7 420 sizealloc = roundup(size, CLBYTES);
961945a8
SL
421#else
422 sizealloc = roundup(size, BUFALLOCSIZE);
423#endif
4f083fd7
SL
424 /*
425 * Buffer size does not change
426 */
427 if (sizealloc == tp->b_bufsize)
428 goto out;
961945a8 429#ifndef sun
4f083fd7
SL
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 }
ad30fb67 451 /*
4f083fd7
SL
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.
ad30fb67 455 */
4f083fd7
SL
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 }
961945a8
SL
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
4f083fd7
SL
519out:
520 tp->b_bcount = size;
961945a8 521 return (1);
ad30fb67
KM
522}
523
524/*
525 * Release space associated with a buffer.
526 */
527bfree(bp)
528 struct buf *bp;
529{
961945a8
SL
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
ad30fb67
KM
536 bp->b_bcount = 0;
537}
538
961945a8
SL
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 */
546bfreemem()
547{
548 register struct buf *bp, *dp;
549 int s;
550
551loop:
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
4f083fd7
SL
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 */
584struct buf *
585getnewbuf()
586{
587 register struct buf *bp, *dp;
588 int s;
589
590loop:
591 s = spl6();
961945a8 592#ifndef sun
4f083fd7 593 for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--)
961945a8
SL
594#else
595 for (dp = &bfreelist[BQ_EMPTY]; dp > bfreelist; dp--)
596#endif
4f083fd7
SL
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
663dbc72
BJ
617/*
618 * Wait for I/O completion on the buffer; return errors
619 * to the user.
620 */
3efdd860 621biowait(bp)
ad30fb67 622 register struct buf *bp;
663dbc72 623{
530d0032 624 int s;
663dbc72 625
530d0032 626 s = spl6();
663dbc72
BJ
627 while ((bp->b_flags&B_DONE)==0)
628 sleep((caddr_t)bp, PRIBIO);
530d0032 629 splx(s);
d6d7360b 630 u.u_error = geterror(bp);
663dbc72
BJ
631}
632
663dbc72
BJ
633/*
634 * Mark I/O complete on a buffer. If the header
635 * indicates a dirty page push completion, the
636 * header is inserted into the ``cleaned'' list
637 * to be processed by the pageout daemon. Otherwise
638 * release it if I/O is asynchronous, and wake
639 * up anyone waiting for it.
640 */
3efdd860
KM
641biodone(bp)
642 register struct buf *bp;
663dbc72
BJ
643{
644 register int s;
645
80e7c811 646 if (bp->b_flags & B_DONE)
3efdd860 647 panic("dup biodone");
663dbc72
BJ
648 bp->b_flags |= B_DONE;
649 if (bp->b_flags & B_DIRTY) {
650 if (bp->b_flags & B_ERROR)
651 panic("IO err in push");
652 s = spl6();
663dbc72
BJ
653 bp->av_forw = bclnlist;
654 bp->b_bcount = swsize[bp - swbuf];
655 bp->b_pfcent = swpf[bp - swbuf];
796c66c0
BJ
656 cnt.v_pgout++;
657 cnt.v_pgpgout += bp->b_bcount / NBPG;
663dbc72
BJ
658 bclnlist = bp;
659 if (bswlist.b_flags & B_WANTED)
660 wakeup((caddr_t)&proc[2]);
661 splx(s);
a3ee1d55 662 return;
663dbc72 663 }
961945a8
SL
664 if (bp->b_flags & B_CALL) {
665 bp->b_flags &= ~B_CALL;
666 (*bp->b_iodone)(bp);
667 return;
668 }
663dbc72
BJ
669 if (bp->b_flags&B_ASYNC)
670 brelse(bp);
671 else {
672 bp->b_flags &= ~B_WANTED;
673 wakeup((caddr_t)bp);
674 }
675}
676
4f083fd7
SL
677/*
678 * Insure that no part of a specified block is in an incore buffer.
679 */
680blkflush(dev, blkno, size)
681 dev_t dev;
682 daddr_t blkno;
683 long size;
684{
685 register struct buf *ep;
686 struct buf *dp;
687 daddr_t start, last;
688 int s;
689
690 start = blkno;
691 last = start + (size / DEV_BSIZE) - 1;
692 dp = BUFHASH(dev, blkno);
693loop:
694 for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
695 if (ep->b_dev != dev || (ep->b_flags&B_INVAL))
696 continue;
697 /* look for overlap */
698 if (ep->b_bcount == 0 || ep->b_blkno > last ||
699 ep->b_blkno + (ep->b_bcount / DEV_BSIZE) <= start)
700 continue;
701 s = spl6();
702 if (ep->b_flags&B_BUSY) {
703 ep->b_flags |= B_WANTED;
704 sleep((caddr_t)ep, PRIBIO+1);
705 splx(s);
706 goto loop;
707 }
708 if (ep->b_flags & B_DELWRI) {
709 splx(s);
710 notavail(ep);
711 bwrite(ep);
712 goto loop;
713 }
714 splx(s);
715 }
716}
717
663dbc72
BJ
718/*
719 * make sure all write-behind blocks
720 * on dev (or NODEV for all)
721 * are flushed out.
722 * (from umount and update)
ad30fb67 723 * (and temporarily pagein)
663dbc72
BJ
724 */
725bflush(dev)
3efdd860 726 dev_t dev;
663dbc72
BJ
727{
728 register struct buf *bp;
46387ee3 729 register struct buf *flist;
530d0032 730 int s;
663dbc72
BJ
731
732loop:
530d0032 733 s = spl6();
4f083fd7 734 for (flist = bfreelist; flist < &bfreelist[BQ_EMPTY]; flist++)
46387ee3 735 for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) {
3efdd860
KM
736 if ((bp->b_flags & B_DELWRI) == 0)
737 continue;
738 if (dev == NODEV || dev == bp->b_dev) {
663dbc72
BJ
739 bp->b_flags |= B_ASYNC;
740 notavail(bp);
741 bwrite(bp);
742 goto loop;
743 }
744 }
530d0032 745 splx(s);
663dbc72
BJ
746}
747
663dbc72
BJ
748/*
749 * Pick up the device's error number and pass it to the user;
750 * if there is an error but the number is 0 set a generalized
751 * code. Actually the latter is always true because devices
752 * don't yet return specific errors.
753 */
754geterror(bp)
3efdd860 755 register struct buf *bp;
663dbc72 756{
d6d7360b 757 int error = 0;
663dbc72
BJ
758
759 if (bp->b_flags&B_ERROR)
d6d7360b
BJ
760 if ((error = bp->b_error)==0)
761 return (EIO);
762 return (error);
663dbc72 763}
7b8b5a01
RE
764
765/*
766 * Invalidate in core blocks belonging to closed or umounted filesystem
767 *
768 * This is not nicely done at all - the buffer ought to be removed from the
769 * hash chains & have its dev/blkno fields clobbered, but unfortunately we
770 * can't do that here, as it is quite possible that the block is still
771 * being used for i/o. Eventually, all disc drivers should be forced to
772 * have a close routine, which ought ensure that the queue is empty, then
773 * properly flush the queues. Until that happy day, this suffices for
774 * correctness. ... kre
775 */
776binval(dev)
3efdd860 777 dev_t dev;
7b8b5a01 778{
634ebdbe
RE
779 register struct buf *bp;
780 register struct bufhd *hp;
781#define dp ((struct buf *)hp)
7b8b5a01 782
634ebdbe
RE
783 for (hp = bufhash; hp < &bufhash[BUFHSZ]; hp++)
784 for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
785 if (bp->b_dev == dev)
786 bp->b_flags |= B_INVAL;
7b8b5a01 787}