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