@@ -981,6 +981,9 @@ EXPORT_SYMBOL(blk_make_request);
*/
void blk_requeue_request(struct request_queue *q, struct request *rq)
{
+ if (test_bit(REQ_ATOM_TIMEDOUT, &rq->atomic_flags))
+ return;
+
blk_delete_timer(rq);
blk_clear_rq_complete(rq);
trace_block_rq_requeue(q, rq);
@@ -156,8 +156,10 @@ void blk_complete_request(struct request *req)
{
if (unlikely(blk_should_fake_timeout(req->q)))
return;
- if (!blk_mark_rq_complete(req))
+ if (!blk_mark_rq_complete(req)) {
+ blk_clear_rq_timedout(req);
__blk_complete_request(req);
+ }
}
EXPORT_SYMBOL(blk_complete_request);
@@ -97,6 +97,7 @@ static void blk_rq_timed_out(struct request *req)
* and we can move more of the generic scsi eh code to
* the blk layer.
*/
+ blk_mark_rq_timedout(req);
break;
default:
printk(KERN_ERR "block: bad eh return: %d\n", ret);
@@ -104,6 +105,25 @@ static void blk_rq_timed_out(struct request *req)
}
}
+/**
+ * blk_requeue_timedout_request - put a request that timedout back on queue
+ * @q: request queue where request should be inserted
+ * @rq: request to be inserted
+ *
+ * Description:
+ * If a module has returned BLK_EH_NOT_HANDLED from its
+ * rq_timed_out_fn and needs to requeue the request this
+ * function should be used instead of blk_requeue_request.
+ *
+ * queue_lock must be held.
+ */
+void blk_requeue_timedout_request(struct request_queue *q, struct request *req)
+{
+ blk_clear_rq_timedout(req);
+ blk_requeue_request(q, req);
+}
+EXPORT_SYMBOL_GPL(blk_requeue_timedout_request);
+
void blk_rq_timed_out_timer(unsigned long data)
{
struct request_queue *q = (struct request_queue *) data;
@@ -30,6 +30,7 @@ void __generic_unplug_device(struct request_queue *);
*/
enum rq_atomic_flags {
REQ_ATOM_COMPLETE = 0,
+ REQ_ATOM_TIMEDOUT = 1,
};
/*
@@ -46,7 +47,15 @@ static inline void blk_clear_rq_complete(struct request *rq)
clear_bit(REQ_ATOM_COMPLETE, &rq->atomic_flags);
}
-/*
+static inline int blk_mark_rq_timedout(struct request *rq)
+{
+ return test_and_set_bit(REQ_ATOM_TIMEDOUT, &rq->atomic_flags);
+}
+
+static inline void blk_clear_rq_timedout(struct request *rq)
+{
+ clear_bit(REQ_ATOM_TIMEDOUT, &rq->atomic_flags);
+}/*
* Internal elevator interface
*/
#define ELV_ON_HASH(rq) (!hlist_unhashed(&(rq)->hash))
@@ -1680,7 +1680,11 @@ void scsi_eh_flush_done_q(struct list_head *done_q)
" retry cmd: %p\n",
current->comm,
scmd));
- scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY);
+ printk(KERN_ERR "scmd %p %p %p\n", scmd,
+ scmd->eh_entry.next, scmd->eh_entry.prev);
+
+ scsi_queue_insert(scmd,
+ SCSI_MLQUEUE_EH_TIMEDOUT_RETRY);
} else {
/*
* If just we got sense for the device (called
@@ -158,7 +158,10 @@ static int __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy)
* and plugs the queue appropriately.
*/
spin_lock_irqsave(q->queue_lock, flags);
- blk_requeue_request(q, cmd->request);
+ if (reason == SCSI_MLQUEUE_EH_TIMEDOUT_RETRY)
+ blk_requeue_timedout_request(q, cmd->request);
+ else
+ blk_requeue_request(q, cmd->request);
spin_unlock_irqrestore(q->queue_lock, flags);
scsi_run_queue(q);
@@ -205,7 +205,10 @@ typedef int (dma_drain_needed_fn)(struct request *);
typedef int (lld_busy_fn) (struct request_queue *q);
enum blk_eh_timer_return {
- BLK_EH_NOT_HANDLED,
+ BLK_EH_NOT_HANDLED, /* If this is returned the module must
+ * call blk_requeue_timedout_request to
+ * requeue it
+ */
BLK_EH_HANDLED,
BLK_EH_RESET_TIMER,
};
@@ -653,6 +656,8 @@ extern struct request *blk_get_request(struct request_queue *, int, gfp_t);
extern struct request *blk_make_request(struct request_queue *, struct bio *,
gfp_t);
extern void blk_insert_request(struct request_queue *, struct request *, int, void *);
+extern void blk_requeue_timedout_request(struct request_queue *,
+ struct request *);
extern void blk_requeue_request(struct request_queue *, struct request *);
extern void blk_add_request_payload(struct request *rq, struct page *page,
unsigned int len);
@@ -442,6 +442,7 @@ static inline int scsi_is_wlun(unsigned int lun)
#define SCSI_MLQUEUE_DEVICE_BUSY 0x1056
#define SCSI_MLQUEUE_EH_RETRY 0x1057
#define SCSI_MLQUEUE_TARGET_BUSY 0x1058
+#define SCSI_MLQUEUE_EH_TIMEDOUT_RETRY 0x1059
/*
* Use these to separate status msg and our bytes