xref: /csrg-svn/sys/ufs/ffs/ufs_disksubr.c (revision 30533)
123397Smckusick /*
229116Smckusick  * 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*30533Skarels  *	@(#)ufs_disksubr.c	7.2 (Berkeley) 02/19/87
723397Smckusick  */
816Sbill 
9*30533Skarels #include "param.h"
10*30533Skarels #include "systm.h"
11*30533Skarels #include "buf.h"
12*30533Skarels #include "disklabel.h"
13*30533Skarels 
1416Sbill /*
152626Swnj  * Seek sort for disks.  We depend on the driver
162626Swnj  * which calls us using b_resid as the current cylinder number.
172626Swnj  *
182626Swnj  * The argument dp structure holds a b_actf activity chain pointer
192626Swnj  * on which we keep two queues, sorted in ascending cylinder order.
202626Swnj  * The first queue holds those requests which are positioned after
212626Swnj  * the current cylinder (in the first request); the second holds
222626Swnj  * requests which came in after their cylinder number was passed.
232626Swnj  * Thus we implement a one way scan, retracting after reaching the
242626Swnj  * end of the drive to the first request on the second queue,
252626Swnj  * at which time it becomes the first queue.
262626Swnj  *
272626Swnj  * A one-way scan is natural because of the way UNIX read-ahead
282626Swnj  * blocks are allocated.
2916Sbill  */
3016Sbill 
3116Sbill #define	b_cylin	b_resid
3216Sbill 
3316Sbill disksort(dp, bp)
342626Swnj 	register struct buf *dp, *bp;
3516Sbill {
3616Sbill 	register struct buf *ap;
3716Sbill 
382626Swnj 	/*
392626Swnj 	 * If nothing on the activity queue, then
402626Swnj 	 * we become the only thing.
412626Swnj 	 */
4216Sbill 	ap = dp->b_actf;
4316Sbill 	if(ap == NULL) {
4416Sbill 		dp->b_actf = bp;
4516Sbill 		dp->b_actl = bp;
4616Sbill 		bp->av_forw = NULL;
4716Sbill 		return;
4816Sbill 	}
492626Swnj 	/*
502626Swnj 	 * If we lie after the first (currently active)
512626Swnj 	 * request, then we must locate the second request list
522626Swnj 	 * and add ourselves to it.
532626Swnj 	 */
542626Swnj 	if (bp->b_cylin < ap->b_cylin) {
552626Swnj 		while (ap->av_forw) {
562626Swnj 			/*
572626Swnj 			 * Check for an ``inversion'' in the
582626Swnj 			 * normally ascending cylinder numbers,
592626Swnj 			 * indicating the start of the second request list.
602626Swnj 			 */
612626Swnj 			if (ap->av_forw->b_cylin < ap->b_cylin) {
622626Swnj 				/*
632626Swnj 				 * Search the second request list
642626Swnj 				 * for the first request at a larger
652626Swnj 				 * cylinder number.  We go before that;
662626Swnj 				 * if there is no such request, we go at end.
672626Swnj 				 */
682626Swnj 				do {
692626Swnj 					if (bp->b_cylin < ap->av_forw->b_cylin)
702626Swnj 						goto insert;
712626Swnj 					ap = ap->av_forw;
722626Swnj 				} while (ap->av_forw);
732626Swnj 				goto insert;		/* after last */
742626Swnj 			}
752626Swnj 			ap = ap->av_forw;
7616Sbill 		}
772626Swnj 		/*
782626Swnj 		 * No inversions... we will go after the last, and
792626Swnj 		 * be the first request in the second request list.
802626Swnj 		 */
812626Swnj 		goto insert;
8216Sbill 	}
832626Swnj 	/*
842626Swnj 	 * Request is at/after the current request...
852626Swnj 	 * sort in the first request list.
862626Swnj 	 */
872626Swnj 	while (ap->av_forw) {
882626Swnj 		/*
892626Swnj 		 * We want to go after the current request
902626Swnj 		 * if there is an inversion after it (i.e. it is
912626Swnj 		 * the end of the first request list), or if
922626Swnj 		 * the next request is a larger cylinder than our request.
932626Swnj 		 */
942626Swnj 		if (ap->av_forw->b_cylin < ap->b_cylin ||
952626Swnj 		    bp->b_cylin < ap->av_forw->b_cylin)
962626Swnj 			goto insert;
972626Swnj 		ap = ap->av_forw;
982626Swnj 	}
992626Swnj 	/*
1002626Swnj 	 * Neither a second list nor a larger
1012626Swnj 	 * request... we go at the end of the first list,
1022626Swnj 	 * which is the same as the end of the whole schebang.
1032626Swnj 	 */
1042626Swnj insert:
1052626Swnj 	bp->av_forw = ap->av_forw;
1062626Swnj 	ap->av_forw = bp;
1072626Swnj 	if (ap == dp->b_actl)
10816Sbill 		dp->b_actl = bp;
10916Sbill }
110*30533Skarels 
111*30533Skarels /*
112*30533Skarels  * Compute checksum for disk label.
113*30533Skarels  */
114*30533Skarels dkcksum(lp)
115*30533Skarels 	register struct disklabel *lp;
116*30533Skarels {
117*30533Skarels 	register u_short *start, *end;
118*30533Skarels 	register u_short sum = 0;
119*30533Skarels 
120*30533Skarels 	start = (u_short *)lp;
121*30533Skarels 	end = (u_short *)&lp->d_partitions[lp->d_npartitions];
122*30533Skarels 	while (start < end)
123*30533Skarels 		sum ^= *start++;
124*30533Skarels 	return (sum);
125*30533Skarels }
126