提交 6c55be8b 编写于 作者: D Dan Williams 提交者: Linus Torvalds

raid5: fix unending write sequence

<debug output from Joel's system>
handling stripe 7629696, state=0x14 cnt=1, pd_idx=2 ops=0:0:0
check 5: state 0x6 toread 0000000000000000 read 0000000000000000 write fffff800ffcffcc0 written 0000000000000000
check 4: state 0x6 toread 0000000000000000 read 0000000000000000 write fffff800fdd4e360 written 0000000000000000
check 3: state 0x1 toread 0000000000000000 read 0000000000000000 write 0000000000000000 written 0000000000000000
check 2: state 0x1 toread 0000000000000000 read 0000000000000000 write 0000000000000000 written 0000000000000000
check 1: state 0x6 toread 0000000000000000 read 0000000000000000 write fffff800ff517e40 written 0000000000000000
check 0: state 0x6 toread 0000000000000000 read 0000000000000000 write fffff800fd4cae60 written 0000000000000000
locked=4 uptodate=2 to_read=0 to_write=4 failed=0 failed_num=0
for sector 7629696, rmw=0 rcw=0
</debug>

These blocks were prepared to be written out, but were never handled in
ops_run_biodrain(), so they remain locked forever.  The operations flags
are all clear which means handle_stripe() thinks nothing else needs to be
done.

This state suggests that the STRIPE_OP_PREXOR bit was sampled 'set' when it
should not have been.  This patch cleans up cases where the code looks at
sh->ops.pending when it should be looking at the consistent stack-based
snapshot of the operations flags.

Report from Joel:
	Resync done. Patch fix this bug.
Signed-off-by: NDan Williams <dan.j.williams@intel.com>
Tested-by: NJoel Bertrand <joel.bertrand@systella.fr>
Cc: <stable@kernel.org>
Cc: Neil Brown <neilb@suse.de>
Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
上级 5b23dbe8
...@@ -688,7 +688,8 @@ ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) ...@@ -688,7 +688,8 @@ ops_run_prexor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
} }
static struct dma_async_tx_descriptor * static struct dma_async_tx_descriptor *
ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
unsigned long pending)
{ {
int disks = sh->disks; int disks = sh->disks;
int pd_idx = sh->pd_idx, i; int pd_idx = sh->pd_idx, i;
...@@ -696,7 +697,7 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) ...@@ -696,7 +697,7 @@ ops_run_biodrain(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
/* check if prexor is active which means only process blocks /* check if prexor is active which means only process blocks
* that are part of a read-modify-write (Wantprexor) * that are part of a read-modify-write (Wantprexor)
*/ */
int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending); int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
pr_debug("%s: stripe %llu\n", __FUNCTION__, pr_debug("%s: stripe %llu\n", __FUNCTION__,
(unsigned long long)sh->sector); (unsigned long long)sh->sector);
...@@ -773,7 +774,8 @@ static void ops_complete_write(void *stripe_head_ref) ...@@ -773,7 +774,8 @@ static void ops_complete_write(void *stripe_head_ref)
} }
static void static void
ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx,
unsigned long pending)
{ {
/* kernel stack size limits the total number of disks */ /* kernel stack size limits the total number of disks */
int disks = sh->disks; int disks = sh->disks;
...@@ -781,7 +783,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) ...@@ -781,7 +783,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
int count = 0, pd_idx = sh->pd_idx, i; int count = 0, pd_idx = sh->pd_idx, i;
struct page *xor_dest; struct page *xor_dest;
int prexor = test_bit(STRIPE_OP_PREXOR, &sh->ops.pending); int prexor = test_bit(STRIPE_OP_PREXOR, &pending);
unsigned long flags; unsigned long flags;
dma_async_tx_callback callback; dma_async_tx_callback callback;
...@@ -808,7 +810,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx) ...@@ -808,7 +810,7 @@ ops_run_postxor(struct stripe_head *sh, struct dma_async_tx_descriptor *tx)
} }
/* check whether this postxor is part of a write */ /* check whether this postxor is part of a write */
callback = test_bit(STRIPE_OP_BIODRAIN, &sh->ops.pending) ? callback = test_bit(STRIPE_OP_BIODRAIN, &pending) ?
ops_complete_write : ops_complete_postxor; ops_complete_write : ops_complete_postxor;
/* 1/ if we prexor'd then the dest is reused as a source /* 1/ if we prexor'd then the dest is reused as a source
...@@ -896,12 +898,12 @@ static void raid5_run_ops(struct stripe_head *sh, unsigned long pending) ...@@ -896,12 +898,12 @@ static void raid5_run_ops(struct stripe_head *sh, unsigned long pending)
tx = ops_run_prexor(sh, tx); tx = ops_run_prexor(sh, tx);
if (test_bit(STRIPE_OP_BIODRAIN, &pending)) { if (test_bit(STRIPE_OP_BIODRAIN, &pending)) {
tx = ops_run_biodrain(sh, tx); tx = ops_run_biodrain(sh, tx, pending);
overlap_clear++; overlap_clear++;
} }
if (test_bit(STRIPE_OP_POSTXOR, &pending)) if (test_bit(STRIPE_OP_POSTXOR, &pending))
ops_run_postxor(sh, tx); ops_run_postxor(sh, tx, pending);
if (test_bit(STRIPE_OP_CHECK, &pending)) if (test_bit(STRIPE_OP_CHECK, &pending))
ops_run_check(sh); ops_run_check(sh);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册