From: Jens Axboe This is needed for several things, one in-tree user which I will introduce after this patch. This adds a ->end_io callback to struct request, so it can be used with async io of any sort. Right now users have to wait for completion in a blocking manner. In the next iteration, ->waiting can be folded into ->end_io_data since it is just a special case of that use. From: Peter Osterlund The problem is that the add-struct-request-end_io-callback patch forgot to update pktcdvd.c. This patch fixes it. Signed-off-by: Jens Axboe Signed-off-by: Peter Osterlund Signed-off-by: Andrew Morton --- 25-akpm/drivers/block/ll_rw_blk.c | 36 ++++++++++++++++++++++++++++-------- 25-akpm/drivers/block/paride/pd.c | 1 + 25-akpm/drivers/block/pktcdvd.c | 1 + 25-akpm/drivers/ide/ide-io.c | 1 + 25-akpm/drivers/ide/ide-tape.c | 1 + 25-akpm/include/linux/blkdev.h | 11 ++++++++++- 6 files changed, 42 insertions(+), 9 deletions(-) diff -puN drivers/block/ll_rw_blk.c~add-struct-request-end_io-callback drivers/block/ll_rw_blk.c --- 25/drivers/block/ll_rw_blk.c~add-struct-request-end_io-callback 2005-02-23 02:11:18.000000000 -0800 +++ 25-akpm/drivers/block/ll_rw_blk.c 2005-02-23 02:11:18.000000000 -0800 @@ -1753,6 +1753,8 @@ rq_starved: rq->data_len = 0; rq->data = NULL; rq->sense = NULL; + rq->end_io = NULL; + rq->end_io_data = NULL; out: put_io_context(ioc); @@ -2018,8 +2020,8 @@ int blk_execute_rq(request_queue_t *q, s } rq->flags |= REQ_NOMERGE; - if (!rq->waiting) - rq->waiting = &wait; + rq->waiting = &wait; + rq->end_io = blk_end_sync_rq; elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); generic_unplug_device(q); wait_for_completion(rq->waiting); @@ -2171,7 +2173,7 @@ void disk_round_stats(struct gendisk *di /* * queue lock must be held */ -void __blk_put_request(request_queue_t *q, struct request *req) +static void __blk_put_request(request_queue_t *q, struct request *req) { struct request_list *rl = req->rl; @@ -2219,6 +2221,25 @@ void blk_put_request(struct request *req EXPORT_SYMBOL(blk_put_request); /** + * blk_end_sync_rq - executes a completion event on a request + * @rq: request to complete + */ +void blk_end_sync_rq(struct request *rq) +{ + struct completion *waiting = rq->waiting; + + rq->waiting = NULL; + __blk_put_request(rq->q, rq); + + /* + * complete last, if this is a stack request the process (and thus + * the rq pointer) could be invalid right after this complete() + */ + complete(waiting); +} +EXPORT_SYMBOL(blk_end_sync_rq); + +/** * blk_congestion_wait - wait for a queue to become uncongested * @rw: READ or WRITE * @timeout: timeout in jiffies @@ -2978,7 +2999,6 @@ EXPORT_SYMBOL(end_that_request_chunk); void end_that_request_last(struct request *req) { struct gendisk *disk = req->rq_disk; - struct completion *waiting = req->waiting; if (unlikely(laptop_mode) && blk_fs_request(req)) laptop_io_completion(); @@ -2998,10 +3018,10 @@ void end_that_request_last(struct reques disk_round_stats(disk); disk->in_flight--; } - __blk_put_request(req->q, req); - /* Do this LAST! The structure may be freed immediately afterwards */ - if (waiting) - complete(waiting); + if (req->end_io) + req->end_io(req); + else + __blk_put_request(req->q, req); } EXPORT_SYMBOL(end_that_request_last); diff -puN drivers/block/paride/pd.c~add-struct-request-end_io-callback drivers/block/paride/pd.c --- 25/drivers/block/paride/pd.c~add-struct-request-end_io-callback 2005-02-23 02:11:18.000000000 -0800 +++ 25-akpm/drivers/block/paride/pd.c 2005-02-23 02:11:18.000000000 -0800 @@ -743,6 +743,7 @@ static int pd_special_command(struct pd_ rq.rq_disk = disk->gd; rq.ref_count = 1; rq.waiting = &wait; + rq.end_io = blk_end_sync_rq; blk_insert_request(disk->gd->queue, &rq, 0, func, 0); wait_for_completion(&wait); rq.waiting = NULL; diff -puN drivers/ide/ide-io.c~add-struct-request-end_io-callback drivers/ide/ide-io.c --- 25/drivers/ide/ide-io.c~add-struct-request-end_io-callback 2005-02-23 02:11:18.000000000 -0800 +++ 25-akpm/drivers/ide/ide-io.c 2005-02-23 02:11:18.000000000 -0800 @@ -1835,6 +1835,7 @@ int ide_do_drive_cmd (ide_drive_t *drive if (must_wait) { rq->ref_count++; rq->waiting = &wait; + rq->end_io = blk_end_sync_rq; } spin_lock_irqsave(&ide_lock, flags); diff -puN drivers/ide/ide-tape.c~add-struct-request-end_io-callback drivers/ide/ide-tape.c --- 25/drivers/ide/ide-tape.c~add-struct-request-end_io-callback 2005-02-23 02:11:18.000000000 -0800 +++ 25-akpm/drivers/ide/ide-tape.c 2005-02-23 02:11:18.000000000 -0800 @@ -2766,6 +2766,7 @@ static void idetape_wait_for_request (id } #endif /* IDETAPE_DEBUG_BUGS */ rq->waiting = &wait; + rq->end_io = blk_end_sync_rq; spin_unlock_irq(&tape->spinlock); wait_for_completion(&wait); /* The stage and its struct request have been deallocated */ diff -puN include/linux/blkdev.h~add-struct-request-end_io-callback include/linux/blkdev.h --- 25/include/linux/blkdev.h~add-struct-request-end_io-callback 2005-02-23 02:11:18.000000000 -0800 +++ 25-akpm/include/linux/blkdev.h 2005-02-23 02:11:18.000000000 -0800 @@ -93,6 +93,9 @@ struct io_context *get_io_context(int gf void copy_io_context(struct io_context **pdst, struct io_context **psrc); void swap_io_context(struct io_context **ioc1, struct io_context **ioc2); +struct request; +typedef void (rq_end_io_fn)(struct request *); + struct request_list { int count[2]; int starved[2]; @@ -176,6 +179,12 @@ struct request { * For Power Management requests */ struct request_pm_state *pm; + + /* + * completion callback. end_io_data should be folded in with waiting + */ + rq_end_io_fn *end_io; + void *end_io_data; }; /* @@ -509,10 +518,10 @@ extern void blk_unregister_queue(struct extern void register_disk(struct gendisk *dev); extern void generic_make_request(struct bio *bio); extern void blk_put_request(struct request *); +extern void blk_end_sync_rq(struct request *rq); extern void blk_attempt_remerge(request_queue_t *, struct request *); extern void __blk_attempt_remerge(request_queue_t *, struct request *); extern struct request *blk_get_request(request_queue_t *, int, int); -extern void blk_put_request(struct request *); extern void blk_insert_request(request_queue_t *, struct request *, int, void *, int); extern void blk_requeue_request(request_queue_t *, struct request *); extern void blk_plug_device(request_queue_t *); diff -puN drivers/block/pktcdvd.c~add-struct-request-end_io-callback drivers/block/pktcdvd.c --- 25/drivers/block/pktcdvd.c~add-struct-request-end_io-callback 2005-02-23 02:11:20.000000000 -0800 +++ 25-akpm/drivers/block/pktcdvd.c 2005-02-23 02:11:20.000000000 -0800 @@ -375,6 +375,7 @@ static int pkt_generic_packet(struct pkt rq->ref_count++; rq->flags |= REQ_NOMERGE; rq->waiting = &wait; + rq->end_io = blk_end_sync_rq; elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 1); generic_unplug_device(q); wait_for_completion(&wait); _