RCS file: /cvs/openbsd/src/sys/dev/flash.c,v retrieving revision 1.2 diff -u -r1.2 flash.c --- dev/flash.c 15 Feb 2007 00:53:26 -0000 1.2 +++ dev/flash.c 1 May 2007 15:27:14 -0000 @@ -886,10 +886,9 @@ while (1) { /* Remove the next buffer from the queue or stop. */ dp = &sc->sc_q; - bp = dp->b_actf; + bp = disksort_getone(dp); if (bp == NULL) return; - dp->b_actf = bp->b_actf; /* Transfer this buffer now. */ _flashstart(sc, bp); Index: dev/vnd.c =================================================================== RCS file: /cvs/openbsd/src/sys/dev/vnd.c,v retrieving revision 1.73 diff -u -r1.73 vnd.c --- dev/vnd.c 29 Apr 2007 18:59:37 -0000 1.73 +++ dev/vnd.c 1 May 2007 15:27:14 -0000 @@ -493,8 +493,7 @@ * routine might queue using same links. */ s = splbio(); - bp = vnd->sc_tab.b_actf; - vnd->sc_tab.b_actf = bp->b_actf; + bp = disksort_getone(&vnd->sc_tab); vnd->sc_tab.b_active--; splx(s); } @@ -609,8 +608,7 @@ * Dequeue now since lower level strategy routine might * queue using same links */ - bp = vnd->sc_tab.b_actf; - vnd->sc_tab.b_actf = bp->b_actf; + bp = disksort_getone(&vnd->sc_tab); DNPRINTF(VDB_IO, "vndstart(%d): bp %p vp %p blkno %x addr %p cnt %lx\n", Index: dev/ata/wd.c =================================================================== RCS file: /cvs/openbsd/src/sys/dev/ata/wd.c,v retrieving revision 1.58 diff -u -r1.58 wd.c --- dev/ata/wd.c 28 Apr 2007 02:24:21 -0000 1.58 +++ dev/ata/wd.c 1 May 2007 15:27:15 -0000 @@ -489,9 +489,8 @@ /* Is there a buf for us ? */ dp = &wd->sc_q; - if ((bp = dp->b_actf) == NULL) /* yes, an assign */ + if ((bp = disksort_getone(dp)) == NULL) /* yes, an assign */ return; - dp->b_actf = bp->b_actf; /* * Make the command. First lock the device Index: dev/isa/mcd.c =================================================================== RCS file: /cvs/openbsd/src/sys/dev/isa/mcd.c,v retrieving revision 1.42 diff -u -r1.42 mcd.c --- dev/isa/mcd.c 29 Apr 2007 22:22:34 -0000 1.42 +++ dev/isa/mcd.c 1 May 2007 15:27:15 -0000 @@ -514,7 +514,7 @@ loop: s = splbio(); - bp = dp->b_actf; + bp = disksort_getone(dp); if (bp == NULL) { /* Nothing to do. */ dp->b_active = 0; @@ -524,7 +524,6 @@ /* Block found to process; dequeue. */ MCD_TRACE("start: found block bp=0x%x\n", bp, 0, 0, 0); - dp->b_actf = bp->b_actf; splx(s); /* Changed media? */ Index: dev/raidframe/rf_openbsdkintf.c =================================================================== RCS file: /cvs/openbsd/src/sys/dev/raidframe/rf_openbsdkintf.c,v retrieving revision 1.35 diff -u -r1.35 rf_openbsdkintf.c --- dev/raidframe/rf_openbsdkintf.c 28 Apr 2007 12:32:13 -0000 1.35 +++ dev/raidframe/rf_openbsdkintf.c 1 May 2007 15:27:17 -0000 @@ -801,8 +801,7 @@ bp->b_resid = 0; - bp->b_actf = rs->sc_q.b_actf; - rs->sc_q.b_actf = bp; + bp = disksort_getone(rs->sc_q); rs->sc_q.b_active++; raidstart(raidPtrs[raidID]); @@ -1742,12 +1741,11 @@ while (raidPtr->openings > 0) { RF_UNLOCK_MUTEX(raidPtr->mutex); - bp = rs->sc_q.b_actf; + bp = disksort_getone(rs->sc_q); if (bp == NULL) { /* Nothing more to do. */ return; } - rs->sc_q.b_actf = bp->b_actf; /* * Ok, for the bp we have here, bp->b_blkno is relative to the Index: kern/subr_disk.c =================================================================== RCS file: /cvs/openbsd/src/sys/kern/subr_disk.c,v retrieving revision 1.34 diff -u -r1.34 subr_disk.c --- kern/subr_disk.c 30 Mar 2007 00:38:56 -0000 1.34 +++ kern/subr_disk.c 1 May 2007 15:27:17 -0000 @@ -68,97 +68,66 @@ * is reset by hw_sysctl() */ -/* - * Seek sort for disks. We depend on the driver which calls us using b_resid - * as the current cylinder number. - * - * The argument ap structure holds a b_actf activity chain pointer on which we - * keep two queues, sorted in ascending cylinder order. The first queue holds - * those requests which are positioned after the current cylinder (in the first - * request); the second holds requests which came in after their cylinder number - * was passed. Thus we implement a one way scan, retracting after reaching the - * end of the drive to the first request on the second queue, at which time it - * becomes the first queue. - * - * A one-way scan is natural because of the way UNIX read-ahead blocks are - * allocated. - */ - -void -disksort(struct buf *ap, struct buf *bp) +struct buf * +disksort_getone(struct buf * const queue) { - struct buf *bq; + struct buf *ret; + struct buf *previous; + struct buf *scanned; + struct buf *previous_best; + struct buf *best; + daddr64_t distance; + daddr64_t best_distance; - /* If the queue is empty, then it's easy. */ - if (ap->b_actf == NULL) { - bp->b_actf = NULL; - ap->b_actf = bp; - return; + if (queue->b_actf == NULL) { + return NULL; } - - /* - * If we lie after the first (currently active) request, then we - * must locate the second request list and add ourselves to it. - */ - bq = ap->b_actf; - if (bp->b_cylinder < bq->b_cylinder) { - while (bq->b_actf) { - /* - * Check for an ``inversion'' in the normally ascending - * cylinder numbers, indicating the start of the second - * request list. - */ - if (bq->b_actf->b_cylinder < bq->b_cylinder) { - /* - * Search the second request list for the first - * request at a larger cylinder number. We go - * before that; if there is no such request, we - * go at end. - */ - do { - if (bp->b_cylinder < - bq->b_actf->b_cylinder) - goto insert; - if (bp->b_cylinder == - bq->b_actf->b_cylinder && - bp->b_blkno < bq->b_actf->b_blkno) - goto insert; - bq = bq->b_actf; - } while (bq->b_actf); - goto insert; /* after last */ - } - bq = bq->b_actf; + best = NULL; + previous_best = NULL; + previous = NULL; + scanned = queue->b_actf; + while (scanned != NULL) { + if (scanned->b_blkno < queue->b_blkno) { + distance = queue->b_blkno - scanned->b_blkno; + } else { + distance = scanned->b_blkno - queue->b_blkno; + } + if (distance < best_distance || previous == NULL) { + best_distance = distance; + previous_best = previous; + best = scanned; } - /* - * No inversions... we will go after the last, and - * be the first request in the second request list. - */ - goto insert; + previous = scanned; + scanned = scanned->b_actf; } - /* - * Request is at/after the current request... - * sort in the first request list. - */ - while (bq->b_actf) { - /* - * We want to go after the current request if there is an - * inversion after it (i.e. it is the end of the first - * request list), or if the next request is a larger cylinder - * than our request. - */ - if (bq->b_actf->b_cylinder < bq->b_cylinder || - bp->b_cylinder < bq->b_actf->b_cylinder || - (bp->b_cylinder == bq->b_actf->b_cylinder && - bp->b_blkno < bq->b_actf->b_blkno)) - goto insert; - bq = bq->b_actf; + if (best == NULL) { + ret = queue->b_actf; + queue->b_actf = ret->b_actf; + } else { + ret = best; + if (previous_best == NULL) { + queue->b_actf = best->b_actf; + } else { + previous_best->b_actf = best->b_actf; + } + } + queue->b_blkno = ret->b_blkno; + + return ret; +} + +void +disksort(struct buf *queue, struct buf *bp) +{ + (queue->generation)++; + bp->generation = queue->generation; + if (queue->b_actf == NULL) { + bp->b_actf = NULL; + queue->b_actf = bp; + return; } - /* - * Neither a second list nor a larger request... we go at the end of - * the first list, which is the same as the end of the whole schebang. - */ -insert: bp->b_actf = bq->b_actf; - bq->b_actf = bp; + bp->b_actf = queue->b_actf; + queue->b_actf = bp; } /* Index: kern/vfs_bio.c =================================================================== RCS file: /cvs/openbsd/src/sys/kern/vfs_bio.c,v retrieving revision 1.87 diff -u -r1.87 vfs_bio.c --- kern/vfs_bio.c 21 Oct 2006 18:09:52 -0000 1.87 +++ kern/vfs_bio.c 1 May 2007 15:27:17 -0000 @@ -244,6 +244,7 @@ */ if (!ISSET(bp->b_flags, (B_DONE | B_DELWRI))) { SET(bp->b_flags, B_READ | async); + bp->b_proc = curproc; VOP_STRATEGY(bp); /* Pay for the read. */ @@ -363,6 +364,7 @@ bp->b_vp->v_numoutput++; splx(s); SET(bp->b_flags, B_WRITEINPROG); + bp->b_proc = curproc; VOP_STRATEGY(bp); if (async) @@ -442,7 +444,7 @@ void bawrite(struct buf *bp) { - + bp->b_proc = curproc; SET(bp->b_flags, B_ASYNC); VOP_BWRITE(bp); } @@ -949,6 +951,8 @@ { splassert(IPL_BIO); + bp->b_proc = NULL; + if (ISSET(bp->b_flags, B_DONE)) panic("biodone already"); SET(bp->b_flags, B_DONE); /* note that it's done */ Index: scsi/cd.c =================================================================== RCS file: /cvs/openbsd/src/sys/scsi/cd.c,v retrieving revision 1.124 diff -u -r1.124 cd.c --- scsi/cd.c 28 Apr 2007 02:24:21 -0000 1.124 +++ scsi/cd.c 1 May 2007 15:27:18 -0000 @@ -592,9 +592,8 @@ * See if there is a buf with work for us to do.. */ dp = &cd->buf_queue; - if ((bp = dp->b_actf) == NULL) /* yes, an assign */ + if ((bp = disksort_getone(dp)) == NULL) /* yes, an assign */ return; - dp->b_actf = bp->b_actf; /* * If the deivce has become invalid, abort all the Index: scsi/sd.c =================================================================== RCS file: /cvs/openbsd/src/sys/scsi/sd.c,v retrieving revision 1.127 diff -u -r1.127 sd.c --- scsi/sd.c 28 Apr 2007 02:24:21 -0000 1.127 +++ scsi/sd.c 1 May 2007 15:27:18 -0000 @@ -621,9 +621,8 @@ * See if there is a buf with work for us to do.. */ dp = &sd->buf_queue; - if ((bp = dp->b_actf) == NULL) /* yes, an assign */ + if ((bp = disksort_getone(dp)) == NULL) /* yes, an assign */ return; - dp->b_actf = bp->b_actf; /* * If the device has become invalid, abort all the Index: scsi/ss.c =================================================================== RCS file: /cvs/openbsd/src/sys/scsi/ss.c,v retrieving revision 1.58 diff -u -r1.58 ss.c --- scsi/ss.c 21 Dec 2006 02:05:46 -0000 1.58 +++ scsi/ss.c 1 May 2007 15:27:19 -0000 @@ -361,7 +361,7 @@ * Set up the buf queue for this device */ ss->buf_queue.b_active = 0; - ss->buf_queue.b_actf = 0; + ss->buf_queue.b_actf = NULL; ss->buf_queue.b_actb = &ss->buf_queue.b_actf; } Index: scsi/st.c =================================================================== RCS file: /cvs/openbsd/src/sys/scsi/st.c,v retrieving revision 1.73 diff -u -r1.73 st.c --- scsi/st.c 10 Apr 2007 17:47:56 -0000 1.73 +++ scsi/st.c 1 May 2007 15:27:19 -0000 @@ -334,7 +334,7 @@ * Set up the buf queue for this device */ st->buf_queue.b_active = 0; - st->buf_queue.b_actf = 0; + st->buf_queue.b_actf = NULL; st->buf_queue.b_actb = &st->buf_queue.b_actf; /* Start up with media position unknown. */ Index: sys/buf.h =================================================================== RCS file: /cvs/openbsd/src/sys/sys/buf.h,v retrieving revision 1.55 diff -u -r1.55 buf.h --- sys/buf.h 23 Mar 2007 22:04:16 -0000 1.55 +++ sys/buf.h 1 May 2007 15:27:19 -0000 @@ -90,6 +90,7 @@ daddr64_t b_blkno; /* Underlying physical block number. */ /* Function to call upon completion. * Will be called at splbio(). */ + unsigned long generation; /* Request counter. */ void (*b_iodone)(struct buf *); struct vnode *b_vp; /* Device vnode. */ int b_dirtyoff; /* Offset in buffer of dirty region. */ Index: sys/disklabel.h =================================================================== RCS file: /cvs/openbsd/src/sys/sys/disklabel.h,v retrieving revision 1.28 diff -u -r1.28 disklabel.h --- sys/disklabel.h 26 Sep 2006 23:33:04 -0000 1.28 +++ sys/disklabel.h 1 May 2007 15:27:19 -0000 @@ -351,6 +351,7 @@ }; #ifdef _KERNEL +struct buf *disksort_getone(struct buf * const); void diskerr(struct buf *, char *, char *, int, int, struct disklabel *); void disksort(struct buf *, struct buf *); u_int dkcksum(struct disklabel *); Index: uvm/uvm_swap.c =================================================================== RCS file: /cvs/openbsd/src/sys/uvm/uvm_swap.c,v retrieving revision 1.68 diff -u -r1.68 uvm_swap.c --- uvm/uvm_swap.c 13 Apr 2007 18:57:49 -0000 1.68 +++ uvm/uvm_swap.c 1 May 2007 15:27:21 -0000 @@ -1473,10 +1473,9 @@ sdp->swd_flags |= SWF_BUSY; while (sdp->swd_tab.b_active < sdp->swd_maxactive) { - bp = sdp->swd_tab.b_actf; + bp = disksort_getone(&sdp->swd_tab); if (bp == NULL) break; - sdp->swd_tab.b_actf = bp->b_actf; sdp->swd_tab.b_active++; UVMHIST_LOG(pdhist,