diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-05-24 14:13:34 +0300 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2009-06-02 13:53:35 +0300 |
commit | b86a2c56e512f46d140a4bcb4e35e8a7d4a99a4b (patch) | |
tree | 59c3e036dfd767b73e700bd7fd8cb4bee15c4f58 /drivers/mtd/ubi/eba.c | |
parent | 87960c0b12d0c5a0b37e0c79aef77aa1a0b10d44 (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.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 587b6cb5040..632b95f3ff3 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -419,8 +419,9 @@ retry: * not implemented. */ if (err == UBI_IO_BAD_VID_HDR) { - ubi_warn("bad VID header at PEB %d, LEB" - "%d:%d", pnum, vol_id, lnum); + ubi_warn("corrupted VID header at PEB " + "%d, LEB %d:%d", pnum, vol_id, + lnum); err = -EBADMSG; } else ubi_ro_mode(ubi); @@ -1032,6 +1033,8 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, if (err && err != UBI_IO_BITFLIPS) { ubi_warn("error %d while reading data from PEB %d", err, from); + if (err == -EIO) + err = MOVE_SOURCE_RD_ERR; goto out_unlock_buf; } @@ -1078,9 +1081,11 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, /* Read the VID header back and check if it was written correctly */ err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1); if (err) { - if (err != UBI_IO_BITFLIPS) + if (err != UBI_IO_BITFLIPS) { ubi_warn("cannot read VID header back from PEB %d", to); - else + if (err == -EIO) + err = MOVE_TARGET_RD_ERR; + } else err = MOVE_CANCEL_BITFLIPS; goto out_unlock_buf; } @@ -1102,10 +1107,12 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size); if (err) { - if (err != UBI_IO_BITFLIPS) + if (err != UBI_IO_BITFLIPS) { ubi_warn("cannot read data back from PEB %d", to); - else + if (err == -EIO) + err = MOVE_TARGET_RD_ERR; + } else err = MOVE_CANCEL_BITFLIPS; goto out_unlock_buf; } |