summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>1995-02-22 21:51:53 +0000
committerbde <bde@FreeBSD.org>1995-02-22 21:51:53 +0000
commitff8bdff80e2ef9a697f3c965fa8a263b02f56c95 (patch)
treef035b840486e92de4aed083f24ad0f9fe514a11a
parent693b12067de1bc84ab8f5dc29f2a4db461baee88 (diff)
downloadFreeBSD-src-ff8bdff80e2ef9a697f3c965fa8a263b02f56c95.zip
FreeBSD-src-ff8bdff80e2ef9a697f3c965fa8a263b02f56c95.tar.gz
Fix initialization of the copy of the label passed to setdisklabel().
Fix the sign of the adjustment after writing a label. Writing of labels should work now. Merge adjust_label() into fixlabel(). Detect more errors and don't write if there is an error. Adjust sectors/unit and total sectors to the numbers on the slice. Add a function dsname() to print slice device names consistently, and use it.
-rw-r--r--sys/kern/subr_diskslice.c235
1 files changed, 120 insertions, 115 deletions
diff --git a/sys/kern/subr_diskslice.c b/sys/kern/subr_diskslice.c
index 0914215..d41d35a 100644
--- a/sys/kern/subr_diskslice.c
+++ b/sys/kern/subr_diskslice.c
@@ -43,7 +43,7 @@
* from: wd.c,v 1.55 1994/10/22 01:57:12 phk Exp $
* from: @(#)ufs_disksubr.c 7.16 (Berkeley) 5/4/91
* from: ufs_disksubr.c,v 1.8 1994/06/07 01:21:39 phk Exp $
- * $Id: subr_diskslice.c,v 1.5 1995/02/18 22:10:44 bde Exp $
+ * $Id: subr_diskslice.c,v 1.6 1995/02/21 08:38:24 bde Exp $
*/
#include <sys/param.h>
@@ -65,14 +65,11 @@
typedef u_char bool_t;
-static void adjust_label __P((struct disklabel *lp, u_long offset));
static void dsiodone __P((struct buf *bp));
-static char *fixlabel __P((char *dname, int unit, int slice,
- struct diskslice *sp, struct disklabel *lp));
-static void partition_info __P((char *dname, int unit, int slice,
- int part, struct partition *pp));
-static void slice_info __P((char *dname, int unit, int slice,
- struct diskslice *sp));
+static char *fixlabel __P((char *sname, struct diskslice *sp,
+ struct disklabel *lp, int writeflag));
+static void partition_info __P((char *sname, int part, struct partition *pp));
+static void slice_info __P((char *sname, struct diskslice *sp));
static void set_ds_bad __P((struct diskslices *ssp, int slice,
struct dkbad_intern *btp));
static void set_ds_label __P((struct diskslices *ssp, int slice,
@@ -80,45 +77,6 @@ static void set_ds_label __P((struct diskslices *ssp, int slice,
static void set_ds_wlabel __P((struct diskslices *ssp, int slice,
int wlabel));
-static void
-adjust_label(lp, offset)
- struct disklabel *lp;
- u_long offset;
-{
- u_long end;
- int part;
- struct partition *pp;
- u_long start;
-
- if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC
- || dkcksum(lp) != 0) {
- printf("adjust_label failed: bad magic or checksum\n");
- return;
- }
- pp = &lp->d_partitions[RAW_PART];
- start = pp->p_offset;
- end = start + pp->p_size;
- if (start > end || start + offset > end + offset) {
- printf(
- "adjust_label failed: invalid raw partition or offset\n");
- return;
- }
- pp -= RAW_PART;
- for (part = 0; part < lp->d_npartitions; part++, pp++) {
- if (pp->p_offset != 0 || pp->p_size != 0) {
- /* XXX silently discard junk. */
- if (pp->p_offset < start
- || pp->p_offset + pp->p_size > end
- || pp->p_offset + pp->p_size < pp->p_offset)
- bzero(pp, sizeof *pp);
- else
- pp->p_offset += offset;
- }
- }
- lp->d_checksum = 0;
- lp->d_checksum = dkcksum(lp);
-}
-
/*
* Determine the size of the transfer, and make sure it is
* within the boundaries of the partition. Adjust transfer
@@ -139,6 +97,7 @@ dscheck(bp, ssp)
daddr_t labelsect;
struct disklabel *lp;
u_long maxsz;
+ char *msg;
struct partition *pp;
struct diskslice *sp;
long sz;
@@ -227,7 +186,7 @@ if (labelsect != 0) Debugger("labelsect != 0 in dscheck()");
ic->ic_prev_iodone_chain = bp->b_iodone_chain;
ic->ic_args[0].ia_long = (LABELSECTOR + labelsect - blkno)
<< DEV_BSHIFT;
- ic->ic_args[1].ia_long = sp->ds_offset;
+ ic->ic_args[1].ia_ptr = sp;
bp->b_flags |= B_CALL;
bp->b_iodone = dsiodone;
bp->b_iodone_chain = ic;
@@ -241,9 +200,15 @@ if (labelsect != 0) Debugger("labelsect != 0 in dscheck()");
* XXX probably need to copy the data to avoid even
* temporarily corrupting the in-core copy.
*/
- adjust_label((struct disklabel *)
- (bp->b_data + ic->ic_args[0].ia_long),
- sp->ds_offset);
+ msg = fixlabel((char *)NULL, sp,
+ (struct disklabel *)
+ (bp->b_data + ic->ic_args[0].ia_long),
+ TRUE);
+ if (msg != NULL) {
+ printf("%s\n", msg);
+ bp->b_error = EROFS;
+ goto bad;
+ }
}
}
return (1);
@@ -363,6 +328,10 @@ dsioctl(dev, cmd, data, flags, ssp, strat, setgeom)
if (!(flags & FWRITE))
return (EBADF);
lp = malloc(sizeof *lp, M_DEVBUF, M_WAITOK);
+ if (sp->ds_label == NULL)
+ bzero(lp, sizeof *lp);
+ else
+ bcopy(sp->ds_label, lp, sizeof *lp);
error = setdisklabel(lp, (struct disklabel *)data,
sp->ds_label != NULL
? sp->ds_openmask : (u_long)0);
@@ -393,17 +362,8 @@ dsioctl(dev, cmd, data, flags, ssp, strat, setgeom)
*/
old_wlabel = sp->ds_wlabel;
set_ds_wlabel(ssp, slice, TRUE);
- /*
- * XXX convert on-disk label offsets to absolute sectors for
- * backwards compatibility.
- */
- lp = malloc(sizeof *lp, M_DEVBUF, M_WAITOK);
- *lp = *sp->ds_label;
- adjust_label(lp, sp->ds_offset);
-
- error = correct_writedisklabel(dev, strat, lp);
- /* XXX should restore old label if writedisklabel() failed. */
- free(lp, M_DEVBUF);
+ error = correct_writedisklabel(dev, strat, sp->ds_label);
+ /* XXX should invalidate in-core label if write failed. */
set_ds_wlabel(ssp, slice, old_wlabel);
return (error);
@@ -425,19 +385,23 @@ dsiodone(bp)
struct buf *bp;
{
struct iodone_chain *ic;
- struct disklabel *lp;
+ char *msg;
ic = bp->b_iodone_chain;
bp->b_flags = (ic->ic_prev_flags & B_CALL)
| (bp->b_flags & ~(B_CALL | B_DONE));
bp->b_iodone = ic->ic_prev_iodone;
bp->b_iodone_chain = ic->ic_prev_iodone_chain;
+ if (!(bp->b_flags & B_READ)
+ || (!(bp->b_flags & B_ERROR) && bp->b_error == 0)) {
+ msg = fixlabel((char *)NULL, ic->ic_args[1].ia_ptr,
+ (struct disklabel *)
+ (bp->b_data + ic->ic_args[0].ia_long),
+ FALSE);
+ if (msg != NULL)
+ printf("%s\n", msg);
+ }
free(ic, M_DEVBUF);
- lp = (struct disklabel *)(bp->b_data + ic->ic_args[0].ia_long);
- if (!(bp->b_flags & B_READ))
- adjust_label(lp, ic->ic_args[1].ia_long);
- else if (!(bp->b_flags & B_ERROR) && bp->b_error == 0)
- adjust_label(lp, -lp->d_partitions[RAW_PART].p_offset);
biodone(bp);
}
@@ -446,7 +410,6 @@ dsisopen(ssp)
struct diskslices *ssp;
{
int slice;
- struct diskslice *sp;
if (ssp == NULL)
return (0);
@@ -456,6 +419,29 @@ dsisopen(ssp)
return (0);
}
+char *
+dsname(dname, unit, slice, part, partname)
+ char *dname;
+ int unit;
+ int slice;
+ int part;
+ char *partname;
+{
+ static char name[32];
+
+ if (strlen(dname) > 16)
+ dname = "nametoolong";
+ sprintf(name, "%s%d", dname, unit);
+ partname[0] = '\0';
+ if (slice != WHOLE_DISK_SLICE || part != RAW_PART) {
+ partname[0] = 'a' + part;
+ partname[1] = '\0';
+ if (slice != COMPATIBILITY_SLICE)
+ sprintf(name + strlen(name), "s%d", slice - 1);
+ }
+ return (name);
+}
+
/*
* This should only be called when the unit is inactive and the strategy
* routine should not allow it to become active unless we call it. Our
@@ -476,7 +462,9 @@ dsopen(dname, dev, mode, sspp, lp, strat, setgeom)
u_char mask;
bool_t need_init;
int part;
+ char partname[2];
int slice;
+ char *sname;
struct diskslice *sp;
struct diskslices *ssp;
int unit;
@@ -534,12 +522,13 @@ dsopen(dname, dev, mode, sspp, lp, strat, setgeom)
if (msg == NULL && setgeom != NULL && setgeom(lp) != 0)
msg = "setgeom failed";
#endif
+ sname = dsname(dname, unit, slice, RAW_PART, partname);
if (msg == NULL)
- msg = fixlabel(dname, unit, slice, sp, lp);
+ msg = fixlabel(sname, sp, lp, FALSE);
if (msg != NULL) {
free(lp, M_DEVBUF);
- log(LOG_WARNING, "%s%ds%d: cannot find label (%s)\n",
- dname, unit, slice, msg);
+ log(LOG_WARNING, "%s: cannot find label (%s)\n",
+ sname, msg);
if (part == RAW_PART)
goto out;
return (EINVAL); /* XXX needs translation */
@@ -552,8 +541,8 @@ dsopen(dname, dev, mode, sspp, lp, strat, setgeom)
msg = readbad144(dev, strat, lp, btp);
if (msg != NULL) {
log(LOG_WARNING,
- "%s%ds%d: cannot find bad sector table (%s)\n",
- dname, unit, slice, msg);
+ "%s: cannot find bad sector table (%s)\n",
+ sname, msg);
free(btp, M_DEVBUF);
free(lp, M_DEVBUF);
if (part == RAW_PART)
@@ -589,41 +578,61 @@ out:
}
static char *
-fixlabel(dname, unit, slice, sp, lp)
- char *dname;
- int unit;
- int slice;
+fixlabel(sname, sp, lp, writeflag)
+ char *sname;
struct diskslice *sp;
struct disklabel *lp;
+ int writeflag;
{
u_long end;
+ u_long offset;
int part;
struct partition *pp;
u_long start;
bool_t warned;
+ /* These errors "can't happen" so don't bother reporting details. */
+ if (lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC)
+ return ("fixlabel: invalid magic");
+ if (dkcksum(lp) != 0)
+ return ("fixlabel: invalid checksum");
+
pp = &lp->d_partitions[RAW_PART];
- if (pp->p_offset != sp->ds_offset) {
- printf(
-"%s%ds%d: rejecting BSD label: raw partition start != slice start\n",
- dname, unit, slice);
- slice_info(dname, unit, slice, sp);
- partition_info(dname, unit, slice, RAW_PART, pp);
- return ("invalid partition table");
+ if (writeflag) {
+ start = 0;
+ offset = sp->ds_offset;
+ } else {
+ start = sp->ds_offset;
+ offset = -sp->ds_offset;
+ }
+ if (pp->p_offset != start) {
+ if (sname != NULL) {
+ printf(
+"%s: rejecting BSD label: raw partition offset != slice offset\n",
+ sname);
+ slice_info(sname, sp);
+ partition_info(sname, RAW_PART, pp);
+ }
+ return ("fixlabel: raw partition offset != slice offset");
}
if (pp->p_size != sp->ds_size) {
- printf("%s%ds%d: raw partition size != slice size\n",
- dname, unit, slice);
- slice_info(dname, unit, slice, sp);
- partition_info(dname, unit, slice, RAW_PART, pp);
+ if (sname != NULL) {
+ printf("%s: raw partition size != slice size\n", sname);
+ slice_info(sname, sp);
+ partition_info(sname, RAW_PART, pp);
+ }
if (pp->p_size > sp->ds_size) {
- printf("%s%ds%d: truncating raw partition\n",
- dname, unit, slice);
+ if (sname == NULL)
+ return ("fixlabel: raw partition size > slice size");
+ printf("%s: truncating raw partition\n", sname);
pp->p_size = sp->ds_size;
}
}
- start = sp->ds_offset;
end = start + sp->ds_size;
+ if (start > end)
+ return ("fixlabel: slice wraps");
+ if (lp->d_secpercyl <= 0)
+ return ("fixlabel: d_secpercyl <= 0");
pp -= RAW_PART;
warned = FALSE;
for (part = 0; part < lp->d_npartitions; part++, pp++) {
@@ -631,49 +640,45 @@ fixlabel(dname, unit, slice, sp, lp)
if (pp->p_offset < start
|| pp->p_offset + pp->p_size > end
|| pp->p_offset + pp->p_size < pp->p_offset) {
- printf(
-"%s%ds%d: rejecting partition in BSD label: it isn't entirely within the slice\n",
- dname, unit, slice);
- if (!warned) {
- slice_info(dname, unit, slice, sp);
- warned = TRUE;
+ if (sname != NULL) {
+ printf(
+"%s: rejecting partition in BSD label: it isn't entirely within the slice\n",
+ sname);
+ if (!warned) {
+ slice_info(sname, sp);
+ warned = TRUE;
+ }
+ partition_info(sname, part, pp);
}
- partition_info(dname, unit, slice, part, pp);
+ /* XXX else silently discard junk. */
bzero(pp, sizeof *pp);
} else
- pp->p_offset -= sp->ds_offset;
+ pp->p_offset += offset;
}
}
+ lp->d_ncylinders = sp->ds_size / lp->d_secpercyl;
+ lp->d_secperunit = sp->ds_size;
lp->d_checksum = 0;
lp->d_checksum = dkcksum(lp);
-
- /* XXX TODO: fix general params in *lp? */
-
return (NULL);
}
static void
-partition_info(dname, unit, slice, part, pp)
- char *dname;
- int unit;
- int slice;
+partition_info(sname, part, pp)
+ char *sname;
int part;
struct partition *pp;
{
- printf("%s%ds%d%c: start %lu, end %lu, size %lu\n",
- dname, unit, slice, 'a' + part,
+ printf("%s%c: start %lu, end %lu, size %lu\n", sname, 'a' + part,
pp->p_offset, pp->p_offset + pp->p_size - 1, pp->p_size);
}
static void
-slice_info(dname, unit, slice, sp)
- char *dname;
- int unit;
- int slice;
+slice_info(sname, sp)
+ char *sname;
struct diskslice *sp;
{
- printf("%s%ds%d: start %lu, end %lu, size %lu\n",
- dname, unit, slice,
+ printf("%s: start %lu, end %lu, size %lu\n", sname,
sp->ds_offset, sp->ds_offset + sp->ds_size - 1, sp->ds_size);
}
OpenPOWER on IntegriCloud