/* * Mark I/O complete on a buffer. * * If a callback has been requested, e.g. the pageout * daemon, do so. Otherwise, awaken waiting processes. * * [ Leffler, et al., says on p.247: * "This routine wakes up the blocked process, frees the buffer * for an asynchronous write, or, for a request by the pagedaemon * process, invokes a procedure specified in the buffer structure" ] * * In real life, the pagedaemon (or other system processes) wants * to do async stuff to, and doesn't want the buffer brelse()'d. * (for swap pager, that puts swap buffers on the free lists (!!!), * for the vn device, that puts malloc'd buffers on the free lists!) * * Must be called at splbio(). */ void biodone(struct buf *bp) { splassert(IPL_BIO); if (ISSET(bp->b_flags, B_DONE)) panic("biodone already"); SET(bp->b_flags, B_DONE); /* note that it's done */ if (LIST_FIRST(&bp->b_dep) != NULL) buf_complete(bp); if (!ISSET(bp->b_flags, B_READ)) { CLR(bp->b_flags, B_WRITEINPROG); vwakeup(bp->b_vp); } if (ISSET(bp->b_flags, B_CALL)) { /* if necessary, call out */ CLR(bp->b_flags, B_CALL); /* but note callout done */ (*bp->b_iodone)(bp); } else { if (ISSET(bp->b_flags, B_ASYNC)) {/* if async, release it */ brelse(bp); } else { /* or just wakeup the buffer */ CLR(bp->b_flags, B_WANTED); wakeup(bp); } } }
/* * Finish up operations on a buffer, calling an optional * function (if requested), and releasing the buffer if * marked asynchronous. Then mark this buffer done so that * others biowait()'ing for it will notice when they are * woken up from sleep(). */ int biodone(register struct buf *bp) { int x; x = splbio(); if (bp->b_flags & B_CALL) (*bp->b_iodone)(bp); bp->b_flags &= ~B_CALL; if ((bp->b_flags & (B_READ|B_DIRTY)) == B_DIRTY) { bp->b_flags &= ~B_DIRTY; vwakeup(bp); } if (bp->b_flags & B_ASYNC) brelse(bp); bp->b_flags &= ~B_ASYNC; bp->b_flags |= B_DONE; wakeup(bp); splx(x); }