diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/geom/geom.h | 19 | ||||
-rw-r--r-- | sys/geom/geom_bsd.c | 215 | ||||
-rw-r--r-- | sys/geom/geom_dev.c | 45 | ||||
-rw-r--r-- | sys/geom/geom_disk.c | 30 | ||||
-rw-r--r-- | sys/geom/geom_mbr.c | 74 | ||||
-rw-r--r-- | sys/geom/geom_pc98.c | 72 |
6 files changed, 146 insertions, 309 deletions
diff --git a/sys/geom/geom.h b/sys/geom/geom.h index cdb5de2..40ba390 100644 --- a/sys/geom/geom.h +++ b/sys/geom/geom.h @@ -64,8 +64,8 @@ typedef int g_ctl_destroy_geom_t (struct gctl_req *, struct g_class *cp, struct typedef int g_ctl_config_geom_t (struct gctl_req *, struct g_geom *gp, const char *verb); typedef void g_init_t (struct g_class *mp); typedef void g_fini_t (struct g_class *mp); -typedef struct g_geom * g_taste_t (struct g_class *, struct g_provider *, - int flags); +typedef struct g_geom * g_taste_t (struct g_class *, struct g_provider *, int flags); +typedef int g_ioctl_t(struct g_provider *pp, u_long cmd, void *data, struct thread *td); #define G_TF_NORMAL 0 #define G_TF_INSIST 1 #define G_TF_TRANSPARENT 2 @@ -116,6 +116,7 @@ struct g_geom { g_dumpconf_t *dumpconf; g_access_t *access; g_orphan_t *orphan; + g_ioctl_t *ioctl; void *softc; unsigned flags; #define G_GEOM_WITHER 1 @@ -231,20 +232,6 @@ int g_write_data(struct g_consumer *cp, off_t offset, void *ptr, off_t length); /* geom_kern.c / geom_kernsim.c */ -#ifndef _SYS_CONF_H_ -typedef int d_ioctl_t(dev_t dev, u_long cmd, caddr_t data, - int fflag, struct thread *td); -#endif - -struct g_ioctl { - u_long cmd; - void *data; - int fflag; - struct thread *td; - d_ioctl_t *func; - void *dev; -}; - #ifdef _KERNEL struct g_kerneldump { diff --git a/sys/geom/geom_bsd.c b/sys/geom/geom_bsd.c index 4f4d565..1a309eb 100644 --- a/sys/geom/geom_bsd.c +++ b/sys/geom/geom_bsd.c @@ -267,98 +267,6 @@ g_bsd_writelabel(struct g_geom *gp, u_char *bootcode) return(error); } - -/* - * Implement certain ioctls to modify disklabels with. This function - * is called by the event handler thread with topology locked as result - * of the g_post_event() in g_bsd_start(). It is not necessary to keep - * topology locked all the time but make sure to return with topology - * locked as well. - */ - -static void -g_bsd_ioctl(void *arg, int flag) -{ - struct bio *bp; - struct g_geom *gp; - struct g_ioctl *gio; - u_char *label; - int error; - - g_topology_assert(); - bp = arg; - if (flag == EV_CANCEL) { - g_io_deliver(bp, ENXIO); - return; - } - - gp = bp->bio_to->geom; - gio = (struct g_ioctl *)bp->bio_data; - - label = g_malloc(LABELSIZE, M_WAITOK); - - /* The disklabel to set is the ioctl argument. */ - bsd_disklabel_le_enc(label, gio->data); - - /* Validate and modify our slice instance to match. */ - error = g_bsd_modify(gp, label); /* Picks up topology lock on success. */ - g_free(label); - if (error || gio->cmd == DIOCSDINFO) { - g_io_deliver(bp, error); - return; - } - - KASSERT(gio->cmd == DIOCWDINFO, ("Unknown ioctl in g_bsd_ioctl")); - g_io_deliver(bp, g_bsd_writelabel(gp, NULL)); -} - -/* - * Rewrite the bootblock, which is BBSIZE bytes from the start of the disk. - * We punch down the disklabel where we expect it to be before writing. - */ -static int -g_bsd_diocbsdbb(dev_t dev, u_long cmd __unused, caddr_t data, int fflag __unused, struct thread *td __unused) -{ - struct g_geom *gp; - struct g_slicer *gsp; - struct g_bsd_softc *ms; - struct g_consumer *cp; - u_char *buf; - void *p; - int error, i; - uint64_t sum; - - /* Get hold of the interesting bits from the bio. */ - gp = (void *)dev; - gsp = gp->softc; - ms = gsp->softc; - - /* The disklabel to set is the ioctl argument. */ - buf = g_malloc(BBSIZE, M_WAITOK); - p = *(void **)data; - error = copyin(p, buf, BBSIZE); - if (!error) { - DROP_GIANT(); - g_topology_lock(); - /* Validate and modify our slice instance to match. */ - error = g_bsd_modify(gp, buf + ms->labeloffset); - if (!error) { - cp = LIST_FIRST(&gp->consumer); - if (ms->labeloffset == ALPHA_LABEL_OFFSET) { - sum = 0; - for (i = 0; i < 63; i++) - sum += le64dec(buf + i * 8); - le64enc(buf + 504, sum); - } - error = g_write_data(cp, 0, buf, BBSIZE); - } - g_topology_unlock(); - PICKUP_GIANT(); - } - g_free(buf); - return (error); -} - /* * If the user tries to overwrite our disklabel through an open partition * or via a magicwrite config call, we end up here and try to prevent @@ -406,70 +314,98 @@ g_bsd_hotwrite(void *arg, int flag) * * Don't grab the topology lock. * * Don't call biowait, g_getattr(), g_setattr() or g_read_data() */ - static int -g_bsd_start(struct bio *bp) +g_bsd_ioctl(struct g_provider *pp, u_long cmd, void * data, struct thread *td) { struct g_geom *gp; struct g_bsd_softc *ms; struct g_slicer *gsp; - struct g_ioctl *gio; + u_char *label; int error; - gp = bp->bio_to->geom; + gp = pp->geom; gsp = gp->softc; ms = gsp->softc; - switch(bp->bio_cmd) { - case BIO_GETATTR: - if (g_handleattr(bp, "BSD::labelsum", ms->labelsum, - sizeof(ms->labelsum))) - return (1); - break; - default: - KASSERT(0 == 1, ("Unknown bio_cmd in g_bsd_start (%d)", - bp->bio_cmd)); - } - - /* We only handle ioctl(2) requests of the right format. */ - if (strcmp(bp->bio_attribute, "GEOM::ioctl")) - return (0); - else if (bp->bio_length != sizeof(*gio)) - return (0); - /* Get hold of the ioctl parameters. */ - gio = (struct g_ioctl *)bp->bio_data; - - switch (gio->cmd) { + switch(cmd) { case DIOCGDINFO: /* Return a copy of the disklabel to userland. */ - bsd_disklabel_le_dec(ms->label, gio->data, MAXPARTITIONS); - g_io_deliver(bp, 0); - return (1); - case DIOCBSDBB: - gio->func = g_bsd_diocbsdbb; - gio->dev = (void *)gp; - g_io_deliver(bp, EDIRIOCTL); - return (1); + bsd_disklabel_le_dec(ms->label, data, MAXPARTITIONS); + return(0); + case DIOCBSDBB: { + struct g_consumer *cp; + u_char *buf; + void *p; + int error, i; + uint64_t sum; + + /* The disklabel to set is the ioctl argument. */ + buf = g_malloc(BBSIZE, M_WAITOK); + p = *(void **)data; + error = copyin(p, buf, BBSIZE); + if (!error) { + /* XXX: Rude, but supposedly safe */ + DROP_GIANT(); + g_topology_lock(); + /* Validate and modify our slice instance to match. */ + error = g_bsd_modify(gp, buf + ms->labeloffset); + if (!error) { + cp = LIST_FIRST(&gp->consumer); + if (ms->labeloffset == ALPHA_LABEL_OFFSET) { + sum = 0; + for (i = 0; i < 63; i++) + sum += le64dec(buf + i * 8); + le64enc(buf + 504, sum); + } + error = g_write_data(cp, 0, buf, BBSIZE); + } + g_topology_unlock(); + PICKUP_GIANT(); + } + g_free(buf); + return (error); + } case DIOCSDINFO: - case DIOCWDINFO: - /* - * These we cannot do without the topology lock and some - * some I/O requests. Ask the event-handler to schedule - * us in a less restricted environment. - */ - error = g_post_event(g_bsd_ioctl, bp, M_NOWAIT, gp, NULL); - if (error) - g_io_deliver(bp, error); - /* - * We must return non-zero to indicate that we will deal - * with this bio, even though we have not done so yet. - */ - return (1); + case DIOCWDINFO: { + label = g_malloc(LABELSIZE, M_WAITOK); + + /* The disklabel to set is the ioctl argument. */ + bsd_disklabel_le_enc(label, data); + + DROP_GIANT(); + g_topology_lock(); + /* Validate and modify our slice instance to match. */ + error = g_bsd_modify(gp, label); + if (error == 0 && cmd == DIOCWDINFO) + error = g_bsd_writelabel(gp, NULL); + g_topology_unlock(); + PICKUP_GIANT(); + g_free(label); + return(error); + } default: - return (0); + return (ENOIOCTL); } } +static int +g_bsd_start(struct bio *bp) +{ + struct g_geom *gp; + struct g_bsd_softc *ms; + struct g_slicer *gsp; + + gp = bp->bio_to->geom; + gsp = gp->softc; + ms = gsp->softc; + if (bp->bio_cmd == BIO_GETATTR) { + if (g_handleattr(bp, "BSD::labelsum", ms->labelsum, + sizeof(ms->labelsum))) + return (1); + } + return (0); +} + /* * Dump configuration information in XML format. * Notice that the function is called once for the geom and once for each @@ -559,6 +495,7 @@ g_bsd_taste(struct g_class *mp, struct g_provider *pp, int flags) * routine which the "slice" code should call at the right time */ gp->dumpconf = g_bsd_dumpconf; + gp->ioctl = g_bsd_ioctl; /* Get the geom_slicer softc from the geom. */ gsp = gp->softc; diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c index 470ac8d..8da252f 100644 --- a/sys/geom/geom_dev.c +++ b/sys/geom/geom_dev.c @@ -279,17 +279,14 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) struct g_kerneldump kd; int i, error; u_int u; - struct g_ioctl *gio; gp = dev->si_drv1; cp = dev->si_drv2; - gio = NULL; error = 0; KASSERT(cp->acr || cp->acw, ("Consumer with zero access count in g_dev_ioctl")); - gio = NULL; i = IOCPARM_LEN(cmd); switch (cmd) { case DIOCGSECTORSIZE: @@ -331,46 +328,14 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) break; default: - gio = g_malloc(sizeof *gio, M_WAITOK | M_ZERO); - gio->cmd = cmd; - gio->data = data; - gio->fflag = fflag; - gio->td = td; - i = sizeof *gio; - /* - * We always issue ioctls as getattr since the direction of data - * movement in ioctl is no indication of the ioctl being a "set" - * or "get" type ioctl or if such simplistic terms even apply - */ - error = g_io_getattr("GEOM::ioctl", cp, &i, gio); - break; + if (cp->provider->geom->ioctl != NULL) { + error = cp->provider->geom->ioctl(cp->provider, cmd, data, td); + if (error != ENOIOCTL) + return (error); + } } - if (error == EDIRIOCTL) { - KASSERT(gio != NULL, ("NULL gio but EDIRIOCTL")); - KASSERT(gio->func != NULL, ("NULL function but EDIRIOCTL")); - error = (gio->func)(gio->dev, cmd, data, fflag, td); - } g_waitidle(); - if (gio != NULL && (error == EOPNOTSUPP || error == ENOIOCTL)) { - if (g_debugflags & G_T_TOPOLOGY) { - i = IOCGROUP(cmd); - printf("IOCTL(0x%lx) \"%s\"", cmd, gp->name); - if (i > ' ' && i <= '~') - printf(" '%c'", (int)IOCGROUP(cmd)); - else - printf(" 0x%lx", IOCGROUP(cmd)); - printf("/%ld ", cmd & 0xff); - if (cmd & IOC_IN) - printf("I"); - if (cmd & IOC_OUT) - printf("O"); - printf("(%ld) = ENOIOCTL\n", IOCPARM_LEN(cmd)); - } - error = ENOTTY; - } - if (gio != NULL) - g_free(gio); return (error); } diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c index 43c8614..5746415 100644 --- a/sys/geom/geom_disk.c +++ b/sys/geom/geom_disk.c @@ -194,12 +194,29 @@ g_disk_done(struct bio *bp) mtx_unlock(&g_disk_done_mtx); } +static int +g_disk_ioctl(struct g_provider *pp, u_long cmd, void * data, struct thread *td) +{ + struct g_geom *gp; + struct disk *dp; + int error; + + gp = pp->geom; + dp = gp->softc; + + if (dp->d_ioctl == NULL) + return (ENOIOCTL); + g_disk_lock_giant(dp); + error = dp->d_ioctl(dp, cmd, data, 0, td); + g_disk_unlock_giant(dp); + return(error); +} + static void g_disk_start(struct bio *bp) { struct bio *bp2, *bp3; struct disk *dp; - struct g_ioctl *gio; int error; off_t off; @@ -264,15 +281,7 @@ g_disk_start(struct bio *bp) break; else if (!strcmp(bp->bio_attribute, "GEOM::kerneldump")) g_disk_kerneldump(bp, dp); - else if ((g_debugflags & G_F_DISKIOCTL) && - (dp->d_ioctl != NULL) && - !strcmp(bp->bio_attribute, "GEOM::ioctl") && - bp->bio_length == sizeof *gio) { - gio = (struct g_ioctl *)bp->bio_data; - gio->dev = dp; - gio->func = (d_ioctl_t *)(dp->d_ioctl); - error = EDIRIOCTL; - } else + else error = ENOIOCTL; break; default: @@ -317,6 +326,7 @@ g_disk_create(void *arg, int flag) gp = g_new_geomf(&g_disk_class, "%s%d", dp->d_name, dp->d_unit); gp->start = g_disk_start; gp->access = g_disk_access; + gp->ioctl = g_disk_ioctl; gp->softc = dp; gp->dumpconf = g_disk_dumpconf; pp = g_new_providerf(gp, "%s", gp->name); diff --git a/sys/geom/geom_mbr.c b/sys/geom/geom_mbr.c index 7d5994a..877f090 100644 --- a/sys/geom/geom_mbr.c +++ b/sys/geom/geom_mbr.c @@ -152,42 +152,36 @@ g_mbr_modify(struct g_geom *gp, struct g_mbr_softc *ms, u_char *sec0) return (0); } -static void -g_mbr_ioctl(void *arg, int flag) +static int +g_mbr_ioctl(struct g_provider *pp, u_long cmd, void *data, struct thread *td) { - struct bio *bp; struct g_geom *gp; - struct g_slicer *gsp; struct g_mbr_softc *ms; - struct g_ioctl *gio; + struct g_slicer *gsp; struct g_consumer *cp; - u_char *sec0; int error; - bp = arg; - if (flag == EV_CANCEL) { - g_io_deliver(bp, ENXIO); - return; - } - gp = bp->bio_to->geom; + gp = pp->geom; gsp = gp->softc; ms = gsp->softc; - gio = (struct g_ioctl *)bp->bio_data; - /* The disklabel to set is the ioctl argument. */ - sec0 = gio->data; - - error = g_mbr_modify(gp, ms, sec0); - if (error) { - g_io_deliver(bp, error); - return; + switch(cmd) { + case DIOCSMBR: { + DROP_GIANT(); + g_topology_lock(); + /* Validate and modify our slicer instance to match. */ + error = g_mbr_modify(gp, ms, data); + cp = LIST_FIRST(&gp->consumer); + error = g_write_data(cp, 0, data, 512); + g_topology_unlock(); + PICKUP_GIANT(); + return(error); + } + default: + return (ENOIOCTL); } - cp = LIST_FIRST(&gp->consumer); - error = g_write_data(cp, 0, sec0, 512); - g_io_deliver(bp, error); } - static int g_mbr_start(struct bio *bp) { @@ -195,8 +189,7 @@ g_mbr_start(struct bio *bp) struct g_geom *gp; struct g_mbr_softc *mp; struct g_slicer *gsp; - struct g_ioctl *gio; - int idx, error; + int idx; pp = bp->bio_to; idx = pp->index; @@ -211,33 +204,7 @@ g_mbr_start(struct bio *bp) return (1); } - /* We only handle ioctl(2) requests of the right format. */ - if (strcmp(bp->bio_attribute, "GEOM::ioctl")) - return (0); - else if (bp->bio_length != sizeof(*gio)) - return (0); - - /* Get hold of the ioctl parameters. */ - gio = (struct g_ioctl *)bp->bio_data; - - switch (gio->cmd) { - case DIOCSMBR: - /* - * These we cannot do without the topology lock and some - * some I/O requests. Ask the event-handler to schedule - * us in a less restricted environment. - */ - error = g_post_event(g_mbr_ioctl, bp, M_NOWAIT, gp, NULL); - if (error) - g_io_deliver(bp, error); - /* - * We must return non-zero to indicate that we will deal - * with this bio, even though we have not done so yet. - */ - return (1); - default: - return (0); - } + return (0); } static void @@ -275,6 +242,7 @@ g_mbr_taste(struct g_class *mp, struct g_provider *pp, int insist) return (NULL); g_topology_unlock(); gp->dumpconf = g_mbr_dumpconf; + gp->ioctl = g_mbr_ioctl; do { if (gp->rank != 2 && insist == 0) break; diff --git a/sys/geom/geom_pc98.c b/sys/geom/geom_pc98.c index b6d2c21..6be3ed9 100644 --- a/sys/geom/geom_pc98.c +++ b/sys/geom/geom_pc98.c @@ -134,39 +134,34 @@ g_pc98_modify(struct g_geom *gp, struct g_pc98_softc *ms, u_char *sec) return (0); } -static void -g_pc98_ioctl(void *arg, int flag) +static int +g_pc98_ioctl(struct g_provider *pp, u_long cmd, void *data, struct thread *td) { - struct bio *bp; struct g_geom *gp; - struct g_slicer *gsp; struct g_pc98_softc *ms; - struct g_ioctl *gio; + struct g_slicer *gsp; struct g_consumer *cp; - u_char *sec; int error; - bp = arg; - if (flag == EV_CANCEL) { - g_io_deliver(bp, ENXIO); - return; - } - gp = bp->bio_to->geom; + gp = pp->geom; gsp = gp->softc; ms = gsp->softc; - gio = (struct g_ioctl *)bp->bio_data; - /* The disklabel to set is the ioctl argument. */ - sec = gio->data; - - error = g_pc98_modify(gp, ms, sec); - if (error) { - g_io_deliver(bp, error); - return; + switch(cmd) { + case DIOCSPC98: { + DROP_GIANT(); + g_topology_lock(); + /* Validate and modify our slicer instance to match. */ + error = g_pc98_modify(gp, ms, data); + cp = LIST_FIRST(&gp->consumer); + error = g_write_data(cp, 0, data, 8192); + g_topology_unlock(); + PICKUP_GIANT(); + return(error); + } + default: + return (ENOIOCTL); } - cp = LIST_FIRST(&gp->consumer); - error = g_write_data(cp, 0, sec, 8192); - g_io_deliver(bp, error); } static int @@ -176,8 +171,7 @@ g_pc98_start(struct bio *bp) struct g_geom *gp; struct g_pc98_softc *mp; struct g_slicer *gsp; - struct g_ioctl *gio; - int idx, error; + int idx; pp = bp->bio_to; idx = pp->index; @@ -192,32 +186,7 @@ g_pc98_start(struct bio *bp) return (1); } - /* We only handle ioctl(2) requests of the right format. */ - if (strcmp(bp->bio_attribute, "GEOM::ioctl")) - return (0); - else if (bp->bio_length != sizeof(*gio)) - return (0); - /* Get hold of the ioctl parameters. */ - gio = (struct g_ioctl *)bp->bio_data; - - switch (gio->cmd) { - case DIOCSPC98: - /* - * These we cannot do without the topology lock and some - * some I/O requests. Ask the event-handler to schedule - * us in a less restricted environment. - */ - error = g_post_event(g_pc98_ioctl, bp, M_NOWAIT, gp, NULL); - if (error) - g_io_deliver(bp, error); - /* - * We must return non-zero to indicate that we will deal - * with this bio, even though we have not done so yet. - */ - return (1); - default: - return (0); - } + return (0); } static void @@ -270,6 +239,7 @@ g_pc98_taste(struct g_class *mp, struct g_provider *pp, int flags) return (NULL); g_topology_unlock(); gp->dumpconf = g_pc98_dumpconf; + gp->ioctl = g_pc98_ioctl; do { if (gp->rank != 2 && flags == G_TF_NORMAL) break; |