@@ -1920,9 +1920,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) {
@@ -1981,6 +1983,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,
@@ -1998,6 +2010,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))
@@ -2011,6 +2024,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;
@@ -2370,6 +2390,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;
@@ -2390,6 +2412,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;
@@ -2455,6 +2483,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;
@@ -68,8 +68,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 */
@@ -108,15 +106,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);
@@ -794,7 +789,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;
@@ -806,7 +801,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;
}
@@ -816,12 +812,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)
Expand the inline data read & fiemap to support inline tail. Signed-off-by: Wu Bo <bo.wu@vivo.com> --- fs/f2fs/data.c | 31 ++++++++++++++++++++++++++++++- fs/f2fs/inline.c | 26 ++++++++++++-------------- 2 files changed, 42 insertions(+), 15 deletions(-)