Expand the inline data read & fiemap to support inline tail. Signed-off-by: Wu Bo <bo...@vivo.com> --- fs/f2fs/data.c | 31 ++++++++++++++++++++++++++++++- fs/f2fs/inline.c | 26 ++++++++++++-------------- 2 files changed, 42 insertions(+), 15 deletions(-)
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index cd13b5703228..476325a26d4e 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1922,9 +1922,11 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 logical = 0, phys = 0, size = 0; u32 flags = 0; int ret = 0; - bool compr_cluster = false, compr_appended; + bool compr_cluster = false, compr_appended, inline_tail = false; unsigned int cluster_size = F2FS_I(inode)->i_cluster_size; unsigned int count_in_cluster = 0; + loff_t i_size = i_size_read(inode); + pgoff_t end_index = i_size >> PAGE_SHIFT; loff_t maxbytes; if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) { @@ -1983,6 +1985,16 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, /* HOLE */ if (!compr_cluster && !(map.m_flags & F2FS_MAP_FLAGS)) { + /* + * There is a reserved space between address array and inline + * data. So it must meet this hole state before inline data. + */ + if (f2fs_has_inline_tail(inode) && start_blk == end_index + && f2fs_exist_data(inode)) { + inline_tail = true; + goto fill_extent; + } + start_blk = next_pgofs; if (blks_to_bytes(inode, start_blk) < blks_to_bytes(inode, @@ -2000,6 +2012,7 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, goto skip_fill; } +fill_extent: if (size) { flags |= FIEMAP_EXTENT_MERGED; if (IS_ENCRYPTED(inode)) @@ -2013,6 +2026,13 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, size = 0; } + if (inline_tail) { + start = blks_to_bytes(inode, start_blk); + ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len); + if (ret != -EAGAIN) + goto out; + } + if (start_blk > last_blk) goto out; @@ -2377,6 +2397,8 @@ static int f2fs_mpage_readpages(struct inode *inode, #endif unsigned nr_pages = rac ? readahead_count(rac) : 1; unsigned max_nr_pages = nr_pages; + loff_t i_size = i_size_read(inode); + pgoff_t end_index = i_size >> PAGE_SHIFT; pgoff_t index; int ret = 0; @@ -2397,6 +2419,12 @@ static int f2fs_mpage_readpages(struct inode *inode, index = folio_index(folio); + if (f2fs_has_inline_tail(inode) && index == end_index && + f2fs_exist_data(inode)) { + ret = f2fs_read_inline_data(inode, folio); + goto out; + } + #ifdef CONFIG_F2FS_FS_COMPRESSION if (!f2fs_compressed_file(inode)) goto read_single_page; @@ -2462,6 +2490,7 @@ static int f2fs_mpage_readpages(struct inode *inode, } #endif } +out: if (bio) f2fs_submit_read_bio(F2FS_I_SB(inode), bio, DATA); return ret; diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 2e63e9389fd7..30b18053e784 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -86,8 +86,6 @@ void f2fs_do_read_inline_data(struct folio *folio, struct page *ipage) if (folio_test_uptodate(folio)) return; - f2fs_bug_on(F2FS_I_SB(inode), folio_index(folio)); - folio_zero_segment(folio, MAX_INLINE_DATA(inode), folio_size(folio)); /* Copy the whole inline data block */ @@ -126,15 +124,12 @@ int f2fs_read_inline_data(struct inode *inode, struct folio *folio) return PTR_ERR(ipage); } - if (!f2fs_has_inline_data(inode)) { + if (!f2fs_has_inline_data(inode) && !f2fs_has_inline_tail(inode)) { f2fs_put_page(ipage, 1); return -EAGAIN; } - if (folio_index(folio)) - folio_zero_segment(folio, 0, folio_size(folio)); - else - f2fs_do_read_inline_data(folio, ipage); + f2fs_do_read_inline_data(folio, ipage); if (!folio_test_uptodate(folio)) folio_mark_uptodate(folio); @@ -814,7 +809,7 @@ int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx, int f2fs_inline_data_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, __u64 start, __u64 len) { - __u64 byteaddr, ilen; + __u64 byteaddr, ilen, offset; __u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED | FIEMAP_EXTENT_LAST; struct node_info ni; @@ -826,7 +821,8 @@ int f2fs_inline_data_fiemap(struct inode *inode, return PTR_ERR(ipage); if ((S_ISREG(inode->i_mode) || S_ISLNK(inode->i_mode)) && - !f2fs_has_inline_data(inode)) { + !f2fs_has_inline_data(inode) && + !f2fs_has_inline_tail(inode)) { err = -EAGAIN; goto out; } @@ -836,12 +832,14 @@ int f2fs_inline_data_fiemap(struct inode *inode, goto out; } - ilen = min_t(size_t, MAX_INLINE_DATA(inode), i_size_read(inode)); - if (start >= ilen) + ilen = min_t(size_t, MAX_INLINE_DATA(inode), + i_size_read(inode) & (PAGE_SIZE - 1)); + offset = start & (PAGE_SIZE - 1); + if (offset >= ilen) goto out; - if (start + len < ilen) - ilen = start + len; - ilen -= start; + if (offset + len < ilen) + ilen = offset + len; + ilen -= offset; err = f2fs_get_node_info(F2FS_I_SB(inode), inode->i_ino, &ni, false); if (err) -- 2.35.3 _______________________________________________ Linux-f2fs-devel mailing list Linux-f2fs-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel