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:
parent
c7b1a1d1c3
commit
1bdb20a68e
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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, §orsize);
|
||||
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, §orsize);
|
||||
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)
|
||||
|
@ -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, §orsize);
|
||||
error = g_getattr("GEOM::sectorsize", cp, §orsize);
|
||||
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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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, §orsize);
|
||||
error = g_getattr("GEOM::sectorsize", cp, §orsize);
|
||||
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",
|
||||
|
@ -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);
|
||||
|
@ -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_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user