|
@@ -1535,6 +1535,46 @@ void recover_node_page(struct f2fs_sb_info *sbi, struct page *page,
|
|
|
clear_node_page_dirty(page);
|
|
|
}
|
|
|
|
|
|
+bool recover_xattr_data(struct inode *inode, struct page *page, block_t blkaddr)
|
|
|
+{
|
|
|
+ struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
|
|
|
+ nid_t prev_xnid = F2FS_I(inode)->i_xattr_nid;
|
|
|
+ nid_t new_xnid = nid_of_node(page);
|
|
|
+ struct node_info ni;
|
|
|
+
|
|
|
+ if (ofs_of_node(page) != XATTR_NODE_OFFSET)
|
|
|
+ return false;
|
|
|
+
|
|
|
+ /* 1: invalidate the previous xattr nid */
|
|
|
+ if (!prev_xnid)
|
|
|
+ goto recover_xnid;
|
|
|
+
|
|
|
+ /* Deallocate node address */
|
|
|
+ get_node_info(sbi, prev_xnid, &ni);
|
|
|
+ f2fs_bug_on(ni.blk_addr == NULL_ADDR);
|
|
|
+ invalidate_blocks(sbi, ni.blk_addr);
|
|
|
+ dec_valid_node_count(sbi, inode);
|
|
|
+ set_node_addr(sbi, &ni, NULL_ADDR);
|
|
|
+
|
|
|
+recover_xnid:
|
|
|
+ /* 2: allocate new xattr nid */
|
|
|
+ if (unlikely(!inc_valid_node_count(sbi, inode)))
|
|
|
+ f2fs_bug_on(1);
|
|
|
+
|
|
|
+ remove_free_nid(NM_I(sbi), new_xnid);
|
|
|
+ get_node_info(sbi, new_xnid, &ni);
|
|
|
+ ni.ino = inode->i_ino;
|
|
|
+ set_node_addr(sbi, &ni, NEW_ADDR);
|
|
|
+ F2FS_I(inode)->i_xattr_nid = new_xnid;
|
|
|
+
|
|
|
+ /* 3: update xattr blkaddr */
|
|
|
+ refresh_sit_entry(sbi, NEW_ADDR, blkaddr);
|
|
|
+ set_node_addr(sbi, &ni, blkaddr);
|
|
|
+
|
|
|
+ update_inode_page(inode);
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
int recover_inode_page(struct f2fs_sb_info *sbi, struct page *page)
|
|
|
{
|
|
|
struct f2fs_inode *src, *dst;
|