diff options
author | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2013-12-26 12:49:48 +0900 |
---|---|---|
committer | Jaegeuk Kim <jaegeuk.kim@samsung.com> | 2014-01-06 16:42:20 +0900 |
commit | 1e1bb4baf10be371f72150e2801d97a04d40b3b9 (patch) | |
tree | 708ae4f4d93b05f063aa1c50538c53cdcbae5350 /fs/f2fs/inline.c | |
parent | 0dbdc2ae9bba0a358816cc4a22e41a6ef16db8a2 (diff) |
f2fs: add inline_data recovery routine
This patch adds a inline_data recovery routine with the following policy.
[prev.] [next] of inline_data flag
o o -> recover inline_data
o x -> remove inline_data, and then recover data blocks
x o -> remove inline_data, and then recover inline_data
x x -> recover data blocks
Signed-off-by: Jaegeuk Kim <jaegeuk.kim@samsung.com>
Diffstat (limited to 'fs/f2fs/inline.c')
-rw-r--r-- | fs/f2fs/inline.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 3c9261cd215f..2a756e57aed9 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -169,3 +169,51 @@ int f2fs_write_inline_data(struct inode *inode, return 0; } + +int recover_inline_data(struct inode *inode, struct page *npage) +{ + struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb); + struct f2fs_inode *ri = NULL; + void *src_addr, *dst_addr; + struct page *ipage; + + /* + * The inline_data recovery policy is as follows. + * [prev.] [next] of inline_data flag + * o o -> recover inline_data + * o x -> remove inline_data, and then recover data blocks + * x o -> remove inline_data, and then recover inline_data + * x x -> recover data blocks + */ + if (IS_INODE(npage)) + ri = F2FS_INODE(npage); + + if (f2fs_has_inline_data(inode) && + ri && ri->i_inline & F2FS_INLINE_DATA) { +process_inline: + ipage = get_node_page(sbi, inode->i_ino); + f2fs_bug_on(IS_ERR(ipage)); + + src_addr = inline_data_addr(npage); + dst_addr = inline_data_addr(ipage); + memcpy(dst_addr, src_addr, MAX_INLINE_DATA); + update_inode(inode, ipage); + f2fs_put_page(ipage, 1); + return -1; + } + + if (f2fs_has_inline_data(inode)) { + ipage = get_node_page(sbi, inode->i_ino); + f2fs_bug_on(IS_ERR(ipage)); + zero_user_segment(ipage, INLINE_DATA_OFFSET, + INLINE_DATA_OFFSET + MAX_INLINE_DATA); + clear_inode_flag(F2FS_I(inode), FI_INLINE_DATA); + update_inode(inode, ipage); + f2fs_put_page(ipage, 1); + } else if (ri && ri->i_inline & F2FS_INLINE_DATA) { + truncate_blocks(inode, 0); + set_inode_flag(F2FS_I(inode), FI_INLINE_DATA); + goto process_inline; + } + return 0; +} |