summaryrefslogtreecommitdiffstats
path: root/sys/geom/gate
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2005-07-08 21:08:53 +0000
committerpjd <pjd@FreeBSD.org>2005-07-08 21:08:53 +0000
commit9ef3d97ebe1d220afd368af05a870dd6fb7896b4 (patch)
tree4e6e9f2306700f1cc241094a7fb915860de44dbe /sys/geom/gate
parent1519a773f9d524d631e7ce8794ca5b710b7fe58f (diff)
downloadFreeBSD-src-9ef3d97ebe1d220afd368af05a870dd6fb7896b4.zip
FreeBSD-src-9ef3d97ebe1d220afd368af05a870dd6fb7896b4.tar.gz
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)
Diffstat (limited to 'sys/geom/gate')
-rw-r--r--sys/geom/gate/g_gate.c44
-rw-r--r--sys/geom/gate/g_gate.h13
2 files changed, 53 insertions, 4 deletions
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;
OpenPOWER on IntegriCloud