diff options
author | phk <phk@FreeBSD.org> | 2002-10-07 06:25:26 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 2002-10-07 06:25:26 +0000 |
commit | 05568a1e183e75bdc8edaa948f276ddd47ebc8cb (patch) | |
tree | 12c86e8396fed513177c4639d423b328584ee616 /sys/geom/geom_dev.c | |
parent | d0cb388eeab801d8cb58ad70b358a55fe82b5976 (diff) | |
download | FreeBSD-src-05568a1e183e75bdc8edaa948f276ddd47ebc8cb.zip FreeBSD-src-05568a1e183e75bdc8edaa948f276ddd47ebc8cb.tar.gz |
Copyin and copyout are only possible from a process-native thread,
and therefore we need a way for ioctl handlers to run in that thread
in GEOM. Rather than invent a complicated registration system to
recognize which ioctl handler to use for a given ioctl, we still
schedule all ioctls down the tree as bio transactions but add a
special return code that means "call me directly" and have the
geom_dev layer do that.
Use this for all ioctls that make it as far as a diskdriver to
avoid any backwards compatibility problems.
Requested by: scottl
Sponsored by: DARPA & NAI Labs
Diffstat (limited to 'sys/geom/geom_dev.c')
-rw-r--r-- | sys/geom/geom_dev.c | 28 |
1 files changed, 10 insertions, 18 deletions
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c index c926e18..1b30703 100644 --- a/sys/geom/geom_dev.c +++ b/sys/geom/geom_dev.c @@ -231,14 +231,12 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) int i, error; u_int u; struct g_ioctl *gio; -#if 0 - struct sbuf *usb, *sb; -#endif gp = dev->si_drv1; cp = dev->si_drv2; pp2 = cp->provider; gp2 = pp2->geom; + gio = NULL; error = 0; DROP_GIANT(); @@ -274,21 +272,9 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) if (!error) dev->si_flags |= SI_DUMPDEV; break; -#if 0 - case GEOMGETCONF: - /* we bogusly pass cp to avoid getting any consumers listed */ - sb = g_conf_specific(gp2->class, gp2, pp2, cp); - usb = (struct sbuf *)data; - if (usb->s_size - 1 < sbuf_len(sb)) - error = ENOMEM; - else - error = copyout(sbuf_data(sb), usb->s_buf, sbuf_len(sb) + 1); - if (!error) - usb->s_len = sbuf_len(sb); - break; -#endif + default: - gio = g_malloc(sizeof *gio, M_WAITOK); + gio = g_malloc(sizeof *gio, M_WAITOK | M_ZERO); gio->cmd = cmd; gio->data = data; gio->fflag = fflag; @@ -298,11 +284,17 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td) error = g_io_setattr("GEOM::ioctl", cp, i, gio); else error = g_io_getattr("GEOM::ioctl", cp, &i, gio); - g_free(gio); break; } PICKUP_GIANT(); + 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); + } + if (gio != NULL) + g_free(gio); g_waitidle(); if (error == ENOIOCTL) { if (g_debugflags & G_T_TOPOLOGY) { |