alpha2.1 release from Henry Spencer
[unix-history] / usr / src / sys / kern / vfs_cluster.c
CommitLineData
5dc2581e
KB
1/*-
2 * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
7188ac27 3 * All rights reserved.
da7c5cc6 4 *
217c3be4
KM
5 * This module is believed to contain source code proprietary to AT&T.
6 * Use and redistribution is subject to the Berkeley Software License
7 * Agreement and your Software Agreement with AT&T (Western Electric).
7188ac27 8 *
0649728d 9 * @(#)vfs_cluster.c 7.53 (Berkeley) %G%
da7c5cc6 10 */
961945a8 11
251f56ba
KB
12#include <sys/param.h>
13#include <sys/proc.h>
14#include <sys/buf.h>
15#include <sys/vnode.h>
251f56ba
KB
16#include <sys/mount.h>
17#include <sys/trace.h>
18#include <sys/resourcevar.h>
663dbc72 19
e7db227e
MK
20/*
21 * Initialize buffers and hash links for buffers.
22 */
251f56ba 23void
e7db227e
MK
24bufinit()
25{
26 register int i;
27 register struct buf *bp, *dp;
28 register struct bufhd *hp;
29 int base, residual;
30
31 for (hp = bufhash, i = 0; i < BUFHSZ; i++, hp++)
32 hp->b_forw = hp->b_back = (struct buf *)hp;
33
34 for (dp = bfreelist; dp < &bfreelist[BQUEUES]; dp++) {
35 dp->b_forw = dp->b_back = dp->av_forw = dp->av_back = dp;
36 dp->b_flags = B_HEAD;
37 }
38 base = bufpages / nbuf;
39 residual = bufpages % nbuf;
40 for (i = 0; i < nbuf; i++) {
41 bp = &buf[i];
42 bp->b_dev = NODEV;
43 bp->b_bcount = 0;
44 bp->b_rcred = NOCRED;
45 bp->b_wcred = NOCRED;
46 bp->b_dirtyoff = 0;
47 bp->b_dirtyend = 0;
bb1626f7
KM
48 bp->b_validoff = 0;
49 bp->b_validend = 0;
e7db227e
MK
50 bp->b_un.b_addr = buffers + i * MAXBSIZE;
51 if (i < residual)
52 bp->b_bufsize = (base + 1) * CLBYTES;
53 else
54 bp->b_bufsize = base * CLBYTES;
55 binshash(bp, &bfreelist[BQ_AGE]);
31222d0d
CT
56 bp->b_flags = B_INVAL;
57 dp = bp->b_bufsize ? &bfreelist[BQ_AGE] : &bfreelist[BQ_EMPTY];
58 binsheadfree(bp, dp);
e7db227e
MK
59 }
60}
61
663dbc72 62/*
d42a4811
KM
63 * Find the block in the buffer pool.
64 * If the buffer is not present, allocate a new buffer and load
65 * its contents according to the filesystem fill routine.
663dbc72 66 */
a937f856 67bread(vp, blkno, size, cred, bpp)
7188ac27 68 struct vnode *vp;
ad30fb67
KM
69 daddr_t blkno;
70 int size;
a937f856 71 struct ucred *cred;
7188ac27 72 struct buf **bpp;
ec67a3ce
MK
73#ifdef SECSIZE
74 long secsize;
75#endif SECSIZE
663dbc72 76{
3789a403 77 struct proc *p = curproc; /* XXX */
663dbc72
BJ
78 register struct buf *bp;
79
4f083fd7
SL
80 if (size == 0)
81 panic("bread: size 0");
ec67a3ce
MK
82#ifdef SECSIZE
83 bp = getblk(dev, blkno, size, secsize);
84#else SECSIZE
7188ac27 85 *bpp = bp = getblk(vp, blkno, size);
ec67a3ce 86#endif SECSIZE
d42a4811 87 if (bp->b_flags & (B_DONE | B_DELWRI)) {
c5a600cf 88 trace(TR_BREADHIT, pack(vp, size), blkno);
7188ac27 89 return (0);
663dbc72
BJ
90 }
91 bp->b_flags |= B_READ;
4f083fd7
SL
92 if (bp->b_bcount > bp->b_bufsize)
93 panic("bread");
a937f856
KM
94 if (bp->b_rcred == NOCRED && cred != NOCRED) {
95 crhold(cred);
96 bp->b_rcred = cred;
97 }
7188ac27 98 VOP_STRATEGY(bp);
c5a600cf 99 trace(TR_BREADMISS, pack(vp, size), blkno);
3789a403 100 p->p_stats->p_ru.ru_inblock++; /* pay for read */
7188ac27 101 return (biowait(bp));
663dbc72
BJ
102}
103
104/*
bb1626f7
KM
105 * Operates like bread, but also starts I/O on the N specified
106 * read-ahead blocks.
663dbc72 107 */
bb1626f7 108breadn(vp, blkno, size, rablkno, rabsize, num, cred, bpp)
7188ac27 109 struct vnode *vp;
84baaab3 110 daddr_t blkno; int size;
ec67a3ce
MK
111#ifdef SECSIZE
112 long secsize;
113#endif SECSIZE
bb1626f7
KM
114 daddr_t rablkno[]; int rabsize[];
115 int num;
a937f856 116 struct ucred *cred;
7188ac27 117 struct buf **bpp;
663dbc72 118{
3789a403 119 struct proc *p = curproc; /* XXX */
663dbc72 120 register struct buf *bp, *rabp;
bb1626f7 121 register int i;
663dbc72
BJ
122
123 bp = NULL;
3efdd860 124 /*
d42a4811
KM
125 * If the block is not memory resident,
126 * allocate a buffer and start I/O.
3efdd860 127 */
7188ac27
KM
128 if (!incore(vp, blkno)) {
129 *bpp = bp = getblk(vp, blkno, size);
ec67a3ce 130#endif SECSIZE
d42a4811 131 if ((bp->b_flags & (B_DONE | B_DELWRI)) == 0) {
663dbc72 132 bp->b_flags |= B_READ;
4f083fd7 133 if (bp->b_bcount > bp->b_bufsize)
bb1626f7 134 panic("breadn");
a937f856
KM
135 if (bp->b_rcred == NOCRED && cred != NOCRED) {
136 crhold(cred);
137 bp->b_rcred = cred;
138 }
7188ac27 139 VOP_STRATEGY(bp);
c5a600cf 140 trace(TR_BREADMISS, pack(vp, size), blkno);
3789a403 141 p->p_stats->p_ru.ru_inblock++; /* pay for read */
7d1e9cf4 142 } else {
c5a600cf 143 trace(TR_BREADHIT, pack(vp, size), blkno);
7d1e9cf4 144 }
663dbc72 145 }
3efdd860
KM
146
147 /*
bb1626f7
KM
148 * If there's read-ahead block(s), start I/O
149 * on them also (as above).
3efdd860 150 */
bb1626f7
KM
151 for (i = 0; i < num; i++) {
152 if (incore(vp, rablkno[i]))
153 continue;
154 rabp = getblk(vp, rablkno[i], rabsize[i]);
ec67a3ce 155#endif SECSIZE
d42a4811 156 if (rabp->b_flags & (B_DONE | B_DELWRI)) {
663dbc72 157 brelse(rabp);
bb1626f7 158 trace(TR_BREADHITRA, pack(vp, rabsize[i]), rablkno[i]);
973ecc4f 159 } else {
d42a4811 160 rabp->b_flags |= B_ASYNC | B_READ;
4f083fd7
SL
161 if (rabp->b_bcount > rabp->b_bufsize)
162 panic("breadrabp");
5062ac4a 163 if (rabp->b_rcred == NOCRED && cred != NOCRED) {
a937f856 164 crhold(cred);
5062ac4a 165 rabp->b_rcred = cred;
a937f856 166 }
7188ac27 167 VOP_STRATEGY(rabp);
bb1626f7 168 trace(TR_BREADMISSRA, pack(vp, rabsize[i]), rablkno[i]);
3789a403 169 p->p_stats->p_ru.ru_inblock++; /* pay in advance */
663dbc72
BJ
170 }
171 }
3efdd860
KM
172
173 /*
d42a4811
KM
174 * If block was memory resident, let bread get it.
175 * If block was not memory resident, the read was
176 * started above, so just wait for the read to complete.
3efdd860 177 */
84baaab3 178 if (bp == NULL)
ec67a3ce
MK
179#ifdef SECSIZE
180 return (bread(dev, blkno, size, secsize));
181#else SECSIZE
a937f856 182 return (bread(vp, blkno, size, cred, bpp));
7188ac27 183 return (biowait(bp));
663dbc72
BJ
184}
185
186/*
d42a4811
KM
187 * Synchronous write.
188 * Release buffer on completion.
663dbc72
BJ
189 */
190bwrite(bp)
3efdd860 191 register struct buf *bp;
663dbc72 192{
3789a403 193 struct proc *p = curproc; /* XXX */
7188ac27 194 register int flag;
31222d0d 195 int s, error = 0;
663dbc72
BJ
196
197 flag = bp->b_flags;
f844ee62 198 bp->b_flags &= ~(B_READ | B_DONE | B_ERROR | B_DELWRI);
77dc8a8c
KM
199 if (flag & B_ASYNC) {
200 if ((flag & B_DELWRI) == 0)
201 p->p_stats->p_ru.ru_oublock++; /* no one paid yet */
202 else
203 reassignbuf(bp, bp->b_vp);
204 }
c5a600cf 205 trace(TR_BWRITE, pack(bp->b_vp, bp->b_bcount), bp->b_lblkno);
4f083fd7
SL
206 if (bp->b_bcount > bp->b_bufsize)
207 panic("bwrite");
86e7dd3b 208 s = splbio();
c669f646 209 bp->b_vp->v_numoutput++;
86e7dd3b 210 splx(s);
7188ac27 211 VOP_STRATEGY(bp);
3efdd860
KM
212
213 /*
d42a4811 214 * If the write was synchronous, then await I/O completion.
3efdd860 215 * If the write was "delayed", then we put the buffer on
d42a4811 216 * the queue of blocks awaiting I/O completion status.
3efdd860 217 */
d42a4811 218 if ((flag & B_ASYNC) == 0) {
7188ac27 219 error = biowait(bp);
77dc8a8c
KM
220 if ((flag&B_DELWRI) == 0)
221 p->p_stats->p_ru.ru_oublock++; /* no one paid yet */
222 else
223 reassignbuf(bp, bp->b_vp);
663dbc72 224 brelse(bp);
7188ac27 225 } else if (flag & B_DELWRI) {
31222d0d 226 s = splbio();
663dbc72 227 bp->b_flags |= B_AGE;
31222d0d 228 splx(s);
7188ac27
KM
229 }
230 return (error);
663dbc72
BJ
231}
232
80746147
JH
233int
234vn_bwrite(ap)
235 struct vop_bwrite_args *ap;
236{
237 return bwrite (ap->a_bp);
238}
239
240
663dbc72 241/*
d42a4811
KM
242 * Delayed write.
243 *
244 * The buffer is marked dirty, but is not queued for I/O.
245 * This routine should be used when the buffer is expected
246 * to be modified again soon, typically a small write that
247 * partially fills a buffer.
248 *
249 * NB: magnetic tapes cannot be delayed; they must be
250 * written in the order that the writes are requested.
663dbc72
BJ
251 */
252bdwrite(bp)
3efdd860 253 register struct buf *bp;
663dbc72 254{
3789a403 255 struct proc *p = curproc; /* XXX */
663dbc72 256
c669f646
KM
257 if ((bp->b_flags & B_DELWRI) == 0) {
258 bp->b_flags |= B_DELWRI;
259 reassignbuf(bp, bp->b_vp);
3789a403 260 p->p_stats->p_ru.ru_oublock++; /* no one paid yet */
c669f646 261 }
7188ac27 262 /*
edadbc2c 263 * If this is a tape drive, the write must be initiated.
7188ac27 264 */
ec67a3ce 265 if (bdevsw[major(bp->b_dev)].d_flags & B_TAPE)
663dbc72 266 bawrite(bp);
edadbc2c 267 } else {
d42a4811 268 bp->b_flags |= (B_DONE | B_DELWRI);
663dbc72
BJ
269 brelse(bp);
270 }
271}
272
273/*
d42a4811
KM
274 * Asynchronous write.
275 * Start I/O on a buffer, but do not wait for it to complete.
276 * The buffer is released when the I/O completes.
663dbc72
BJ
277 */
278bawrite(bp)
3efdd860 279 register struct buf *bp;
663dbc72
BJ
280{
281
d42a4811
KM
282 /*
283 * Setting the ASYNC flag causes bwrite to return
284 * after starting the I/O.
285 */
663dbc72 286 bp->b_flags |= B_ASYNC;
7188ac27 287 (void) bwrite(bp);
663dbc72
BJ
288}
289
290/*
d42a4811
KM
291 * Release a buffer.
292 * Even if the buffer is dirty, no I/O is started.
663dbc72
BJ
293 */
294brelse(bp)
3efdd860 295 register struct buf *bp;
663dbc72 296{
46387ee3 297 register struct buf *flist;
d42a4811 298 int s;
663dbc72 299
c5a600cf 300 trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno);
3efdd860 301 /*
edadbc2c
KM
302 * If a process is waiting for the buffer, or
303 * is waiting for a free buffer, awaken it.
3efdd860 304 */
d42a4811 305 if (bp->b_flags & B_WANTED)
663dbc72 306 wakeup((caddr_t)bp);
d42a4811 307 if (bfreelist[0].b_flags & B_WANTED) {
46387ee3
BJ
308 bfreelist[0].b_flags &= ~B_WANTED;
309 wakeup((caddr_t)bfreelist);
663dbc72 310 }
edadbc2c
KM
311 /*
312 * Retry I/O for locked buffers rather than invalidating them.
313 */
31222d0d 314 s = splbio();
edadbc2c
KM
315 if ((bp->b_flags & B_ERROR) && (bp->b_flags & B_LOCKED))
316 bp->b_flags &= ~B_ERROR;
edadbc2c
KM
317 /*
318 * Disassociate buffers that are no longer valid.
319 */
d42a4811 320 if (bp->b_flags & (B_NOCACHE | B_ERROR))
7188ac27 321 bp->b_flags |= B_INVAL;
d42a4811 322 if ((bp->b_bufsize <= 0) || (bp->b_flags & (B_ERROR | B_INVAL))) {
edadbc2c
KM
323 if (bp->b_vp)
324 brelvp(bp);
325 bp->b_flags &= ~B_DELWRI;
7188ac27 326 }
3efdd860
KM
327 /*
328 * Stick the buffer back on a free list.
329 */
4f083fd7
SL
330 if (bp->b_bufsize <= 0) {
331 /* block has no buffer ... put at front of unused buffer list */
332 flist = &bfreelist[BQ_EMPTY];
333 binsheadfree(bp, flist);
d42a4811 334 } else if (bp->b_flags & (B_ERROR | B_INVAL)) {
46387ee3 335 /* block has no info ... put at front of most free list */
4f083fd7 336 flist = &bfreelist[BQ_AGE];
3efdd860 337 binsheadfree(bp, flist);
663dbc72 338 } else {
46387ee3
BJ
339 if (bp->b_flags & B_LOCKED)
340 flist = &bfreelist[BQ_LOCKED];
341 else if (bp->b_flags & B_AGE)
342 flist = &bfreelist[BQ_AGE];
343 else
344 flist = &bfreelist[BQ_LRU];
3efdd860 345 binstailfree(bp, flist);
663dbc72 346 }
d42a4811 347 bp->b_flags &= ~(B_WANTED | B_BUSY | B_ASYNC | B_AGE | B_NOCACHE);
663dbc72
BJ
348 splx(s);
349}
350
351/*
d42a4811 352 * Check to see if a block is currently memory resident.
663dbc72 353 */
7188ac27
KM
354incore(vp, blkno)
355 struct vnode *vp;
3efdd860 356 daddr_t blkno;
663dbc72
BJ
357{
358 register struct buf *bp;
46387ee3 359 register struct buf *dp;
663dbc72 360
243d4743 361 dp = BUFHASH(vp, blkno);
46387ee3 362 for (bp = dp->b_forw; bp != dp; bp = bp->b_forw)
edadbc2c 363 if (bp->b_lblkno == blkno && bp->b_vp == vp &&
3efdd860 364 (bp->b_flags & B_INVAL) == 0)
5603d07d 365 return (1);
5603d07d 366 return (0);
663dbc72
BJ
367}
368
edadbc2c 369/*
d42a4811
KM
370 * Check to see if a block is currently memory resident.
371 * If it is resident, return it. If it is not resident,
372 * allocate a new buffer and assign it to the block.
663dbc72
BJ
373 */
374struct buf *
ec67a3ce
MK
375#ifdef SECSIZE
376getblk(dev, blkno, size, secsize)
377#else SECSIZE
7188ac27
KM
378getblk(vp, blkno, size)
379 register struct vnode *vp;
ad30fb67
KM
380 daddr_t blkno;
381 int size;
ec67a3ce
MK
382#ifdef SECSIZE
383 long secsize;
384#endif SECSIZE
663dbc72 385{
4f083fd7 386 register struct buf *bp, *dp;
23900030 387 int s;
663dbc72 388
00a6a148
KM
389 if (size > MAXBSIZE)
390 panic("getblk: size too big");
3efdd860 391 /*
d42a4811
KM
392 * Search the cache for the block. If the buffer is found,
393 * but it is currently locked, the we must wait for it to
394 * become available.
3efdd860 395 */
7188ac27 396 dp = BUFHASH(vp, blkno);
3efdd860 397loop:
46387ee3 398 for (bp = dp->b_forw; bp != dp; bp = bp->b_forw) {
edadbc2c 399 if (bp->b_lblkno != blkno || bp->b_vp != vp ||
d42a4811 400 (bp->b_flags & B_INVAL))
663dbc72 401 continue;
a5e62f37 402 s = splbio();
d42a4811 403 if (bp->b_flags & B_BUSY) {
663dbc72 404 bp->b_flags |= B_WANTED;
d42a4811 405 sleep((caddr_t)bp, PRIBIO + 1);
23900030 406 splx(s);
663dbc72
BJ
407 goto loop;
408 }
c669f646
KM
409 bremfree(bp);
410 bp->b_flags |= B_BUSY;
23900030 411 splx(s);
32a56bda 412 if (bp->b_bcount != size) {
edadbc2c
KM
413 printf("getblk: stray size");
414 bp->b_flags |= B_INVAL;
415 bwrite(bp);
9d6d37ce 416 goto loop;
edadbc2c 417 }
663dbc72 418 bp->b_flags |= B_CACHE;
a5e62f37 419 return (bp);
663dbc72 420 }
4f083fd7 421 bp = getnewbuf();
3efdd860 422 bremhash(bp);
edadbc2c 423 bgetvp(vp, bp);
521a4688 424 bp->b_bcount = 0;
edadbc2c 425 bp->b_lblkno = blkno;
ec67a3ce
MK
426#ifdef SECSIZE
427 bp->b_blksize = secsize;
428#endif SECSIZE
ad30fb67 429 bp->b_blkno = blkno;
4f083fd7 430 bp->b_error = 0;
7188ac27
KM
431 bp->b_resid = 0;
432 binshash(bp, dp);
521a4688 433 allocbuf(bp, size);
a5e62f37 434 return (bp);
663dbc72
BJ
435}
436
437/*
d42a4811
KM
438 * Allocate a buffer.
439 * The caller will assign it to a block.
663dbc72
BJ
440 */
441struct buf *
ad30fb67
KM
442geteblk(size)
443 int size;
663dbc72 444{
4f083fd7 445 register struct buf *bp, *flist;
663dbc72 446
00a6a148
KM
447 if (size > MAXBSIZE)
448 panic("geteblk: size too big");
4f083fd7
SL
449 bp = getnewbuf();
450 bp->b_flags |= B_INVAL;
3efdd860 451 bremhash(bp);
4f083fd7 452 flist = &bfreelist[BQ_AGE];
521a4688 453 bp->b_bcount = 0;
ec67a3ce
MK
454#ifdef SECSIZE
455 bp->b_blksize = DEV_BSIZE;
456#endif SECSIZE
4f083fd7 457 bp->b_error = 0;
7188ac27
KM
458 bp->b_resid = 0;
459 binshash(bp, flist);
521a4688 460 allocbuf(bp, size);
a5e62f37 461 return (bp);
663dbc72
BJ
462}
463
ad30fb67 464/*
521a4688 465 * Expand or contract the actual memory allocated to a buffer.
d42a4811 466 * If no memory is available, release buffer and take error exit.
ad30fb67 467 */
521a4688
KM
468allocbuf(tp, size)
469 register struct buf *tp;
ad30fb67
KM
470 int size;
471{
521a4688
KM
472 register struct buf *bp, *ep;
473 int sizealloc, take, s;
ad30fb67 474
521a4688
KM
475 sizealloc = roundup(size, CLBYTES);
476 /*
477 * Buffer size does not change
478 */
479 if (sizealloc == tp->b_bufsize)
480 goto out;
481 /*
482 * Buffer size is shrinking.
483 * Place excess space in a buffer header taken from the
484 * BQ_EMPTY buffer list and placed on the "most free" list.
485 * If no extra buffer headers are available, leave the
486 * extra space in the present buffer.
487 */
488 if (sizealloc < tp->b_bufsize) {
489 ep = bfreelist[BQ_EMPTY].av_forw;
490 if (ep == &bfreelist[BQ_EMPTY])
491 goto out;
492 s = splbio();
493 bremfree(ep);
494 ep->b_flags |= B_BUSY;
495 splx(s);
496 pagemove(tp->b_un.b_addr + sizealloc, ep->b_un.b_addr,
497 (int)tp->b_bufsize - sizealloc);
498 ep->b_bufsize = tp->b_bufsize - sizealloc;
499 tp->b_bufsize = sizealloc;
500 ep->b_flags |= B_INVAL;
501 ep->b_bcount = 0;
502 brelse(ep);
503 goto out;
504 }
505 /*
506 * More buffer space is needed. Get it out of buffers on
507 * the "most free" list, placing the empty headers on the
508 * BQ_EMPTY buffer header list.
509 */
510 while (tp->b_bufsize < sizealloc) {
511 take = sizealloc - tp->b_bufsize;
512 bp = getnewbuf();
513 if (take >= bp->b_bufsize)
514 take = bp->b_bufsize;
515 pagemove(&bp->b_un.b_addr[bp->b_bufsize - take],
516 &tp->b_un.b_addr[tp->b_bufsize], take);
517 tp->b_bufsize += take;
518 bp->b_bufsize = bp->b_bufsize - take;
519 if (bp->b_bcount > bp->b_bufsize)
520 bp->b_bcount = bp->b_bufsize;
521 if (bp->b_bufsize <= 0) {
522 bremhash(bp);
523 binshash(bp, &bfreelist[BQ_EMPTY]);
d42a4811 524 bp->b_dev = NODEV;
521a4688
KM
525 bp->b_error = 0;
526 bp->b_flags |= B_INVAL;
527 }
528 brelse(bp);
529 }
530out:
531 tp->b_bcount = size;
532 return (1);
4f083fd7
SL
533}
534
4f083fd7
SL
535/*
536 * Find a buffer which is available for use.
537 * Select something from a free list.
538 * Preference is to AGE list, then LRU list.
539 */
540struct buf *
541getnewbuf()
542{
543 register struct buf *bp, *dp;
a937f856 544 register struct ucred *cred;
4f083fd7
SL
545 int s;
546
547loop:
a5e62f37 548 s = splbio();
4f083fd7
SL
549 for (dp = &bfreelist[BQ_AGE]; dp > bfreelist; dp--)
550 if (dp->av_forw != dp)
551 break;
552 if (dp == bfreelist) { /* no free blocks */
553 dp->b_flags |= B_WANTED;
d42a4811 554 sleep((caddr_t)dp, PRIBIO + 1);
4b7d506c 555 splx(s);
4f083fd7
SL
556 goto loop;
557 }
4f083fd7 558 bp = dp->av_forw;
c669f646
KM
559 bremfree(bp);
560 bp->b_flags |= B_BUSY;
561 splx(s);
4f083fd7 562 if (bp->b_flags & B_DELWRI) {
033a786e 563 (void) bawrite(bp);
4f083fd7
SL
564 goto loop;
565 }
c5a600cf 566 trace(TR_BRELSE, pack(bp->b_vp, bp->b_bufsize), bp->b_lblkno);
edadbc2c
KM
567 if (bp->b_vp)
568 brelvp(bp);
a937f856
KM
569 if (bp->b_rcred != NOCRED) {
570 cred = bp->b_rcred;
571 bp->b_rcred = NOCRED;
572 crfree(cred);
573 }
574 if (bp->b_wcred != NOCRED) {
575 cred = bp->b_wcred;
576 bp->b_wcred = NOCRED;
577 crfree(cred);
578 }
4f083fd7 579 bp->b_flags = B_BUSY;
1c89915d 580 bp->b_dirtyoff = bp->b_dirtyend = 0;
bb1626f7 581 bp->b_validoff = bp->b_validend = 0;
4f083fd7
SL
582 return (bp);
583}
584
663dbc72 585/*
d42a4811
KM
586 * Wait for I/O to complete.
587 *
588 * Extract and return any errors associated with the I/O.
589 * If the error flag is set, but no specific error is
590 * given, return EIO.
663dbc72 591 */
3efdd860 592biowait(bp)
ad30fb67 593 register struct buf *bp;
663dbc72 594{
530d0032 595 int s;
663dbc72 596
a5e62f37 597 s = splbio();
a937f856 598 while ((bp->b_flags & B_DONE) == 0)
663dbc72 599 sleep((caddr_t)bp, PRIBIO);
530d0032 600 splx(s);
7188ac27
KM
601 if ((bp->b_flags & B_ERROR) == 0)
602 return (0);
603 if (bp->b_error)
604 return (bp->b_error);
605 return (EIO);
663dbc72
BJ
606}
607
663dbc72 608/*
af04ce66 609 * Mark I/O complete on a buffer.
d42a4811
KM
610 *
611 * If a callback has been requested, e.g. the pageout
612 * daemon, do so. Otherwise, awaken waiting processes.
663dbc72 613 */
251f56ba 614void
3efdd860
KM
615biodone(bp)
616 register struct buf *bp;
663dbc72 617{
663dbc72 618
80e7c811 619 if (bp->b_flags & B_DONE)
3efdd860 620 panic("dup biodone");
663dbc72 621 bp->b_flags |= B_DONE;
76429560
KM
622 if ((bp->b_flags & B_READ) == 0)
623 vwakeup(bp);
961945a8
SL
624 if (bp->b_flags & B_CALL) {
625 bp->b_flags &= ~B_CALL;
626 (*bp->b_iodone)(bp);
627 return;
628 }
d42a4811 629 if (bp->b_flags & B_ASYNC)
663dbc72
BJ
630 brelse(bp);
631 else {
632 bp->b_flags &= ~B_WANTED;
633 wakeup((caddr_t)bp);
634 }
635}