Map normal/compressed cluster of compressed inode correctly, and give
the right fiemap flag FIEMAP_EXTENT_ENCODED on mapped compressed extent.

Signed-off-by: Chao Yu <[email protected]>
---
 fs/f2fs/data.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 53 insertions(+), 2 deletions(-)

diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 89b73ee74120..363f7f1b6dc0 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -1808,6 +1808,25 @@ static int f2fs_xattr_fiemap(struct inode *inode,
        return (err < 0 ? err : 0);
 }
 
+static loff_t max_inode_blocks(struct inode *inode)
+{
+       loff_t result = ADDRS_PER_INODE(inode);
+       loff_t leaf_count = ADDRS_PER_BLOCK(inode);
+
+       /* two direct node blocks */
+       result += (leaf_count * 2);
+
+       /* two indirect node blocks */
+       leaf_count *= NIDS_PER_BLOCK;
+       result += (leaf_count * 2);
+
+       /* one double indirect node block */
+       leaf_count *= NIDS_PER_BLOCK;
+       result += leaf_count;
+
+       return result;
+}
+
 int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
                u64 start, u64 len)
 {
@@ -1817,6 +1836,8 @@ 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;
+       unsigned int cluster_size = F2FS_I(inode)->i_cluster_size;
 
        if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) {
                ret = f2fs_precache_extents(inode);
@@ -1851,6 +1872,9 @@ int f2fs_fiemap(struct inode *inode, struct 
fiemap_extent_info *fieinfo,
        memset(&map_bh, 0, sizeof(struct buffer_head));
        map_bh.b_size = len;
 
+       if (compr_cluster)
+               map_bh.b_size = blk_to_logical(inode, cluster_size - 1);
+
        ret = get_data_block(inode, start_blk, &map_bh, 0,
                                        F2FS_GET_BLOCK_FIEMAP, &next_pgofs);
        if (ret)
@@ -1861,7 +1885,7 @@ int f2fs_fiemap(struct inode *inode, struct 
fiemap_extent_info *fieinfo,
                start_blk = next_pgofs;
 
                if (blk_to_logical(inode, start_blk) < blk_to_logical(inode,
-                                       F2FS_I_SB(inode)->max_file_blocks))
+                                               max_inode_blocks(inode)))
                        goto prep_next;
 
                flags |= FIEMAP_EXTENT_LAST;
@@ -1873,11 +1897,38 @@ int f2fs_fiemap(struct inode *inode, struct 
fiemap_extent_info *fieinfo,
 
                ret = fiemap_fill_next_extent(fieinfo, logical,
                                phys, size, flags);
+               if (ret)
+                       goto out;
+               size = 0;
        }
 
-       if (start_blk > last_blk || ret)
+       if (start_blk > last_blk)
                goto out;
 
+       if (compr_cluster) {
+               compr_cluster = false;
+
+
+               logical = blk_to_logical(inode, start_blk - 1);
+               phys = blk_to_logical(inode, map_bh.b_blocknr);
+               size = blk_to_logical(inode, cluster_size);
+
+               flags |= FIEMAP_EXTENT_ENCODED;
+
+               start_blk += cluster_size - 1;
+
+               if (start_blk > last_blk)
+                       goto out;
+
+               goto prep_next;
+       }
+
+       if (map_bh.b_blocknr == COMPRESS_ADDR) {
+               compr_cluster = true;
+               start_blk++;
+               goto prep_next;
+       }
+
        logical = blk_to_logical(inode, start_blk);
        phys = blk_to_logical(inode, map_bh.b_blocknr);
        size = map_bh.b_size;
-- 
2.18.0.rc1



_______________________________________________
Linux-f2fs-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to