aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/ubi/eba.c
diff options
context:
space:
mode:
authorArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-05-24 07:13:34 -0400
committerArtem Bityutskiy <Artem.Bityutskiy@nokia.com>2009-06-02 06:53:35 -0400
commitb86a2c56e512f46d140a4bcb4e35e8a7d4a99a4b (patch)
tree59c3e036dfd767b73e700bd7fd8cb4bee15c4f58 /drivers/mtd/ubi/eba.c
parent87960c0b12d0c5a0b37e0c79aef77aa1a0b10d44 (diff)
UBI: do not switch to R/O mode on read errors
This patch improves UBI errors handling. ATM UBI switches to R/O mode when the WL worker fails to read the source PEB. This means that the upper layers (e.g., UBIFS) has no chances to unmap the erroneous PEB and fix the error. This patch changes this behaviour and makes UBI put PEBs like this into a separate RB-tree, thus preventing the WL worker from hitting the same read errors again and again. But there is a 10% limit on a maximum amount of PEBs like this. If there are too much of them, UBI switches to R/O mode. Additionally, this patch teaches UBI not to panic and switch to R/O mode if after a PEB has been copied, the target LEB cannot be read back. Instead, now UBI cancels the operation and schedules the target PEB for torturing. The error paths has been tested by ingecting errors into 'ubi_eba_copy_leb()'. Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy@nokia.com>
Diffstat (limited to 'drivers/mtd/ubi/eba.c')
-rw-r--r--drivers/mtd/ubi/eba.c19
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c
index 587b6cb5040f..632b95f3ff3f 100644
--- a/drivers/mtd/ubi/eba.c
+++ b/drivers/mtd/ubi/eba.c
@@ -419,8 +419,9 @@ retry:
419 * not implemented. 419 * not implemented.
420 */ 420 */
421 if (err == UBI_IO_BAD_VID_HDR) { 421 if (err == UBI_IO_BAD_VID_HDR) {
422 ubi_warn("bad VID header at PEB %d, LEB" 422 ubi_warn("corrupted VID header at PEB "
423 "%d:%d", pnum, vol_id, lnum); 423 "%d, LEB %d:%d", pnum, vol_id,
424 lnum);
424 err = -EBADMSG; 425 err = -EBADMSG;
425 } else 426 } else
426 ubi_ro_mode(ubi); 427 ubi_ro_mode(ubi);
@@ -1032,6 +1033,8 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
1032 if (err && err != UBI_IO_BITFLIPS) { 1033 if (err && err != UBI_IO_BITFLIPS) {
1033 ubi_warn("error %d while reading data from PEB %d", 1034 ubi_warn("error %d while reading data from PEB %d",
1034 err, from); 1035 err, from);
1036 if (err == -EIO)
1037 err = MOVE_SOURCE_RD_ERR;
1035 goto out_unlock_buf; 1038 goto out_unlock_buf;
1036 } 1039 }
1037 1040
@@ -1078,9 +1081,11 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
1078 /* Read the VID header back and check if it was written correctly */ 1081 /* Read the VID header back and check if it was written correctly */
1079 err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1); 1082 err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1);
1080 if (err) { 1083 if (err) {
1081 if (err != UBI_IO_BITFLIPS) 1084 if (err != UBI_IO_BITFLIPS) {
1082 ubi_warn("cannot read VID header back from PEB %d", to); 1085 ubi_warn("cannot read VID header back from PEB %d", to);
1083 else 1086 if (err == -EIO)
1087 err = MOVE_TARGET_RD_ERR;
1088 } else
1084 err = MOVE_CANCEL_BITFLIPS; 1089 err = MOVE_CANCEL_BITFLIPS;
1085 goto out_unlock_buf; 1090 goto out_unlock_buf;
1086 } 1091 }
@@ -1102,10 +1107,12 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to,
1102 1107
1103 err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size); 1108 err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size);
1104 if (err) { 1109 if (err) {
1105 if (err != UBI_IO_BITFLIPS) 1110 if (err != UBI_IO_BITFLIPS) {
1106 ubi_warn("cannot read data back from PEB %d", 1111 ubi_warn("cannot read data back from PEB %d",
1107 to); 1112 to);
1108 else 1113 if (err == -EIO)
1114 err = MOVE_TARGET_RD_ERR;
1115 } else
1109 err = MOVE_CANCEL_BITFLIPS; 1116 err = MOVE_CANCEL_BITFLIPS;
1110 goto out_unlock_buf; 1117 goto out_unlock_buf;
1111 } 1118 }