summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/geom/geom.h19
-rw-r--r--sys/geom/geom_bsd.c215
-rw-r--r--sys/geom/geom_dev.c45
-rw-r--r--sys/geom/geom_disk.c30
-rw-r--r--sys/geom/geom_mbr.c74
-rw-r--r--sys/geom/geom_pc98.c72
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;
OpenPOWER on IntegriCloud