Implement DIOCGFRONTSTUFF ioctl which reports how many bytes from the start

of the device magic stuff might occupy.

Sponsored by: DARPA & NAI Labs.
This commit is contained in:
Poul-Henning Kamp 2002-04-09 15:43:32 +00:00
parent c7b1a1d1c3
commit 1bdb20a68e
10 changed files with 99 additions and 43 deletions

View File

@ -226,7 +226,7 @@ g_bsd_lesum(struct disklabel *dl, u_char *p)
}
static int
g_bsd_i386(struct g_consumer *cp, int secsize, struct disklabel *dl)
g_bsd_i386(struct g_slicer *gsp, struct g_consumer *cp, int secsize, struct disklabel *dl)
{
int error;
u_char *buf;
@ -242,11 +242,12 @@ g_bsd_i386(struct g_consumer *cp, int secsize, struct disklabel *dl)
else
error = ENOENT;
g_free(buf);
gsp->frontstuff = 16 * secsize;
return(error);
}
static int
g_bsd_alpha(struct g_consumer *cp, int secsize, struct disklabel *dl)
g_bsd_alpha(struct g_slicer *gsp, struct g_consumer *cp, int secsize, struct disklabel *dl)
{
int error;
u_char *buf;
@ -262,6 +263,7 @@ g_bsd_alpha(struct g_consumer *cp, int secsize, struct disklabel *dl)
else
error = ENOENT;
g_free(buf);
gsp->frontstuff = 16 * secsize;
return(error);
}
@ -320,6 +322,7 @@ g_bsd_taste(struct g_class *mp, struct g_provider *pp, int flags)
u_int fwsectors, fwheads;
off_t mediasize;
struct partition *ppp, *ppr;
struct g_slicer *gsp;
g_trace(G_T_TOPOLOGY, "bsd_taste(%s,%s)", mp->name, pp->name);
g_topology_assert();
@ -329,31 +332,29 @@ g_bsd_taste(struct g_class *mp, struct g_provider *pp, int flags)
gp = g_slice_new(mp, 8, pp, &cp, &ms, sizeof *ms, g_bsd_start);
if (gp == NULL)
return (NULL);
gsp = gp->softc;
g_topology_unlock();
gp->dumpconf = g_bsd_dumpconf;
npart = 0;
while (1) { /* a trick to allow us to use break */
j = sizeof i;
error = g_io_getattr("MBR::type", cp, &j, &i);
error = g_getattr("MBR::type", cp, &i);
if (!error && i != 165 && flags == G_TF_NORMAL)
break;
j = sizeof secsize;
error = g_io_getattr("GEOM::sectorsize", cp, &j, &secsize);
error = g_getattr("GEOM::sectorsize", cp, &secsize);
if (error) {
secsize = 512;
printf("g_bsd_taste: error %d Sectors are %d bytes\n",
error, secsize);
}
j = sizeof mediasize;
error = g_io_getattr("GEOM::mediasize", cp, &j, &mediasize);
error = g_getattr("GEOM::mediasize", cp, &mediasize);
if (error) {
mediasize = 0;
printf("g_error %d Mediasize is %lld bytes\n",
error, (long long)mediasize);
}
error = g_bsd_i386(cp, secsize, &ms->ondisk);
error = g_bsd_i386(gsp, cp, secsize, &ms->ondisk);
if (error)
error = g_bsd_alpha(cp, secsize, &ms->ondisk);
error = g_bsd_alpha(gsp, cp, secsize, &ms->ondisk);
if (error)
break;
dl = &ms->ondisk;

View File

@ -155,7 +155,7 @@ g_dev_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
error = g_io_getattr("GEOM::mediasize", cp, &j, &mediasize);
if (error) {
mediasize = 0;
printf("g_dev_taste: %d Mediasize is %lld bytes\n",
printf("g_dev_taste: error %d Mediasize is %lld bytes\n",
error, (long long)mediasize);
}
g_topology_lock();
@ -262,6 +262,9 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
case DIOCGFWHEADS:
error = g_io_getattr("GEOM::fwheads", cp, &i, data);
break;
case DIOCGFRONTSTUFF:
error = g_io_getattr("GEOM::frontstuff", cp, &i, data);
break;
default:
gio = g_malloc(sizeof *gio, M_WAITOK);
gio->cmd = cmd;

View File

@ -146,6 +146,8 @@ g_disk_start(struct bio *bp)
else if (g_haveattr_off_t(bp, "GEOM::mediasize",
dp->d_label.d_secsize * (off_t)dp->d_label.d_secperunit))
break;
else if (g_haveattr_off_t(bp, "GEOM::frontstuff", 0))
break;
else if (!strcmp(bp->bio_attribute, "GEOM::ioctl") &&
bp->bio_length == sizeof *gio) {
gio = (struct g_ioctl *)bp->bio_data;

View File

@ -169,33 +169,35 @@ g_mbr_taste(struct g_class *mp, struct g_provider *pp, int insist)
struct g_geom *gp;
struct g_consumer *cp;
struct g_provider *pp2;
int error, i, j, npart;
int error, i, npart;
struct dos_partition dp[NDOSPART];
struct g_mbr_softc *ms;
struct g_slicer *gsp;
u_int fwsectors, sectorsize;
u_char *buf;
if (sizeof(struct dos_partition) != 16) {
printf("WARNING: struct dos_partition compiles to %d bytes, should be 16.\n",
(int)sizeof(struct dos_partition));
return (NULL);
}
g_trace(G_T_TOPOLOGY, "mbr_taste(%s,%s)", mp->name, pp->name);
g_topology_assert();
gp = g_slice_new(mp, NDOSPART, pp, &cp, &ms, sizeof *ms, g_mbr_start);
if (gp == NULL)
return (NULL);
gsp = gp->softc;
g_topology_unlock();
gp->dumpconf = g_mbr_dumpconf;
npart = 0;
while (1) { /* a trick to allow us to use break */
if (gp->rank != 2 && insist == 0)
break;
j = sizeof i;
/* For now we only support 512 bytes sectors */
error = g_io_getattr("GEOM::sectorsize", cp, &j, &i);
if (!error && i != 512)
error = g_getattr("GEOM::fwsectors", cp, &fwsectors);
if (error)
fwsectors = 17;
error = g_getattr("GEOM::sectorsize", cp, &sectorsize);
if (error)
break;
buf = g_read_data(cp, 0, 512, &error);
if (!error && sectorsize != 512)
break;
gsp->frontstuff = sectorsize * fwsectors;
buf = g_read_data(cp, 0, sectorsize, &error);
if (buf == NULL || error != 0)
break;
if (buf[0x1fe] != 0x55 && buf[0x1ff] != 0xaa) {
@ -307,11 +309,13 @@ g_mbrext_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
struct g_geom *gp;
struct g_consumer *cp;
struct g_provider *pp2;
int error, i, j, slice;
int error, i, slice;
struct g_mbrext_softc *ms;
off_t off;
u_char *buf;
struct dos_partition dp[4];
u_int fwsectors, sectorsize;
struct g_slicer *gsp;
g_trace(G_T_TOPOLOGY, "g_mbrext_taste(%s,%s)", mp->name, pp->name);
g_topology_assert();
@ -320,17 +324,26 @@ g_mbrext_taste(struct g_class *mp, struct g_provider *pp, int insist __unused)
gp = g_slice_new(mp, NDOSEXTPART, pp, &cp, &ms, sizeof *ms, g_mbrext_start);
if (gp == NULL)
return (NULL);
gsp = gp->softc;
g_topology_unlock();
gp->dumpconf = g_mbrext_dumpconf;
off = 0;
slice = 0;
while (1) { /* a trick to allow us to use break */
j = sizeof i;
error = g_io_getattr("MBR::type", cp, &j, &i);
error = g_getattr("MBR::type", cp, &i);
if (error || i != DOSPTYP_EXT)
break;
error = g_getattr("GEOM::fwsectors", cp, &fwsectors);
if (error)
fwsectors = 17;
error = g_getattr("GEOM::sectorsize", cp, &sectorsize);
if (error)
break;
if (!error && sectorsize != 512)
break;
gsp->frontstuff = sectorsize * fwsectors;
for (;;) {
buf = g_read_data(cp, off, DEV_BSIZE, &error);
buf = g_read_data(cp, off, sectorsize, &error);
if (buf == NULL || error != 0)
break;
if (buf[0x1fe] != 0x55 && buf[0x1ff] != 0xaa)

View File

@ -89,12 +89,13 @@ g_pc98_taste(struct g_class *mp, struct g_provider *pp, int flags)
struct g_geom *gp;
struct g_consumer *cp;
struct g_provider *pp2;
int error, i, j, npart;
int error, i, npart;
u_char *buf;
struct g_pc98_softc *ms;
u_int sectorsize, u, v;
u_int fwsect, fwhead;
off_t mediasize, start, length;
struct g_slicer *gsp;
g_trace(G_T_TOPOLOGY, "g_pc98_taste(%s,%s)", mp->name, pp->name);
g_topology_assert();
@ -104,40 +105,38 @@ g_pc98_taste(struct g_class *mp, struct g_provider *pp, int flags)
gp = g_slice_new(mp, 8, pp, &cp, &ms, sizeof *ms, g_pc98_start);
if (gp == NULL)
return (NULL);
gsp = gp->softc;
g_topology_unlock();
gp->dumpconf = g_pc98_dumpconf;
npart = 0;
while (1) { /* a trick to allow us to use break */
if (gp->rank != 2 && flags == G_TF_NORMAL)
break;
j = sizeof sectorsize;
error = g_io_getattr("GEOM::sectorsize", cp, &j, &sectorsize);
error = g_getattr("GEOM::sectorsize", cp, &sectorsize);
if (error) {
sectorsize = 512;
printf("g_pc98_taste: error %d Sectors are %d bytes\n",
error, sectorsize);
}
j = sizeof mediasize;
error = g_io_getattr("GEOM::mediasize", cp, &j, &mediasize);
error = g_getattr("GEOM::mediasize", cp, &mediasize);
if (error) {
mediasize = 0;
printf("g_error %d Mediasize is %lld bytes\n",
error, (long long)mediasize);
}
j = sizeof fwsect;
error = g_io_getattr("GEOM::fwsectors", cp, &j, &fwsect);
error = g_getattr("GEOM::fwsectors", cp, &fwsect);
if (error || fwsect == 0) {
fwsect = 17;
printf("g_pc98_taste: error %d guessing %d sectors\n",
error, fwsect);
}
j = sizeof fwhead;
error = g_io_getattr("GEOM::fwheads", cp, &j, &fwhead);
error = g_getattr("GEOM::fwheads", cp, &fwhead);
if (error || fwhead == 0) {
fwhead = 8;
printf("g_pc98_taste: error %d guessing %d heads\n",
error, fwhead);
}
gsp->frontstuff = fwsect * sectorsize;
buf = g_read_data(cp, 0,
sectorsize < 1024 ? 1024 : sectorsize, &error);
if (buf == NULL || error != 0)

View File

@ -129,17 +129,18 @@ g_slice_start(struct bio *bp)
struct g_slicer *gsp;
struct g_slice *gsl;
int index;
off_t t;
pp = bp->bio_to;
gp = pp->geom;
gsp = gp->softc;
cp = LIST_FIRST(&gp->consumer);
index = pp->index;
gsl = &gsp->slices[index];
switch(bp->bio_cmd) {
case BIO_READ:
case BIO_WRITE:
case BIO_DELETE:
gsl = &gsp->slices[index];
if (bp->bio_offset > gsl->length) {
bp->bio_error = EINVAL; /* XXX: EWHAT ? */
g_io_deliver(bp);
@ -154,11 +155,24 @@ g_slice_start(struct bio *bp)
return;
case BIO_GETATTR:
case BIO_SETATTR:
/* Give the real method a chance to override */
if (gsp->start(bp))
return;
if (g_haveattr_off_t(bp, "GEOM::mediasize",
gsp->slices[index].length))
return;
if (gsp->start(bp))
if (!strcmp("GEOM::frontstuff", bp->bio_attribute)) {
t = gsp->cfrontstuff;
if (gsp->frontstuff > t)
t = gsp->frontstuff;
t -= gsl->offset;
if (t < 0)
t = 0;
if (t > gsl->length)
t = gsl->length;
g_haveattr_off_t(bp, "GEOM::frontstuff", t);
return;
}
bp2 = g_clone_bio(bp);
bp2->bio_done = g_std_done;
g_io_request(bp2, cp);
@ -178,6 +192,10 @@ g_slice_dumpconf(struct sbuf *sb, char *indent, struct g_geom *gp, struct g_cons
gsp = gp->softc;
mp = gsp->softc;
if (gp != NULL) {
sbuf_printf(sb, "%s<frontstuff>%llu</frontstuff>\n",
indent, (unsigned long long)gsp->frontstuff);
}
if (pp != NULL) {
sbuf_printf(sb, "%s<index>%u</index>\n", indent, pp->index);
sbuf_printf(sb, "%s<length>%llu</length>\n",
@ -224,7 +242,7 @@ g_slice_new(struct g_class *mp, int slices, struct g_provider *pp, struct g_cons
struct g_slicer *gsp;
struct g_consumer *cp;
void **vp;
int error;
int error, i;
g_topology_assert();
vp = (void **)extrap;
@ -248,6 +266,11 @@ g_slice_new(struct g_class *mp, int slices, struct g_provider *pp, struct g_cons
g_destroy_geom(gp);
return (NULL);
}
/* Find out if there are any magic bytes on the consumer */
i = sizeof gsp->cfrontstuff;
error = g_io_getattr("GEOM::frontstuff", cp, &i, &gsp->cfrontstuff);
if (error)
gsp->cfrontstuff = 0;
*vp = gsp->softc;
*cpp = cp;
return (gp);

View File

@ -45,6 +45,8 @@ typedef int g_slice_start_t (struct bio *bp);
struct g_slicer {
int nslice;
off_t cfrontstuff;
off_t frontstuff;
struct g_slice *slices;
void *softc;
g_slice_start_t *start;

View File

@ -89,11 +89,12 @@ g_sunlabel_taste(struct g_class *mp, struct g_provider *pp, int flags)
struct g_geom *gp;
struct g_consumer *cp;
struct g_provider *pp2;
int error, i, j, npart;
int error, i, npart;
u_char *buf;
struct g_sunlabel_softc *ms;
u_int sectorsize, u, v, csize;
off_t mediasize;
struct g_slicer *gsp;
g_trace(G_T_TOPOLOGY, "g_sunlabel_taste(%s,%s)", mp->name, pp->name);
g_topology_assert();
@ -103,21 +104,21 @@ g_sunlabel_taste(struct g_class *mp, struct g_provider *pp, int flags)
gp = g_slice_new(mp, 8, pp, &cp, &ms, sizeof *ms, g_sunlabel_start);
if (gp == NULL)
return (NULL);
gsp = gp->softc;
g_topology_unlock();
gp->dumpconf = g_sunlabel_dumpconf;
npart = 0;
while (1) { /* a trick to allow us to use break */
if (gp->rank != 2 && flags == G_TF_NORMAL)
break;
j = sizeof sectorsize;
error = g_io_getattr("GEOM::sectorsize", cp, &j, &sectorsize);
error = g_getattr("GEOM::sectorsize", cp, &sectorsize);
if (error) {
sectorsize = 512;
printf("g_sunlabel_taste: error %d Sectors are %d bytes\n",
error, sectorsize);
}
j = sizeof mediasize;
error = g_io_getattr("GEOM::mediasize", cp, &j, &mediasize);
gsp->frontstuff = 16 * sectorsize;
error = g_getattr("GEOM::mediasize", cp, &mediasize);
if (error) {
mediasize = 0;
printf("g_error %d Mediasize is %lld bytes\n",

View File

@ -394,6 +394,10 @@ diskioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
u = *(u_int *)data;
return (diskdumpconf(u, dev, dp));
}
if (cmd == DIOCGFRONTSTUFF) {
*(off_t *)data = 8192; /* XXX: crude but enough) */
return (0);
}
error = dsioctl(dev, cmd, data, fflag, &dp->d_slice);
if (error == ENOIOCTL)
error = dp->d_devsw->d_ioctl(dev, cmd, data, fflag, td);

View File

@ -80,4 +80,12 @@ void disk_invalidate(struct disk *disk);
* core dumps.
*/
#define DIOCGFRONTSTUFF _IOR('d', 134, off_t)
/*-
* Many disk formats have some amount of space reserved at the
* start of the disk to hold bootblocks, various disklabels and
* similar stuff. This ioctl returns the number of such bytes
* which may apply to the device.
*/
#endif /* _SYS_DISK_H_ */