Message ID | 57e1dbb2f348ab61cbc82be7161d788a08b5fbed.1726024117.git.bo.wu@vivo.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | f2fs: introduce inline tail | expand |
Hi Wu, kernel test robot noticed the following build warnings: [auto build test WARNING on 67784a74e258a467225f0e68335df77acd67b7ab] url: https://github.com/intel-lab-lkp/linux/commits/Wu-Bo/f2fs-add-inline-tail-mount-option/20240911-114705 base: 67784a74e258a467225f0e68335df77acd67b7ab patch link: https://lore.kernel.org/r/57e1dbb2f348ab61cbc82be7161d788a08b5fbed.1726024117.git.bo.wu%40vivo.com patch subject: [PATCH v2 13/13] f2fs: implement inline tail forward recovery config: x86_64-randconfig-121-20240913 (https://download.01.org/0day-ci/archive/20240913/202409131549.6E5c04Zg-lkp@intel.com/config) compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240913/202409131549.6E5c04Zg-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202409131549.6E5c04Zg-lkp@intel.com/ sparse warnings: (new ones prefixed by >>) >> fs/f2fs/inline.c:457:27: sparse: sparse: cast to restricted __le32 vim +457 fs/f2fs/inline.c 416 417 int f2fs_recover_inline_tail(struct inode *inode, struct page *npage) 418 { 419 struct f2fs_sb_info *sbi = F2FS_I_SB(inode); 420 struct f2fs_inode *ri = NULL; 421 void *src_addr, *dst_addr; 422 struct page *ipage; 423 424 if (IS_INODE(npage)) 425 ri = F2FS_INODE(npage); 426 427 if (f2fs_has_inline_tail(inode) && 428 ri && (le32_to_cpu(ri->i_flags) & F2FS_INLINE_TAIL)) { 429 process_inline: 430 if (!(ri->i_inline & F2FS_DATA_EXIST)) 431 return 0; 432 433 ipage = f2fs_get_node_page(sbi, inode->i_ino); 434 if (IS_ERR(ipage)) 435 return PTR_ERR(ipage); 436 437 f2fs_wait_on_page_writeback(ipage, NODE, true, true); 438 439 src_addr = inline_data_addr(inode, npage); 440 dst_addr = inline_data_addr(inode, ipage); 441 memcpy(dst_addr, src_addr, MAX_INLINE_DATA(inode)); 442 443 set_inode_flag(inode, FI_DATA_EXIST); 444 445 set_page_dirty(ipage); 446 f2fs_put_page(ipage, 1); 447 return 0; 448 } 449 450 if (f2fs_has_inline_tail(inode)) { 451 ipage = f2fs_get_node_page(sbi, inode->i_ino); 452 if (IS_ERR(ipage)) 453 return PTR_ERR(ipage); 454 f2fs_truncate_inline_inode(inode, ipage, 0); 455 clear_inode_flag(inode, FI_INLINE_TAIL); 456 f2fs_put_page(ipage, 1); > 457 } else if (ri && (le32_to_cpu(ri->i_inline) & F2FS_INLINE_TAIL)) { 458 int ret; 459 460 ret = f2fs_truncate_blocks(inode, 461 COMPACT_ADDRS_PER_INODE >> PAGE_SHIFT, false); 462 if (ret) 463 return ret; 464 goto process_inline; 465 } 466 return 0; 467 } 468 struct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir, 469 const struct f2fs_filename *fname, 470 struct page **res_page) 471 { 472 struct f2fs_sb_info *sbi = F2FS_SB(dir->i_sb); 473 struct f2fs_dir_entry *de; 474 struct f2fs_dentry_ptr d; 475 struct page *ipage; 476 void *inline_dentry; 477 478 ipage = f2fs_get_node_page(sbi, dir->i_ino); 479 if (IS_ERR(ipage)) { 480 *res_page = ipage; 481 return NULL; 482 } 483 484 inline_dentry = inline_data_addr(dir, ipage); 485 486 make_dentry_ptr_inline(dir, &d, inline_dentry); 487 de = f2fs_find_target_dentry(&d, fname, NULL); 488 unlock_page(ipage); 489 if (IS_ERR(de)) { 490 *res_page = ERR_CAST(de); 491 de = NULL; 492 } 493 if (de) 494 *res_page = ipage; 495 else 496 f2fs_put_page(ipage, 0); 497 498 return de; 499 } 500
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index f889d97209c7..7d5348e2127b 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -4217,6 +4217,7 @@ int f2fs_clear_inline_tail(struct inode *inode, bool force); int f2fs_try_convert_inline_dir(struct inode *dir, struct dentry *dentry); int f2fs_write_inline_data(struct inode *inode, struct page *page); int f2fs_recover_inline_data(struct inode *inode, struct page *npage); +int f2fs_recover_inline_tail(struct inode *inode, struct page *npage); struct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir, const struct f2fs_filename *fname, struct page **res_page); diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index c2f84f3dde67..76e0ff62be51 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -414,6 +414,57 @@ int f2fs_recover_inline_data(struct inode *inode, struct page *npage) return 0; } +int f2fs_recover_inline_tail(struct inode *inode, struct page *npage) +{ + struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + struct f2fs_inode *ri = NULL; + void *src_addr, *dst_addr; + struct page *ipage; + + if (IS_INODE(npage)) + ri = F2FS_INODE(npage); + + if (f2fs_has_inline_tail(inode) && + ri && (le32_to_cpu(ri->i_flags) & F2FS_INLINE_TAIL)) { +process_inline: + if (!(ri->i_inline & F2FS_DATA_EXIST)) + return 0; + + ipage = f2fs_get_node_page(sbi, inode->i_ino); + if (IS_ERR(ipage)) + return PTR_ERR(ipage); + + f2fs_wait_on_page_writeback(ipage, NODE, true, true); + + src_addr = inline_data_addr(inode, npage); + dst_addr = inline_data_addr(inode, ipage); + memcpy(dst_addr, src_addr, MAX_INLINE_DATA(inode)); + + set_inode_flag(inode, FI_DATA_EXIST); + + set_page_dirty(ipage); + f2fs_put_page(ipage, 1); + return 0; + } + + if (f2fs_has_inline_tail(inode)) { + ipage = f2fs_get_node_page(sbi, inode->i_ino); + if (IS_ERR(ipage)) + return PTR_ERR(ipage); + f2fs_truncate_inline_inode(inode, ipage, 0); + clear_inode_flag(inode, FI_INLINE_TAIL); + f2fs_put_page(ipage, 1); + } else if (ri && (le32_to_cpu(ri->i_inline) & F2FS_INLINE_TAIL)) { + int ret; + + ret = f2fs_truncate_blocks(inode, + COMPACT_ADDRS_PER_INODE >> PAGE_SHIFT, false); + if (ret) + return ret; + goto process_inline; + } + return 0; +} struct f2fs_dir_entry *f2fs_find_in_inline_dir(struct inode *dir, const struct f2fs_filename *fname, struct page **res_page) diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c index 9756f0f2b7f7..d73a557b82d9 100644 --- a/fs/f2fs/recovery.c +++ b/fs/f2fs/recovery.c @@ -645,9 +645,16 @@ static int do_recover_data(struct f2fs_sb_info *sbi, struct inode *inode, goto out; } + err = f2fs_recover_inline_tail(inode, page); + if (err) + goto out; + /* step 3: recover data indices */ start = f2fs_start_bidx_of_node(ofs_of_node(page), inode); - end = start + ADDRS_PER_PAGE(page, inode); + if (f2fs_has_inline_tail(inode)) + end = COMPACT_ADDRS_PER_INODE; + else + end = start + ADDRS_PER_PAGE(page, inode); set_new_dnode(&dn, inode, NULL, NULL, 0); retry_dn:
The recovery logic is similar to that of inline data, except that the inline tail may require recovery of some blocks. This is because the inline tail has a 16-size block address array, whereas inline data does not. Signed-off-by: Wu Bo <bo.wu@vivo.com> --- fs/f2fs/f2fs.h | 1 + fs/f2fs/inline.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ fs/f2fs/recovery.c | 9 +++++++- 3 files changed, 60 insertions(+), 1 deletion(-)