Branch data Line data Source code
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 : : #include <linux/blk-mq.h>
9 : : #include <linux/sched/sysctl.h>
10 : :
11 : : #include "blk.h"
12 : :
13 : : /*
14 : : * for max sense size
15 : : */
16 : : #include <scsi/scsi_cmnd.h>
17 : :
18 : : /**
19 : : * blk_end_sync_rq - executes a completion event on a request
20 : : * @rq: request to complete
21 : : * @error: end I/O status of the request
22 : : */
23 : 0 : static void blk_end_sync_rq(struct request *rq, int error)
24 : : {
25 : 14876 : struct completion *waiting = rq->end_io_data;
26 : :
27 : 14876 : rq->end_io_data = NULL;
28 : :
29 : : /*
30 : : * complete last, if this is a stack request the process (and thus
31 : : * the rq pointer) could be invalid right after this complete()
32 : : */
33 : 14876 : complete(waiting);
34 : 14876 : }
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 I/O scheduler queue
46 : : * for execution. Don't wait for completion.
47 : : *
48 : : * Note:
49 : : * This function will invoke @done directly if the queue is dead.
50 : : */
51 : 0 : void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk,
52 : : struct request *rq, int at_head,
53 : : rq_end_io_fn *done)
54 : : {
55 [ - + ]: 14876 : int where = at_head ? ELEVATOR_INSERT_FRONT : ELEVATOR_INSERT_BACK;
56 : : bool is_pm_resume;
57 : :
58 [ - + ]: 14876 : WARN_ON(irqs_disabled());
59 : :
60 : 14876 : rq->rq_disk = bd_disk;
61 : 14876 : rq->end_io = done;
62 : :
63 : : /*
64 : : * don't check dying flag for MQ because the request won't
65 : : * be resued after dying flag is set
66 : : */
67 [ - + ]: 14876 : if (q->mq_ops) {
68 : 0 : blk_mq_insert_request(rq, at_head, true, false);
69 : 0 : return;
70 : : }
71 : :
72 : : /*
73 : : * need to check this before __blk_run_queue(), because rq can
74 : : * be freed before that returns.
75 : : */
76 : 14876 : is_pm_resume = rq->cmd_type == REQ_TYPE_PM_RESUME;
77 : :
78 : 14876 : spin_lock_irq(q->queue_lock);
79 : :
80 [ - + ]: 14876 : if (unlikely(blk_queue_dying(q))) {
81 : 0 : rq->cmd_flags |= REQ_QUIET;
82 : 0 : rq->errors = -ENXIO;
83 : 0 : __blk_end_request_all(rq, rq->errors);
84 : 0 : spin_unlock_irq(q->queue_lock);
85 : : return;
86 : : }
87 : :
88 : 14876 : __elv_add_request(q, rq, where);
89 : 14876 : __blk_run_queue(q);
90 : : /* the queue is stopped so it won't be run */
91 [ - + ]: 14876 : if (is_pm_resume)
92 : 0 : __blk_run_queue_uncond(q);
93 : 14876 : spin_unlock_irq(q->queue_lock);
94 : : }
95 : : EXPORT_SYMBOL_GPL(blk_execute_rq_nowait);
96 : :
97 : : /**
98 : : * blk_execute_rq - insert a request into queue for execution
99 : : * @q: queue to insert the request in
100 : : * @bd_disk: matching gendisk
101 : : * @rq: request to insert
102 : : * @at_head: insert request at head or tail of queue
103 : : *
104 : : * Description:
105 : : * Insert a fully prepared request at the back of the I/O scheduler queue
106 : : * for execution and wait for completion.
107 : : */
108 : 0 : int blk_execute_rq(struct request_queue *q, struct gendisk *bd_disk,
109 : : struct request *rq, int at_head)
110 : : {
111 : 14876 : DECLARE_COMPLETION_ONSTACK(wait);
112 : : char sense[SCSI_SENSE_BUFFERSIZE];
113 : : int err = 0;
114 : : unsigned long hang_check;
115 : :
116 [ - + ]: 14876 : if (!rq->sense) {
117 : 0 : memset(sense, 0, sizeof(sense));
118 : 0 : rq->sense = sense;
119 : 0 : rq->sense_len = 0;
120 : : }
121 : :
122 : 14876 : rq->end_io_data = &wait;
123 : 14876 : blk_execute_rq_nowait(q, bd_disk, rq, at_head, blk_end_sync_rq);
124 : :
125 : : /* Prevent hang_check timer from firing at us during very long I/O */
126 : : hang_check = sysctl_hung_task_timeout_secs;
127 : : if (hang_check)
128 : : while (!wait_for_completion_io_timeout(&wait, hang_check * (HZ/2)));
129 : : else
130 : 14876 : wait_for_completion_io(&wait);
131 : :
132 [ - + ]: 14876 : if (rq->errors)
133 : : err = -EIO;
134 : :
135 : 14876 : return err;
136 : : }
137 : : EXPORT_SYMBOL(blk_execute_rq);
|