|
@@ -399,14 +399,35 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
|
|
|
f2fs_bug_on(sbi, ni.ino != ino_of_node(page));
|
|
|
f2fs_bug_on(sbi, ofs_of_node(dn.node_page) != ofs_of_node(page));
|
|
|
|
|
|
- for (; start < end; start++) {
|
|
|
+ for (; start < end; start++, dn.ofs_in_node++) {
|
|
|
block_t src, dest;
|
|
|
|
|
|
src = datablock_addr(dn.node_page, dn.ofs_in_node);
|
|
|
dest = datablock_addr(page, dn.ofs_in_node);
|
|
|
|
|
|
- if (src != dest && dest != NEW_ADDR && dest != NULL_ADDR &&
|
|
|
- is_valid_blkaddr(sbi, dest, META_POR)) {
|
|
|
+ /* skip recovering if dest is the same as src */
|
|
|
+ if (src == dest)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ /* dest is invalid, just invalidate src block */
|
|
|
+ if (dest == NULL_ADDR) {
|
|
|
+ truncate_data_blocks_range(&dn, 1);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * dest is reserved block, invalidate src block
|
|
|
+ * and then reserve one new block in dnode page.
|
|
|
+ */
|
|
|
+ if (dest == NEW_ADDR) {
|
|
|
+ truncate_data_blocks_range(&dn, 1);
|
|
|
+ err = reserve_new_block(&dn);
|
|
|
+ f2fs_bug_on(sbi, err);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* dest is valid block, try to recover from src to dest */
|
|
|
+ if (is_valid_blkaddr(sbi, dest, META_POR)) {
|
|
|
|
|
|
if (src == NULL_ADDR) {
|
|
|
err = reserve_new_block(&dn);
|
|
@@ -424,7 +445,6 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode,
|
|
|
ni.version, false);
|
|
|
recovered++;
|
|
|
}
|
|
|
- dn.ofs_in_node++;
|
|
|
}
|
|
|
|
|
|
if (IS_INODE(dn.node_page))
|