diff options
Diffstat (limited to 'drivers/mtd/ubi/eba.c')
-rw-r--r-- | drivers/mtd/ubi/eba.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index b6565561218e..0f2034c3ed2f 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c | |||
@@ -941,6 +941,33 @@ write_error: | |||
941 | } | 941 | } |
942 | 942 | ||
943 | /** | 943 | /** |
944 | * is_error_sane - check whether a read error is sane. | ||
945 | * @err: code of the error happened during reading | ||
946 | * | ||
947 | * This is a helper function for 'ubi_eba_copy_leb()' which is called when we | ||
948 | * cannot read data from the target PEB (an error @err happened). If the error | ||
949 | * code is sane, then we treat this error as non-fatal. Otherwise the error is | ||
950 | * fatal and UBI will be switched to R/O mode later. | ||
951 | * | ||
952 | * The idea is that we try not to switch to R/O mode if the read error is | ||
953 | * something which suggests there was a real read problem. E.g., %-EIO. Or a | ||
954 | * memory allocation failed (-%ENOMEM). Otherwise, it is safer to switch to R/O | ||
955 | * mode, simply because we do not know what happened at the MTD level, and we | ||
956 | * cannot handle this. E.g., the underlying driver may have become crazy, and | ||
957 | * it is safer to switch to R/O mode to preserve the data. | ||
958 | * | ||
959 | * And bear in mind, this is about reading from the target PEB, i.e. the PEB | ||
960 | * which we have just written. | ||
961 | */ | ||
962 | static int is_error_sane(int err) | ||
963 | { | ||
964 | if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_VID_HDR || | ||
965 | err == -ETIMEDOUT) | ||
966 | return 0; | ||
967 | return 1; | ||
968 | } | ||
969 | |||
970 | /** | ||
944 | * ubi_eba_copy_leb - copy logical eraseblock. | 971 | * ubi_eba_copy_leb - copy logical eraseblock. |
945 | * @ubi: UBI device description object | 972 | * @ubi: UBI device description object |
946 | * @from: physical eraseblock number from where to copy | 973 | * @from: physical eraseblock number from where to copy |
@@ -1033,8 +1060,7 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1033 | if (err && err != UBI_IO_BITFLIPS) { | 1060 | if (err && err != UBI_IO_BITFLIPS) { |
1034 | ubi_warn("error %d while reading data from PEB %d", | 1061 | ubi_warn("error %d while reading data from PEB %d", |
1035 | err, from); | 1062 | err, from); |
1036 | if (err == -EIO) | 1063 | err = MOVE_SOURCE_RD_ERR; |
1037 | err = MOVE_SOURCE_RD_ERR; | ||
1038 | goto out_unlock_buf; | 1064 | goto out_unlock_buf; |
1039 | } | 1065 | } |
1040 | 1066 | ||
@@ -1082,8 +1108,9 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1082 | err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1); | 1108 | err = ubi_io_read_vid_hdr(ubi, to, vid_hdr, 1); |
1083 | if (err) { | 1109 | if (err) { |
1084 | if (err != UBI_IO_BITFLIPS) { | 1110 | if (err != UBI_IO_BITFLIPS) { |
1085 | ubi_warn("cannot read VID header back from PEB %d", to); | 1111 | ubi_warn("error %d while reading VID header back from " |
1086 | if (err == -EIO) | 1112 | "PEB %d", err, to); |
1113 | if (is_error_sane(err)) | ||
1087 | err = MOVE_TARGET_RD_ERR; | 1114 | err = MOVE_TARGET_RD_ERR; |
1088 | } else | 1115 | } else |
1089 | err = MOVE_CANCEL_BITFLIPS; | 1116 | err = MOVE_CANCEL_BITFLIPS; |
@@ -1108,9 +1135,9 @@ int ubi_eba_copy_leb(struct ubi_device *ubi, int from, int to, | |||
1108 | err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size); | 1135 | err = ubi_io_read_data(ubi, ubi->peb_buf2, to, 0, aldata_size); |
1109 | if (err) { | 1136 | if (err) { |
1110 | if (err != UBI_IO_BITFLIPS) { | 1137 | if (err != UBI_IO_BITFLIPS) { |
1111 | ubi_warn("cannot read data back from PEB %d", | 1138 | ubi_warn("error %d while reading data back " |
1112 | to); | 1139 | "from PEB %d", err, to); |
1113 | if (err == -EIO) | 1140 | if (is_error_sane(err)) |
1114 | err = MOVE_TARGET_RD_ERR; | 1141 | err = MOVE_TARGET_RD_ERR; |
1115 | } else | 1142 | } else |
1116 | err = MOVE_CANCEL_BITFLIPS; | 1143 | err = MOVE_CANCEL_BITFLIPS; |