aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/inftlcore.c
diff options
context:
space:
mode:
authorDaniel Rosenthal <danielrosenthal@acm.org>2008-10-05 17:43:10 -0400
committerDavid Woodhouse <David.Woodhouse@intel.com>2008-10-08 11:26:38 +0100
commit63fd7f30f328f99956d3c774d17219c3c8d54131 (patch)
treed99fed43f643798b44052335af41ca5803250d17 /drivers/mtd/inftlcore.c
parentf324277cf70ad284dd99acf5ac5101e32bc8c55b (diff)
downloadkernel_samsung_smdk4412-63fd7f30f328f99956d3c774d17219c3c8d54131.zip
kernel_samsung_smdk4412-63fd7f30f328f99956d3c774d17219c3c8d54131.tar.gz
kernel_samsung_smdk4412-63fd7f30f328f99956d3c774d17219c3c8d54131.tar.bz2
[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.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index c4f9d33..50ce138 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
if (thisEUN == targetEUN)
break;
+ /* Unlink the last block from the chain. */
+ inftl->PUtable[prevEUN] = BLOCK_NIL;
+
+ /* Now try to erase it. */
if (INFTL_formatblock(inftl, thisEUN) < 0) {
/*
* Could not erase : mark block as reserved.
@@ -396,7 +400,6 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
} else {
/* Correctly erased : mark it as free */
inftl->PUtable[thisEUN] = BLOCK_FREE;
- inftl->PUtable[prevEUN] = BLOCK_NIL;
inftl->numfreeEUNs++;
}
}