From patchwork Wed Nov 10 07:09:24 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Christie X-Patchwork-Id: 313292 Received: from mx4-phx2.redhat.com (mx4-phx2.redhat.com [209.132.183.25]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id oAA74hvh002728 for ; Wed, 10 Nov 2010 07:05:04 GMT Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by mx4-phx2.redhat.com (8.13.8/8.13.8) with ESMTP id oAA72FW6029363; Wed, 10 Nov 2010 02:02:16 -0500 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id oAA72ETj029643 for ; Wed, 10 Nov 2010 02:02:14 -0500 Received: from mx1.redhat.com (ext-mx09.extmail.prod.ext.phx2.redhat.com [10.5.110.13]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id oAA7292i023688 for ; Wed, 10 Nov 2010 02:02:09 -0500 Received: from sabe.cs.wisc.edu (sabe.cs.wisc.edu [128.105.6.20]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oAA71sTU030406 for ; Wed, 10 Nov 2010 02:01:54 -0500 Received: from [20.15.0.9] (c-76-17-202-29.hsd1.mn.comcast.net [76.17.202.29]) (authenticated bits=0) by sabe.cs.wisc.edu (8.14.1/8.14.1) with ESMTP id oAA71m2p008995 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 10 Nov 2010 01:01:48 -0600 Message-ID: <4CDA4524.4010204@cs.wisc.edu> Date: Wed, 10 Nov 2010 01:09:24 -0600 From: Mike Christie User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.12) Gecko/20100907 Fedora/3.0.7-1.fc12 Thunderbird/3.0.7 MIME-Version: 1.0 To: device-mapper development References: <20100512052336.GB15240@linux.vnet.ibm.com> In-Reply-To: <20100512052336.GB15240@linux.vnet.ibm.com> X-RedHat-Spam-Score: -0.01 (T_RP_MATCHES_RCVD) X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-Scanned-By: MIMEDefang 2.67 on 10.5.110.13 X-loop: dm-devel@redhat.com Cc: Mike Anderson , James Bottomley , linux-scsi@vger.kernel.org, Jens Axboe Subject: Re: [dm-devel] block_abort_queue (blk_abort_request) racing with scsi_request_fn X-BeenThere: dm-devel@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk Reply-To: device-mapper development List-Id: device-mapper development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: dm-devel-bounces@redhat.com Errors-To: dm-devel-bounces@redhat.com X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter1.kernel.org [140.211.167.41]); Wed, 10 Nov 2010 07:05:04 +0000 (UTC) diff --git a/block/blk-core.c b/block/blk-core.c index f0834e2..92279d4 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -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); diff --git a/block/blk-softirq.c b/block/blk-softirq.c index ee9c216..e0a8d11 100644 --- a/block/blk-softirq.c +++ b/block/blk-softirq.c @@ -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); diff --git a/block/blk-timeout.c b/block/blk-timeout.c index 4f0c06c..afc6e5f 100644 --- a/block/blk-timeout.c +++ b/block/blk-timeout.c @@ -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; diff --git a/block/blk.h b/block/blk.h index 2db8f32..ad93258 100644 --- a/block/blk.h +++ b/block/blk.h @@ -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)) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 1de30eb..06df25a 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -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 diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index eafeeda..cef49b2 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -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); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 5027a59..e56f28e 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -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); diff --git a/include/scsi/scsi.h b/include/scsi/scsi.h index 216af85..5bde952 100644 --- a/include/scsi/scsi.h +++ b/include/scsi/scsi.h @@ -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