diff options
author | pjd <pjd@FreeBSD.org> | 2005-07-08 21:08:53 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2005-07-08 21:08:53 +0000 |
commit | 9ef3d97ebe1d220afd368af05a870dd6fb7896b4 (patch) | |
tree | 4e6e9f2306700f1cc241094a7fb915860de44dbe | |
parent | 1519a773f9d524d631e7ce8794ca5b710b7fe58f (diff) | |
download | FreeBSD-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)
-rw-r--r-- | sys/geom/gate/g_gate.c | 44 | ||||
-rw-r--r-- | sys/geom/gate/g_gate.h | 13 |
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; |