|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ ! 23: /* ! 24: * Copyright (c) 1982, 1986, 1988, 1993 ! 25: * The Regents of the University of California. All rights reserved. ! 26: * (c) UNIX System Laboratories, Inc. ! 27: * All or some portions of this file are derived from material licensed ! 28: * to the University of California by American Telephone and Telegraph ! 29: * Co. or Unix System Laboratories, Inc. and are reproduced herein with ! 30: * the permission of UNIX System Laboratories, Inc. ! 31: * ! 32: * Redistribution and use in source and binary forms, with or without ! 33: * modification, are permitted provided that the following conditions ! 34: * are met: ! 35: * 1. Redistributions of source code must retain the above copyright ! 36: * notice, this list of conditions and the following disclaimer. ! 37: * 2. Redistributions in binary form must reproduce the above copyright ! 38: * notice, this list of conditions and the following disclaimer in the ! 39: * documentation and/or other materials provided with the distribution. ! 40: * 3. All advertising materials mentioning features or use of this software ! 41: * must display the following acknowledgement: ! 42: * This product includes software developed by the University of ! 43: * California, Berkeley and its contributors. ! 44: * 4. Neither the name of the University nor the names of its contributors ! 45: * may be used to endorse or promote products derived from this software ! 46: * without specific prior written permission. ! 47: * ! 48: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 49: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 50: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 51: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 52: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 53: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 54: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 55: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 56: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 57: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 58: * SUCH DAMAGE. ! 59: * ! 60: * @(#)ufs_disksubr.c 8.5 (Berkeley) 1/21/94 ! 61: */ ! 62: ! 63: #include <sys/param.h> ! 64: #include <sys/systm.h> ! 65: #include <sys/buf.h> ! 66: #include <sys/disklabel.h> ! 67: #include <sys/syslog.h> ! 68: ! 69: /* ! 70: * Seek sort for disks. We depend on the driver which calls us using b_resid ! 71: * as the current cylinder number. ! 72: * ! 73: * The argument ap structure holds a b_actf activity chain pointer on which we ! 74: * keep two queues, sorted in ascending cylinder order. The first queue holds ! 75: * those requests which are positioned after the current cylinder (in the first ! 76: * request); the second holds requests which came in after their cylinder number ! 77: * was passed. Thus we implement a one way scan, retracting after reaching the ! 78: * end of the drive to the first request on the second queue, at which time it ! 79: * becomes the first queue. ! 80: * ! 81: * A one-way scan is natural because of the way UNIX read-ahead blocks are ! 82: * allocated. ! 83: */ ! 84: ! 85: /* ! 86: * For portability with historic industry practice, the ! 87: * cylinder number has to be maintained in the `b_resid' ! 88: * field. ! 89: */ ! 90: #define b_cylinder b_resid ! 91: ! 92: void ! 93: disksort(ap, bp) ! 94: register struct buf *ap, *bp; ! 95: { ! 96: register struct buf *bq; ! 97: ! 98: /* If the queue is empty, then it's easy. */ ! 99: if (ap->b_actf == NULL) { ! 100: bp->b_actf = NULL; ! 101: ap->b_actf = bp; ! 102: return; ! 103: } ! 104: ! 105: /* ! 106: * If we lie after the first (currently active) request, then we ! 107: * must locate the second request list and add ourselves to it. ! 108: */ ! 109: bq = ap->b_actf; ! 110: if (bp->b_cylinder < bq->b_cylinder) { ! 111: while (bq->b_actf) { ! 112: /* ! 113: * Check for an ``inversion'' in the normally ascending ! 114: * cylinder numbers, indicating the start of the second ! 115: * request list. ! 116: */ ! 117: if (bq->b_actf->b_cylinder < bq->b_cylinder) { ! 118: /* ! 119: * Search the second request list for the first ! 120: * request at a larger cylinder number. We go ! 121: * before that; if there is no such request, we ! 122: * go at end. ! 123: */ ! 124: do { ! 125: if (bp->b_cylinder < ! 126: bq->b_actf->b_cylinder) ! 127: goto insert; ! 128: if (bp->b_cylinder == ! 129: bq->b_actf->b_cylinder && ! 130: bp->b_blkno < bq->b_actf->b_blkno) ! 131: goto insert; ! 132: bq = bq->b_actf; ! 133: } while (bq->b_actf); ! 134: goto insert; /* after last */ ! 135: } ! 136: bq = bq->b_actf; ! 137: } ! 138: /* ! 139: * No inversions... we will go after the last, and ! 140: * be the first request in the second request list. ! 141: */ ! 142: goto insert; ! 143: } ! 144: /* ! 145: * Request is at/after the current request... ! 146: * sort in the first request list. ! 147: */ ! 148: while (bq->b_actf) { ! 149: /* ! 150: * We want to go after the current request if there is an ! 151: * inversion after it (i.e. it is the end of the first ! 152: * request list), or if the next request is a larger cylinder ! 153: * than our request. ! 154: */ ! 155: if (bq->b_actf->b_cylinder < bq->b_cylinder || ! 156: bp->b_cylinder < bq->b_actf->b_cylinder || ! 157: (bp->b_cylinder == bq->b_actf->b_cylinder && ! 158: bp->b_blkno < bq->b_actf->b_blkno)) ! 159: goto insert; ! 160: bq = bq->b_actf; ! 161: } ! 162: /* ! 163: * Neither a second list nor a larger request... we go at the end of ! 164: * the first list, which is the same as the end of the whole schebang. ! 165: */ ! 166: insert: bp->b_actf = bq->b_actf; ! 167: bq->b_actf = bp; ! 168: } ! 169: ! 170: /* encoding of disk minor numbers, should be elsewhere... */ ! 171: #define dkunit(dev) (minor(dev) >> 3) ! 172: #define dkpart(dev) (minor(dev) & 07) ! 173: #define dkminor(unit, part) (((unit) << 3) | (part)) ! 174: ! 175: /* ! 176: * Compute checksum for disk label. ! 177: */ ! 178: u_int ! 179: dkcksum(lp) ! 180: register struct disklabel *lp; ! 181: { ! 182: register u_short *start, *end; ! 183: register u_short sum = 0; ! 184: ! 185: start = (u_short *)lp; ! 186: end = (u_short *)&lp->d_partitions[lp->d_npartitions]; ! 187: while (start < end) ! 188: sum ^= *start++; ! 189: return (sum); ! 190: } ! 191: ! 192: /* ! 193: * Disk error is the preface to plaintive error messages ! 194: * about failing disk transfers. It prints messages of the form ! 195: ! 196: hp0g: hard error reading fsbn 12345 of 12344-12347 (hp0 bn %d cn %d tn %d sn %d) ! 197: ! 198: * if the offset of the error in the transfer and a disk label ! 199: * are both available. blkdone should be -1 if the position of the error ! 200: * is unknown; the disklabel pointer may be null from drivers that have not ! 201: * been converted to use them. The message is printed with printf ! 202: * if pri is LOG_PRINTF, otherwise it uses log at the specified priority. ! 203: * The message should be completed (with at least a newline) with printf ! 204: * or addlog, respectively. There is no trailing space. ! 205: */ ! 206: void ! 207: diskerr(bp, dname, what, pri, blkdone, lp) ! 208: register struct buf *bp; ! 209: char *dname, *what; ! 210: int pri, blkdone; ! 211: register struct disklabel *lp; ! 212: { ! 213: int unit = dkunit(bp->b_dev), part = dkpart(bp->b_dev); ! 214: register void (*pr) __P((const char *, ...)); ! 215: char partname = 'a' + part; ! 216: int sn; ! 217: ! 218: if (pri != LOG_PRINTF) { ! 219: log(pri, ""); ! 220: pr = addlog; ! 221: } else ! 222: pr = printf; ! 223: (*pr)("%s%d%c: %s %sing fsbn ", dname, unit, partname, what, ! 224: bp->b_flags & B_READ ? "read" : "writ"); ! 225: sn = bp->b_blkno; ! 226: if (bp->b_bcount <= DEV_BSIZE) ! 227: (*pr)("%d", sn); ! 228: else { ! 229: if (blkdone >= 0) { ! 230: sn += blkdone; ! 231: (*pr)("%d of ", sn); ! 232: } ! 233: (*pr)("%d-%d", bp->b_blkno, ! 234: bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE); ! 235: } ! 236: if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) { ! 237: #ifdef tahoe ! 238: sn *= DEV_BSIZE / lp->d_secsize; /* XXX */ ! 239: #endif ! 240: sn += lp->d_partitions[part].p_offset; ! 241: (*pr)(" (%s%d bn %d; cn %d", dname, unit, sn, ! 242: sn / lp->d_secpercyl); ! 243: sn %= lp->d_secpercyl; ! 244: (*pr)(" tn %d sn %d)", sn / lp->d_nsectors, sn % lp->d_nsectors); ! 245: } ! 246: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.