+ register struct buf *ep;
+ struct buf *dp;
+ daddr_t curblk, nextblk, ecurblk, lastblk;
+ int s, error, allerrors = 0;
+
+ /*
+ * Iterate through each possible hash chain.
+ */
+ lastblk = blkno + btodb(size) - 1;
+ for (curblk = blkno; curblk <= lastblk; curblk = nextblk) {
+#if RND & (RND-1)
+ nextblk = ((curblk / RND) + 1) * RND;
+#else
+ nextblk = ((curblk & ~(RND-1)) + RND);
+#endif
+ ecurblk = nextblk > lastblk ? lastblk : nextblk - 1;
+ dp = BUFHASH(vp, curblk);
+loop:
+ for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
+ if (ep->b_vp != vp || (ep->b_flags & B_INVAL))
+ continue;
+ /* look for overlap */
+ if (ep->b_bcount == 0 || ep->b_lblkno > ecurblk ||
+ ep->b_lblkno + btodb(ep->b_bcount) <= curblk)
+ continue;
+ s = splbio();
+ if (ep->b_flags&B_BUSY) {
+ ep->b_flags |= B_WANTED;
+ sleep((caddr_t)ep, PRIBIO+1);
+ splx(s);
+ goto loop;
+ }
+ if (ep->b_flags & B_DELWRI) {
+ splx(s);
+ notavail(ep);
+ if (error = bwrite(ep))
+ allerrors = error;
+ goto loop;
+ }
+ splx(s);
+ }
+ }
+ return (allerrors);