* [PATCH] target/iblock: Fix double iblock_complete_cmd callback bug
@ 2012-11-08 19:58 Nicholas A. Bellinger
2012-11-15 10:49 ` Christoph Hellwig
0 siblings, 1 reply; 5+ messages in thread
From: Nicholas A. Bellinger @ 2012-11-08 19:58 UTC (permalink / raw)
To: target-devel; +Cc: linux-scsi, Nicholas Bellinger, Christoph Hellwig, stable
From: Nicholas Bellinger <nab@linux-iscsi.org>
This patch fixes a double completion bug where ibr->pending = 2 usage
plus the extra callback to iblock_complete_cmd() invoked after bio
submission in iblock_execute_rw() can interfere with the normal
bio->bi_done() -> iblock_bio_done() -> iblock_complete_cmd() completion
path, causing a double target_complete_cmd() call to occur.
This bug was introduced during v3.4-rc2 code with:
commit 5787cacd0bd5ee016ad807b244550d34fe2beebe
Author: Christoph Hellwig <hch@infradead.org>
Date: Tue Apr 24 00:25:06 2012 -0400
target: remove struct se_task
Also drop the bio_cnt >= IBLOCK_MAX_BIO_PER_TASK rolling call to
iblock_submit_bios() to avoid the exception case where outstanding
bios completing via iblock_bio_done() are not accounted for when
returning returning non zero from iblock_execute_rw().
This bug was originally reported by Kelsey when a single se_cmd
descriptor required more than one bio to complete.
Reported-by: Kelsey Prantis <kelsey.prantis@intel.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: stable@vger.kernel.org
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
---
drivers/target/target_core_iblock.c | 11 +----------
1 files changed, 1 insertions(+), 10 deletions(-)
diff --git a/drivers/target/target_core_iblock.c b/drivers/target/target_core_iblock.c
index 57d7674..d066932 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -47,7 +47,6 @@
#include "target_core_iblock.h"
-#define IBLOCK_MAX_BIO_PER_TASK 32 /* max # of bios to submit at a time */
#define IBLOCK_BIO_POOL_SIZE 128
static struct se_subsystem_api iblock_template;
@@ -602,7 +601,6 @@ static int iblock_execute_rw(struct se_cmd *cmd)
struct scatterlist *sg;
u32 sg_num = sgl_nents;
sector_t block_lba;
- unsigned bio_cnt;
int rw;
int i;
@@ -658,8 +656,7 @@ static int iblock_execute_rw(struct se_cmd *cmd)
bio_list_init(&list);
bio_list_add(&list, bio);
- atomic_set(&ibr->pending, 2);
- bio_cnt = 1;
+ atomic_set(&ibr->pending, 1);
for_each_sg(sgl, sg, sgl_nents, i) {
/*
@@ -669,10 +666,6 @@ static int iblock_execute_rw(struct se_cmd *cmd)
*/
while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset)
!= sg->length) {
- if (bio_cnt >= IBLOCK_MAX_BIO_PER_TASK) {
- iblock_submit_bios(&list, rw);
- bio_cnt = 0;
- }
bio = iblock_get_bio(cmd, block_lba, sg_num);
if (!bio)
@@ -680,7 +673,6 @@ static int iblock_execute_rw(struct se_cmd *cmd)
atomic_inc(&ibr->pending);
bio_list_add(&list, bio);
- bio_cnt++;
}
/* Always in 512 byte units for Linux/Block */
@@ -689,7 +681,6 @@ static int iblock_execute_rw(struct se_cmd *cmd)
}
iblock_submit_bios(&list, rw);
- iblock_complete_cmd(cmd);
return 0;
fail_put_bios:
--
1.7.2.5
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] target/iblock: Fix double iblock_complete_cmd callback bug
2012-11-08 19:58 [PATCH] target/iblock: Fix double iblock_complete_cmd callback bug Nicholas A. Bellinger
@ 2012-11-15 10:49 ` Christoph Hellwig
2012-11-15 22:36 ` Nicholas A. Bellinger
0 siblings, 1 reply; 5+ messages in thread
From: Christoph Hellwig @ 2012-11-15 10:49 UTC (permalink / raw)
To: Nicholas A. Bellinger; +Cc: target-devel, linux-scsi, Christoph Hellwig, stable
On Thu, Nov 08, 2012 at 07:58:59PM +0000, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger <nab@linux-iscsi.org>
>
> This patch fixes a double completion bug where ibr->pending = 2 usage
> plus the extra callback to iblock_complete_cmd() invoked after bio
> submission in iblock_execute_rw() can interfere with the normal
> bio->bi_done() -> iblock_bio_done() -> iblock_complete_cmd() completion
> path, causing a double target_complete_cmd() call to occur.
How so exactly? Please provide an explanation, and preferably a test
case.
> Also drop the bio_cnt >= IBLOCK_MAX_BIO_PER_TASK rolling call to
> iblock_submit_bios() to avoid the exception case where outstanding
> bios completing via iblock_bio_done() are not accounted for when
> returning returning non zero from iblock_execute_rw().
This will cause deadlocks when we can't allocate enough bios for
a too large request.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] target/iblock: Fix double iblock_complete_cmd callback bug
2012-11-15 10:49 ` Christoph Hellwig
@ 2012-11-15 22:36 ` Nicholas A. Bellinger
2012-11-15 22:50 ` Nicholas A. Bellinger
2012-11-16 19:25 ` Christoph Hellwig
0 siblings, 2 replies; 5+ messages in thread
From: Nicholas A. Bellinger @ 2012-11-15 22:36 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: target-devel, linux-scsi, Christoph Hellwig, Jens Axboe
On Thu, 2012-11-15 at 05:49 -0500, Christoph Hellwig wrote:
> On Thu, Nov 08, 2012 at 07:58:59PM +0000, Nicholas A. Bellinger wrote:
> > From: Nicholas Bellinger <nab@linux-iscsi.org>
> >
> > This patch fixes a double completion bug where ibr->pending = 2 usage
> > plus the extra callback to iblock_complete_cmd() invoked after bio
> > submission in iblock_execute_rw() can interfere with the normal
> > bio->bi_done() -> iblock_bio_done() -> iblock_complete_cmd() completion
> > path, causing a double target_complete_cmd() call to occur.
>
> How so exactly? Please provide an explanation, and preferably a test
> case.
>
So, I was getting a bit confused here while debugging Kelsey's issue
with dispatched multiple bios throwing an with a virtio-blk backend.
However, setting the default ibr->pending=2 value before dispatch, and
making a extra iblock_complete_cmd() call from iblock_execute_rw(),
while doing the normal iblock_complete_cmd() calls from
iblock_bio_done() is AFAICT a pointless extra atomic_dec_and_test() call
per I/O.
Was there a reason why you changed ->pending from 1 -> 2 during the
se_task removal in commit 5787cacd0bd5ee01..?
> > Also drop the bio_cnt >= IBLOCK_MAX_BIO_PER_TASK rolling call to
> > iblock_submit_bios() to avoid the exception case where outstanding
> > bios completing via iblock_bio_done() are not accounted for when
> > returning returning non zero from iblock_execute_rw().
>
> This will cause deadlocks when we can't allocate enough bios for
> a too large request.
>
Mmmm..
So the case this patch tries to avoid is where iblock_submit_bio() is
called multiple times before the final ibr->pending value is set, this
could potentially cause bios completion calls to decrement the value +
complete to core before iblock_execute_rw() is done incrementing
ibr->pending.
How about returning an exception here instead when IBLOCK_MAX_BIOS in
reached..? Btw, where did the default of 32 for this come from..?
--nab
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] target/iblock: Fix double iblock_complete_cmd callback bug
2012-11-15 22:36 ` Nicholas A. Bellinger
@ 2012-11-15 22:50 ` Nicholas A. Bellinger
2012-11-16 19:25 ` Christoph Hellwig
1 sibling, 0 replies; 5+ messages in thread
From: Nicholas A. Bellinger @ 2012-11-15 22:50 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: target-devel, linux-scsi, Christoph Hellwig, Jens Axboe
On Thu, 2012-11-15 at 14:36 -0800, Nicholas A. Bellinger wrote:
> On Thu, 2012-11-15 at 05:49 -0500, Christoph Hellwig wrote:
> > On Thu, Nov 08, 2012 at 07:58:59PM +0000, Nicholas A. Bellinger wrote:
> > > From: Nicholas Bellinger <nab@linux-iscsi.org>
> > >
> > > This patch fixes a double completion bug where ibr->pending = 2 usage
> > > plus the extra callback to iblock_complete_cmd() invoked after bio
> > > submission in iblock_execute_rw() can interfere with the normal
> > > bio->bi_done() -> iblock_bio_done() -> iblock_complete_cmd() completion
> > > path, causing a double target_complete_cmd() call to occur.
> >
> > How so exactly? Please provide an explanation, and preferably a test
> > case.
> >
>
> So, I was getting a bit confused here while debugging Kelsey's issue
> with dispatched multiple bios throwing an with a virtio-blk backend.
>
> However, setting the default ibr->pending=2 value before dispatch, and
> making a extra iblock_complete_cmd() call from iblock_execute_rw(),
> while doing the normal iblock_complete_cmd() calls from
> iblock_bio_done() is AFAICT a pointless extra atomic_dec_and_test() call
> per I/O.
>
> Was there a reason why you changed ->pending from 1 -> 2 during the
> se_task removal in commit 5787cacd0bd5ee01..?
>
> > > Also drop the bio_cnt >= IBLOCK_MAX_BIO_PER_TASK rolling call to
> > > iblock_submit_bios() to avoid the exception case where outstanding
> > > bios completing via iblock_bio_done() are not accounted for when
> > > returning returning non zero from iblock_execute_rw().
> >
> > This will cause deadlocks when we can't allocate enough bios for
> > a too large request.
> >
>
> Mmmm..
>
> So the case this patch tries to avoid is where iblock_submit_bio() is
> called multiple times before the final ibr->pending value is set, this
> could potentially cause bios completion calls to decrement the value +
> complete to core before iblock_execute_rw() is done incrementing
> ibr->pending.
>
Err, nevermind.. Dropping this patch as v3.7 material for the moment
while debugging the Kelsey's multiple-bio IBLOCK+virtio-blk bug..
> How about returning an exception here instead when IBLOCK_MAX_BIOS in
> reached..? Btw, where did the default of 32 for this come from..?
>
Still curious where this value comes from..? :)
--nab
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] target/iblock: Fix double iblock_complete_cmd callback bug
2012-11-15 22:36 ` Nicholas A. Bellinger
2012-11-15 22:50 ` Nicholas A. Bellinger
@ 2012-11-16 19:25 ` Christoph Hellwig
1 sibling, 0 replies; 5+ messages in thread
From: Christoph Hellwig @ 2012-11-16 19:25 UTC (permalink / raw)
To: Nicholas A. Bellinger
Cc: Christoph Hellwig, target-devel, linux-scsi, Christoph Hellwig,
Jens Axboe
On Thu, Nov 15, 2012 at 02:36:30PM -0800, Nicholas A. Bellinger wrote:
> However, setting the default ibr->pending=2 value before dispatch, and
> making a extra iblock_complete_cmd() call from iblock_execute_rw(),
> while doing the normal iblock_complete_cmd() calls from
> iblock_bio_done() is AFAICT a pointless extra atomic_dec_and_test() call
> per I/O.
>
> Was there a reason why you changed ->pending from 1 -> 2 during the
> se_task removal in commit 5787cacd0bd5ee01..?
It is to avoid having the request completed before even submitting all
bios. As soon as one is submitted it could on a very fast device
complete before we've incremented the count for the next bio.
It's a very common scheme used all over the kernel when submitting
I/O in smaller subdivisions.
> So the case this patch tries to avoid is where iblock_submit_bio() is
> called multiple times before the final ibr->pending value is set, this
> could potentially cause bios completion calls to decrement the value +
> complete to core before iblock_execute_rw() is done incrementing
> ibr->pending.
That's exacltly what we try to avoid here.
> How about returning an exception here instead when IBLOCK_MAX_BIOS in
> reached..?
Why? As soon as we kicked the first batch off we're guaranteed to make
progress allocating more as sson as the first of the submitted ones
completes.
> Btw, where did the default of 32 for this come from..?
It's a random number, with the important property that it's considerably
smaller than IBLOCK_BIO_POOL_SIZE.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2012-11-16 19:25 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-11-08 19:58 [PATCH] target/iblock: Fix double iblock_complete_cmd callback bug Nicholas A. Bellinger
2012-11-15 10:49 ` Christoph Hellwig
2012-11-15 22:36 ` Nicholas A. Bellinger
2012-11-15 22:50 ` Nicholas A. Bellinger
2012-11-16 19:25 ` Christoph Hellwig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).