aboutsummaryrefslogtreecommitdiff
path: root/sys/geom/gate/g_gate.c
diff options
context:
space:
mode:
authorPawel Jakub Dawidek <pjd@FreeBSD.org>2004-05-03 18:06:24 +0000
committerPawel Jakub Dawidek <pjd@FreeBSD.org>2004-05-03 18:06:24 +0000
commit4d1e1bf3f557ed853a91087e365db8bcb30066d3 (patch)
treef04f82cd8135dc3544f7f6907d3a578c30057923 /sys/geom/gate/g_gate.c
parent1a0c4873ed54e6ee0c4f5363ccd02baf0f3932f2 (diff)
downloadsrc-4d1e1bf3f557ed853a91087e365db8bcb30066d3.tar.gz
src-4d1e1bf3f557ed853a91087e365db8bcb30066d3.zip
- Hold g_gate_list_mtx lock while generating/checking unit number.
Found by: mtx_assert() g_gate.c:273 - Set command before returning to userland with ENOMEM error value. Found by: assert() ggatel.c:108
Notes
Notes: svn path=/head/; revision=128881
Diffstat (limited to 'sys/geom/gate/g_gate.c')
-rw-r--r--sys/geom/gate/g_gate.c14
1 files changed, 9 insertions, 5 deletions
diff --git a/sys/geom/gate/g_gate.c b/sys/geom/gate/g_gate.c
index 027c70d9120c..92ad3e70b2c6 100644
--- a/sys/geom/gate/g_gate.c
+++ b/sys/geom/gate/g_gate.c
@@ -380,9 +380,6 @@ g_gate_create(struct g_gate_ctl_create *ggio)
G_GATE_DEBUG(1, "Invalid unit number.");
return (EINVAL);
}
- ggio->gctl_unit = g_gate_getunit(ggio->gctl_unit);
- if (ggio->gctl_unit == -1)
- return (EBUSY);
sc = malloc(sizeof(*sc), M_GATE, M_WAITOK | M_ZERO);
sc->sc_flags = (ggio->gctl_flags & G_GATE_USERFLAGS);
@@ -397,9 +394,16 @@ g_gate_create(struct g_gate_ctl_create *ggio)
if (sc->sc_queue_size > G_GATE_MAX_QUEUE_SIZE)
sc->sc_queue_size = G_GATE_MAX_QUEUE_SIZE;
sc->sc_timeout = ggio->gctl_timeout;
+ callout_init(&sc->sc_callout, CALLOUT_MPSAFE);
mtx_lock(&g_gate_list_mtx);
+ ggio->gctl_unit = g_gate_getunit(ggio->gctl_unit);
+ if (ggio->gctl_unit == -1) {
+ mtx_destroy(&sc->sc_inqueue_mtx);
+ mtx_destroy(&sc->sc_outqueue_mtx);
+ free(sc, M_GATE);
+ return (EBUSY);
+ }
sc->sc_unit = ggio->gctl_unit;
- callout_init(&sc->sc_callout, CALLOUT_MPSAFE);
LIST_INSERT_HEAD(&g_gate_list, sc, sc_next);
mtx_unlock(&g_gate_list_mtx);
@@ -490,6 +494,7 @@ g_gate_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
return (0);
}
}
+ ggio->gctl_cmd = bp->bio_cmd;
if ((bp->bio_cmd == BIO_DELETE || bp->bio_cmd == BIO_WRITE) &&
bp->bio_length > ggio->gctl_length) {
mtx_unlock(&sc->sc_inqueue_mtx);
@@ -502,7 +507,6 @@ g_gate_ioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
atomic_subtract_rel_32(&sc->sc_queue_count, 1);
mtx_unlock(&sc->sc_inqueue_mtx);
ggio->gctl_seq = (uintptr_t)bp->bio_driver1;
- ggio->gctl_cmd = bp->bio_cmd;
ggio->gctl_offset = bp->bio_offset;
ggio->gctl_length = bp->bio_length;
switch (bp->bio_cmd) {