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,
