Commit e8be9091 authored by Jens Axboe's avatar Jens Axboe Committed by Linus Torvalds

[PATCH] Add struct request end_io callback

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 <petero2@telia.com>

The problem is that the add-struct-request-end_io-callback patch forgot to
update pktcdvd.c.  This patch fixes it.
Signed-off-by: default avatarJens Axboe <axboe@suse.de>
Signed-off-by: default avatarPeter Osterlund <petero2@telia.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent cd67725a
......@@ -1753,6 +1753,8 @@ static struct request *get_request(request_queue_t *q, int rw, int gfp_mask)
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, struct gendisk *bd_disk,
}
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 *disk)
/*
* 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;
......@@ -2218,6 +2220,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
......@@ -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 request *req)
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);
......
......@@ -743,6 +743,7 @@ static int pd_special_command(struct pd_unit *disk,
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;
......
......@@ -375,6 +375,7 @@ static int pkt_generic_packet(struct pktcdvd_device *pd, struct packet_command *
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);
......
......@@ -1607,6 +1607,7 @@ int ide_do_drive_cmd (ide_drive_t *drive, struct request *rq, ide_action_t actio
if (must_wait) {
rq->ref_count++;
rq->waiting = &wait;
rq->end_io = blk_end_sync_rq;
}
spin_lock_irqsave(&ide_lock, flags);
......
......@@ -2720,6 +2720,7 @@ static void idetape_wait_for_request (ide_drive_t *drive, struct request *rq)
}
#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 */
......
......@@ -93,6 +93,9 @@ struct io_context *get_io_context(int gfp_flags);
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 gendisk *disk);
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 *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment