| From e801e128b2200c40a0ec236cf2330b2586b6e05a Mon Sep 17 00:00:00 2001 |
| From: Bhavesh Parekh <bparekh@nvidia.com> |
| Date: Wed, 30 Nov 2011 17:43:42 +0530 |
| Subject: UBI: fix missing scrub when there is a bit-flip |
| |
| From: Bhavesh Parekh <bparekh@nvidia.com> |
| |
| commit e801e128b2200c40a0ec236cf2330b2586b6e05a upstream. |
| |
| Under some cases, when scrubbing the PEB if we did not get the lock on |
| the PEB it fails to scrub. Add that PEB again to the scrub list |
| |
| Artem: minor amendments. |
| |
| Signed-off-by: Bhavesh Parekh <bparekh@nvidia.com> |
| Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| drivers/mtd/ubi/eba.c | 6 ++++-- |
| drivers/mtd/ubi/ubi.h | 2 ++ |
| drivers/mtd/ubi/wl.c | 5 ++++- |
| 3 files changed, 10 insertions(+), 3 deletions(-) |
| |
| --- a/drivers/mtd/ubi/eba.c |
| +++ b/drivers/mtd/ubi/eba.c |
| @@ -1028,12 +1028,14 @@ int ubi_eba_copy_leb(struct ubi_device * |
| * 'ubi_wl_put_peb()' function on the @ubi->move_mutex. In turn, we are |
| * holding @ubi->move_mutex and go sleep on the LEB lock. So, if the |
| * LEB is already locked, we just do not move it and return |
| - * %MOVE_CANCEL_RACE, which means that UBI will re-try, but later. |
| + * %MOVE_RETRY. Note, we do not return %MOVE_CANCEL_RACE here because |
| + * we do not know the reasons of the contention - it may be just a |
| + * normal I/O on this LEB, so we want to re-try. |
| */ |
| err = leb_write_trylock(ubi, vol_id, lnum); |
| if (err) { |
| dbg_wl("contention on LEB %d:%d, cancel", vol_id, lnum); |
| - return MOVE_CANCEL_RACE; |
| + return MOVE_RETRY; |
| } |
| |
| /* |
| --- a/drivers/mtd/ubi/ubi.h |
| +++ b/drivers/mtd/ubi/ubi.h |
| @@ -121,6 +121,7 @@ enum { |
| * PEB |
| * MOVE_CANCEL_BITFLIPS: canceled because a bit-flip was detected in the |
| * target PEB |
| + * MOVE_RETRY: retry scrubbing the PEB |
| */ |
| enum { |
| MOVE_CANCEL_RACE = 1, |
| @@ -128,6 +129,7 @@ enum { |
| MOVE_TARGET_RD_ERR, |
| MOVE_TARGET_WR_ERR, |
| MOVE_CANCEL_BITFLIPS, |
| + MOVE_RETRY, |
| }; |
| |
| /** |
| --- a/drivers/mtd/ubi/wl.c |
| +++ b/drivers/mtd/ubi/wl.c |
| @@ -792,7 +792,10 @@ static int wear_leveling_worker(struct u |
| protect = 1; |
| goto out_not_moved; |
| } |
| - |
| + if (err == MOVE_RETRY) { |
| + scrubbing = 1; |
| + goto out_not_moved; |
| + } |
| if (err == MOVE_CANCEL_BITFLIPS || err == MOVE_TARGET_WR_ERR || |
| err == MOVE_TARGET_RD_ERR) { |
| /* |