From a90e28ebbb699c856787836be56197be575fad47 Mon Sep 17 00:00:00 2001 From: phk Date: Tue, 9 Apr 2002 15:43:32 +0000 Subject: Implement DIOCGFRONTSTUFF ioctl which reports how many bytes from the start of the device magic stuff might occupy. Sponsored by: DARPA & NAI Labs. --- sys/geom/geom_bsd.c | 21 +++++++++++---------- sys/geom/geom_dev.c | 5 ++++- sys/geom/geom_disk.c | 2 ++ sys/geom/geom_mbr.c | 43 ++++++++++++++++++++++++++++--------------- sys/geom/geom_pc98.c | 17 ++++++++--------- sys/geom/geom_slice.c | 29 ++++++++++++++++++++++++++--- sys/geom/geom_slice.h | 2 ++ sys/geom/geom_sunlabel.c | 11 ++++++----- sys/kern/subr_disk.c | 4 ++++ sys/sys/disk.h | 8 ++++++++ 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, §orsize); + 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, §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) 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, §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) 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%llu\n", + indent, (unsigned long long)gsp->frontstuff); + } if (pp != NULL) { sbuf_printf(sb, "%s%u\n", indent, pp->index); sbuf_printf(sb, "%s%llu\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, §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", 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_ */ -- cgit v1.1