- return (1);
- if (size < bp->b_bcount) {
- if (bp->b_flags & B_DELWRI) {
- (void) bwrite(bp);
- return (0);
- }
- if (bp->b_flags & B_LOCKED)
- panic("brealloc");
- return (allocbuf(bp, size));
- }
- bp->b_flags &= ~B_DONE;
- if (bp->b_vp == (struct vnode *)0)
- return (allocbuf(bp, size));
-
- trace(TR_BREALLOC,
- pack(bp->b_vp->v_mount->m_fsid[0], size), bp->b_blkno);
- /*
- * Search cache for any buffers that overlap the one that we
- * are trying to allocate. Overlapping buffers must be marked
- * invalid, after being written out if they are dirty. (indicated
- * by B_DELWRI) A disk block must be mapped by at most one buffer
- * at any point in time. Care must be taken to avoid deadlocking
- * when two buffer are trying to get the same set of disk blocks.
- */
- start = bp->b_blkno;
-#ifdef SECSIZE
- last = start + size/bp->b_blksize - 1;
-#else SECSIZE
- last = start + btodb(size) - 1;
-#endif SECSIZE
- dp = BUFHASH(bp->b_vp, bp->b_blkno);
-loop:
- for (ep = dp->b_forw; ep != dp; ep = ep->b_forw) {
- if (ep == bp || ep->b_vp != bp->b_vp ||
- (ep->b_flags & B_INVAL))
- continue;
- /* look for overlap */
- if (ep->b_bcount == 0 || ep->b_blkno > last ||
-#ifdef SECSIZE
- ep->b_blkno + ep->b_bcount/ep->b_blksize <= start)
-#else SECSIZE
- ep->b_blkno + btodb(ep->b_bcount) <= start)
-#endif SECSIZE
- continue;
- s = splbio();
- if (ep->b_flags&B_BUSY) {
- ep->b_flags |= B_WANTED;
- sleep((caddr_t)ep, PRIBIO+1);
- splx(s);
- goto loop;
- }
- splx(s);
- notavail(ep);
- if (ep->b_flags & B_DELWRI) {
- (void) bwrite(ep);
- goto loop;
- }
- ep->b_flags |= B_INVAL;
- brelse(ep);
- }
- return (allocbuf(bp, size));