[PATCH v2 04/13] f2fs: implement inline tail read & fiemap

From: Wu Bo
Date: Tue Sep 10 2024 - 23:44:12 EST


Expand the inline data read & fiemap to support inline tail.

Signed-off-by: Wu Bo <bo.wu@xxxxxxxx>
---
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