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