Annotation of Net2/ufs/ufs_disksubr.c, revision 1.1.1.2

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"
1.1.1.2 ! root       39: #include "dkbad.h"
1.1       root       40: #include "disklabel.h"
                     41: #include "syslog.h"
                     42: 
                     43: /*
                     44:  * Seek sort for disks.  We depend on the driver
                     45:  * which calls us using b_resid as the current cylinder number.
                     46:  *
                     47:  * The argument dp structure holds a b_actf activity chain pointer
                     48:  * on which we keep two queues, sorted in ascending cylinder order.
                     49:  * The first queue holds those requests which are positioned after
                     50:  * the current cylinder (in the first request); the second holds
                     51:  * requests which came in after their cylinder number was passed.
                     52:  * Thus we implement a one way scan, retracting after reaching the
                     53:  * end of the drive to the first request on the second queue,
                     54:  * at which time it becomes the first queue.
                     55:  *
                     56:  * A one-way scan is natural because of the way UNIX read-ahead
                     57:  * blocks are allocated.
                     58:  */
                     59: 
                     60: #define        b_cylin b_resid
                     61: 
1.1.1.2 ! root       62: void
1.1       root       63: disksort(dp, bp)
                     64:        register struct buf *dp, *bp;
                     65: {
                     66:        register struct buf *ap;
                     67: 
                     68:        /*
                     69:         * If nothing on the activity queue, then
                     70:         * we become the only thing.
                     71:         */
                     72:        ap = dp->b_actf;
                     73:        if(ap == NULL) {
                     74:                dp->b_actf = bp;
                     75:                dp->b_actl = bp;
                     76:                bp->av_forw = NULL;
                     77:                return;
                     78:        }
                     79:        /*
                     80:         * If we lie after the first (currently active)
                     81:         * request, then we must locate the second request list
                     82:         * and add ourselves to it.
                     83:         */
                     84:        if (bp->b_cylin < ap->b_cylin) {
                     85:                while (ap->av_forw) {
                     86:                        /*
                     87:                         * Check for an ``inversion'' in the
                     88:                         * normally ascending cylinder numbers,
                     89:                         * indicating the start of the second request list.
                     90:                         */
                     91:                        if (ap->av_forw->b_cylin < ap->b_cylin) {
                     92:                                /*
                     93:                                 * Search the second request list
                     94:                                 * for the first request at a larger
                     95:                                 * cylinder number.  We go before that;
                     96:                                 * if there is no such request, we go at end.
                     97:                                 */
                     98:                                do {
                     99:                                        if (bp->b_cylin < ap->av_forw->b_cylin)
                    100:                                                goto insert;
                    101:                                        if (bp->b_cylin == ap->av_forw->b_cylin &&
                    102:                                            bp->b_blkno < ap->av_forw->b_blkno)
                    103:                                                goto insert;
                    104:                                        ap = ap->av_forw;
                    105:                                } while (ap->av_forw);
                    106:                                goto insert;            /* after last */
                    107:                        }
                    108:                        ap = ap->av_forw;
                    109:                }
                    110:                /*
                    111:                 * No inversions... we will go after the last, and
                    112:                 * be the first request in the second request list.
                    113:                 */
                    114:                goto insert;
                    115:        }
                    116:        /*
                    117:         * Request is at/after the current request...
                    118:         * sort in the first request list.
                    119:         */
                    120:        while (ap->av_forw) {
                    121:                /*
                    122:                 * We want to go after the current request
                    123:                 * if there is an inversion after it (i.e. it is
                    124:                 * the end of the first request list), or if
                    125:                 * the next request is a larger cylinder than our request.
                    126:                 */
                    127:                if (ap->av_forw->b_cylin < ap->b_cylin ||
                    128:                    bp->b_cylin < ap->av_forw->b_cylin ||
                    129:                    (bp->b_cylin == ap->av_forw->b_cylin &&
                    130:                    bp->b_blkno < ap->av_forw->b_blkno))
                    131:                        goto insert;
                    132:                ap = ap->av_forw;
                    133:        }
                    134:        /*
                    135:         * Neither a second list nor a larger
                    136:         * request... we go at the end of the first list,
                    137:         * which is the same as the end of the whole schebang.
                    138:         */
                    139: insert:
                    140:        bp->av_forw = ap->av_forw;
                    141:        ap->av_forw = bp;
                    142:        if (ap == dp->b_actl)
                    143:                dp->b_actl = bp;
                    144: }
                    145: 
1.1.1.2 ! root      146: /* encoding of disk minor numbers, should be elsewhere... */
        !           147: #define dkunit(dev)            (minor(dev) >> 3)
        !           148: #define dkpart(dev)            (minor(dev) & 7)
        !           149: #define dkminor(unit, part)    (((unit) << 3) | (part))
        !           150: 
1.1       root      151: /*
                    152:  * Attempt to read a disk label from a device
                    153:  * using the indicated stategy routine.
                    154:  * The label must be partly set up before this:
1.1.1.2 ! root      155:  * secpercyl, secsize and anything required for a block i/o read
        !           156:  * operation in the driver's strategy/start routines
        !           157:  * must be filled in before calling us.
        !           158:  *
        !           159:  * If dos partition table requested, attempt to load it and
        !           160:  * find disklabel inside a DOS partition. Also, if bad block
        !           161:  * table needed, attempt to extract it as well. Return buffer
        !           162:  * for use in signalling errors if requested.
        !           163:  *
1.1       root      164:  * Returns null on success and an error string on failure.
                    165:  */
                    166: char *
1.1.1.2 ! root      167: readdisklabel(dev, strat, lp, dp, bdp, bpp)
1.1       root      168:        dev_t dev;
                    169:        int (*strat)();
                    170:        register struct disklabel *lp;
1.1.1.2 ! root      171:        struct dos_partition *dp;
        !           172:        struct dkbad *bdp;
        !           173:        struct buf **bpp;
1.1       root      174: {
                    175:        register struct buf *bp;
                    176:        struct disklabel *dlp;
                    177:        char *msg = NULL;
1.1.1.2 ! root      178:        int cyl, dospartoff, i;
1.1       root      179: 
1.1.1.2 ! root      180:        /* minimal requirements for archtypal disk label */
1.1       root      181:        if (lp->d_secperunit == 0)
                    182:                lp->d_secperunit = 0x1fffffff;
                    183:        lp->d_npartitions = 1;
                    184:        if (lp->d_partitions[0].p_size == 0)
                    185:                lp->d_partitions[0].p_size = 0x1fffffff;
                    186:        lp->d_partitions[0].p_offset = 0;
                    187: 
1.1.1.2 ! root      188:        /* obtain buffer to probe drive with */
1.1       root      189:        bp = geteblk((int)lp->d_secsize);
1.1.1.2 ! root      190:        
        !           191:        /* request no partition relocation by driver on I/O operations */
        !           192:        bp->b_dev = makedev(major(dev), dkminor((dkunit(dev)), 3));
        !           193: 
        !           194:        /* do dos partitions in the process of getting disklabel? */
        !           195:        dospartoff = 0;
        !           196:        cyl = LABELSECTOR / lp->d_secpercyl;
        !           197:        if (dp) {
        !           198:                struct dos_partition *ap;
        !           199: 
        !           200:                /* read master boot record */
        !           201:                bp->b_blkno = DOSBBSECTOR;
        !           202:                bp->b_bcount = lp->d_secsize;
        !           203:                bp->b_flags = B_BUSY | B_READ;
        !           204:                bp->b_cylin = DOSBBSECTOR / lp->d_secpercyl;
        !           205:                (*strat)(bp);
        !           206: 
        !           207:                /* if successful, wander through dos partition table */
        !           208:                if (biowait(bp)) {
        !           209:                        msg = "dos partition I/O error";
        !           210:                        goto done;
        !           211:                } else {
        !           212:                        /* XXX how do we check veracity/bounds of this? */
        !           213:                        bcopy(bp->b_un.b_addr + DOSPARTOFF, dp,
        !           214:                                NDOSPART * sizeof(*dp));
        !           215:                        for (i = 0; i < NDOSPART; i++, dp++)
        !           216:                                /* is this ours? */
        !           217:                                if (dp->dp_size &&
        !           218:                                        dp->dp_typ == DOSPTYP_386BSD
        !           219:                                        && dospartoff == 0) {
        !           220: 
        !           221:                                        /* need sector address for SCSI/IDE,
        !           222:                                           cylinder for ESDI/ST506/RLL */
        !           223:                                        dospartoff = dp->dp_start;
        !           224:                                        cyl = DPCYL(dp->dp_scyl, dp->dp_ssect);
        !           225: 
        !           226:                                        /* update disklabel with details */
        !           227:                                        lp->d_partitions[0].p_size =
        !           228:                                                dp->dp_size;
        !           229:                                        lp->d_partitions[0].p_offset = 
        !           230:                                                dp->dp_start;
        !           231:                                        lp->d_ntracks = dp->dp_ehd + 1;
        !           232:                                        lp->d_nsectors = DPSECT(dp->dp_esect);
        !           233:                                        lp->d_subtype |= (lp->d_subtype & 3)
        !           234:                                                        + i | DSTYPE_INDOSPART;
        !           235:                                        lp->d_secpercyl = lp->d_ntracks *
        !           236:                                                lp->d_nsectors;
        !           237:                                }
        !           238:                }
        !           239:                        
        !           240:        }
        !           241:        
        !           242:        /* next, dig out disk label */
        !           243:        bp->b_blkno = dospartoff + LABELSECTOR;
        !           244:        bp->b_cylin = cyl;
1.1       root      245:        bp->b_bcount = lp->d_secsize;
                    246:        bp->b_flags = B_BUSY | B_READ;
                    247:        (*strat)(bp);
1.1.1.2 ! root      248: 
        !           249:        /* if successful, locate disk label within block and validate */
1.1       root      250:        if (biowait(bp)) {
1.1.1.2 ! root      251:                msg = "disk label I/O error";
        !           252:                goto done;
1.1       root      253:        } else for (dlp = (struct disklabel *)bp->b_un.b_addr;
                    254:            dlp <= (struct disklabel *)(bp->b_un.b_addr+DEV_BSIZE-sizeof(*dlp));
                    255:            dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
                    256:                if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) {
                    257:                        if (msg == NULL)
                    258:                                msg = "no disk label";
                    259:                } else if (dlp->d_npartitions > MAXPARTITIONS ||
                    260:                           dkcksum(dlp) != 0)
                    261:                        msg = "disk label corrupted";
                    262:                else {
                    263:                        *lp = *dlp;
                    264:                        msg = NULL;
                    265:                        break;
                    266:                }
                    267:        }
1.1.1.2 ! root      268: 
        !           269:        if (msg)
        !           270:                goto done;
        !           271: 
        !           272:        /* obtain bad sector table if requested and present */
        !           273:        if (bdp && (lp->d_flags & D_BADSECT)) {
        !           274:                struct dkbad *db;
        !           275: 
        !           276:                i = 0;
        !           277:                do {
        !           278:                        /* read a bad sector table */
        !           279:                        bp->b_flags = B_BUSY | B_READ;
        !           280:                        bp->b_blkno = lp->d_secperunit - lp->d_nsectors + i;
        !           281:                        if (lp->d_secsize > DEV_BSIZE)
        !           282:                                bp->b_blkno *= lp->d_secsize / DEV_BSIZE;
        !           283:                        else
        !           284:                                bp->b_blkno /= DEV_BSIZE / lp->d_secsize;
        !           285:                        bp->b_bcount = lp->d_secsize;
        !           286:                        bp->b_cylin = lp->d_ncylinders - 1;
        !           287:                        (*strat)(bp);
        !           288: 
        !           289:                        /* if successful, validate, otherwise try another */
        !           290:                        if (biowait(bp)) {
        !           291:                                msg = "bad sector table I/O error";
        !           292:                        } else {
        !           293:                                db = (struct dkbad *)(bp->b_un.b_addr);
        !           294: #define DKBAD_MAGIC 0x4321
        !           295:                                if (db->bt_mbz == 0
        !           296:                                        && db->bt_flag == DKBAD_MAGIC) {
        !           297:                                        msg = NULL;
        !           298:                                        *bdp = *db;
        !           299:                                        break;
        !           300:                                } else
        !           301:                                        msg = "bad sector table corrupted";
        !           302:                        }
        !           303:                } while ((bp->b_flags & B_ERROR) && (i += 2) < 10 &&
        !           304:                        i < lp->d_nsectors);
        !           305:        }
        !           306: 
        !           307: done:
        !           308:        bp->b_flags = B_INVAL | B_AGE | B_READ;
        !           309: #ifndef old
        !           310:        /* if desired, pass back allocated block so caller can use */
        !           311:        if (bpp)
        !           312:                *bpp = bp;
        !           313:        else
        !           314: #endif
1.1       root      315:        brelse(bp);
                    316:        return (msg);
                    317: }
                    318: 
                    319: /*
                    320:  * Check new disk label for sensibility
                    321:  * before setting it.
                    322:  */
1.1.1.2 ! root      323: setdisklabel(olp, nlp, openmask, dp)
1.1       root      324:        register struct disklabel *olp, *nlp;
                    325:        u_long openmask;
1.1.1.2 ! root      326:        struct dos_partition *dp;
1.1       root      327: {
                    328:        register i;
                    329:        register struct partition *opp, *npp;
                    330: 
1.1.1.2 ! root      331:        /* sanity clause */
        !           332:        if (nlp->d_secpercyl == 0 || nlp->d_secsize == 0
        !           333:                || (nlp->d_secsize % DEV_BSIZE) != 0)
        !           334:                        return(EINVAL);
        !           335: 
        !           336:        /* special case to allow disklabel to be invalidated */
        !           337:        if (nlp->d_magic == 0xffffffff) {
        !           338:                *olp = *nlp;
        !           339:                return (0);
        !           340:        }
        !           341: 
1.1       root      342:        if (nlp->d_magic != DISKMAGIC || nlp->d_magic2 != DISKMAGIC ||
                    343:            dkcksum(nlp) != 0)
                    344:                return (EINVAL);
1.1.1.2 ! root      345: 
        !           346:        /* XXX missing check if other dos partitions will be overwritten */
        !           347: 
1.1       root      348:        while ((i = ffs((long)openmask)) != 0) {
                    349:                i--;
                    350:                openmask &= ~(1 << i);
                    351:                if (nlp->d_npartitions <= i)
                    352:                        return (EBUSY);
                    353:                opp = &olp->d_partitions[i];
                    354:                npp = &nlp->d_partitions[i];
                    355:                if (npp->p_offset != opp->p_offset || npp->p_size < opp->p_size)
                    356:                        return (EBUSY);
                    357:                /*
                    358:                 * Copy internally-set partition information
                    359:                 * if new label doesn't include it.             XXX
                    360:                 */
                    361:                if (npp->p_fstype == FS_UNUSED && opp->p_fstype != FS_UNUSED) {
                    362:                        npp->p_fstype = opp->p_fstype;
                    363:                        npp->p_fsize = opp->p_fsize;
                    364:                        npp->p_frag = opp->p_frag;
                    365:                        npp->p_cpg = opp->p_cpg;
                    366:                }
                    367:        }
                    368:        nlp->d_checksum = 0;
                    369:        nlp->d_checksum = dkcksum(nlp);
                    370:        *olp = *nlp;
                    371:        return (0);
                    372: }
                    373: 
                    374: 
                    375: /*
                    376:  * Write disk label back to device after modification.
                    377:  */
1.1.1.2 ! root      378: writedisklabel(dev, strat, lp, dp)
1.1       root      379:        dev_t dev;
                    380:        int (*strat)();
                    381:        register struct disklabel *lp;
1.1.1.2 ! root      382:        struct dos_partition *dp;
1.1       root      383: {
                    384:        struct buf *bp;
                    385:        struct disklabel *dlp;
1.1.1.2 ! root      386:        int labelpart, error = 0, dospartoff, cyl, i;
1.1       root      387: 
                    388:        labelpart = dkpart(dev);
1.1.1.2 ! root      389: #ifdef nope
1.1       root      390:        if (lp->d_partitions[labelpart].p_offset != 0) {
                    391:                if (lp->d_partitions[0].p_offset != 0)
                    392:                        return (EXDEV);                 /* not quite right */
                    393:                labelpart = 0;
                    394:        }
1.1.1.2 ! root      395: #else
        !           396:                labelpart = 3;
        !           397: #endif
        !           398: 
1.1       root      399:        bp = geteblk((int)lp->d_secsize);
1.1.1.2 ! root      400:        /* request no partition relocation by driver on I/O operations */
        !           401:        bp->b_dev = makedev(major(dev), dkminor((dkunit(dev)), 3));
        !           402: 
        !           403:        /* do dos partitions in the process of getting disklabel? */
        !           404:        dospartoff = 0;
        !           405:        cyl = LABELSECTOR / lp->d_secpercyl;
        !           406:        if (dp) {
        !           407:                bp->b_blkno = DOSBBSECTOR;
        !           408:                bp->b_bcount = lp->d_secsize;
        !           409:                bp->b_flags = B_BUSY | B_READ;
        !           410:                bp->b_cylin = DOSBBSECTOR / lp->d_secpercyl;
        !           411:                (*strat)(bp);
        !           412:                if ((error = biowait(bp)) == 0) {
        !           413:                        bcopy(bp->b_un.b_addr + DOSPARTOFF, dp,
        !           414:                                NDOSPART * sizeof(*dp));
        !           415:                        for (i = 0; i < NDOSPART; i++, dp++)
        !           416:                                if(dp->dp_size && dp->dp_typ == DOSPTYP_386BSD
        !           417:                                        && dospartoff == 0) {
        !           418:                                        /* need sector address for SCSI/IDE,
        !           419:                                           cylinder for ESDI/ST506/RLL */
        !           420:                                        dospartoff = dp->dp_start;
        !           421:                                        cyl = dp->dp_scyl |
        !           422:                                                ((dp->dp_ssect & 0xc0) << 2);
        !           423:                                }
        !           424:                }
        !           425:                        
        !           426:        }
        !           427:        
        !           428: #ifdef maybe
        !           429:        /* disklabel in appropriate location? */
        !           430:        if (lp->d_partitions[0].p_offset != 0
        !           431:                && lp->d_partitions[0].p_offset != dospartoff) {
        !           432:                error = EXDEV;          
        !           433:                goto done;
        !           434:        }
        !           435: #endif
        !           436: 
        !           437:        bp->b_blkno = dospartoff + LABELSECTOR;
        !           438:        bp->b_cylin = cyl;
1.1       root      439:        bp->b_bcount = lp->d_secsize;
                    440:        bp->b_flags = B_READ;
                    441:        (*strat)(bp);
                    442:        if (error = biowait(bp))
                    443:                goto done;
                    444:        for (dlp = (struct disklabel *)bp->b_un.b_addr;
                    445:            dlp <= (struct disklabel *)
                    446:              (bp->b_un.b_addr + lp->d_secsize - sizeof(*dlp));
                    447:            dlp = (struct disklabel *)((char *)dlp + sizeof(long))) {
                    448:                if (dlp->d_magic == DISKMAGIC && dlp->d_magic2 == DISKMAGIC &&
                    449:                    dkcksum(dlp) == 0) {
                    450:                        *dlp = *lp;
                    451:                        bp->b_flags = B_WRITE;
                    452:                        (*strat)(bp);
                    453:                        error = biowait(bp);
                    454:                        goto done;
                    455:                }
                    456:        }
                    457:        error = ESRCH;
                    458: done:
                    459:        brelse(bp);
                    460:        return (error);
                    461: }
                    462: 
                    463: /*
                    464:  * Compute checksum for disk label.
                    465:  */
                    466: dkcksum(lp)
                    467:        register struct disklabel *lp;
                    468: {
                    469:        register u_short *start, *end;
                    470:        register u_short sum = 0;
                    471: 
                    472:        start = (u_short *)lp;
                    473:        end = (u_short *)&lp->d_partitions[lp->d_npartitions];
                    474:        while (start < end)
                    475:                sum ^= *start++;
                    476:        return (sum);
                    477: }
                    478: 
                    479: /*
1.1.1.2 ! root      480:  * Determine the size of the transfer, and make sure it is
        !           481:  * within the boundaries of the partition. Adjust transfer
        !           482:  * if needed, and signal errors or early completion.
        !           483:  */
        !           484: int
        !           485: bounds_check_with_label(struct buf *bp, struct disklabel *lp, int wlabel)
        !           486: {
        !           487:        struct partition *p = lp->d_partitions + dkpart(bp->b_dev);
        !           488:        int labelsect = lp->d_partitions[0].p_offset;
        !           489:        int maxsz = p->p_size,
        !           490:                sz = (bp->b_bcount + DEV_BSIZE - 1) >> DEV_BSHIFT;
        !           491: 
        !           492:        /* overwriting disk label ? */
        !           493:        /* XXX should also protect bootstrap in first 8K */
        !           494:         if (bp->b_blkno + p->p_offset <= LABELSECTOR + labelsect &&
        !           495: #if LABELSECTOR != 0
        !           496:             bp->b_blkno + p->p_offset + sz > LABELSECTOR + labelsect &&
        !           497: #endif
        !           498:             (bp->b_flags & B_READ) == 0 && wlabel == 0) {
        !           499:                 bp->b_error = EROFS;
        !           500:                 goto bad;
        !           501:         }
        !           502: 
        !           503: #if    defined(DOSBBSECTOR) && defined(notyet)
        !           504:        /* overwriting master boot record? */
        !           505:         if (bp->b_blkno + p->p_offset <= DOSBBSECTOR &&
        !           506:             (bp->b_flags & B_READ) == 0 && wlabel == 0) {
        !           507:                 bp->b_error = EROFS;
        !           508:                 goto bad;
        !           509:         }
        !           510: #endif
        !           511: 
        !           512:        /* beyond partition? */
        !           513:         if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
        !           514:                 /* if exactly at end of disk, return an EOF */
        !           515:                 if (bp->b_blkno == maxsz) {
        !           516:                         bp->b_resid = bp->b_bcount;
        !           517:                         return(0);
        !           518:                 }
        !           519:                 /* or truncate if part of it fits */
        !           520:                 sz = maxsz - bp->b_blkno;
        !           521:                 if (sz <= 0) {
        !           522:                        bp->b_error = EINVAL;
        !           523:                         goto bad;
        !           524:                }
        !           525:                 bp->b_bcount = sz << DEV_BSHIFT;
        !           526:         }
        !           527: 
        !           528:        /* calculate cylinder for disksort to order transfers with */
        !           529:         bp->b_cylin = (bp->b_blkno + p->p_offset) / lp->d_secpercyl;
        !           530:        return(1);
        !           531: 
        !           532: bad:
        !           533:        bp->b_flags |= B_ERROR;
        !           534:        return(-1);
        !           535: }
        !           536: 
        !           537: /*
1.1       root      538:  * Disk error is the preface to plaintive error messages
                    539:  * about failing disk transfers.  It prints messages of the form
                    540: 
                    541: hp0g: hard error reading fsbn 12345 of 12344-12347 (hp0 bn %d cn %d tn %d sn %d)
                    542: 
                    543:  * if the offset of the error in the transfer and a disk label
                    544:  * are both available.  blkdone should be -1 if the position of the error
                    545:  * is unknown; the disklabel pointer may be null from drivers that have not
                    546:  * been converted to use them.  The message is printed with printf
                    547:  * if pri is LOG_PRINTF, otherwise it uses log at the specified priority.
                    548:  * The message should be completed (with at least a newline) with printf
                    549:  * or addlog, respectively.  There is no trailing space.
                    550:  */
1.1.1.2 ! root      551: void
1.1       root      552: diskerr(bp, dname, what, pri, blkdone, lp)
                    553:        register struct buf *bp;
                    554:        char *dname, *what;
                    555:        int pri, blkdone;
                    556:        register struct disklabel *lp;
                    557: {
                    558:        int unit = dkunit(bp->b_dev), part = dkpart(bp->b_dev);
                    559:        register void (*pr) __P((const char *, ...));
                    560:        char partname = 'a' + part;
                    561:        int sn;
                    562: 
                    563:        if (pri != LOG_PRINTF) {
                    564:                log(pri, "");
                    565:                pr = addlog;
                    566:        } else
                    567:                pr = printf;
                    568:        (*pr)("%s%d%c: %s %sing fsbn ", dname, unit, partname, what,
                    569:            bp->b_flags & B_READ ? "read" : "writ");
                    570:        sn = bp->b_blkno;
                    571:        if (bp->b_bcount <= DEV_BSIZE)
                    572:                (*pr)("%d", sn);
                    573:        else {
                    574:                if (blkdone >= 0) {
                    575:                        sn += blkdone;
                    576:                        (*pr)("%d of ", sn);
                    577:                }
                    578:                (*pr)("%d-%d", bp->b_blkno,
                    579:                    bp->b_blkno + (bp->b_bcount - 1) / DEV_BSIZE);
                    580:        }
                    581:        if (lp && (blkdone >= 0 || bp->b_bcount <= lp->d_secsize)) {
                    582: #ifdef tahoe
                    583:                sn *= DEV_BSIZE / lp->d_secsize;                /* XXX */
                    584: #endif
                    585:                sn += lp->d_partitions[part].p_offset;
                    586:                (*pr)(" (%s%d bn %d; cn %d", dname, unit, sn,
                    587:                    sn / lp->d_secpercyl);
                    588:                sn %= lp->d_secpercyl;
                    589:                (*pr)(" tn %d sn %d)", sn / lp->d_nsectors, sn % lp->d_nsectors);
                    590:        }
                    591: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.