From cc770c4e7a80ca23d62287cffd8bb222e5ccefb7 Mon Sep 17 00:00:00 2001 From: Jon Lin Date: Sat, 30 Jan 2021 14:56:21 +0800 Subject: [PATCH] ubifs: Recovery for cases of unclean reboot After power lost, spinand may work in a unkonw state and result in bit flip, including: 1.Write to cache invalid and dirty cache data write to page's array which result in node CRC error for some pages. 2.One page write fail but the next page write success result in empty space corruption. Change-Id: I212c237202b32de0217efc8dd5a4e84174953a3f Signed-off-by: Jon Lin --- fs/ubifs/recovery.c | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index f116f7b3f9e5..4061fd58602f 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -662,10 +662,43 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum, offs += ret; buf += ret; len -= ret; - } else if (ret == SCANNED_EMPTY_SPACE || - ret == SCANNED_GARBAGE || - ret == SCANNED_A_BAD_PAD_NODE || - ret == SCANNED_A_CORRUPT_NODE) { + } else if (ret == SCANNED_A_CORRUPT_NODE) { + dbg_rcvry("found corruption (%d) at %d:%d", + ret, lnum, offs); + if (ubifs_check_node(c, buf, lnum, offs, 1, 1) == -EUCLEAN && + !no_more_nodes(c, buf, len, lnum, offs)) { + int skip; + struct ubifs_ch *ch = buf; + + /* + * If the flash voltage power down suddenly in the programming + * process, it may lead to abnormal data written by the flash + * in the low-voltage operation process, and the last data + * should be discarded. + */ + ubifs_msg(c, "recovery corrupt node\n"); + skip = ALIGN(offs + le32_to_cpu(ch->len), c->max_write_size) - offs; + memset(buf + skip, 0xff, len - skip); + } + + break; + } else if (ret == SCANNED_EMPTY_SPACE) { + dbg_rcvry("found corruption (%d) at %d:%d", + ret, lnum, offs); + if (!is_empty(buf, len) && !is_last_write(c, buf, offs)) { + /* + * If the flash voltage power down suddenly in the programming + * process, it may lead to the data was programmed to the wroge + * page written by the flash in the low-voltage operation process, + * and the data should be discarded. + */ + ubifs_msg(c, "recovery empty space\n"); + memset(buf, 0xff, len); + } + + break; + } else if (ret == SCANNED_GARBAGE || + ret == SCANNED_A_BAD_PAD_NODE) { dbg_rcvry("found corruption (%d) at %d:%d", ret, lnum, offs); break;