diff options
Diffstat (limited to 'block/blk-exec.c')
-rw-r--r-- | block/blk-exec.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/block/blk-exec.c b/block/blk-exec.c new file mode 100644 index 000000000000..ebfb44e959a9 --- /dev/null +++ b/block/blk-exec.c | |||
@@ -0,0 +1,105 @@ | |||
1 | /* | ||
2 | * Functions related to setting various queue properties from drivers | ||
3 | */ | ||
4 | #include <linux/kernel.h> | ||
5 | #include <linux/module.h> | ||
6 | #include <linux/bio.h> | ||
7 | #include <linux/blkdev.h> | ||
8 | |||
9 | #include "blk.h" | ||
10 | |||
11 | /* | ||
12 | * for max sense size | ||
13 | */ | ||
14 | #include <scsi/scsi_cmnd.h> | ||
15 | |||
16 | /** | ||
17 | * blk_end_sync_rq - executes a completion event on a request | ||
18 | * @rq: request to complete | ||
19 | * @error: end io status of the request | ||
20 | */ | ||
21 | void blk_end_sync_rq(struct request *rq, int error) | ||
22 | { | ||
23 | struct completion *waiting = rq->end_io_data; | ||
24 | |||
25 | rq->end_io_data = NULL; | ||
26 | __blk_put_request(rq->q, rq); | ||
27 | |||
28 | /* | ||
29 | * complete last, if this is a stack request the process (and thus | ||
30 | * the rq pointer) could be invalid right after this complete() | ||
31 | */ | ||
32 | complete(waiting); | ||
33 | } | ||
34 | EXPORT_SYMBOL(blk_end_sync_rq); | ||
35 | |||
36 | /** | ||
37 | * blk_execute_rq_nowait - insert a request into queue for execution | ||
38 | * @q: queue to insert the request in | ||
39 | * @bd_disk: matching gendisk | ||
40 | * @rq: request to insert | ||
41 | * @at_head: insert request at head or tail of queue | ||
42 | * @done: I/O completion handler | ||
43 | * | ||
44 | * Description: | ||
45 | * Insert a fully prepared request at the back of the io scheduler queue | ||
46 | * for execution. Don't wait for completion. | ||
47 | */ | ||
48 | void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, | ||
49 | struct request *rq, int at_head, | ||
50 | rq_end_io_fn *done) | ||
51 | { | ||
52 | int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK; | ||
53 | |||
54 | rq->rq_disk = bd_disk; | ||
55 | rq->cmd_flags |= REQ_NOMERGE; | ||
56 | rq->end_io = done; | ||
57 | WARN_ON(irqs_disabled()); | ||
58 | spin_lock_irq(q->queue_lock); | ||
59 | __elv_add_request(q, rq, where, 1); | ||
60 | __generic_unplug_device(q); | ||
61 | spin_unlock_irq(q->queue_lock); | ||
62 | } | ||
63 | EXPORT_SYMBOL_GPL(blk_execute_rq_nowait); | ||
64 | |||
65 | /** | ||
66 | * blk_execute_rq - insert a request into queue for execution | ||
67 | * @q: queue to insert the request in | ||
68 | * @bd_disk: matching gendisk | ||
69 | * @rq: request to insert | ||
70 | * @at_head: insert request at head or tail of queue | ||
71 | * | ||
72 | * Description: | ||
73 | * Insert a fully prepared request at the back of the io scheduler queue | ||
74 | * for execution and wait for completion. | ||
75 | */ | ||
76 | int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk, | ||
77 | struct request *rq, int at_head) | ||
78 | { | ||
79 | DECLARE_COMPLETION_ONSTACK(wait); | ||
80 | char sense[SCSI_SENSE_BUFFERSIZE]; | ||
81 | int err = 0; | ||
82 | |||
83 | /* | ||
84 | * we need an extra reference to the request, so we can look at | ||
85 | * it after io completion | ||
86 | */ | ||
87 | rq->ref_count++; | ||
88 | |||
89 | if (!rq->sense) { | ||
90 | memset(sense, 0, sizeof(sense)); | ||
91 | rq->sense = sense; | ||
92 | rq->sense_len = 0; | ||
93 | } | ||
94 | |||
95 | rq->end_io_data = &wait; | ||
96 | blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq); | ||
97 | wait_for_completion(&wait); | ||
98 | |||
99 | if (rq->errors) | ||
100 | err = -EIO; | ||
101 | |||
102 | return err; | ||
103 | } | ||
104 | |||
105 | EXPORT_SYMBOL(blk_execute_rq); | ||