summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2002-04-09 15:43:32 +0000
committerphk <phk@FreeBSD.org>2002-04-09 15:43:32 +0000
commita90e28ebbb699c856787836be56197be575fad47 (patch)
treeb29d97c613e2113a270ed79ca6d8e042d070ec82
parentc2f17d16c728a0248466b433fc6c8ad52023ac3d (diff)
downloadFreeBSD-src-a90e28ebbb699c856787836be56197be575fad47.zip
FreeBSD-src-a90e28ebbb699c856787836be56197be575fad47.tar.gz
Implement DIOCGFRONTSTUFF ioctl which reports how many bytes from the start
of the device magic stuff might occupy. Sponsored by: DARPA & NAI Labs.
-rw-r--r--sys/geom/geom_bsd.c21
-rw-r--r--sys/geom/geom_dev.c5
-rw-r--r--sys/geom/geom_disk.c2
-rw-r--r--sys/geom/geom_mbr.c43
-rw-r--r--sys/geom/geom_pc98.c17
-rw-r--r--sys/geom/geom_slice.c29
-rw-r--r--sys/geom/geom_slice.h2
-rw-r--r--sys/geom/geom_sunlabel.c11
-rw-r--r--sys/kern/subr_disk.c4
-rw-r--r--sys/sys/disk.h8
10 files changed, 99 insertions, 43 deletions
diff --git a/sys/geom/geom_bsd.c b/sys/geom/geom_bsd.c
index af19a4b..419998a 100644
--- a/sys/geom/geom_bsd.c
+++ b/sys/geom/geom_bsd.c
@@ -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;
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index a2deec1..3711fb0 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -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;
diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c
index 3b7b239..e6a2bcd 100644
--- a/sys/geom/geom_disk.c
+++ b/sys/geom/geom_disk.c
@@ -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;
diff --git a/sys/geom/geom_mbr.c b/sys/geom/geom_mbr.c
index 9520bde6..0dc6c32 100644
--- a/sys/geom/geom_mbr.c
+++ b/sys/geom/geom_mbr.c
@@ -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;
+ if (!error && sectorsize != 512)
break;
- buf = g_read_data(cp, 0, 512, &error);
+ 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)
diff --git a/sys/geom/geom_pc98.c b/sys/geom/geom_pc98.c
index ce5e181..a89bf36 100644
--- a/sys/geom/geom_pc98.c
+++ b/sys/geom/geom_pc98.c
@@ -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)
diff --git a/sys/geom/geom_slice.c b/sys/geom/geom_slice.c
index 1ac1d0a..21b514c 100644
--- a/sys/geom/geom_slice.c
+++ b/sys/geom/geom_slice.c
@@ -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);
diff --git a/sys/geom/geom_slice.h b/sys/geom/geom_slice.h
index 4d21533..acc20ee 100644
--- a/sys/geom/geom_slice.h
+++ b/sys/geom/geom_slice.h
@@ -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;
diff --git a/sys/geom/geom_sunlabel.c b/sys/geom/geom_sunlabel.c
index 78d9c87..3363f4e 100644
--- a/sys/geom/geom_sunlabel.c
+++ b/sys/geom/geom_sunlabel.c
@@ -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",
diff --git a/sys/kern/subr_disk.c b/sys/kern/subr_disk.c
index b1f3e6a..1982e7f 100644
--- a/sys/kern/subr_disk.c
+++ b/sys/kern/subr_disk.c
@@ -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);
diff --git a/sys/sys/disk.h b/sys/sys/disk.h
index a0fbb0d..ffbd786 100644
--- a/sys/sys/disk.h
+++ b/sys/sys/disk.h
@@ -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_ */
OpenPOWER on IntegriCloud