From 9ef3d97ebe1d220afd368af05a870dd6fb7896b4 Mon Sep 17 00:00:00 2001 From: pjd Date: Fri, 8 Jul 2005 21:08:53 +0000 Subject: Add CANCEL command which allows to remove one request from the queue or all requests from the queue if request number is not given. Bump version number. Approved by: re (scottl) --- sys/geom/gate/g_gate.c | 44 +++++++++++++++++++++++++++++++++++++++++++- sys/geom/gate/g_gate.h | 13 ++++++++++--- 2 files changed, 53 insertions(+), 4 deletions(-) (limited to 'sys') diff --git a/sys/geom/gate/g_gate.c b/sys/geom/gate/g_gate.c index 4e5e92b..9734cbe 100644 --- a/sys/geom/gate/g_gate.c +++ b/sys/geom/gate/g_gate.c @@ -442,8 +442,11 @@ g_gate_create(struct g_gate_ctl_create *ggio) } #define G_GATE_CHECK_VERSION(ggio) do { \ - if ((ggio)->gctl_version != G_GATE_VERSION) \ + if ((ggio)->gctl_version != G_GATE_VERSION) { \ + printf("Version mismatch %d != %d.\n", \ + ggio->gctl_version, G_GATE_VERSION); \ return (EINVAL); \ + } \ } while (0) static int g_gate_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td) @@ -488,6 +491,44 @@ g_gate_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct threa g_gate_release(sc); return (error); } + case G_GATE_CMD_CANCEL: + { + struct g_gate_ctl_cancel *ggio = (void *)addr; + struct bio *tbp, *lbp; + + G_GATE_CHECK_VERSION(ggio); + sc = g_gate_hold(ggio->gctl_unit); + if (sc == NULL) + return (ENXIO); + lbp = NULL; + mtx_lock(&sc->sc_queue_mtx); + TAILQ_FOREACH_SAFE(bp, &sc->sc_outqueue.queue, bio_queue, tbp) { + if (ggio->gctl_seq == 0 || + ggio->gctl_seq == (uintptr_t)bp->bio_driver1) { + G_GATE_LOGREQ(1, bp, "Request canceled."); + bioq_remove(&sc->sc_outqueue, bp); + /* + * Be sure to put requests back onto incoming + * queue in the proper order. + */ + if (lbp == NULL) + bioq_insert_head(&sc->sc_inqueue, bp); + else { + TAILQ_INSERT_AFTER(&sc->sc_inqueue.queue, + lbp, bp, bio_queue); + } + lbp = bp; + /* + * If only one request was canceled, leave now. + */ + if (ggio->gctl_seq != 0) + break; + } + } + mtx_unlock(&sc->sc_queue_mtx); + g_gate_release(sc); + return (error); + } case G_GATE_CMD_START: { struct g_gate_ctl_io *ggio = (void *)addr; @@ -526,6 +567,7 @@ g_gate_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct threa ggio->gctl_seq = (uintptr_t)bp->bio_driver1; ggio->gctl_offset = bp->bio_offset; ggio->gctl_length = bp->bio_length; + switch (bp->bio_cmd) { case BIO_READ: break; diff --git a/sys/geom/gate/g_gate.h b/sys/geom/gate/g_gate.h index 63e5a3f..5e655d5 100644 --- a/sys/geom/gate/g_gate.h +++ b/sys/geom/gate/g_gate.h @@ -41,7 +41,7 @@ #define G_GATE_MOD_NAME "ggate" #define G_GATE_CTL_NAME "ggctl" -#define G_GATE_VERSION 0 +#define G_GATE_VERSION 1 /* * Maximum number of request that can be stored in @@ -56,8 +56,9 @@ #define G_GATE_CMD_CREATE _IOWR('m', 0, struct g_gate_ctl_create) #define G_GATE_CMD_DESTROY _IOWR('m', 1, struct g_gate_ctl_destroy) -#define G_GATE_CMD_START _IOWR('m', 2, struct g_gate_ctl_io) -#define G_GATE_CMD_DONE _IOWR('m', 3, struct g_gate_ctl_io) +#define G_GATE_CMD_CANCEL _IOWR('m', 2, struct g_gate_ctl_cancel) +#define G_GATE_CMD_START _IOWR('m', 3, struct g_gate_ctl_io) +#define G_GATE_CMD_DONE _IOWR('m', 4, struct g_gate_ctl_io) #define G_GATE_INFOSIZE 2048 @@ -129,6 +130,12 @@ struct g_gate_ctl_destroy { int gctl_force; }; +struct g_gate_ctl_cancel { + u_int gctl_version; + int gctl_unit; + uintptr_t gctl_seq; +}; + struct g_gate_ctl_io { u_int gctl_version; int gctl_unit; -- cgit v1.1