do not mark dirs with eighth bit set as corrupt;
[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 *
93d6e9b8 17 * @(#)vfs_cluster.c 7.24 (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"
edadbc2c 24#include "mount.h"
94368568 25#include "trace.h"
a937f856 26#include "ucred.h"
663dbc72 27
663dbc72
BJ
28/*
29 * Read in (if necessary) the block and return a buffer pointer.
30 */
a937f856 31bread(vp, blkno, size, cred, bpp)
7188ac27 32 struct vnode *vp;
ad30fb67
KM
33 daddr_t blkno;
34 int size;
a937f856 35 struct ucred *cred;
7188ac27 36 struct buf **bpp;
ec67a3ce
MK
37#ifdef SECSIZE
38 long secsize;
39#endif SECSIZE
663dbc72
BJ
40{
41 register struct buf *bp;
42
4f083fd7
SL
43 if (size == 0)
44 panic("bread: size 0");
ec67a3ce
MK
45#ifdef SECSIZE
46 bp = getblk(dev, blkno, size, secsize);
47#else SECSIZE
7188ac27 48 *bpp = bp = getblk(vp, blkno, size);
ec67a3ce 49#endif SECSIZE
32a56bda 50 if (bp->b_flags&(B_DONE|B_DELWRI)) {
c5a600cf 51 trace(TR_BREADHIT, pack(vp, size), blkno);
7188ac27 52 return (0);
663dbc72
BJ
53 }
54 bp->b_flags |= B_READ;
4f083fd7
SL
55 if (bp->b_bcount > bp->b_bufsize)
56 panic("bread");
a937f856
KM
57 if (bp->b_rcred == NOCRED && cred != NOCRED) {
58 crhold(cred);
59 bp->b_rcred = cred;
60 }
7188ac27 61 VOP_STRATEGY(bp);
c5a600cf 62 trace(TR_BREADMISS, pack(vp, size), blkno);
fb99a9a1 63 u.u_ru.ru_inblock++; /* pay for read */
7188ac27 64 return (biowait(bp));
663dbc72
BJ
65}
66
67/*
68 * Read in the block, like bread, but also start I/O on the
69 * read-ahead block (which is not allocated to the caller)
70 */
a937f856 71breada(vp, blkno, size, rablkno, rabsize, cred, bpp)
7188ac27 72 struct vnode *vp;
84baaab3 73 daddr_t blkno; int size;
ec67a3ce
MK
74#ifdef SECSIZE
75 long secsize;
76#endif SECSIZE
a8d3bf7f 77 daddr_t rablkno; int rabsize;
a937f856 78 struct ucred *cred;
7188ac27 79 struct buf **bpp;
663dbc72
BJ
80{
81 register struct buf *bp, *rabp;
82
83 bp = NULL;
3efdd860
KM
84 /*
85 * If the block isn't in core, then allocate
86 * a buffer and initiate i/o (getblk checks
87 * for a cache hit).
88 */
7188ac27
KM
89 if (!incore(vp, blkno)) {
90 *bpp = bp = getblk(vp, 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");
a937f856
KM
96 if (bp->b_rcred == NOCRED && cred != NOCRED) {
97 crhold(cred);
98 bp->b_rcred = cred;
99 }
7188ac27 100 VOP_STRATEGY(bp);
c5a600cf 101 trace(TR_BREADMISS, pack(vp, size), blkno);
fb99a9a1 102 u.u_ru.ru_inblock++; /* pay for read */
3efdd860 103 } else
c5a600cf 104 trace(TR_BREADHIT, pack(vp, size), blkno);
663dbc72 105 }
3efdd860
KM
106
107 /*
108 * If there's a read-ahead block, start i/o
109 * on it also (as above).
110 */
ee19707c 111 if (!incore(vp, rablkno)) {
7188ac27 112 rabp = getblk(vp, rablkno, rabsize);
ec67a3ce 113#endif SECSIZE
32a56bda 114 if (rabp->b_flags & (B_DONE|B_DELWRI)) {
663dbc72 115 brelse(rabp);
c5a600cf 116 trace(TR_BREADHITRA, pack(vp, rabsize), rablkno);
973ecc4f 117 } else {
663dbc72 118 rabp->b_flags |= B_READ|B_ASYNC;
4f083fd7
SL
119 if (rabp->b_bcount > rabp->b_bufsize)
120 panic("breadrabp");
5062ac4a 121 if (rabp->b_rcred == NOCRED && cred != NOCRED) {
a937f856 122 crhold(cred);
5062ac4a 123 rabp->b_rcred = cred;
a937f856 124 }
7188ac27 125 VOP_STRATEGY(rabp);
c5a600cf 126 trace(TR_BREADMISSRA, pack(vp, rabsize), rablkno);
fb99a9a1 127 u.u_ru.ru_inblock++; /* pay in advance */
663dbc72
BJ
128 }
129 }
3efdd860
KM
130
131 /*
84baaab3
KM
132 * If block was in core, let bread get it.
133 * If block wasn't in core, then the read was started
134 * above, and just wait for it.
3efdd860 135 */
84baaab3 136 if (bp == NULL)
ec67a3ce
MK
137#ifdef SECSIZE
138 return (bread(dev, blkno, size, secsize));
139#else SECSIZE
a937f856 140 return (bread(vp, blkno, size, cred, bpp));
7188ac27 141 return (biowait(bp));
663dbc72
BJ
142}
143
144/*
145 * Write the buffer, waiting for completion.
146 * Then release the buffer.
147 */
148bwrite(bp)
3efdd860 149 register struct buf *bp;
663dbc72 150{
7188ac27 151 register int flag;
86e7dd3b 152 int s, error;
663dbc72
BJ
153
154 flag = bp->b_flags;
f844ee62 155 bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI);
663dbc72 156 if ((flag&B_DELWRI) == 0)
fb99a9a1 157 u.u_ru.ru_oublock++; /* noone paid yet */
c669f646
KM
158 else
159 reassignbuf(bp, bp->b_vp);
c5a600cf 160 trace(TR_BWRITE, pack(bp->b_vp, bp->b_bcount), bp->b_lblkno);
4f083fd7
SL
161 if (bp->b_bcount > bp->b_bufsize)
162 panic("bwrite");
86e7dd3b 163 s = splbio();
c669f646 164 bp->b_vp->v_numoutput++;
86e7dd3b 165 splx(s);
7188ac27 166 VOP_STRATEGY(bp);
3efdd860
KM
167
168 /*
169 * If the write was synchronous, then await i/o completion.
170 * If the write was "delayed", then we put the buffer on
171 * the q of blocks awaiting i/o completion status.
3efdd860 172 */
663dbc72 173 if ((flag&B_ASYNC) == 0) {
7188ac27 174 error = biowait(bp);
663dbc72 175 brelse(bp);
7188ac27 176 } else if (flag & B_DELWRI) {
663dbc72 177 bp->b_flags |= B_AGE;
7188ac27
KM
178 error = 0;
179 }
180 return (error);
663dbc72
BJ
181}
182
183/*
184 * Release the buffer, marking it so that if it is grabbed
185 * for another purpose it will be written out before being
186 * given up (e.g. when writing a partial block where it is
187 * assumed that another write for the same block will soon follow).
188 * This can't be done for magtape, since writes must be done
189 * in the same order as requested.
190 */
191bdwrite(bp)
3efdd860 192 register struct buf *bp;
663dbc72 193{
663dbc72 194
c669f646
KM
195 if ((bp->b_flags & B_DELWRI) == 0) {
196 bp->b_flags |= B_DELWRI;
197 reassignbuf(bp, bp->b_vp);
fb99a9a1 198 u.u_ru.ru_oublock++; /* noone paid yet */
c669f646 199 }
7188ac27 200 /*
edadbc2c 201 * If this is a tape drive, the write must be initiated.
7188ac27 202 */
ec67a3ce 203 if (bdevsw[major(bp->b_dev)].d_flags & B_TAPE)
663dbc72 204 bawrite(bp);
edadbc2c 205 } else {
663dbc72
BJ
206 bp->b_flags |= B_DELWRI | B_DONE;
207 brelse(bp);
208 }
209}
210
211/*
212 * Release the buffer, start I/O on it, but don't wait for completion.
213 */
214bawrite(bp)
3efdd860 215 register struct buf *bp;
663dbc72
BJ
216{
217
218 bp->b_flags |= B_ASYNC;
7188ac27 219 (void) bwrite(bp);
663dbc72
BJ
220}
221
222/*
3efdd860 223 * Release the buffer, with no I/O implied.
663dbc72
BJ
224 */
225brelse(bp)
3efdd860 226 register struct buf *bp;
663dbc72 227{
46387ee3 228 register struct buf *flist;
663dbc72
BJ
229 register s;
230
c5a600cf 231 trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno);
3efdd860 232 /*
edadbc2c
KM
233 * If a process is waiting for the buffer, or
234 * is waiting for a free buffer, awaken it.
3efdd860 235 */
663dbc72
BJ
236 if (bp->b_flags&B_WANTED)
237 wakeup((caddr_t)bp);
46387ee3
BJ
238 if (bfreelist[0].b_flags&B_WANTED) {
239 bfreelist[0].b_flags &= ~B_WANTED;
240 wakeup((caddr_t)bfreelist);
663dbc72 241 }
edadbc2c
KM
242 /*
243 * Retry I/O for locked buffers rather than invalidating them.
244 */
245 if ((bp->b_flags & B_ERROR) && (bp->b_flags & B_LOCKED))
246 bp->b_flags &= ~B_ERROR;
247
248 /*
249 * Disassociate buffers that are no longer valid.
250 */
251 if (bp->b_flags & (B_NOCACHE|B_ERROR))
7188ac27 252 bp->b_flags |= B_INVAL;
edadbc2c
KM
253 if ((bp->b_bufsize <= 0) || (bp->b_flags & (B_ERROR|B_INVAL))) {
254 if (bp->b_vp)
255 brelvp(bp);
256 bp->b_flags &= ~B_DELWRI;
7188ac27 257 }
3efdd860
KM
258 /*
259 * Stick the buffer back on a free list.
260 */
a5e62f37 261 s = splbio();
4f083fd7
SL
262 if (bp->b_bufsize <= 0) {
263 /* block has no buffer ... put at front of unused buffer list */
264 flist = &bfreelist[BQ_EMPTY];
265 binsheadfree(bp, flist);
266 } else if (bp->b_flags & (B_ERROR|B_INVAL)) {
46387ee3 267 /* block has no info ... put at front of most free list */
4f083fd7 268 flist = &bfreelist[BQ_AGE];
3efdd860 269 binsheadfree(bp, flist);
663dbc72 270 } else {
46387ee3
BJ
271 if (bp->b_flags & B_LOCKED)
272 flist = &bfreelist[BQ_LOCKED];
273 else if (bp->b_flags & B_AGE)
274 flist = &bfreelist[BQ_AGE];
275 else
276 flist = &bfreelist[BQ_LRU];
3efdd860 277 binstailfree(bp, flist);
663dbc72 278 }
7188ac27 279 bp->b_flags &= ~(B_WANTED|B_BUSY|B_ASYNC|B_AGE|B_NOCACHE);
663dbc72
BJ
280 splx(s);
281}
282
283/*
284 * See if the block is associated with some buffer
285 * (mainly to avoid getting hung up on a wait in breada)
286 */
7188ac27
KM
287incore(vp, blkno)
288 struct vnode *vp;
3efdd860 289 daddr_t blkno;
663dbc72
BJ
290{
291 register struct buf *bp;
46387ee3 292 register struct buf *dp;
663dbc72 293
243d4743 294 dp = BUFHASH(vp, blkno);
46387ee3 295 for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
edadbc2c 296 if (bp->b_lblkno == blkno && bp->b_vp == vp &&
3efdd860 297 (bp->b_flags & B_INVAL) == 0)
5603d07d 298 return (1);
5603d07d 299 return (0);
663dbc72
BJ
300}
301
edadbc2c
KM
302/*
303 * Return a block if it is in memory.
304 */
a937f856 305baddr(vp, blkno, size, cred, bpp)
7188ac27 306 struct vnode *vp;
ad30fb67
KM
307 daddr_t blkno;
308 int size;
a937f856 309 struct ucred *cred;
7188ac27 310 struct buf **bpp;
ec67a3ce
MK
311#ifdef SECSIZE
312 long secsize;
313#endif SECSIZE
663dbc72
BJ
314{
315
7188ac27 316 if (incore(vp, blkno))
a937f856 317 return (bread(vp, blkno, size, cred, bpp));
7188ac27 318 *bpp = 0;
ec67a3ce 319#endif SECSIZE
663dbc72
BJ
320 return (0);
321}
322
323/*
324 * Assign a buffer for the given block. If the appropriate
325 * block is already associated, return it; otherwise search
326 * for the oldest non-busy buffer and reassign it.
23900030
BJ
327 *
328 * We use splx here because this routine may be called
329 * on the interrupt stack during a dump, and we don't
330 * want to lower the ipl back to 0.
663dbc72
BJ
331 */
332struct buf *
ec67a3ce
MK
333#ifdef SECSIZE
334getblk(dev, blkno, size, secsize)
335#else SECSIZE
7188ac27
KM
336getblk(vp, blkno, size)
337 register struct vnode *vp;
ad30fb67
KM
338 daddr_t blkno;
339 int size;
ec67a3ce
MK
340#ifdef SECSIZE
341 long secsize;
342#endif SECSIZE
663dbc72 343{
4f083fd7 344 register struct buf *bp, *dp;
23900030 345 int s;
663dbc72 346
00a6a148
KM
347 if (size > MAXBSIZE)
348 panic("getblk: size too big");
751af33e
KM
349 /*
350 * To prevent overflow of 32-bit ints when converting block
351 * numbers to byte offsets, blknos > 2^32 / DEV_BSIZE are set
352 * to the maximum number that can be converted to a byte offset
353 * without overflow. This is historic code; what bug it fixed,
354 * or whether it is still a reasonable thing to do is open to
355 * dispute. mkm 9/85
edadbc2c
KM
356 *
357 * Make it a panic to see if it ever really happens. mkm 11/89
751af33e 358 */
edadbc2c
KM
359 if ((unsigned)blkno >= 1 << (sizeof(int)*NBBY-DEV_BSHIFT)) {
360 panic("getblk: blkno too big");
751af33e 361 blkno = 1 << ((sizeof(int)*NBBY-DEV_BSHIFT) + 1);
edadbc2c 362 }
3efdd860
KM
363 /*
364 * Search the cache for the block. If we hit, but
365 * the buffer is in use for i/o, then we wait until
366 * the i/o has completed.
367 */
7188ac27 368 dp = BUFHASH(vp, blkno);
3efdd860 369loop:
46387ee3 370 for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) {
edadbc2c 371 if (bp->b_lblkno != blkno || bp->b_vp != vp ||
46387ee3 372 bp->b_flags&B_INVAL)
663dbc72 373 continue;
a5e62f37 374 s = splbio();
663dbc72
BJ
375 if (bp->b_flags&B_BUSY) {
376 bp->b_flags |= B_WANTED;
377 sleep((caddr_t)bp, PRIBIO+1);
23900030 378 splx(s);
663dbc72
BJ
379 goto loop;
380 }
c669f646
KM
381 bremfree(bp);
382 bp->b_flags |= B_BUSY;
23900030 383 splx(s);
32a56bda 384 if (bp->b_bcount != size) {
edadbc2c
KM
385 printf("getblk: stray size");
386 bp->b_flags |= B_INVAL;
387 bwrite(bp);
9d6d37ce 388 goto loop;
edadbc2c 389 }
663dbc72 390 bp->b_flags |= B_CACHE;
a5e62f37 391 return (bp);
663dbc72 392 }
4f083fd7 393 bp = getnewbuf();
ad30fb67 394 bfree(bp);
3efdd860 395 bremhash(bp);
edadbc2c
KM
396 bgetvp(vp, bp);
397 bp->b_lblkno = blkno;
ec67a3ce
MK
398#ifdef SECSIZE
399 bp->b_blksize = secsize;
400#endif SECSIZE
ad30fb67 401 bp->b_blkno = blkno;
4f083fd7 402 bp->b_error = 0;
7188ac27
KM
403 bp->b_resid = 0;
404 binshash(bp, dp);
edadbc2c 405 brealloc(bp, size);
a5e62f37 406 return (bp);
663dbc72
BJ
407}
408
409/*
410 * get an empty block,
411 * not assigned to any particular device
412 */
413struct buf *
ad30fb67
KM
414geteblk(size)
415 int size;
663dbc72 416{
4f083fd7 417 register struct buf *bp, *flist;
663dbc72 418
00a6a148
KM
419 if (size > MAXBSIZE)
420 panic("geteblk: size too big");
4f083fd7
SL
421 bp = getnewbuf();
422 bp->b_flags |= B_INVAL;
3efdd860
KM
423 bfree(bp);
424 bremhash(bp);
4f083fd7 425 flist = &bfreelist[BQ_AGE];
ec67a3ce
MK
426#ifdef SECSIZE
427 bp->b_blksize = DEV_BSIZE;
428#endif SECSIZE
4f083fd7 429 bp->b_error = 0;
7188ac27
KM
430 bp->b_resid = 0;
431 binshash(bp, flist);
edadbc2c 432 brealloc(bp, size);
a5e62f37 433 return (bp);
663dbc72
BJ
434}
435
ad30fb67
KM
436/*
437 * Allocate space associated with a buffer.
438 */
439brealloc(bp, size)
440 register struct buf *bp;
441 int size;
442{
443 daddr_t start, last;
444 register struct buf *ep;
445 struct buf *dp;
446 int s;
447
ad30fb67 448 if (size == bp->b_bcount)
edadbc2c
KM
449 return;
450 allocbuf(bp, size);
4f083fd7
SL
451}
452
4f083fd7
SL
453/*
454 * Find a buffer which is available for use.
455 * Select something from a free list.
456 * Preference is to AGE list, then LRU list.
457 */
458struct buf *
459getnewbuf()
460{
461 register struct buf *bp, *dp;
a937f856 462 register struct ucred *cred;
4f083fd7
SL
463 int s;
464
465loop:
a5e62f37 466 s = splbio();
4f083fd7
SL
467 for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--)
468 if (dp->av_forw != dp)
469 break;
470 if (dp == bfreelist) { /* no free blocks */
471 dp->b_flags |= B_WANTED;
472 sleep((caddr_t)dp, PRIBIO+1);
4b7d506c 473 splx(s);
4f083fd7
SL
474 goto loop;
475 }
4f083fd7 476 bp = dp->av_forw;
c669f646
KM
477 bremfree(bp);
478 bp->b_flags |= B_BUSY;
479 splx(s);
4f083fd7 480 if (bp->b_flags & B_DELWRI) {
033a786e 481 (void) bawrite(bp);
4f083fd7
SL
482 goto loop;
483 }
c5a600cf 484 trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno);
edadbc2c
KM
485 if (bp->b_vp)
486 brelvp(bp);
a937f856
KM
487 if (bp->b_rcred != NOCRED) {
488 cred = bp->b_rcred;
489 bp->b_rcred = NOCRED;
490 crfree(cred);
491 }
492 if (bp->b_wcred != NOCRED) {
493 cred = bp->b_wcred;
494 bp->b_wcred = NOCRED;
495 crfree(cred);
496 }
4f083fd7
SL
497 bp->b_flags = B_BUSY;
498 return (bp);
499}
500
663dbc72
BJ
501/*
502 * Wait for I/O completion on the buffer; return errors
503 * to the user.
504 */
3efdd860 505biowait(bp)
ad30fb67 506 register struct buf *bp;
663dbc72 507{
530d0032 508 int s;
663dbc72 509
a5e62f37 510 s = splbio();
a937f856 511 while ((bp->b_flags & B_DONE) == 0)
663dbc72 512 sleep((caddr_t)bp, PRIBIO);
530d0032 513 splx(s);
7188ac27
KM
514 /*
515 * Pick up the device's error number and pass it to the user;
516 * if there is an error but the number is 0 set a generalized code.
517 */
518 if ((bp->b_flags & B_ERROR) == 0)
519 return (0);
520 if (bp->b_error)
521 return (bp->b_error);
522 return (EIO);
663dbc72
BJ
523}
524
663dbc72 525/*
af04ce66
SL
526 * Mark I/O complete on a buffer.
527 * If someone should be called, e.g. the pageout
528 * daemon, do so. Otherwise, wake up anyone
529 * waiting for it.
663dbc72 530 */
3efdd860
KM
531biodone(bp)
532 register struct buf *bp;
663dbc72 533{
c669f646 534 register struct vnode *vp;
663dbc72 535
80e7c811 536 if (bp->b_flags & B_DONE)
3efdd860 537 panic("dup biodone");
663dbc72 538 bp->b_flags |= B_DONE;
c669f646 539 if ((bp->b_flags & B_READ) == 0) {
a937f856 540 bp->b_dirtyoff = bp->b_dirtyend = 0;
c669f646
KM
541 if (vp = bp->b_vp) {
542 vp->v_numoutput--;
543 if ((vp->v_flag & VBWAIT) && vp->v_numoutput <= 0) {
544 if (vp->v_numoutput < 0)
545 panic("biodone: neg numoutput");
546 vp->v_flag &= ~VBWAIT;
547 wakeup((caddr_t)&vp->v_numoutput);
548 }
549 }
550 }
961945a8
SL
551 if (bp->b_flags & B_CALL) {
552 bp->b_flags &= ~B_CALL;
553 (*bp->b_iodone)(bp);
554 return;
555 }
663dbc72
BJ
556 if (bp->b_flags&B_ASYNC)
557 brelse(bp);
558 else {
559 bp->b_flags &= ~B_WANTED;
560 wakeup((caddr_t)bp);
561 }
562}
563
663dbc72 564/*
7188ac27 565 * Make sure all write-behind blocks associated
a937f856 566 * with mount point are flushed out (from sync).
663dbc72 567 */
edadbc2c 568mntflushbuf(mountp, flags)
a937f856 569 struct mount *mountp;
edadbc2c 570 int flags;
663dbc72 571{
099798da 572 register struct vnode *vp;
c02aa1e0 573 struct vnode *nvp;
edadbc2c
KM
574
575loop:
c02aa1e0
KM
576 for (vp = mountp->m_mounth; vp; vp = nvp) {
577 nvp = vp->v_mountf;
edadbc2c
KM
578 if (vget(vp))
579 goto loop;
580 vflushbuf(vp, flags);
581 vput(vp);
582 }
583}
584
585/*
586 * Flush all dirty buffers associated with a vnode.
587 */
588vflushbuf(vp, flags)
589 register struct vnode *vp;
590 int flags;
591{
592 register struct buf *bp;
593 struct buf *nbp;
530d0032 594 int s;
663dbc72
BJ
595
596loop:
a5e62f37 597 s = splbio();
c669f646 598 for (bp = vp->v_dirtyblkhd; bp; bp = nbp) {
edadbc2c
KM
599 nbp = bp->b_blockf;
600 if ((bp->b_flags & B_BUSY))
601 continue;
602 if ((bp->b_flags & B_DELWRI) == 0)
c669f646
KM
603 panic("vflushbuf: not dirty");
604 bremfree(bp);
605 bp->b_flags |= B_BUSY;
edadbc2c 606 splx(s);
c669f646
KM
607 /*
608 * Wait for I/O associated with indirect blocks to complete,
609 * since there is no way to quickly wait for them below.
610 * NB - This is really specific to ufs, but is done here
611 * as it is easier and quicker.
612 */
613 if (bp->b_vp == vp || (flags & B_SYNC) == 0) {
614 (void) bawrite(bp);
93d6e9b8 615 s = splbio();
c669f646
KM
616 } else {
617 (void) bwrite(bp);
618 goto loop;
619 }
edadbc2c 620 }
9c1dffd6 621 splx(s);
edadbc2c
KM
622 if ((flags & B_SYNC) == 0)
623 return;
edadbc2c 624 s = splbio();
c669f646
KM
625 while (vp->v_numoutput) {
626 vp->v_flag |= VBWAIT;
627 sleep((caddr_t)&vp->v_numoutput, PRIBIO+1);
7188ac27 628 }
9c1dffd6 629 splx(s);
c669f646
KM
630 if (vp->v_dirtyblkhd) {
631 vprint("vflushbuf: dirty", vp);
632 goto loop;
633 }
663dbc72 634}
7b8b5a01
RE
635
636/*
637 * Invalidate in core blocks belonging to closed or umounted filesystem
638 *
edadbc2c
KM
639 * Go through the list of vnodes associated with the file system;
640 * for each vnode invalidate any buffers that it holds. Normally
641 * this routine is preceeded by a bflush call, so that on a quiescent
642 * filesystem there will be no dirty buffers when we are done. Binval
643 * returns the count of dirty buffers when it is finished.
7b8b5a01 644 */
edadbc2c 645mntinvalbuf(mountp)
a937f856 646 struct mount *mountp;
7b8b5a01 647{
099798da 648 register struct vnode *vp;
c02aa1e0 649 struct vnode *nvp;
edadbc2c
KM
650 int dirty = 0;
651
652loop:
c02aa1e0
KM
653 for (vp = mountp->m_mounth; vp; vp = nvp) {
654 nvp = vp->v_mountf;
edadbc2c
KM
655 if (vget(vp))
656 goto loop;
657 dirty += vinvalbuf(vp, 1);
658 vput(vp);
659 }
660 return (dirty);
661}
662
663/*
664 * Flush out and invalidate all buffers associated with a vnode.
665 * Called with the underlying object locked.
666 */
667vinvalbuf(vp, save)
668 register struct vnode *vp;
669 int save;
670{
671 register struct buf *bp;
c669f646 672 struct buf *nbp, *blist;
1a24c701 673 int s, dirty = 0;
7b8b5a01 674
c669f646
KM
675 for (;;) {
676 if (blist = vp->v_dirtyblkhd)
677 /* void */;
678 else if (blist = vp->v_cleanblkhd)
679 /* void */;
680 else
681 break;
682 for (bp = blist; bp; bp = nbp) {
683 nbp = bp->b_blockf;
684 s = splbio();
685 if (bp->b_flags & B_BUSY) {
686 bp->b_flags |= B_WANTED;
687 sleep((caddr_t)bp, PRIBIO+1);
688 splx(s);
689 break;
690 }
691 bremfree(bp);
692 bp->b_flags |= B_BUSY;
5a3e32e2 693 splx(s);
c669f646 694 if (save && (bp->b_flags & B_DELWRI)) {
033a786e 695 dirty++;
edadbc2c 696 (void) bwrite(bp);
c669f646 697 break;
7188ac27 698 }
05a0ddc9
KM
699 if (bp->b_vp != vp)
700 reassignbuf(bp, bp->b_vp);
701 else
702 bp->b_flags |= B_INVAL;
c669f646 703 brelse(bp);
033a786e
KM
704 }
705 }
c669f646 706 if (vp->v_dirtyblkhd || vp->v_cleanblkhd)
edadbc2c 707 panic("vinvalbuf: flush failed");
033a786e 708 return (dirty);
7188ac27
KM
709}
710
edadbc2c
KM
711/*
712 * Associate a buffer with a vnode.
713 */
714bgetvp(vp, bp)
715 register struct vnode *vp;
716 register struct buf *bp;
717{
718
719 if (bp->b_vp)
720 panic("bgetvp: not free");
79b10da1 721 VHOLD(vp);
edadbc2c
KM
722 bp->b_vp = vp;
723 if (vp->v_type == VBLK || vp->v_type == VCHR)
724 bp->b_dev = vp->v_rdev;
725 else
726 bp->b_dev = NODEV;
727 /*
728 * Insert onto list for new vnode.
729 */
c669f646
KM
730 if (vp->v_cleanblkhd) {
731 bp->b_blockf = vp->v_cleanblkhd;
732 bp->b_blockb = &vp->v_cleanblkhd;
733 vp->v_cleanblkhd->b_blockb = &bp->b_blockf;
734 vp->v_cleanblkhd = bp;
edadbc2c 735 } else {
c669f646
KM
736 vp->v_cleanblkhd = bp;
737 bp->b_blockb = &vp->v_cleanblkhd;
edadbc2c
KM
738 bp->b_blockf = NULL;
739 }
740}
741
742/*
743 * Disassociate a buffer from a vnode.
744 */
7188ac27 745brelvp(bp)
edadbc2c 746 register struct buf *bp;
7188ac27 747{
edadbc2c 748 struct buf *bq;
7188ac27
KM
749 struct vnode *vp;
750
751 if (bp->b_vp == (struct vnode *) 0)
edadbc2c
KM
752 panic("brelvp: NULL");
753 /*
754 * Delete from old vnode list, if on one.
755 */
756 if (bp->b_blockb) {
757 if (bq = bp->b_blockf)
758 bq->b_blockb = bp->b_blockb;
759 *bp->b_blockb = bq;
760 bp->b_blockf = NULL;
761 bp->b_blockb = NULL;
762 }
7188ac27
KM
763 vp = bp->b_vp;
764 bp->b_vp = (struct vnode *) 0;
79b10da1 765 HOLDRELE(vp);
7b8b5a01 766}
edadbc2c
KM
767
768/*
769 * Reassign a buffer from one vnode to another.
770 * Used to assign file specific control information
771 * (indirect blocks) to the vnode to which they belong.
772 */
773reassignbuf(bp, newvp)
774 register struct buf *bp;
775 register struct vnode *newvp;
776{
c669f646 777 register struct buf *bq, **listheadp;
edadbc2c 778
c669f646
KM
779 if (newvp == NULL)
780 panic("reassignbuf: NULL");
edadbc2c
KM
781 /*
782 * Delete from old vnode list, if on one.
783 */
784 if (bp->b_blockb) {
785 if (bq = bp->b_blockf)
786 bq->b_blockb = bp->b_blockb;
787 *bp->b_blockb = bq;
788 }
789 /*
c669f646
KM
790 * If dirty, put on list of dirty buffers;
791 * otherwise insert onto list of clean buffers.
edadbc2c 792 */
c669f646
KM
793 if (bp->b_flags & B_DELWRI)
794 listheadp = &newvp->v_dirtyblkhd;
795 else
796 listheadp = &newvp->v_cleanblkhd;
797 if (*listheadp) {
798 bp->b_blockf = *listheadp;
799 bp->b_blockb = listheadp;
800 bp->b_blockf->b_blockb = &bp->b_blockf;
801 *listheadp = bp;
edadbc2c 802 } else {
c669f646
KM
803 *listheadp = bp;
804 bp->b_blockb = listheadp;
edadbc2c
KM
805 bp->b_blockf = NULL;
806 }
807}