blk-timeout.c (4ba25a496f62129a2ad8c2436ab2b402752dc66c) | blk-timeout.c (320ae51feed5c2f13664aa05a76bec198967e04d) |
---|---|
1/* 2 * Functions related to generic timeout handling of requests. 3 */ 4#include <linux/kernel.h> 5#include <linux/module.h> 6#include <linux/blkdev.h> 7#include <linux/fault-inject.h> 8 9#include "blk.h" | 1/* 2 * Functions related to generic timeout handling of requests. 3 */ 4#include <linux/kernel.h> 5#include <linux/module.h> 6#include <linux/blkdev.h> 7#include <linux/fault-inject.h> 8 9#include "blk.h" |
10#include "blk-mq.h" |
|
10 11#ifdef CONFIG_FAIL_IO_TIMEOUT 12 13static DECLARE_FAULT_ATTR(fail_io_timeout); 14 15static int __init setup_fail_io_timeout(char *str) 16{ 17 return setup_fault_attr(&fail_io_timeout, str); --- 65 unchanged lines hidden (view full) --- 83{ 84 struct request_queue *q = req->q; 85 enum blk_eh_timer_return ret = BLK_EH_RESET_TIMER; 86 87 if (q->rq_timed_out_fn) 88 ret = q->rq_timed_out_fn(req); 89 switch (ret) { 90 case BLK_EH_HANDLED: | 11 12#ifdef CONFIG_FAIL_IO_TIMEOUT 13 14static DECLARE_FAULT_ATTR(fail_io_timeout); 15 16static int __init setup_fail_io_timeout(char *str) 17{ 18 return setup_fault_attr(&fail_io_timeout, str); --- 65 unchanged lines hidden (view full) --- 84{ 85 struct request_queue *q = req->q; 86 enum blk_eh_timer_return ret = BLK_EH_RESET_TIMER; 87 88 if (q->rq_timed_out_fn) 89 ret = q->rq_timed_out_fn(req); 90 switch (ret) { 91 case BLK_EH_HANDLED: |
91 __blk_complete_request(req); | 92 /* Can we use req->errors here? */ 93 if (q->mq_ops) 94 blk_mq_complete_request(req, req->errors); 95 else 96 __blk_complete_request(req); |
92 break; 93 case BLK_EH_RESET_TIMER: 94 blk_clear_rq_complete(req); | 97 break; 98 case BLK_EH_RESET_TIMER: 99 blk_clear_rq_complete(req); |
95 blk_add_timer(req); | 100 if (q->mq_ops) 101 blk_mq_add_timer(req); 102 else 103 blk_add_timer(req); |
96 break; 97 case BLK_EH_NOT_HANDLED: 98 /* 99 * LLD handles this for now but in the future 100 * we can send a request msg to abort the command 101 * and we can move more of the generic scsi eh code to 102 * the blk layer. 103 */ 104 break; 105 default: 106 printk(KERN_ERR "block: bad eh return: %d\n", ret); 107 break; 108 } 109} 110 | 104 break; 105 case BLK_EH_NOT_HANDLED: 106 /* 107 * LLD handles this for now but in the future 108 * we can send a request msg to abort the command 109 * and we can move more of the generic scsi eh code to 110 * the blk layer. 111 */ 112 break; 113 default: 114 printk(KERN_ERR "block: bad eh return: %d\n", ret); 115 break; 116 } 117} 118 |
119void blk_rq_check_expired(struct request *rq, unsigned long *next_timeout, 120 unsigned int *next_set) 121{ 122 if (time_after_eq(jiffies, rq->deadline)) { 123 list_del_init(&rq->timeout_list); 124 125 /* 126 * Check if we raced with end io completion 127 */ 128 if (!blk_mark_rq_complete(rq)) 129 blk_rq_timed_out(rq); 130 } else if (!*next_set || time_after(*next_timeout, rq->deadline)) { 131 *next_timeout = rq->deadline; 132 *next_set = 1; 133 } 134} 135 |
|
111void blk_rq_timed_out_timer(unsigned long data) 112{ 113 struct request_queue *q = (struct request_queue *) data; 114 unsigned long flags, next = 0; 115 struct request *rq, *tmp; 116 int next_set = 0; 117 118 spin_lock_irqsave(q->queue_lock, flags); 119 | 136void blk_rq_timed_out_timer(unsigned long data) 137{ 138 struct request_queue *q = (struct request_queue *) data; 139 unsigned long flags, next = 0; 140 struct request *rq, *tmp; 141 int next_set = 0; 142 143 spin_lock_irqsave(q->queue_lock, flags); 144 |
120 list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list) { 121 if (time_after_eq(jiffies, rq->deadline)) { 122 list_del_init(&rq->timeout_list); | 145 list_for_each_entry_safe(rq, tmp, &q->timeout_list, timeout_list) 146 blk_rq_check_expired(rq, &next, &next_set); |
123 | 147 |
124 /* 125 * Check if we raced with end io completion 126 */ 127 if (blk_mark_rq_complete(rq)) 128 continue; 129 blk_rq_timed_out(rq); 130 } else if (!next_set || time_after(next, rq->deadline)) { 131 next = rq->deadline; 132 next_set = 1; 133 } 134 } 135 | |
136 if (next_set) 137 mod_timer(&q->timeout, round_jiffies_up(next)); 138 139 spin_unlock_irqrestore(q->queue_lock, flags); 140} 141 142/** 143 * blk_abort_request -- Request request recovery for the specified command --- 8 unchanged lines hidden (view full) --- 152{ 153 if (blk_mark_rq_complete(req)) 154 return; 155 blk_delete_timer(req); 156 blk_rq_timed_out(req); 157} 158EXPORT_SYMBOL_GPL(blk_abort_request); 159 | 148 if (next_set) 149 mod_timer(&q->timeout, round_jiffies_up(next)); 150 151 spin_unlock_irqrestore(q->queue_lock, flags); 152} 153 154/** 155 * blk_abort_request -- Request request recovery for the specified command --- 8 unchanged lines hidden (view full) --- 164{ 165 if (blk_mark_rq_complete(req)) 166 return; 167 blk_delete_timer(req); 168 blk_rq_timed_out(req); 169} 170EXPORT_SYMBOL_GPL(blk_abort_request); 171 |
160/** 161 * blk_add_timer - Start timeout timer for a single request 162 * @req: request that is about to start running. 163 * 164 * Notes: 165 * Each request has its own timer, and as it is added to the queue, we 166 * set up the timer. When the request completes, we cancel the timer. 167 */ 168void blk_add_timer(struct request *req) | 172void __blk_add_timer(struct request *req, struct list_head *timeout_list) |
169{ 170 struct request_queue *q = req->q; 171 unsigned long expiry; 172 173 if (!q->rq_timed_out_fn) 174 return; 175 176 BUG_ON(!list_empty(&req->timeout_list)); 177 BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags)); 178 179 /* 180 * Some LLDs, like scsi, peek at the timeout to prevent a 181 * command from being retried forever. 182 */ 183 if (!req->timeout) 184 req->timeout = q->rq_timeout; 185 186 req->deadline = jiffies + req->timeout; | 173{ 174 struct request_queue *q = req->q; 175 unsigned long expiry; 176 177 if (!q->rq_timed_out_fn) 178 return; 179 180 BUG_ON(!list_empty(&req->timeout_list)); 181 BUG_ON(test_bit(REQ_ATOM_COMPLETE, &req->atomic_flags)); 182 183 /* 184 * Some LLDs, like scsi, peek at the timeout to prevent a 185 * command from being retried forever. 186 */ 187 if (!req->timeout) 188 req->timeout = q->rq_timeout; 189 190 req->deadline = jiffies + req->timeout; |
187 list_add_tail(&req->timeout_list, &q->timeout_list); | 191 if (timeout_list) 192 list_add_tail(&req->timeout_list, timeout_list); |
188 189 /* 190 * If the timer isn't already pending or this timeout is earlier 191 * than an existing one, modify the timer. Round up to next nearest 192 * second. 193 */ 194 expiry = round_jiffies_up(req->deadline); 195 196 if (!timer_pending(&q->timeout) || 197 time_before(expiry, q->timeout.expires)) 198 mod_timer(&q->timeout, expiry); | 193 194 /* 195 * If the timer isn't already pending or this timeout is earlier 196 * than an existing one, modify the timer. Round up to next nearest 197 * second. 198 */ 199 expiry = round_jiffies_up(req->deadline); 200 201 if (!timer_pending(&q->timeout) || 202 time_before(expiry, q->timeout.expires)) 203 mod_timer(&q->timeout, expiry); |
204 |
|
199} 200 | 205} 206 |
207/** 208 * blk_add_timer - Start timeout timer for a single request 209 * @req: request that is about to start running. 210 * 211 * Notes: 212 * Each request has its own timer, and as it is added to the queue, we 213 * set up the timer. When the request completes, we cancel the timer. 214 */ 215void blk_add_timer(struct request *req) 216{ 217 __blk_add_timer(req, &req->q->timeout_list); 218} 219 |
|