new naming convention
[unix-history] / usr / src / sys / kern / vfs_cluster.c
CommitLineData
da7c5cc6 1/*
0880b18e 2 * Copyright (c) 1982, 1986 Regents of the University of California.
da7c5cc6
KM
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
d301d150 6 * @(#)vfs_cluster.c 7.4 (Berkeley) %G%
da7c5cc6 7 */
961945a8 8
94368568
JB
9#include "param.h"
10#include "systm.h"
11#include "dir.h"
12#include "user.h"
13#include "buf.h"
14#include "conf.h"
15#include "proc.h"
16#include "seg.h"
17#include "vm.h"
18#include "trace.h"
663dbc72 19
d301d150
KM
20#include "machine/pte.h"
21
663dbc72
BJ
22/*
23 * Read in (if necessary) the block and return a buffer pointer.
24 */
25struct buf *
ec67a3ce
MK
26#ifdef SECSIZE
27bread(dev, blkno, size, secsize)
28#else SECSIZE
ad30fb67 29bread(dev, blkno, size)
ec67a3ce 30#endif SECSIZE
ad30fb67
KM
31 dev_t dev;
32 daddr_t blkno;
33 int size;
ec67a3ce
MK
34#ifdef SECSIZE
35 long secsize;
36#endif SECSIZE
663dbc72
BJ
37{
38 register struct buf *bp;
39
4f083fd7
SL
40 if (size == 0)
41 panic("bread: size 0");
ec67a3ce
MK
42#ifdef SECSIZE
43 bp = getblk(dev, blkno, size, secsize);
44#else SECSIZE
ad30fb67 45 bp = getblk(dev, blkno, size);
ec67a3ce 46#endif SECSIZE
32a56bda 47 if (bp->b_flags&(B_DONE|B_DELWRI)) {
720c861e 48 trace(TR_BREADHIT, pack(dev, size), blkno);
a5e62f37 49 return (bp);
663dbc72
BJ
50 }
51 bp->b_flags |= B_READ;
4f083fd7
SL
52 if (bp->b_bcount > bp->b_bufsize)
53 panic("bread");
663dbc72 54 (*bdevsw[major(dev)].d_strategy)(bp);
720c861e 55 trace(TR_BREADMISS, pack(dev, size), blkno);
fb99a9a1 56 u.u_ru.ru_inblock++; /* pay for read */
3efdd860 57 biowait(bp);
a5e62f37 58 return (bp);
663dbc72
BJ
59}
60
61/*
62 * Read in the block, like bread, but also start I/O on the
63 * read-ahead block (which is not allocated to the caller)
64 */
65struct buf *
ec67a3ce
MK
66#ifdef SECSIZE
67breada(dev, blkno, size, secsize, rablkno, rabsize)
68#else SECSIZE
a8d3bf7f 69breada(dev, blkno, size, rablkno, rabsize)
ec67a3ce 70#endif SECSIZE
ad30fb67 71 dev_t dev;
84baaab3 72 daddr_t blkno; int size;
ec67a3ce
MK
73#ifdef SECSIZE
74 long secsize;
75#endif SECSIZE
a8d3bf7f 76 daddr_t rablkno; int rabsize;
663dbc72
BJ
77{
78 register struct buf *bp, *rabp;
79
80 bp = NULL;
3efdd860
KM
81 /*
82 * If the block isn't in core, then allocate
83 * a buffer and initiate i/o (getblk checks
84 * for a cache hit).
85 */
663dbc72 86 if (!incore(dev, blkno)) {
ec67a3ce
MK
87#ifdef SECSIZE
88 bp = getblk(dev, blkno, size, secsize);
89#else SECSIZE
ad30fb67 90 bp = getblk(dev, blkno, size);
ec67a3ce 91#endif SECSIZE
32a56bda 92 if ((bp->b_flags&(B_DONE|B_DELWRI)) == 0) {
663dbc72 93 bp->b_flags |= B_READ;
4f083fd7
SL
94 if (bp->b_bcount > bp->b_bufsize)
95 panic("breada");
663dbc72 96 (*bdevsw[major(dev)].d_strategy)(bp);
720c861e 97 trace(TR_BREADMISS, pack(dev, size), blkno);
fb99a9a1 98 u.u_ru.ru_inblock++; /* pay for read */
3efdd860 99 } else
720c861e 100 trace(TR_BREADHIT, pack(dev, size), blkno);
663dbc72 101 }
3efdd860
KM
102
103 /*
104 * If there's a read-ahead block, start i/o
105 * on it also (as above).
106 */
663dbc72 107 if (rablkno && !incore(dev, rablkno)) {
ec67a3ce
MK
108#ifdef SECSIZE
109 rabp = getblk(dev, rablkno, rabsize, secsize);
110#else SECSIZE
a8d3bf7f 111 rabp = getblk(dev, rablkno, rabsize);
ec67a3ce 112#endif SECSIZE
32a56bda 113 if (rabp->b_flags & (B_DONE|B_DELWRI)) {
663dbc72 114 brelse(rabp);
720c861e 115 trace(TR_BREADHITRA, pack(dev, rabsize), blkno);
973ecc4f 116 } else {
663dbc72 117 rabp->b_flags |= B_READ|B_ASYNC;
4f083fd7
SL
118 if (rabp->b_bcount > rabp->b_bufsize)
119 panic("breadrabp");
663dbc72 120 (*bdevsw[major(dev)].d_strategy)(rabp);
720c861e 121 trace(TR_BREADMISSRA, pack(dev, rabsize), rablock);
fb99a9a1 122 u.u_ru.ru_inblock++; /* pay in advance */
663dbc72
BJ
123 }
124 }
3efdd860
KM
125
126 /*
84baaab3
KM
127 * If block was in core, let bread get it.
128 * If block wasn't in core, then the read was started
129 * above, and just wait for it.
3efdd860 130 */
84baaab3 131 if (bp == NULL)
ec67a3ce
MK
132#ifdef SECSIZE
133 return (bread(dev, blkno, size, secsize));
134#else SECSIZE
84baaab3 135 return (bread(dev, blkno, size));
ec67a3ce 136#endif SECSIZE
3efdd860 137 biowait(bp);
84baaab3 138 return (bp);
663dbc72
BJ
139}
140
141/*
142 * Write the buffer, waiting for completion.
143 * Then release the buffer.
144 */
145bwrite(bp)
3efdd860 146 register struct buf *bp;
663dbc72
BJ
147{
148 register flag;
149
150 flag = bp->b_flags;
f844ee62 151 bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI);
663dbc72 152 if ((flag&B_DELWRI) == 0)
fb99a9a1 153 u.u_ru.ru_oublock++; /* noone paid yet */
720c861e 154 trace(TR_BWRITE, pack(bp->b_dev, bp->b_bcount), bp->b_blkno);
4f083fd7
SL
155 if (bp->b_bcount > bp->b_bufsize)
156 panic("bwrite");
663dbc72 157 (*bdevsw[major(bp->b_dev)].d_strategy)(bp);
3efdd860
KM
158
159 /*
160 * If the write was synchronous, then await i/o completion.
161 * If the write was "delayed", then we put the buffer on
162 * the q of blocks awaiting i/o completion status.
3efdd860 163 */
663dbc72 164 if ((flag&B_ASYNC) == 0) {
3efdd860 165 biowait(bp);
663dbc72
BJ
166 brelse(bp);
167 } else if (flag & B_DELWRI)
168 bp->b_flags |= B_AGE;
663dbc72
BJ
169}
170
171/*
172 * Release the buffer, marking it so that if it is grabbed
173 * for another purpose it will be written out before being
174 * given up (e.g. when writing a partial block where it is
175 * assumed that another write for the same block will soon follow).
176 * This can't be done for magtape, since writes must be done
177 * in the same order as requested.
178 */
179bdwrite(bp)
3efdd860 180 register struct buf *bp;
663dbc72 181{
663dbc72
BJ
182
183 if ((bp->b_flags&B_DELWRI) == 0)
fb99a9a1 184 u.u_ru.ru_oublock++; /* noone paid yet */
ec67a3ce 185 if (bdevsw[major(bp->b_dev)].d_flags & B_TAPE)
663dbc72
BJ
186 bawrite(bp);
187 else {
188 bp->b_flags |= B_DELWRI | B_DONE;
189 brelse(bp);
190 }
191}
192
193/*
194 * Release the buffer, start I/O on it, but don't wait for completion.
195 */
196bawrite(bp)
3efdd860 197 register struct buf *bp;
663dbc72
BJ
198{
199
200 bp->b_flags |= B_ASYNC;
201 bwrite(bp);
202}
203
204/*
3efdd860 205 * Release the buffer, with no I/O implied.
663dbc72
BJ
206 */
207brelse(bp)
3efdd860 208 register struct buf *bp;
663dbc72 209{
46387ee3 210 register struct buf *flist;
663dbc72
BJ
211 register s;
212
720c861e 213 trace(TR_BRELSE, pack(bp->b_dev, bp->b_bufsize), bp->b_blkno);
3efdd860
KM
214 /*
215 * If someone's waiting for the buffer, or
216 * is waiting for a buffer wake 'em up.
217 */
663dbc72
BJ
218 if (bp->b_flags&B_WANTED)
219 wakeup((caddr_t)bp);
46387ee3
BJ
220 if (bfreelist[0].b_flags&B_WANTED) {
221 bfreelist[0].b_flags &= ~B_WANTED;
222 wakeup((caddr_t)bfreelist);
663dbc72 223 }
60a71525
BJ
224 if (bp->b_flags&B_ERROR)
225 if (bp->b_flags & B_LOCKED)
226 bp->b_flags &= ~B_ERROR; /* try again later */
227 else
228 bp->b_dev = NODEV; /* no assoc */
3efdd860
KM
229
230 /*
231 * Stick the buffer back on a free list.
232 */
a5e62f37 233 s = splbio();
4f083fd7
SL
234 if (bp->b_bufsize <= 0) {
235 /* block has no buffer ... put at front of unused buffer list */
236 flist = &bfreelist[BQ_EMPTY];
237 binsheadfree(bp, flist);
238 } else if (bp->b_flags & (B_ERROR|B_INVAL)) {
46387ee3 239 /* block has no info ... put at front of most free list */
4f083fd7 240 flist = &bfreelist[BQ_AGE];
3efdd860 241 binsheadfree(bp, flist);
663dbc72 242 } else {
46387ee3
BJ
243 if (bp->b_flags & B_LOCKED)
244 flist = &bfreelist[BQ_LOCKED];
245 else if (bp->b_flags & B_AGE)
246 flist = &bfreelist[BQ_AGE];
247 else
248 flist = &bfreelist[BQ_LRU];
3efdd860 249 binstailfree(bp, flist);
663dbc72
BJ
250 }
251 bp->b_flags &= ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE);
252 splx(s);
253}
254
255/*
256 * See if the block is associated with some buffer
257 * (mainly to avoid getting hung up on a wait in breada)
258 */
259incore(dev, blkno)
3efdd860
KM
260 dev_t dev;
261 daddr_t blkno;
663dbc72
BJ
262{
263 register struct buf *bp;
46387ee3 264 register struct buf *dp;
663dbc72 265
ad30fb67 266 dp = BUFHASH(dev, blkno);
46387ee3 267 for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
ad30fb67 268 if (bp->b_blkno == blkno && bp->b_dev == dev &&
3efdd860 269 (bp->b_flags & B_INVAL) == 0)
5603d07d 270 return (1);
5603d07d 271 return (0);
663dbc72
BJ
272}
273
274struct buf *
ec67a3ce
MK
275#ifdef SECSIZE
276baddr(dev, blkno, size, secsize)
277#else SECSIZE
ad30fb67 278baddr(dev, blkno, size)
ec67a3ce 279#endif SECSIZE
ad30fb67
KM
280 dev_t dev;
281 daddr_t blkno;
282 int size;
ec67a3ce
MK
283#ifdef SECSIZE
284 long secsize;
285#endif SECSIZE
663dbc72
BJ
286{
287
288 if (incore(dev, blkno))
ec67a3ce
MK
289#ifdef SECSIZE
290 return (bread(dev, blkno, size, secsize));
291#else SECSIZE
ad30fb67 292 return (bread(dev, blkno, size));
ec67a3ce 293#endif SECSIZE
663dbc72
BJ
294 return (0);
295}
296
297/*
298 * Assign a buffer for the given block. If the appropriate
299 * block is already associated, return it; otherwise search
300 * for the oldest non-busy buffer and reassign it.
23900030 301 *
32a56bda
KM
302 * If we find the buffer, but it is dirty (marked DELWRI) and
303 * its size is changing, we must write it out first. When the
304 * buffer is shrinking, the write is done by brealloc to avoid
305 * losing the unwritten data. When the buffer is growing, the
306 * write is done by getblk, so that bread will not read stale
307 * disk data over the modified data in the buffer.
308 *
23900030
BJ
309 * We use splx here because this routine may be called
310 * on the interrupt stack during a dump, and we don't
311 * want to lower the ipl back to 0.
663dbc72
BJ
312 */
313struct buf *
ec67a3ce
MK
314#ifdef SECSIZE
315getblk(dev, blkno, size, secsize)
316#else SECSIZE
ad30fb67 317getblk(dev, blkno, size)
ec67a3ce 318#endif SECSIZE
ad30fb67
KM
319 dev_t dev;
320 daddr_t blkno;
321 int size;
ec67a3ce
MK
322#ifdef SECSIZE
323 long secsize;
324#endif SECSIZE
663dbc72 325{
4f083fd7 326 register struct buf *bp, *dp;
23900030 327 int s;
663dbc72 328
00a6a148
KM
329 if (size > MAXBSIZE)
330 panic("getblk: size too big");
751af33e
KM
331 /*
332 * To prevent overflow of 32-bit ints when converting block
333 * numbers to byte offsets, blknos > 2^32 / DEV_BSIZE are set
334 * to the maximum number that can be converted to a byte offset
335 * without overflow. This is historic code; what bug it fixed,
336 * or whether it is still a reasonable thing to do is open to
337 * dispute. mkm 9/85
338 */
339 if ((unsigned)blkno >= 1 << (sizeof(int)*NBBY-DEV_BSHIFT))
340 blkno = 1 << ((sizeof(int)*NBBY-DEV_BSHIFT) + 1);
3efdd860
KM
341 /*
342 * Search the cache for the block. If we hit, but
343 * the buffer is in use for i/o, then we wait until
344 * the i/o has completed.
345 */
ad30fb67 346 dp = BUFHASH(dev, blkno);
3efdd860 347loop:
46387ee3 348 for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) {
ad30fb67 349 if (bp->b_blkno != blkno || bp->b_dev != dev ||
46387ee3 350 bp->b_flags&B_INVAL)
663dbc72 351 continue;
a5e62f37 352 s = splbio();
663dbc72
BJ
353 if (bp->b_flags&B_BUSY) {
354 bp->b_flags |= B_WANTED;
355 sleep((caddr_t)bp, PRIBIO+1);
23900030 356 splx(s);
663dbc72
BJ
357 goto loop;
358 }
23900030 359 splx(s);
663dbc72 360 notavail(bp);
32a56bda
KM
361 if (bp->b_bcount != size) {
362 if (bp->b_bcount < size && (bp->b_flags&B_DELWRI)) {
363 bp->b_flags &= ~B_ASYNC;
364 bwrite(bp);
365 goto loop;
366 }
367 if (brealloc(bp, size) == 0)
368 goto loop;
369 }
b646a125 370 if (bp->b_bcount != size && brealloc(bp, size) == 0)
9d6d37ce 371 goto loop;
663dbc72 372 bp->b_flags |= B_CACHE;
a5e62f37 373 return (bp);
663dbc72 374 }
5603d07d
BJ
375 if (major(dev) >= nblkdev)
376 panic("blkdev");
4f083fd7 377 bp = getnewbuf();
ad30fb67 378 bfree(bp);
3efdd860
KM
379 bremhash(bp);
380 binshash(bp, dp);
663dbc72 381 bp->b_dev = dev;
ec67a3ce
MK
382#ifdef SECSIZE
383 bp->b_blksize = secsize;
384#endif SECSIZE
ad30fb67 385 bp->b_blkno = blkno;
4f083fd7 386 bp->b_error = 0;
9d6d37ce
BJ
387 if (brealloc(bp, size) == 0)
388 goto loop;
a5e62f37 389 return (bp);
663dbc72
BJ
390}
391
392/*
393 * get an empty block,
394 * not assigned to any particular device
395 */
396struct buf *
ad30fb67
KM
397geteblk(size)
398 int size;
663dbc72 399{
4f083fd7 400 register struct buf *bp, *flist;
663dbc72 401
00a6a148
KM
402 if (size > MAXBSIZE)
403 panic("geteblk: size too big");
663dbc72 404loop:
4f083fd7
SL
405 bp = getnewbuf();
406 bp->b_flags |= B_INVAL;
3efdd860
KM
407 bfree(bp);
408 bremhash(bp);
4f083fd7
SL
409 flist = &bfreelist[BQ_AGE];
410 binshash(bp, flist);
663dbc72 411 bp->b_dev = (dev_t)NODEV;
ec67a3ce
MK
412#ifdef SECSIZE
413 bp->b_blksize = DEV_BSIZE;
414#endif SECSIZE
4f083fd7 415 bp->b_error = 0;
9d6d37ce
BJ
416 if (brealloc(bp, size) == 0)
417 goto loop;
a5e62f37 418 return (bp);
663dbc72
BJ
419}
420
ad30fb67
KM
421/*
422 * Allocate space associated with a buffer.
961945a8 423 * If can't get space, buffer is released
ad30fb67
KM
424 */
425brealloc(bp, size)
426 register struct buf *bp;
427 int size;
428{
429 daddr_t start, last;
430 register struct buf *ep;
431 struct buf *dp;
432 int s;
433
434 /*
ec67a3ce 435 * First need to make sure that all overlapping previous I/O
ad30fb67
KM
436 * is dispatched with.
437 */
438 if (size == bp->b_bcount)
9d6d37ce
BJ
439 return (1);
440 if (size < bp->b_bcount) {
441 if (bp->b_flags & B_DELWRI) {
442 bwrite(bp);
443 return (0);
444 }
445 if (bp->b_flags & B_LOCKED)
446 panic("brealloc");
961945a8 447 return (allocbuf(bp, size));
ad30fb67 448 }
9d6d37ce 449 bp->b_flags &= ~B_DONE;
961945a8
SL
450 if (bp->b_dev == NODEV)
451 return (allocbuf(bp, size));
9d6d37ce 452
720c861e 453 trace(TR_BREALLOC, pack(bp->b_dev, size), bp->b_blkno);
9d6d37ce
BJ
454 /*
455 * Search cache for any buffers that overlap the one that we
456 * are trying to allocate. Overlapping buffers must be marked
457 * invalid, after being written out if they are dirty. (indicated
458 * by B_DELWRI) A disk block must be mapped by at most one buffer
459 * at any point in time. Care must be taken to avoid deadlocking
460 * when two buffer are trying to get the same set of disk blocks.
461 */
462 start = bp->b_blkno;
ec67a3ce
MK
463#ifdef SECSIZE
464 last = start + size/bp->b_blksize - 1;
465#else SECSIZE
ad891b02 466 last = start + btodb(size) - 1;
ec67a3ce 467#endif SECSIZE
ad30fb67
KM
468 dp = BUFHASH(bp->b_dev, bp->b_blkno);
469loop:
ad30fb67 470 for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
9d6d37ce
BJ
471 if (ep == bp || ep->b_dev != bp->b_dev || (ep->b_flags&B_INVAL))
472 continue;
473 /* look for overlap */
474 if (ep->b_bcount == 0 || ep->b_blkno > last ||
ec67a3ce
MK
475#ifdef SECSIZE
476 ep->b_blkno + ep->b_bcount/ep->b_blksize <= start)
477#else SECSIZE
ad891b02 478 ep->b_blkno + btodb(ep->b_bcount) <= start)
ec67a3ce 479#endif SECSIZE
ad30fb67 480 continue;
a5e62f37 481 s = splbio();
ad30fb67
KM
482 if (ep->b_flags&B_BUSY) {
483 ep->b_flags |= B_WANTED;
484 sleep((caddr_t)ep, PRIBIO+1);
4f083fd7 485 splx(s);
ad30fb67
KM
486 goto loop;
487 }
4f083fd7 488 splx(s);
9d6d37ce 489 notavail(ep);
ad30fb67 490 if (ep->b_flags & B_DELWRI) {
ad30fb67
KM
491 bwrite(ep);
492 goto loop;
493 }
9d6d37ce
BJ
494 ep->b_flags |= B_INVAL;
495 brelse(ep);
ad30fb67 496 }
961945a8 497 return (allocbuf(bp, size));
4f083fd7
SL
498}
499
4f083fd7
SL
500/*
501 * Find a buffer which is available for use.
502 * Select something from a free list.
503 * Preference is to AGE list, then LRU list.
504 */
505struct buf *
506getnewbuf()
507{
508 register struct buf *bp, *dp;
509 int s;
510
511loop:
a5e62f37 512 s = splbio();
4f083fd7
SL
513 for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--)
514 if (dp->av_forw != dp)
515 break;
516 if (dp == bfreelist) { /* no free blocks */
517 dp->b_flags |= B_WANTED;
518 sleep((caddr_t)dp, PRIBIO+1);
4b7d506c 519 splx(s);
4f083fd7
SL
520 goto loop;
521 }
522 splx(s);
523 bp = dp->av_forw;
524 notavail(bp);
525 if (bp->b_flags & B_DELWRI) {
526 bp->b_flags |= B_ASYNC;
527 bwrite(bp);
528 goto loop;
529 }
720c861e 530 trace(TR_BRELSE, pack(bp->b_dev, bp->b_bufsize), bp->b_blkno);
4f083fd7
SL
531 bp->b_flags = B_BUSY;
532 return (bp);
533}
534
663dbc72
BJ
535/*
536 * Wait for I/O completion on the buffer; return errors
537 * to the user.
538 */
3efdd860 539biowait(bp)
ad30fb67 540 register struct buf *bp;
663dbc72 541{
530d0032 542 int s;
663dbc72 543
a5e62f37 544 s = splbio();
663dbc72
BJ
545 while ((bp->b_flags&B_DONE)==0)
546 sleep((caddr_t)bp, PRIBIO);
530d0032 547 splx(s);
11391203
SL
548 if (u.u_error == 0) /* XXX */
549 u.u_error = geterror(bp);
663dbc72
BJ
550}
551
663dbc72 552/*
af04ce66
SL
553 * Mark I/O complete on a buffer.
554 * If someone should be called, e.g. the pageout
555 * daemon, do so. Otherwise, wake up anyone
556 * waiting for it.
663dbc72 557 */
3efdd860
KM
558biodone(bp)
559 register struct buf *bp;
663dbc72 560{
663dbc72 561
80e7c811 562 if (bp->b_flags & B_DONE)
3efdd860 563 panic("dup biodone");
663dbc72 564 bp->b_flags |= B_DONE;
961945a8
SL
565 if (bp->b_flags & B_CALL) {
566 bp->b_flags &= ~B_CALL;
567 (*bp->b_iodone)(bp);
568 return;
569 }
663dbc72
BJ
570 if (bp->b_flags&B_ASYNC)
571 brelse(bp);
572 else {
573 bp->b_flags &= ~B_WANTED;
574 wakeup((caddr_t)bp);
575 }
576}
577
4f083fd7
SL
578/*
579 * Insure that no part of a specified block is in an incore buffer.
609e7cfa
MK
580#ifdef SECSIZE
581 * "size" is given in device blocks (the units of b_blkno).
582#endif SECSIZE
ec67a3ce
MK
583#ifdef SECSIZE
584 * "size" is given in device blocks (the units of b_blkno).
585#endif SECSIZE
4f083fd7
SL
586 */
587blkflush(dev, blkno, size)
588 dev_t dev;
589 daddr_t blkno;
ec67a3ce
MK
590#ifdef SECSIZE
591 int size;
592#else SECSIZE
4f083fd7 593 long size;
ec67a3ce 594#endif SECSIZE
4f083fd7
SL
595{
596 register struct buf *ep;
597 struct buf *dp;
598 daddr_t start, last;
599 int s;
600
601 start = blkno;
ec67a3ce
MK
602#ifdef SECSIZE
603 last = start + size - 1;
604#else SECSIZE
ad891b02 605 last = start + btodb(size) - 1;
ec67a3ce 606#endif SECSIZE
4f083fd7
SL
607 dp = BUFHASH(dev, blkno);
608loop:
609 for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
610 if (ep->b_dev != dev || (ep->b_flags&B_INVAL))
611 continue;
612 /* look for overlap */
613 if (ep->b_bcount == 0 || ep->b_blkno > last ||
ec67a3ce
MK
614#ifdef SECSIZE
615 ep->b_blkno + ep->b_bcount / ep->b_blksize <= start)
616#else SECSIZE
ad891b02 617 ep->b_blkno + btodb(ep->b_bcount) <= start)
ec67a3ce 618#endif SECSIZE
4f083fd7 619 continue;
a5e62f37 620 s = splbio();
4f083fd7
SL
621 if (ep->b_flags&B_BUSY) {
622 ep->b_flags |= B_WANTED;
623 sleep((caddr_t)ep, PRIBIO+1);
624 splx(s);
625 goto loop;
626 }
627 if (ep->b_flags & B_DELWRI) {
628 splx(s);
629 notavail(ep);
630 bwrite(ep);
631 goto loop;
632 }
633 splx(s);
634 }
635}
636
663dbc72 637/*
af04ce66 638 * Make sure all write-behind blocks
663dbc72
BJ
639 * on dev (or NODEV for all)
640 * are flushed out.
641 * (from umount and update)
642 */
643bflush(dev)
3efdd860 644 dev_t dev;
663dbc72
BJ
645{
646 register struct buf *bp;
46387ee3 647 register struct buf *flist;
530d0032 648 int s;
663dbc72
BJ
649
650loop:
a5e62f37 651 s = splbio();
4f083fd7 652 for (flist = bfreelist; flist < &bfreelist[BQ_EMPTY]; flist++)
46387ee3 653 for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) {
3efdd860
KM
654 if ((bp->b_flags & B_DELWRI) == 0)
655 continue;
656 if (dev == NODEV || dev == bp->b_dev) {
663dbc72
BJ
657 bp->b_flags |= B_ASYNC;
658 notavail(bp);
659 bwrite(bp);
f7916124 660 splx(s);
663dbc72
BJ
661 goto loop;
662 }
663 }
530d0032 664 splx(s);
663dbc72
BJ
665}
666
663dbc72
BJ
667/*
668 * Pick up the device's error number and pass it to the user;
a5b32f74 669 * if there is an error but the number is 0 set a generalized code.
663dbc72
BJ
670 */
671geterror(bp)
3efdd860 672 register struct buf *bp;
663dbc72 673{
d6d7360b 674 int error = 0;
663dbc72
BJ
675
676 if (bp->b_flags&B_ERROR)
d6d7360b
BJ
677 if ((error = bp->b_error)==0)
678 return (EIO);
679 return (error);
663dbc72 680}
7b8b5a01
RE
681
682/*
683 * Invalidate in core blocks belonging to closed or umounted filesystem
684 *
685 * This is not nicely done at all - the buffer ought to be removed from the
686 * hash chains & have its dev/blkno fields clobbered, but unfortunately we
687 * can't do that here, as it is quite possible that the block is still
688 * being used for i/o. Eventually, all disc drivers should be forced to
689 * have a close routine, which ought ensure that the queue is empty, then
690 * properly flush the queues. Until that happy day, this suffices for
691 * correctness. ... kre
692 */
693binval(dev)
3efdd860 694 dev_t dev;
7b8b5a01 695{
634ebdbe
RE
696 register struct buf *bp;
697 register struct bufhd *hp;
698#define dp ((struct buf *)hp)
7b8b5a01 699
634ebdbe
RE
700 for (hp = bufhash; hp < &bufhash[BUFHSZ]; hp++)
701 for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
702 if (bp->b_dev == dev)
703 bp->b_flags |= B_INVAL;
7b8b5a01 704}