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