xref: /csrg-svn/sys/ufs/ffs/ufs_disksubr.c (revision 29116)
123397Smckusick /*
2*29116Smckusick  * Copyright (c) 1982, 1986 Regents of the University of California.
323397Smckusick  * All rights reserved.  The Berkeley software License Agreement
423397Smckusick  * specifies the terms and conditions for redistribution.
523397Smckusick  *
6*29116Smckusick  *	@(#)ufs_disksubr.c	7.1 (Berkeley) 06/05/86
723397Smckusick  */
816Sbill 
916Sbill /*
102626Swnj  * Seek sort for disks.  We depend on the driver
112626Swnj  * which calls us using b_resid as the current cylinder number.
122626Swnj  *
132626Swnj  * The argument dp structure holds a b_actf activity chain pointer
142626Swnj  * on which we keep two queues, sorted in ascending cylinder order.
152626Swnj  * The first queue holds those requests which are positioned after
162626Swnj  * the current cylinder (in the first request); the second holds
172626Swnj  * requests which came in after their cylinder number was passed.
182626Swnj  * Thus we implement a one way scan, retracting after reaching the
192626Swnj  * end of the drive to the first request on the second queue,
202626Swnj  * at which time it becomes the first queue.
212626Swnj  *
222626Swnj  * A one-way scan is natural because of the way UNIX read-ahead
232626Swnj  * blocks are allocated.
2416Sbill  */
2516Sbill 
2617099Sbloom #include "param.h"
2717099Sbloom #include "systm.h"
2817099Sbloom #include "buf.h"
2916Sbill 
3016Sbill #define	b_cylin	b_resid
3116Sbill 
3216Sbill disksort(dp, bp)
332626Swnj 	register struct buf *dp, *bp;
3416Sbill {
3516Sbill 	register struct buf *ap;
3616Sbill 
372626Swnj 	/*
382626Swnj 	 * If nothing on the activity queue, then
392626Swnj 	 * we become the only thing.
402626Swnj 	 */
4116Sbill 	ap = dp->b_actf;
4216Sbill 	if(ap == NULL) {
4316Sbill 		dp->b_actf = bp;
4416Sbill 		dp->b_actl = bp;
4516Sbill 		bp->av_forw = NULL;
4616Sbill 		return;
4716Sbill 	}
482626Swnj 	/*
492626Swnj 	 * If we lie after the first (currently active)
502626Swnj 	 * request, then we must locate the second request list
512626Swnj 	 * and add ourselves to it.
522626Swnj 	 */
532626Swnj 	if (bp->b_cylin < ap->b_cylin) {
542626Swnj 		while (ap->av_forw) {
552626Swnj 			/*
562626Swnj 			 * Check for an ``inversion'' in the
572626Swnj 			 * normally ascending cylinder numbers,
582626Swnj 			 * indicating the start of the second request list.
592626Swnj 			 */
602626Swnj 			if (ap->av_forw->b_cylin < ap->b_cylin) {
612626Swnj 				/*
622626Swnj 				 * Search the second request list
632626Swnj 				 * for the first request at a larger
642626Swnj 				 * cylinder number.  We go before that;
652626Swnj 				 * if there is no such request, we go at end.
662626Swnj 				 */
672626Swnj 				do {
682626Swnj 					if (bp->b_cylin < ap->av_forw->b_cylin)
692626Swnj 						goto insert;
702626Swnj 					ap = ap->av_forw;
712626Swnj 				} while (ap->av_forw);
722626Swnj 				goto insert;		/* after last */
732626Swnj 			}
742626Swnj 			ap = ap->av_forw;
7516Sbill 		}
762626Swnj 		/*
772626Swnj 		 * No inversions... we will go after the last, and
782626Swnj 		 * be the first request in the second request list.
792626Swnj 		 */
802626Swnj 		goto insert;
8116Sbill 	}
822626Swnj 	/*
832626Swnj 	 * Request is at/after the current request...
842626Swnj 	 * sort in the first request list.
852626Swnj 	 */
862626Swnj 	while (ap->av_forw) {
872626Swnj 		/*
882626Swnj 		 * We want to go after the current request
892626Swnj 		 * if there is an inversion after it (i.e. it is
902626Swnj 		 * the end of the first request list), or if
912626Swnj 		 * the next request is a larger cylinder than our request.
922626Swnj 		 */
932626Swnj 		if (ap->av_forw->b_cylin < ap->b_cylin ||
942626Swnj 		    bp->b_cylin < ap->av_forw->b_cylin)
952626Swnj 			goto insert;
962626Swnj 		ap = ap->av_forw;
972626Swnj 	}
982626Swnj 	/*
992626Swnj 	 * Neither a second list nor a larger
1002626Swnj 	 * request... we go at the end of the first list,
1012626Swnj 	 * which is the same as the end of the whole schebang.
1022626Swnj 	 */
1032626Swnj insert:
1042626Swnj 	bp->av_forw = ap->av_forw;
1052626Swnj 	ap->av_forw = bp;
1062626Swnj 	if (ap == dp->b_actl)
10716Sbill 		dp->b_actl = bp;
10816Sbill }
109