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