kernel: handle bad blocks in ubi auto attach code
authorMathias Kresin <[email protected]>
Sat, 7 Jul 2018 23:47:28 +0000 (01:47 +0200)
committerJo-Philipp Wich <[email protected]>
Tue, 18 Dec 2018 08:50:51 +0000 (09:50 +0100)
The first block(s) of the ubi mtd device might be bad. We need to take
care on our own to skip the bad block(s) and read the next one(s).

Don't treat recoverable read errors as fatal and check for the UBI magic
if the data of a block could be recovered using ECC or similar.

Signed-off-by: Mathias Kresin <[email protected]>
(backported from 0ac91d82ed4d077150db902eb12d383c2be44fb2)
(rebased patches)
Signed-off-by: Jo-Philipp Wich <[email protected]>
target/linux/generic/pending-4.14/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch
target/linux/generic/pending-4.9/490-ubi-auto-attach-mtd-device-named-ubi-or-data-on-boot.patch

index 89bac648304acdf0e9e9dca014aae373df994f95..ff3490bf9e07781ff8ff192e60e508ae2a4a6b53 100644 (file)
@@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 
 --- a/drivers/mtd/ubi/build.c
 +++ b/drivers/mtd/ubi/build.c
-@@ -1172,6 +1172,54 @@ static struct mtd_info * __init open_mtd
+@@ -1172,6 +1172,68 @@ static struct mtd_info * __init open_mtd
        return mtd;
  }
  
@@ -20,6 +20,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +{
 +      int err;
 +      struct mtd_info *mtd;
++      loff_t offset = 0;
 +      size_t len;
 +      char magic[4];
 +
@@ -31,9 +32,22 @@ Signed-off-by: Daniel Golle <[email protected]>
 +      if (IS_ERR(mtd))
 +              return;
 +
++      /* get the first not bad block */
++      if (mtd_can_have_bb(mtd))
++              while (mtd_block_isbad(mtd, offset)) {
++                      offset += mtd->erasesize;
++
++                      if (offset > mtd->size) {
++                              pr_err("UBI error: Failed to find a non-bad "
++                                     "block on mtd%d\n", mtd->index);
++                              goto cleanup;
++                      }
++              }
++
 +      /* check for a valid ubi magic if read from flash was successful */
-+      err = mtd_read(mtd, 0, 4, &len, (void *) magic);
-+      if (!err && len == 4 && strncmp(magic, "UBI#", 4)) {
++      err = mtd_read(mtd, offset, 4, &len, (void *) magic);
++      if ((!err || mtd_is_bitflip(err)) &&
++          len == 4 && strncmp(magic, "UBI#", 4)) {
 +              pr_err("UBI error: no valid UBI magic found inside mtd%d\n", mtd->index);
 +              goto cleanup;
 +      }
@@ -63,7 +77,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int __init ubi_init(void)
  {
        int err, i, k;
-@@ -1255,6 +1303,12 @@ static int __init ubi_init(void)
+@@ -1255,6 +1317,12 @@ static int __init ubi_init(void)
                }
        }
  
index 1436e486ddee54ad98003b94089ba71a0047181b..8b923d17d6342e8fb2bb6b0aa5c041b3ccf5eeba 100644 (file)
@@ -8,7 +8,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 
 --- a/drivers/mtd/ubi/build.c
 +++ b/drivers/mtd/ubi/build.c
-@@ -1226,6 +1226,54 @@ static struct mtd_info * __init open_mtd
+@@ -1226,6 +1226,68 @@ static struct mtd_info * __init open_mtd
        return mtd;
  }
  
@@ -20,6 +20,7 @@ Signed-off-by: Daniel Golle <[email protected]>
 +{
 +      int err;
 +      struct mtd_info *mtd;
++      loff_t offset = 0;
 +      size_t len;
 +      char magic[4];
 +
@@ -31,9 +32,22 @@ Signed-off-by: Daniel Golle <[email protected]>
 +      if (IS_ERR(mtd))
 +              return;
 +
++      /* get the first not bad block */
++      if (mtd_can_have_bb(mtd))
++              while (mtd_block_isbad(mtd, offset)) {
++                      offset += mtd->erasesize;
++
++                      if (offset > mtd->size) {
++                              pr_err("UBI error: Failed to find a non-bad "
++                                     "block on mtd%d\n", mtd->index);
++                              goto cleanup;
++                      }
++              }
++
 +      /* check for a valid ubi magic if read from flash was successful */
-+      err = mtd_read(mtd, 0, 4, &len, (void *) magic);
-+      if (!err && len == 4 && strncmp(magic, "UBI#", 4)) {
++      err = mtd_read(mtd, offset, 4, &len, (void *) magic);
++      if ((!err || mtd_is_bitflip(err)) &&
++          len == 4 && strncmp(magic, "UBI#", 4)) {
 +              pr_err("UBI error: no valid UBI magic found inside mtd%d\n", mtd->index);
 +              goto cleanup;
 +      }
@@ -63,7 +77,7 @@ Signed-off-by: Daniel Golle <[email protected]>
  static int __init ubi_init(void)
  {
        int err, i, k;
-@@ -1309,6 +1357,12 @@ static int __init ubi_init(void)
+@@ -1309,6 +1371,12 @@ static int __init ubi_init(void)
                }
        }