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 +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