|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1982, 1986, 1988 Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * Redistribution and use in source and binary forms, with or without ! 6: * modification, are permitted provided that the following conditions ! 7: * are met: ! 8: * 1. Redistributions of source code must retain the above copyright ! 9: * notice, this list of conditions and the following disclaimer. ! 10: * 2. Redistributions in binary form must reproduce the above copyright ! 11: * notice, this list of conditions and the following disclaimer in the ! 12: * documentation and/or other materials provided with the distribution. ! 13: * 3. All advertising materials mentioning features or use of this software ! 14: * must display the following acknowledgement: ! 15: * This product includes software developed by the University of ! 16: * California, Berkeley and its contributors. ! 17: * 4. Neither the name of the University nor the names of its contributors ! 18: * may be used to endorse or promote products derived from this software ! 19: * without specific prior written permission. ! 20: * ! 21: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 23: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 24: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 25: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 26: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 27: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 28: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 29: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 30: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 31: * SUCH DAMAGE. ! 32: * ! 33: * @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91 ! 34: */ ! 35: ! 36: #include "param.h" ! 37: #include "systm.h" ! 38: #include "buf.h" ! 39: #include "disklabel.h" ! 40: #include "syslog.h" ! 41: ! 42: /* ! 43: * Seek sort for disks. We depend on the driver ! 44: * which calls us using b_resid as the current cylinder number. ! 45: * ! 46: * The argument dp structure holds a b_actf activity chain pointer ! 47: * on which we keep two queues, sorted in ascending cylinder order. ! 48: * The first queue holds those requests which are positioned after ! 49: * the current cylinder (in the first request); the second holds ! 50: * requests which came in after their cylinder number was passed. ! 51: * Thus we implement a one way scan, retracting after reaching the ! 52: * end of the drive to the first request on the second queue, ! 53: * at which time it becomes the first queue. ! 54: * ! 55: * A one-way scan is natural because of the way UNIX read-ahead ! 56: * blocks are allocated. ! 57: */ ! 58: ! 59: #define b_cylin b_resid ! 60: ! 61: disksort(dp, bp) ! 62: register struct buf *dp, *bp; ! 63: { ! 64: register struct buf *ap; ! 65: ! 66: /* ! 67: * If nothing on the activity queue, then ! 68: * we become the only thing. ! 69: */ ! 70: ap = dp->b_actf; ! 71: if(ap == NULL) { ! 72: dp->b_actf = bp; ! 73: dp->b_actl = bp; ! 74: bp->av_forw = NULL; ! 75: return; ! 76: } ! 77: /* ! 78: * If we lie after the first (currently active) ! 79: * request, then we must locate the second request list ! 80: * and add ourselves to it. ! 81: */ ! 82: if (bp->b_cylin < ap->b_cylin) { ! 83: while (ap->av_forw) { ! 84: /* ! 85: * Check for an ``inversion'' in the ! 86: * normally ascending cylinder numbers, ! 87: * indicating the start of the second request list. ! 88: */ ! 89: if (ap->av_forw->b_cylin < ap->b_cylin) { ! 90: /* ! 91: * Search the second request list ! 92: * for the first request at a larger ! 93: * cylinder number. We go before that; ! 94: * if there is no such request, we go at end. ! 95: */ ! 96: do { ! 97: if (bp->b_cylin < ap->av_forw->b_cylin) ! 98: goto insert; ! 99: if (bp->b_cylin == ap->av_forw->b_cylin && ! 100: bp->b_blkno < ap->av_forw->b_blkno) ! 101: goto insert; ! 102: ap = ap->av_forw; ! 103: } while (ap->av_forw); ! 104: goto insert; /* after last */ ! 105: } ! 106: ap = ap->av_forw; ! 107: } ! 108: /* ! 109: * No inversions... we will go after the last, and ! 110: * be the first request in the second request list. ! 111: */ ! 112: goto insert; ! 113: } ! 114: /* ! 115: * Request is at/after the current request... ! 116: * sort in the first request list. ! 117: */ ! 118: while (ap->av_forw) { ! 119: /* ! 120: * We want to go after the current request ! 121: * if there is an inversion after it (i.e. it is ! 122: * the end of the first request list), or if ! 123: * the next request is a larger cylinder than our request. ! 124: */ ! 125: if (ap->av_forw->b_cylin < ap->b_cylin || ! 126: bp->b_cylin < ap->av_forw->b_cylin || ! 127: (bp->b_cylin == ap->av_forw->b_cylin && ! 128: bp->b_blkno < ap->av_forw->b_blkno)) ! 129: goto insert; ! 130: ap = ap->av_forw; ! 131: } ! 132: /* ! 133: * Neither a second list nor a larger ! 134: * request... we go at the end of the first list, ! 135: * which is the same as the end of the whole schebang. ! 136: */ ! 137: insert: ! 138: bp->av_forw = ap->av_forw; ! 139: ap->av_forw = bp; ! 140: if (ap == dp->b_actl) ! 141: dp->b_actl = bp; ! 142: } ! 143: ! 144: /* ! 145: * Attempt to read a disk label from a device ! 146: * using the indicated stategy routine. ! 147: * The label must be partly set up before this: ! 148: * secpercyl and anything required in the strategy routine ! 149: * (e.g., sector size) must be filled in before calling us. ! 150: * Returns null on success and an error string on failure. ! 151: */ ! 152: char * ! 153: readdisklabel(dev, strat, lp) ! 154: dev_t dev; ! 155: int (*strat)(); ! 156: register struct disklabel *lp; ! 157: { ! 158: register struct buf *bp; ! 159: struct disklabel *dlp; ! 160: char *msg = NULL; ! 161: ! 162: if (lp->d_secperunit == 0) ! 163: lp->d_secperunit = 0x1fffffff; ! 164: lp->d_npartitions = 1; ! 165: if (lp->d_partitions[0].p_size == 0) ! 166: lp->d_partitions[0].p_size = 0x1fffffff; ! 167: lp->d_partitions[0].p_offset = 0; ! 168: ! 169: bp = geteblk((int)lp->d_secsize); ! 170: bp->b_dev = dev; ! 171: bp->b_blkno = LABELSECTOR; ! 172: bp->b_bcount = lp->d_secsize; ! 173: bp->b_flags = B_BUSY | B_READ; ! 174: bp->b_cylin = LABELSECTOR / lp->d_secpercyl; ! 175: (*strat)(bp); ! 176: if (biowait(bp)) { ! 177: msg = "I/O error"; ! 178: } else for (dlp = (struct disklabel *)bp->b_un.b_addr; ! 179: dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp)); ! 180: dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { ! 181: if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { ! 182: if (msg == NULL) ! 183: msg = "no disk label"; ! 184: } else if (dlp->d_npartitions > MAXPARTITIONS || ! 185: dkcksum(dlp) != 0) ! 186: msg = "disk label corrupted"; ! 187: else { ! 188: *lp = *dlp; ! 189: msg = NULL; ! 190: break; ! 191: } ! 192: } ! 193: bp->b_flags = B_INVAL | B_AGE; ! 194: brelse(bp); ! 195: return (msg); ! 196: } ! 197: ! 198: /* ! 199: * Check new disk label for sensibility ! 200: * before setting it. ! 201: */ ! 202: setdisklabel(olp, nlp, openmask) ! 203: register struct disklabel *olp, *nlp; ! 204: u_long openmask; ! 205: { ! 206: register i; ! 207: register struct partition *opp, *npp; ! 208: ! 209: if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC || ! 210: dkcksum(nlp) != 0) ! 211: return (EINVAL); ! 212: while ((i = ffs((long)openmask)) != 0) { ! 213: i--; ! 214: openmask &= ~(1 << i); ! 215: if (nlp->d_npartitions <= i) ! 216: return (EBUSY); ! 217: opp = &olp->d_partitions[i]; ! 218: npp = &nlp->d_partitions[i]; ! 219: if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size) ! 220: return (EBUSY); ! 221: /* ! 222: * Copy internally-set partition information ! 223: * if new label doesn't include it. XXX ! 224: */ ! 225: if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) { ! 226: npp->p_fstype = opp->p_fstype; ! 227: npp->p_fsize = opp->p_fsize; ! 228: npp->p_frag = opp->p_frag; ! 229: npp->p_cpg = opp->p_cpg; ! 230: } ! 231: } ! 232: nlp->d_checksum = 0; ! 233: nlp->d_checksum = dkcksum(nlp); ! 234: *olp = *nlp; ! 235: return (0); ! 236: } ! 237: ! 238: /* encoding of disk minor numbers, should be elsewhere... */ ! 239: #define dkunit(dev) (minor(dev) >> 3) ! 240: #define dkpart(dev) (minor(dev) & 07) ! 241: #define dkminor(unit, part) (((unit) << 3) | (part)) ! 242: ! 243: /* ! 244: * Write disk label back to device after modification. ! 245: */ ! 246: writedisklabel(dev, strat, lp) ! 247: dev_t dev; ! 248: int (*strat)(); ! 249: register struct disklabel *lp; ! 250: { ! 251: struct buf *bp; ! 252: struct disklabel *dlp; ! 253: int labelpart; ! 254: int error = 0; ! 255: ! 256: labelpart = dkpart(dev); ! 257: if (lp->d_partitions[labelpart].p_offset != 0) { ! 258: if (lp->d_partitions[0].p_offset != 0) ! 259: return (EXDEV); /* not quite right */ ! 260: labelpart = 0; ! 261: } ! 262: bp = geteblk((int)lp->d_secsize); ! 263: bp->b_dev = makedev(major(dev), dkminor(dkunit(dev), labelpart)); ! 264: bp->b_blkno = LABELSECTOR; ! 265: bp->b_bcount = lp->d_secsize; ! 266: bp->b_flags = B_READ; ! 267: (*strat)(bp); ! 268: if (error = biowait(bp)) ! 269: goto done; ! 270: for (dlp = (struct disklabel *)bp->b_un.b_addr; ! 271: dlp <= (struct disklabel *) ! 272: (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp)); ! 273: dlp = (struct disklabel *)((char *)dlp + sizeof(long))) { ! 274: if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC && ! 275: dkcksum(dlp) == 0) { ! 276: *dlp = *lp; ! 277: bp->b_flags = B_WRITE; ! 278: (*strat)(bp); ! 279: error = biowait(bp); ! 280: goto done; ! 281: } ! 282: } ! 283: error = ESRCH; ! 284: done: ! 285: brelse(bp); ! 286: return (error); ! 287: } ! 288: ! 289: /* ! 290: * Compute checksum for disk label. ! 291: */ ! 292: dkcksum(lp) ! 293: register struct disklabel *lp; ! 294: { ! 295: register u_short *start, *end; ! 296: register u_short sum = 0; ! 297: ! 298: start = (u_short *)lp; ! 299: end = (u_short *)&lp->d_partitions[lp->d_npartitions]; ! 300: while (start < end) ! 301: sum ^= *start++; ! 302: return (sum); ! 303: } ! 304: ! 305: /* ! 306: * Disk error is the preface to plaintive error messages ! 307: * about failing disk transfers. It prints messages of the form ! 308: ! 309: hp0g: hard error reading fsbn 12345 of 12344-12347 (hp0 bn %d cn %d tn %d sn %d) ! 310: ! 311: * if the offset of the error in the transfer and a disk label ! 312: * are both available. blkdone should be -1 if the position of the error ! 313: * is unknown; the disklabel pointer may be null from drivers that have not ! 314: * been converted to use them. The message is printed with printf ! 315: * if pri is LOG_PRINTF, otherwise it uses log at the specified priority. ! 316: * The message should be completed (with at least a newline) with printf ! 317: * or addlog, respectively. There is no trailing space. ! 318: */ ! 319: diskerr(bp, dname, what, pri, blkdone, lp) ! 320: register struct buf *bp; ! 321: char *dname, *what; ! 322: int pri, blkdone; ! 323: register struct disklabel *lp; ! 324: { ! 325: int unit = dkunit(bp->b_dev), part = dkpart(bp->b_dev); ! 326: register void (*pr) __P((const char *, ...)); ! 327: char partname = 'a' + part; ! 328: int sn; ! 329: ! 330: if (pri != LOG_PRINTF) { ! 331: log(pri, ""); ! 332: pr = addlog; ! 333: } else ! 334: pr = printf; ! 335: (*pr)("%s%d%c: %s %sing fsbn ", dname, unit, partname, what, ! 336: bp->b_flags & B_READ ? "read" : "writ"); ! 337: sn = bp->b_blkno; ! 338: if (bp->b_bcount <= DEV_BSIZE) ! 339: (*pr)("%d", sn); ! 340: else { ! 341: if (blkdone >= 0) { ! 342: sn += blkdone; ! 343: (*pr)("%d of ", sn); ! 344: } ! 345: (*pr)("%d-%d", bp->b_blkno, ! 346: bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE); ! 347: } ! 348: if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) { ! 349: #ifdef tahoe ! 350: sn *= DEV_BSIZE / lp->d_secsize; /* XXX */ ! 351: #endif ! 352: sn += lp->d_partitions[part].p_offset; ! 353: (*pr)(" (%s%d bn %d; cn %d", dname, unit, sn, ! 354: sn / lp->d_secpercyl); ! 355: sn %= lp->d_secpercyl; ! 356: (*pr)(" tn %d sn %d)", sn / lp->d_nsectors, sn % lp->d_nsectors); ! 357: } ! 358: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.