mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-15 10:17:20 +00:00
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.
This commit is contained in:
parent
07d35ca333
commit
ae623967ec
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=6638
@ -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 @@ dsopen(dname, dev, mode, sspp, lp, strat, setgeom)
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user