diff options
author | Daniel Rosenthal <danielrosenthal@acm.org> | 2008-10-05 17:43:10 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-10-08 06:26:38 -0400 |
commit | 63fd7f30f328f99956d3c774d17219c3c8d54131 (patch) | |
tree | d99fed43f643798b44052335af41ca5803250d17 /drivers/mtd/inftlcore.c | |
parent | f324277cf70ad284dd99acf5ac5101e32bc8c55b (diff) |
[MTD] [INFTL] Fix infinite loop in INFTL_foldchain
When iterating over a chain in reverse (oldest block first), this
patch correctly marks the PUtable[] entry of the second to last erase
block of a chain as BLOCK_NIL, regardless of whether or not it can
format the last block successfully. Before, the second to last block
was only marked as pointing to BLOCK_NIL if INFTL_formatblock()
succeeded on the last block of the chain, which could potentially
result in an infinite loop if the block was worn out and refused to
format.
Signed-off-by: Daniel Rosenthal <danielrosenthal@acm.org>
Acked-by: Greg Ungerer <gerg@snapgear.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/inftlcore.c')
-rw-r--r-- | drivers/mtd/inftlcore.c | 5 |
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c index c4f9d3378b24..50ce13887f63 100644 --- a/drivers/mtd/inftlcore.c +++ b/drivers/mtd/inftlcore.c | |||
@@ -388,6 +388,10 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned | |||
388 | if (thisEUN == targetEUN) | 388 | if (thisEUN == targetEUN) |
389 | break; | 389 | break; |
390 | 390 | ||
391 | /* Unlink the last block from the chain. */ | ||
392 | inftl->PUtable[prevEUN] = BLOCK_NIL; | ||
393 | |||
394 | /* Now try to erase it. */ | ||
391 | if (INFTL_formatblock(inftl, thisEUN) < 0) { | 395 | if (INFTL_formatblock(inftl, thisEUN) < 0) { |
392 | /* | 396 | /* |
393 | * Could not erase : mark block as reserved. | 397 | * Could not erase : mark block as reserved. |
@@ -396,7 +400,6 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned | |||
396 | } else { | 400 | } else { |
397 | /* Correctly erased : mark it as free */ | 401 | /* Correctly erased : mark it as free */ |
398 | inftl->PUtable[thisEUN] = BLOCK_FREE; | 402 | inftl->PUtable[thisEUN] = BLOCK_FREE; |
399 | inftl->PUtable[prevEUN] = BLOCK_NIL; | ||
400 | inftl->numfreeEUNs++; | 403 | inftl->numfreeEUNs++; |
401 | } | 404 | } |
402 | } | 405 | } |