have to remember to lock buffers before trying to grab them
[unix-history] / usr / src / sys / kern / vfs_cluster.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 *
1a24c701 17 * @(#)vfs_cluster.c 7.9 (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
243d4743 276 dp = BUFHASH(vp, 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);
8fe1c702 383 VREF(vp);
7188ac27
KM
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) {
033a786e 535 (void) bawrite(bp);
4f083fd7
SL
536 goto loop;
537 }
7188ac27
KM
538 trace(TR_BRELSE,
539 pack(bp->b_vp->v_mount->m_fsid[0], bp->b_bufsize), bp->b_blkno);
540 brelvp(bp);
4f083fd7
SL
541 bp->b_flags = B_BUSY;
542 return (bp);
543}
544
663dbc72
BJ
545/*
546 * Wait for I/O completion on the buffer; return errors
547 * to the user.
548 */
3efdd860 549biowait(bp)
ad30fb67 550 register struct buf *bp;
663dbc72 551{
530d0032 552 int s;
663dbc72 553
a5e62f37 554 s = splbio();
663dbc72
BJ
555 while ((bp->b_flags&B_DONE)==0)
556 sleep((caddr_t)bp, PRIBIO);
530d0032 557 splx(s);
7188ac27
KM
558 /*
559 * Pick up the device's error number and pass it to the user;
560 * if there is an error but the number is 0 set a generalized code.
561 */
562 if ((bp->b_flags & B_ERROR) == 0)
563 return (0);
564 if (bp->b_error)
565 return (bp->b_error);
566 return (EIO);
663dbc72
BJ
567}
568
663dbc72 569/*
af04ce66
SL
570 * Mark I/O complete on a buffer.
571 * If someone should be called, e.g. the pageout
572 * daemon, do so. Otherwise, wake up anyone
573 * waiting for it.
663dbc72 574 */
3efdd860
KM
575biodone(bp)
576 register struct buf *bp;
663dbc72 577{
663dbc72 578
80e7c811 579 if (bp->b_flags & B_DONE)
3efdd860 580 panic("dup biodone");
663dbc72 581 bp->b_flags |= B_DONE;
961945a8
SL
582 if (bp->b_flags & B_CALL) {
583 bp->b_flags &= ~B_CALL;
584 (*bp->b_iodone)(bp);
585 return;
586 }
663dbc72
BJ
587 if (bp->b_flags&B_ASYNC)
588 brelse(bp);
589 else {
590 bp->b_flags &= ~B_WANTED;
591 wakeup((caddr_t)bp);
592 }
593}
594
4f083fd7 595/*
7188ac27 596 * Ensure that no part of a specified block is in an incore buffer.
609e7cfa
MK
597#ifdef SECSIZE
598 * "size" is given in device blocks (the units of b_blkno).
599#endif SECSIZE
ec67a3ce
MK
600#ifdef SECSIZE
601 * "size" is given in device blocks (the units of b_blkno).
602#endif SECSIZE
4f083fd7 603 */
7188ac27
KM
604blkflush(vp, blkno, size)
605 struct vnode *vp;
4f083fd7 606 daddr_t blkno;
ec67a3ce
MK
607#ifdef SECSIZE
608 int size;
609#else SECSIZE
4f083fd7 610 long size;
ec67a3ce 611#endif SECSIZE
4f083fd7
SL
612{
613 register struct buf *ep;
614 struct buf *dp;
615 daddr_t start, last;
7188ac27 616 int s, error, allerrors = 0;
4f083fd7
SL
617
618 start = blkno;
ec67a3ce
MK
619#ifdef SECSIZE
620 last = start + size - 1;
621#else SECSIZE
ad891b02 622 last = start + btodb(size) - 1;
ec67a3ce 623#endif SECSIZE
7188ac27 624 dp = BUFHASH(vp, blkno);
4f083fd7
SL
625loop:
626 for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
7188ac27 627 if (ep->b_vp != vp || (ep->b_flags & B_INVAL))
4f083fd7
SL
628 continue;
629 /* look for overlap */
630 if (ep->b_bcount == 0 || ep->b_blkno > last ||
ec67a3ce
MK
631#ifdef SECSIZE
632 ep->b_blkno + ep->b_bcount / ep->b_blksize <= start)
633#else SECSIZE
ad891b02 634 ep->b_blkno + btodb(ep->b_bcount) <= start)
ec67a3ce 635#endif SECSIZE
4f083fd7 636 continue;
a5e62f37 637 s = splbio();
4f083fd7
SL
638 if (ep->b_flags&B_BUSY) {
639 ep->b_flags |= B_WANTED;
640 sleep((caddr_t)ep, PRIBIO+1);
641 splx(s);
642 goto loop;
643 }
644 if (ep->b_flags & B_DELWRI) {
645 splx(s);
646 notavail(ep);
7188ac27
KM
647 if (error = bwrite(ep))
648 allerrors = error;
4f083fd7
SL
649 goto loop;
650 }
651 splx(s);
652 }
7188ac27 653 return (allerrors);
4f083fd7
SL
654}
655
663dbc72 656/*
7188ac27
KM
657 * Make sure all write-behind blocks associated
658 * with vp are flushed out (from sync).
663dbc72
BJ
659 */
660bflush(dev)
3efdd860 661 dev_t dev;
663dbc72
BJ
662{
663 register struct buf *bp;
46387ee3 664 register struct buf *flist;
530d0032 665 int s;
663dbc72
BJ
666
667loop:
a5e62f37 668 s = splbio();
4f083fd7 669 for (flist = bfreelist; flist < &bfreelist[BQ_EMPTY]; flist++)
46387ee3 670 for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) {
3efdd860
KM
671 if ((bp->b_flags & B_DELWRI) == 0)
672 continue;
673 if (dev == NODEV || dev == bp->b_dev) {
663dbc72 674 notavail(bp);
033a786e 675 (void) bawrite(bp);
f7916124 676 splx(s);
663dbc72
BJ
677 goto loop;
678 }
679 }
530d0032 680 splx(s);
663dbc72
BJ
681}
682
7188ac27 683#ifdef unused
663dbc72 684/*
7188ac27
KM
685 * Invalidate blocks associated with vp which are on the freelist.
686 * Make sure all write-behind blocks associated with vp are flushed out.
663dbc72 687 */
7188ac27
KM
688binvalfree(vp)
689 struct vnode *vp;
663dbc72 690{
7188ac27
KM
691 register struct buf *bp;
692 register struct buf *flist;
693 int s;
663dbc72 694
7188ac27
KM
695loop:
696 s = splbio();
697 for (flist = bfreelist; flist < &bfreelist[BQ_EMPTY]; flist++)
698 for (bp = flist->av_forw; bp != flist; bp = bp->av_forw) {
699 if (vp == (struct vnode *) 0 || vp == bp->b_vp) {
700 if (bp->b_flags & B_DELWRI) {
7188ac27
KM
701 notavail(bp);
702 (void) splx(s);
033a786e 703 (void) bawrite(bp);
7188ac27
KM
704 } else {
705 bp->b_flags |= B_INVAL;
706 brelvp(bp);
707 (void) splx(s);
708 }
709 goto loop;
710 }
711 }
712 (void) splx(s);
663dbc72 713}
7188ac27 714#endif /* unused */
7b8b5a01
RE
715
716/*
717 * Invalidate in core blocks belonging to closed or umounted filesystem
718 *
033a786e
KM
719 * We walk through the buffer pool and invalidate any buffers for the
720 * indicated device. Normally this routine is preceeded by a bflush
721 * call, so that on a quiescent filesystem there will be no dirty
722 * buffers when we are done. We return the count of dirty buffers when
723 * we are finished.
7b8b5a01
RE
724 */
725binval(dev)
3efdd860 726 dev_t dev;
7b8b5a01 727{
634ebdbe
RE
728 register struct buf *bp;
729 register struct bufhd *hp;
1a24c701 730 int s, dirty = 0;
634ebdbe 731#define dp ((struct buf *)hp)
7b8b5a01 732
033a786e
KM
733 for (hp = bufhash; hp < &bufhash[BUFHSZ]; hp++) {
734 for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) {
735 if (bp->b_dev != dev || (bp->b_flags & B_INVAL))
736 continue;
1a24c701
KM
737 loop:
738 s = splbio();
739 if (bp->b_flags & B_BUSY) {
740 bp->b_flags |= B_WANTED;
741 sleep((caddr_t)bp, PRIBIO+1);
742 splx(s);
743 goto loop;
744 }
033a786e
KM
745 notavail(bp);
746 if (bp->b_flags & B_DELWRI) {
747 (void) bawrite(bp);
748 dirty++;
749 continue;
7188ac27 750 }
033a786e
KM
751 bp->b_flags |= B_INVAL;
752 brelvp(bp);
753 brelse(bp);
754 }
755 }
756 return (dirty);
7188ac27
KM
757}
758
759brelvp(bp)
760 struct buf *bp;
761{
762 struct vnode *vp;
763
764 if (bp->b_vp == (struct vnode *) 0)
765 return;
766 vp = bp->b_vp;
767 bp->b_vp = (struct vnode *) 0;
768 vrele(vp);
7b8b5a01 769}