diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2003-02-24 23:43:15 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2003-02-24 23:43:15 +0000 |
commit | e409103ea056164225d60b7143d4d2fb3a88353e (patch) | |
tree | 79d5172b2a69aaa4c54307d198ab44311b566b83 /sys/arch/mac68k | |
parent | f1a3285ed63083a5d7d7103171127ddc29826210 (diff) |
Hammer the disklabel code once more: a few fixes, lots of simplifications,
read the label and the Apple DPME partition table in one shot (this idea from
NetBSD), and generally make things much safer.
Solves spurious panic while building labels on disks with a large number of
DPME partitions.
Diffstat (limited to 'sys/arch/mac68k')
-rw-r--r-- | sys/arch/mac68k/mac68k/disksubr.c | 263 |
1 files changed, 73 insertions, 190 deletions
diff --git a/sys/arch/mac68k/mac68k/disksubr.c b/sys/arch/mac68k/mac68k/disksubr.c index 20be5778e4a..b96b9b7c4aa 100644 --- a/sys/arch/mac68k/mac68k/disksubr.c +++ b/sys/arch/mac68k/mac68k/disksubr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: disksubr.c,v 1.20 2002/12/10 23:53:22 miod Exp $ */ +/* $OpenBSD: disksubr.c,v 1.21 2003/02/24 23:43:14 miod Exp $ */ /* $NetBSD: disksubr.c,v 1.22 1997/11/26 04:18:20 briggs Exp $ */ /* @@ -100,15 +100,10 @@ int getFreeLabelEntry(struct disklabel *); int whichType(struct partmapentry *); -void fixPartTable(struct partmapentry *, long, char *, int *); -void setRoot(struct partmapentry *, struct disklabel *, int); -void setSwap(struct partmapentry *, struct disklabel *, int); -void setUfs(struct partmapentry *, struct disklabel *, int); -void setHfs(struct partmapentry *, struct disklabel *, int); -void setScratch(struct partmapentry *, struct disklabel *, int); +int fixPartTable(struct partmapentry *, long, char *); +void setPart(struct partmapentry *, struct disklabel *, int, int); int getNamedType(struct partmapentry *, int, struct disklabel *, int, int, int *); -char *read_mac_label(dev_t, void (*)(struct buf *), - struct disklabel *, struct cpu_disklabel *); +char *read_mac_label(char *, struct disklabel *, struct cpu_disklabel *); /* * Find an entry in the disk label that is unused and return it @@ -118,7 +113,7 @@ int getFreeLabelEntry(lp) struct disklabel *lp; { - int i = 0; + int i; for (i = 0; i < MAXPARTITIONS; i++) { if ((i != RAW_PART) @@ -185,136 +180,44 @@ whichType(part) * upon. Make sure names are NUL terminated. Capitalize the names * of part types. */ -void -fixPartTable(partTable, size, base, num) +int +fixPartTable(partTable, size, base) struct partmapentry *partTable; long size; char *base; - int *num; { - int i = 0; + int i; struct partmapentry *pmap; char *s; for (i = 0; i < NUM_PARTS_PROBED; i++) { - pmap = (struct partmapentry *)((i * size) + base); + pmap = (struct partmapentry *)((i * size) + base + DEV_BSIZE); + + partTable[i] = *pmap; + pmap = &partTable[i]; if (pmap->pmSig != DPME_MAGIC) { /* this is not valid */ pmap->pmPartType[0] = '\0'; - break; + return i; } - (*num)++; - pmap->pmPartName[31] = '\0'; pmap->pmPartType[31] = '\0'; for (s = pmap->pmPartType; *s; s++) if ((*s >= 'a') && (*s <= 'z')) *s = (*s - 'a' + 'A'); - - partTable[i] = *pmap; } -} - -void -setRoot(part, lp, slot) - struct partmapentry *part; - struct disklabel *lp; - int slot; -{ - lp->d_partitions[slot].p_size = part->pmPartBlkCnt; - lp->d_partitions[slot].p_offset = part->pmPyPartStart; - lp->d_partitions[slot].p_fstype = FS_BSDFFS; - -#if PRINT_DISKLABELS - printf("%c: Root '%s' at %d size %d\n", slot + 'a', - part->pmPartName, - part->pmPyPartStart, - part->pmPartBlkCnt); -#endif - part->pmPartType[0] = '\0'; + return NUM_PARTS_PROBED; } void -setSwap(part, lp, slot) - struct partmapentry *part; - struct disklabel *lp; - int slot; +setPart(struct partmapentry *part, struct disklabel *lp, int fstype, int slot) { lp->d_partitions[slot].p_size = part->pmPartBlkCnt; lp->d_partitions[slot].p_offset = part->pmPyPartStart; - lp->d_partitions[slot].p_fstype = FS_SWAP; - -#if PRINT_DISKLABELS - printf("%c: Swap '%s' at %d size %d\n", slot + 'a', - part->pmPartName, - part->pmPyPartStart, - part->pmPartBlkCnt); -#endif - - part->pmPartType[0] = '\0'; -} - -void -setUfs(part, lp, slot) - struct partmapentry *part; - struct disklabel *lp; - int slot; -{ - lp->d_partitions[slot].p_size = part->pmPartBlkCnt; - lp->d_partitions[slot].p_offset = part->pmPyPartStart; - lp->d_partitions[slot].p_fstype = FS_BSDFFS; - -#if PRINT_DISKLABELS - printf("%c: Usr '%s' at %d size %d\n", slot + 'a', - part->pmPartName, - part->pmPyPartStart, - part->pmPartBlkCnt); -#endif - - part->pmPartType[0] = '\0'; -} - -void -setHfs(part, lp, slot) - struct partmapentry *part; - struct disklabel *lp; - int slot; -{ - lp->d_partitions[slot].p_size = part->pmPartBlkCnt; - lp->d_partitions[slot].p_offset = part->pmPyPartStart; - lp->d_partitions[slot].p_fstype = FS_HFS; - -#if PRINT_DISKLABELS - printf("%c: HFS_PART '%s' at %d size %d\n", slot + 'a', - part->pmPartName, - part->pmPyPartStart, - part->pmPartBlkCnt); -#endif - - part->pmPartType[0] = '\0'; -} - -void -setScratch(part, lp, slot) - struct partmapentry *part; - struct disklabel *lp; - int slot; -{ - lp->d_partitions[slot].p_size = part->pmPartBlkCnt; - lp->d_partitions[slot].p_offset = part->pmPyPartStart; - lp->d_partitions[slot].p_fstype = FS_OTHER; - -#if PRINT_DISKLABELS - printf("%c: Other (%s) '%s' at %d size %d\n", slot + 'a', - part->pmPartType, - part->pmPartName, - part->pmPyPartStart, - part->pmPartBlkCnt); -#endif - + lp->d_partitions[slot].p_fstype = fstype; part->pmPartType[0] = '\0'; } @@ -327,7 +230,7 @@ getNamedType(part, num_parts, lp, type, alt, maxslot) int *maxslot; { struct blockzeroblock *bzb; - int i = 0; + int i; for (i = 0; i < num_parts; i++) { if (whichType(&(part[i])) == type) { @@ -337,19 +240,21 @@ getNamedType(part, num_parts, lp, type, alt, maxslot) (&part[i].pmBootArgs); if (alt >= 0 && alt != bzb->bzbCluster) goto skip; - setRoot(&(part[i]), lp, 0); + setPart(&(part[i]), lp, FS_BSDFFS, 0); break; case UFS_PART: bzb = (struct blockzeroblock *) (&part[i].pmBootArgs); if (alt >= 0 && alt != bzb->bzbCluster) goto skip; - setUfs(&(part[i]), lp, 6); - if (*maxslot < 6) *maxslot = 6; + setPart(&(part[i]), lp, FS_BSDFFS, 6); + if (*maxslot < 6) + *maxslot = 6; break; case SWAP_PART: - setSwap(&(part[i]), lp, 1); - if (*maxslot < 1) *maxslot = 1; + setPart(&(part[i]), lp, FS_SWAP, 1); + if (*maxslot < 1) + *maxslot = 1; break; default: printf("disksubr.c: can't do type %d\n", type); @@ -381,36 +286,18 @@ skip: * disk. This whole algorithm should probably be changed in the future. */ char * -read_mac_label(dev, strat, lp, osdep) - dev_t dev; - void (*strat)(struct buf *); - struct disklabel *lp; - struct cpu_disklabel *osdep; +read_mac_label(char *dlbuf, struct disklabel *lp, struct cpu_disklabel *osdep) { - struct buf *bp; char *msg = NULL; - int i = 0, num_parts = 0, maxslot = 0; + int i, num_parts, maxslot = RAW_PART; struct partmapentry pmap[NUM_PARTS_PROBED]; - bp = geteblk((int)lp->d_secsize * NUM_PARTS_PROBED); - bp->b_dev = dev; - bp->b_blkno = 1; /* partition map starts at blk 1 */ - bp->b_bcount = lp->d_secsize * NUM_PARTS_PROBED; - bp->b_flags = B_BUSY | B_READ; - bp->b_cylin = 1 / lp->d_secpercyl; - (*strat)(bp); - if (biowait(bp)) { - msg = "I/O error reading partition map."; - goto done; - } - - lp->d_npartitions = 1; /* one for 'c' */ - fixPartTable(pmap, lp->d_secsize, bp->b_un.b_addr, &num_parts); + num_parts = fixPartTable(pmap, lp->d_secsize, dlbuf); if (getNamedType(pmap, num_parts, lp, ROOT_PART, 0, &maxslot)) getNamedType(pmap, num_parts, lp, ROOT_PART, -1, &maxslot); + getNamedType(pmap, num_parts, lp, SWAP_PART, -1, &maxslot); if (getNamedType(pmap, num_parts, lp, UFS_PART, 0, &maxslot)) getNamedType(pmap, num_parts, lp, UFS_PART, -1, &maxslot); - getNamedType(pmap, num_parts, lp, SWAP_PART, -1, &maxslot); for (i = 0; i < num_parts; i++) { int partType; int slot; @@ -429,30 +316,30 @@ read_mac_label(dev, strat, lp, osdep) * UFS_PART partition, live with it. */ case UFS_PART: - setUfs(&(pmap[i]), lp, slot); - if (slot > maxslot) maxslot = slot; + setPart(&(pmap[i]), lp, FS_BSDFFS, slot); + if (slot > maxslot) + maxslot = slot; break; case SWAP_PART: - setSwap(&(pmap[i]), lp, slot); - if (slot > maxslot) maxslot = slot; + setPart(&(pmap[i]), lp, FS_SWAP, slot); + if (slot > maxslot) + maxslot = slot; break; case HFS_PART: - setHfs(&(pmap[i]), lp, slot); - if (slot > maxslot) maxslot = slot; + setPart(&(pmap[i]), lp, FS_HFS, slot); + if (slot > maxslot) + maxslot = slot; break; case SCRATCH_PART: - setScratch(&(pmap[i]), lp, slot); - if (slot > maxslot) maxslot = slot; + setPart(&(pmap[i]), lp, FS_OTHER, slot); + if (slot > maxslot) + maxslot = slot; break; default: break; } } - lp->d_npartitions = maxslot+1; - -done: - bp->b_flags = B_INVAL | B_AGE | B_READ; - brelse(bp); + lp->d_npartitions = maxslot + 1; return msg; } @@ -479,7 +366,7 @@ readdisklabel(dev, strat, lp, osdep, spoofonly) struct buf *bp; char *msg = NULL; struct disklabel *dlp; - int i; + int i, size; /* minimal requirements for archetypal disk label */ if (lp->d_secsize == 0) @@ -489,9 +376,10 @@ readdisklabel(dev, strat, lp, osdep, spoofonly) if (lp->d_secpercyl == 0) lp->d_secpercyl = 1; lp->d_npartitions = RAW_PART + 1; - for (i = 0; i < RAW_PART; i++) { + for (i = 0; i < MAXPARTITIONS; i++) { lp->d_partitions[i].p_size = 0; lp->d_partitions[i].p_offset = 0; + lp->d_partitions[i].p_fstype = FS_UNUSED; } if (lp->d_partitions[RAW_PART].p_size == 0) lp->d_partitions[RAW_PART].p_size = lp->d_secperunit; @@ -501,10 +389,11 @@ readdisklabel(dev, strat, lp, osdep, spoofonly) if (spoofonly) return (NULL); - bp = geteblk((int)lp->d_secsize * MAXPARTITIONS); + size = roundup((NUM_PARTS_PROBED + 1) << DEV_BSHIFT, lp->d_secsize); + bp = geteblk(size); bp->b_dev = dev; bp->b_blkno = LABELSECTOR; - bp->b_bcount = lp->d_secsize; + bp->b_bcount = size; bp->b_flags = B_BUSY | B_READ; bp->b_cylin = LABELSECTOR / lp->d_secpercyl; (*strat)(bp); @@ -513,11 +402,11 @@ readdisklabel(dev, strat, lp, osdep, spoofonly) else { u_int16_t *sbSigp; - sbSigp = (u_int16_t *)bp->b_un.b_addr; + sbSigp = (u_int16_t *)bp->b_data; if (*sbSigp == 0x4552) { - msg = read_mac_label(dev, strat, lp, osdep); + msg = read_mac_label(bp->b_data, lp, osdep); } else { - dlp = (struct disklabel *)(bp->b_un.b_addr + + dlp = (struct disklabel *)(bp->b_data + LABELOFFSET); if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) { @@ -532,11 +421,11 @@ readdisklabel(dev, strat, lp, osdep, spoofonly) } #if defined(CD9660) - if (msg && iso_disklabelspoof(dev, strat, lp) == 0) + if (msg != NULL && iso_disklabelspoof(dev, strat, lp) == 0) msg = NULL; #endif - bp->b_flags = B_INVAL | B_AGE; + bp->b_flags |= B_INVAL; brelse(bp); return (msg); } @@ -633,19 +522,20 @@ writedisklabel(dev, strat, lp, osdep) /* * Check for MacOS fingerprints */ - sbSigp = (u_int16_t *)bp->b_un.b_addr; + sbSigp = (u_int16_t *)bp->b_data; if (*sbSigp == 0x4552) { error = ENODEV; goto done; } - dlp = (struct disklabel *)(bp->b_un.b_addr + LABELOFFSET); + dlp = (struct disklabel *)(bp->b_data + LABELOFFSET); bcopy(lp, dlp, sizeof(struct disklabel)); - bp->b_flags = B_WRITE; + bp->b_flags = B_BUSY | B_WRITE; (*strat)(bp); error = biowait(bp); done: + bp->b_flags |= B_INVAL; brelse(bp); return (error); } @@ -664,7 +554,8 @@ bounds_check_with_label(bp, lp, osdep, wlabel) { #define blockpersec(count, lp) ((count) * (((lp)->d_secsize) / DEV_BSIZE)) struct partition *p = lp->d_partitions + DISKPART(bp->b_dev); - int labelsect = blockpersec(lp->d_partitions[0].p_offset, lp); + int labelsect = blockpersec(lp->d_partitions[RAW_PART].p_offset, lp) + + LABELSECTOR; int sz = howmany(bp->b_bcount, DEV_BSIZE); /* avoid division by zero */ @@ -673,34 +564,13 @@ bounds_check_with_label(bp, lp, osdep, wlabel) goto bad; } - /* overwriting disk label ? */ - /* XXX should also protect bootstrap in first 8K */ - if (bp->b_blkno + blockpersec(p->p_offset, lp) <= LABELSECTOR + labelsect && -#if LABELSECTOR != 0 - bp->b_blkno + blockpersec(p->p_offset, lp) + sz > LABELSECTOR + labelsect && -#endif /* LABELSECTOR != 0 */ - (bp->b_flags & B_READ) == 0 && wlabel == 0) { - bp->b_error = EROFS; - goto bad; - } - -#if defined(DOSBBSECTOR) && defined(notyet) - /* overwriting master boot record? */ - if (bp->b_blkno + blockpersec(p->p_offset, lp) <= - DOSBBSECTOR + labelsect && - (bp->b_flags & B_READ) == 0 && wlabel == 0) { - bp->b_error = EROFS; - goto bad; - } -#endif - /* beyond partition? */ if (bp->b_blkno + sz > blockpersec(p->p_size, lp)) { sz = blockpersec(p->p_size, lp) - bp->b_blkno; if (sz == 0) { /* if exactly at end of disk, return an EOF */ bp->b_resid = bp->b_bcount; - return (0); + goto done; } if (sz <= 0) { bp->b_error = EINVAL; @@ -709,6 +579,18 @@ bounds_check_with_label(bp, lp, osdep, wlabel) /* or truncate if part of it fits */ bp->b_bcount = sz << DEV_BSHIFT; } + + /* overwriting disk label ? */ + /* XXX should also protect bootstrap in first 8K */ + if (bp->b_blkno + blockpersec(p->p_offset, lp) <= labelsect && +#if LABELSECTOR != 0 + bp->b_blkno + blockpersec(p->p_offset, lp) + sz > labelsect && +#endif /* LABELSECTOR != 0 */ + (bp->b_flags & B_READ) == 0 && wlabel == 0) { + bp->b_error = EROFS; + goto bad; + } + /* calculate cylinder for disksort to order transfers with */ bp->b_cylin = (bp->b_blkno + blockpersec(p->p_offset, lp)) / lp->d_secpercyl; @@ -716,7 +598,8 @@ bounds_check_with_label(bp, lp, osdep, wlabel) bad: bp->b_flags |= B_ERROR; - return (-1); +done: + return (0); } void |