blk-req-callback2.patch - was discussed here
https://www.redhat.com/archives/dm-devel/2004-May/msg00047.html. This version
incorporates Jens's comments.
diff -arup linux-2.6.7-rc1/drivers/block/ll_rw_blk.c linux-2.6.7-rc1-patch/drivers/block/ll_rw_blk.c
--- linux-2.6.7-rc1/drivers/block/ll_rw_blk.c 2004-05-24 18:54:18.000000000 -0700
+++ linux-2.6.7-rc1-patch/drivers/block/ll_rw_blk.c 2004-05-25 18:00:41.935174675 -0700
@@ -1598,6 +1598,7 @@ static struct request *get_request(reque
rq->ref_count = 1;
rq->q = q;
rq->rl = rl;
+ rq->end_request = NULL;
rq->waiting = NULL;
rq->special = NULL;
rq->data_len = 0;
@@ -1841,6 +1842,21 @@ int blk_rq_unmap_user(struct request *rq
EXPORT_SYMBOL(blk_rq_unmap_user);
/**
+ * blk_end_sync_rq - executes a completion event on a request
+ * when it has completed.
+ * @rq: request to complete.
+ *
+ * Caveat: If you set this function as your end_request_fn
+ * you must set a valid completion structure to rq->waiting.
+ */
+void blk_end_sync_rq(struct request *rq)
+{
+ struct completion *waiting = rq->waiting;
+
+ complete(waiting);
+}
+
+/**
* blk_execute_rq - insert a request into queue for execution
* @q: queue to insert the request in
* @bd_disk: matching gendisk
@@ -1873,6 +1889,7 @@ int blk_execute_rq(request_queue_t *q, s
rq->flags |= REQ_NOMERGE;
rq->waiting = &wait;
+ rq->end_request = blk_end_sync_rq;
elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1);
generic_unplug_device(q);
wait_for_completion(&wait);
@@ -1970,6 +1987,7 @@ void __blk_put_request(request_queue_t *
req->rq_status = RQ_INACTIVE;
req->q = NULL;
req->rl = NULL;
+ req->end_request = NULL;
/*
* Request may not have originated from ll_rw_blk. if not,
@@ -2732,6 +2750,7 @@ void end_that_request_last(struct reques
{
struct gendisk *disk = req->rq_disk;
struct completion *waiting = req->waiting;
+ end_request_fn *end_fn = req->end_request;
if (unlikely(laptop_mode) && blk_fs_request(req))
laptop_io_completion();
@@ -2753,7 +2772,9 @@ void end_that_request_last(struct reques
}
__blk_put_request(req->q, req);
/* Do this LAST! The structure may be freed immediately afterwards */
- if (waiting)
+ if (end_fn)
+ end_fn(req);
+ else if (waiting)
complete(waiting);
}
diff -arup linux-2.6.7-rc1/include/linux/blkdev.h linux-2.6.7-rc1-patch/include/linux/blkdev.h
--- linux-2.6.7-rc1/include/linux/blkdev.h 2004-05-24 18:55:05.000000000 -0700
+++ linux-2.6.7-rc1-patch/include/linux/blkdev.h 2004-05-25 18:00:23.000000000 -0700
@@ -17,6 +17,7 @@
#include <asm/scatterlist.h>
+struct request;
struct request_queue;
typedef struct request_queue request_queue_t;
struct elevator_s;
@@ -85,6 +86,13 @@ struct request_list {
#define BLK_MAX_CDB 16
/*
+ * When using the end_request_fn, you should get a handle
+ * to the request, then release it in the end_request_fn
+ * (or whenever you are done with the rq).
+ */
+typedef void end_request_fn(struct request *rq);
+
+/*
* try to put the fields that are referenced together in the same cacheline
*/
struct request {
@@ -144,6 +152,7 @@ struct request {
struct completion *waiting;
void *special;
+ end_request_fn *end_request;
/*
* when request is used as a packet command carrier