static void destroy_fsync_dnodes(struct list_head *head, int drop) { struct fsync_inode_entry *entry, *tmp; list_for_each_entry_safe(entry, tmp, head, list) del_fsync_inode(entry, drop); }
static int recover_data(struct f2fs_sb_info *sbi, struct list_head *inode_list, struct list_head *dir_list) { struct curseg_info *curseg; struct page *page = NULL; int err = 0; block_t blkaddr; /* get node pages in the current segment */ curseg = CURSEG_I(sbi, CURSEG_WARM_NODE); blkaddr = NEXT_FREE_BLKADDR(sbi, curseg); while (1) { struct fsync_inode_entry *entry; if (!f2fs_is_valid_blkaddr(sbi, blkaddr, META_POR)) break; f2fs_ra_meta_pages_cond(sbi, blkaddr); page = f2fs_get_tmp_page(sbi, blkaddr); if (IS_ERR(page)) { err = PTR_ERR(page); break; } if (!is_recoverable_dnode(page)) { f2fs_put_page(page, 1); break; } entry = get_fsync_inode(inode_list, ino_of_node(page)); if (!entry) goto next; /* * inode(x) | CP | inode(x) | dnode(F) * In this case, we can lose the latest inode(x). * So, call recover_inode for the inode update. */ if (IS_INODE(page)) recover_inode(entry->inode, page); if (entry->last_dentry == blkaddr) { err = recover_dentry(entry->inode, page, dir_list); if (err) { f2fs_put_page(page, 1); break; } } err = do_recover_data(sbi, entry->inode, page); if (err) { f2fs_put_page(page, 1); break; } if (entry->blkaddr == blkaddr) del_fsync_inode(entry); next: /* check next segment */ blkaddr = next_blkaddr_of_node(page); f2fs_put_page(page, 1); } if (!err) f2fs_allocate_new_segments(sbi); return err; }