diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/geom/geom.h | 8 | ||||
-rw-r--r-- | sys/geom/geom_bsd.c | 24 | ||||
-rw-r--r-- | sys/geom/geom_dev.c | 60 | ||||
-rw-r--r-- | sys/geom/geom_disk.c | 42 |
4 files changed, 84 insertions, 50 deletions
diff --git a/sys/geom/geom.h b/sys/geom/geom.h index 0a3f4807..1249776 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -247,6 +247,12 @@ void * g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error /* geom_kern.c / geom_kernsim.c */ void g_init(void); +struct g_ioctl { + u_long cmd; + void *data; + int fflag; + struct thread *td; +}; #ifdef _KERNEL @@ -272,7 +278,7 @@ g_free(void *ptr) } extern struct sx topology_lock; -#define g_topology_lock() sx_xlock(&topology_lock) +#define g_topology_lock() do { mtx_assert(&Giant, MA_NOTOWNED); sx_xlock(&topology_lock); } while (0) #define g_topology_unlock() sx_xunlock(&topology_lock) #define g_topology_assert() sx_assert(&topology_lock, SX_XLOCKED) diff --git a/sys/geom/geom_bsd.c b/sys/geom/geom_bsd.c index 47e601d..2688be1 100644 --- a/sys/geom/geom_bsd.c +++ b/sys/geom/geom_bsd.c @@ -89,20 +89,42 @@ g_bsd_start(struct bio *bp) struct g_bsd_softc *ms; struct g_slicer *gsp; struct partinfo pi; + struct g_ioctl *gio; gp = bp->bio_to->geom; gsp = gp->softc; ms = gsp->softc; +#if 0 if (g_haveattr(bp, "IOCTL::DIOCGDINFO", &ms->inram, sizeof ms->inram)) return (1); - if (!strcmp(bp->bio_attribute, "IOCTL::DIOCGPART")) { + else if (!strcmp(bp->bio_attribute, "IOCTL::DIOCGPART")) { pi.disklab = &ms->inram; pi.part = &ms->inram.d_partitions[bp->bio_to->index]; if (g_haveattr(bp, "IOCTL::DIOCGPART", &pi, sizeof pi)) return (1); } +#endif + if (strcmp(bp->bio_attribute, "GEOM::ioctl")) + return(0); + else if (bp->bio_length != sizeof *gio) + return(0); + gio = (struct g_ioctl *)bp->bio_data; + if (gio->cmd == DIOCGDINFO) { + bcopy(&ms->inram, gio->data, sizeof ms->inram); + bp->bio_error = 0; + g_io_deliver(bp); + return (1); + } + if (gio->cmd == DIOCGPART) { + pi.disklab = &ms->inram; + pi.part = &ms->inram.d_partitions[bp->bio_to->index]; + bcopy(&pi, gio->data, sizeof pi); + bp->bio_error = 0; + g_io_deliver(bp); + return (1); + } return (0); } diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c index 16f4ad5..1a94f18 100644 --- a/sys/geom/geom_dev.c +++ b/sys/geom/geom_dev.c @@ -35,7 +35,6 @@ * $FreeBSD$ */ - #include <sys/param.h> #include <sys/systm.h> #include <sys/malloc.h> @@ -50,7 +49,6 @@ #include <sys/fcntl.h> #include <geom/geom.h> - #define CDEV_MAJOR 4 static d_open_t g_dev_open; @@ -131,11 +129,9 @@ g_dev_taste(struct g_method *mp, struct g_provider *pp, struct thread *tp __unus struct g_geom *gp; struct g_consumer *cp; static int unit; -#if 1 u_int secsize; off_t mediasize; int error, j; -#endif dev_t dev; g_trace(G_T_TOPOLOGY, "dev_taste(%s,%s)", mp->name, pp->name); @@ -146,7 +142,6 @@ g_dev_taste(struct g_method *mp, struct g_provider *pp, struct thread *tp __unus gp = g_new_geomf(mp, pp->name); cp = g_new_consumer(gp); g_attach(cp, pp); -#if 1 error = g_access_rel(cp, 1, 0, 0); g_topology_unlock(); if (!error) { @@ -171,17 +166,12 @@ g_dev_taste(struct g_method *mp, struct g_provider *pp, struct thread *tp __unus secsize = 512; mediasize = 0; } -#else - g_topology_unlock(); -#endif mtx_lock(&Giant); -#if 1 if (mediasize != 0) printf("GEOM: \"%s\" %lld bytes in %lld sectors of %u bytes\n", pp->name, mediasize, mediasize / secsize, secsize); else printf("GEOM: \"%s\" (size unavailable)\n", pp->name); -#endif dev = make_dev(&g_dev_cdevsw, unit++, UID_ROOT, GID_WHEEL, 0600, gp->name); gp->softc = dev; @@ -249,22 +239,38 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) { struct g_geom *gp; struct g_consumer *cp; - char *nm; int i, error; + struct g_ioctl *gio; gp = dev->si_drv1; cp = dev->si_drv2; error = 0; mtx_unlock(&Giant); - switch (cmd) { - case DIOCGDINFO: nm = "IOCTL::DIOCGDINFO"; break; - case DIOCGDVIRGIN: nm = "IOCTL::DIOCGDVIRGIN"; break; - case DIOCGPART: nm = "IOCTL::DIOCGPART"; break; - default: nm = "?"; break; + + gio = g_malloc(sizeof *gio, M_WAITOK); + gio->cmd = cmd; + gio->data = data; + gio->fflag = fflag; + gio->td = td; + i = sizeof *gio; + if (cmd & IOC_IN) + error = g_io_setattr("GEOM::ioctl", cp, i, gio, td); + else + error = g_io_getattr("GEOM::ioctl", cp, &i, gio, td); + g_free(gio); + + if (error == 0) { + if (error != 0 && cmd == DIOCGDVIRGIN) { + g_topology_lock(); + gp = g_create_geomf("BSD-method", cp->provider, NULL); + g_topology_unlock(); + } } - i = IOCGROUP(cmd); - if (*nm == '?') { + mtx_lock(&Giant); + g_rattle(); + if (error == ENOIOCTL) { + i = IOCGROUP(cmd); printf("IOCTL(0x%lx) \"%s\"", cmd, gp->name); if (i > ' ' && i <= '~') printf(" '%c'", (int)IOCGROUP(cmd)); @@ -275,23 +281,9 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) printf("I"); if (cmd & IOC_OUT) printf("O"); - printf("(%ld)", IOCPARM_LEN(cmd)); - printf(" \"%s\"\n", nm); - error = ENOIOCTL; - } - if (error == 0) { - i = IOCPARM_LEN(cmd); - error = g_io_getattr(nm, cp, &i, data, td); - if (error != 0 && cmd == DIOCGDVIRGIN) { - g_topology_lock(); - gp = g_create_geomf("BSD-method", cp->provider, NULL); - g_topology_unlock(); - } - } - mtx_lock(&Giant); - g_rattle(); - if (error == ENOIOCTL) + printf("(%ld) = ENOIOCTL\n", IOCPARM_LEN(cmd)); error = ENOTTY; + } return (error); } diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c index 62da840..ed0b8be 100644 --- a/sys/geom/geom_disk.c +++ b/sys/geom/geom_disk.c @@ -115,9 +115,12 @@ g_disk_start(struct bio *bp) struct bio *bp2; dev_t dev; struct disk *dp; + struct g_ioctl *gio; + int error; dp = bp->bio_to->geom->softc; dev = dp->d_dev; + error = 0; switch(bp->bio_cmd) { case BIO_READ: case BIO_WRITE: @@ -134,27 +137,38 @@ g_disk_start(struct bio *bp) case BIO_GETATTR: if (g_haveattr_int(bp, "GEOM::sectorsize", dp->d_label.d_secsize)) - return; - if (g_haveattr_int(bp, "GEOM::fwsectors", + break; + else if (g_haveattr_int(bp, "GEOM::fwsectors", dp->d_label.d_nsectors)) - return; - if (g_haveattr_int(bp, "GEOM::fwheads", + break; + else if (g_haveattr_int(bp, "GEOM::fwheads", dp->d_label.d_ntracks)) - return; - if (g_haveattr_int(bp, "GEOM::fwcylinders", + break; + else if (g_haveattr_int(bp, "GEOM::fwcylinders", dp->d_label.d_ncylinders)) - return; - if (g_haveattr_off_t(bp, "GEOM::mediasize", + break; + else if (g_haveattr_off_t(bp, "GEOM::mediasize", dp->d_label.d_secsize * (off_t)dp->d_label.d_secperunit)) - return; - bp->bio_error = ENOIOCTL; - g_io_deliver(bp); - return; + break; + else if (!strcmp(bp->bio_attribute, "GEOM::ioctl") && + bp->bio_length == sizeof *gio) { + gio = (struct g_ioctl *)bp->bio_data; + mtx_lock(&Giant); + error = devsw(dev)->d_ioctl(dev, gio->cmd, + gio->data, gio->fflag, gio->td); + mtx_unlock(&Giant); + } else + error = ENOIOCTL; + break; default: - bp->bio_error = EOPNOTSUPP; + error = EOPNOTSUPP; + break; + } + if (error) { + bp->bio_error = error; g_io_deliver(bp); - return; } + return; } dev_t |