Now that fiemap allows returning extent physical size, make btrfs return
the appropriate extent's actual disk size.

Signed-off-by: Sweet Tea Dorminy <sweettea-ker...@dorminy.me>
---
 fs/btrfs/extent_io.c | 70 ++++++++++++++++++++++++++++----------------
 1 file changed, 45 insertions(+), 25 deletions(-)

diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index e9df670ef7d2..b631f387cc3c 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -2506,7 +2506,8 @@ int try_release_extent_mapping(struct page *page, gfp_t 
mask)
 struct btrfs_fiemap_entry {
        u64 offset;
        u64 phys;
-       u64 len;
+       u64 log_len;
+       u64 phys_len;
        u32 flags;
 };
 
@@ -2564,7 +2565,8 @@ struct fiemap_cache {
        /* Fields for the cached extent (unsubmitted, not ready, extent). */
        u64 offset;
        u64 phys;
-       u64 len;
+       u64 log_len;
+       u64 phys_len;
        u32 flags;
        bool cached;
 };
@@ -2577,8 +2579,8 @@ static int flush_fiemap_cache(struct fiemap_extent_info 
*fieinfo,
                int ret;
 
                ret = fiemap_fill_next_extent(fieinfo, entry->offset,
-                                             entry->phys, entry->len, 0,
-                                             entry->flags);
+                                             entry->phys, entry->log_len,
+                                             entry->phys_len, entry->flags);
                /*
                 * Ignore 1 (reached max entries) because we keep track of that
                 * ourselves in emit_fiemap_extent().
@@ -2603,7 +2605,8 @@ static int flush_fiemap_cache(struct fiemap_extent_info 
*fieinfo,
  */
 static int emit_fiemap_extent(struct fiemap_extent_info *fieinfo,
                                struct fiemap_cache *cache,
-                               u64 offset, u64 phys, u64 len, u32 flags)
+                               u64 offset, u64 phys, u64 log_len,
+                               u64 phys_len, u32 flags)
 {
        struct btrfs_fiemap_entry *entry;
        u64 cache_end;
@@ -2611,6 +2614,9 @@ static int emit_fiemap_extent(struct fiemap_extent_info 
*fieinfo,
        /* Set at the end of extent_fiemap(). */
        ASSERT((flags & FIEMAP_EXTENT_LAST) == 0);
 
+       /* We always set the correct physical length. */
+       flags |= FIEMAP_EXTENT_HAS_PHYS_LEN;
+
        if (!cache->cached)
                goto assign;
 
@@ -2646,7 +2652,7 @@ static int emit_fiemap_extent(struct fiemap_extent_info 
*fieinfo,
         * or equals to what we have in cache->offset. We deal with this as
         * described below.
         */
-       cache_end = cache->offset + cache->len;
+       cache_end = cache->offset + cache->log_len;
        if (cache_end > offset) {
                if (offset == cache->offset) {
                        /*
@@ -2670,10 +2676,10 @@ static int emit_fiemap_extent(struct fiemap_extent_info 
*fieinfo,
                         * where a previously found file extent item was split
                         * due to an ordered extent completing.
                         */
-                       cache->len = offset - cache->offset;
+                       cache->log_len = offset - cache->offset;
                        goto emit;
                } else {
-                       const u64 range_end = offset + len;
+                       const u64 range_end = offset + log_len;
 
                        /*
                         * The offset of the file extent item we have just found
@@ -2706,11 +2712,13 @@ static int emit_fiemap_extent(struct fiemap_extent_info 
*fieinfo,
                        if (range_end <= cache_end)
                                return 0;
 
-                       if (!(flags & (FIEMAP_EXTENT_DATA_COMPRESSED | 
FIEMAP_EXTENT_DELALLOC)))
+                       if (!(flags & (FIEMAP_EXTENT_DATA_COMPRESSED | 
FIEMAP_EXTENT_DELALLOC))) {
                                phys += cache_end - offset;
+                               phys_len -= cache_end - offset;
+                       }
 
                        offset = cache_end;
-                       len = range_end - cache_end;
+                       log_len = range_end - cache_end;
                        goto emit;
                }
        }
@@ -2720,15 +2728,17 @@ static int emit_fiemap_extent(struct fiemap_extent_info 
*fieinfo,
         * 1) Their logical addresses are continuous
         *
         * 2) Their physical addresses are continuous
-        *    So truly compressed (physical size smaller than logical size)
-        *    extents won't get merged with each other
         *
         * 3) Share same flags
+        *
+        * 4) Not compressed
         */
-       if (cache->offset + cache->len  == offset &&
-           cache->phys + cache->len == phys  &&
-           cache->flags == flags) {
-               cache->len += len;
+       if (cache->offset + cache->log_len  == offset &&
+           cache->phys + cache->log_len == phys  &&
+           cache->flags == flags &&
+           !(flags & FIEMAP_EXTENT_DATA_COMPRESSED)) {
+               cache->log_len += log_len;
+               cache->phys_len += phys_len;
                return 0;
        }
 
@@ -2745,7 +2755,7 @@ static int emit_fiemap_extent(struct fiemap_extent_info 
*fieinfo,
                 * to miss it.
                 */
                entry = &cache->entries[cache->entries_size - 1];
-               cache->next_search_offset = entry->offset + entry->len;
+               cache->next_search_offset = entry->offset + entry->log_len;
                cache->cached = false;
 
                return BTRFS_FIEMAP_FLUSH_CACHE;
@@ -2754,7 +2764,8 @@ static int emit_fiemap_extent(struct fiemap_extent_info 
*fieinfo,
        entry = &cache->entries[cache->entries_pos];
        entry->offset = cache->offset;
        entry->phys = cache->phys;
-       entry->len = cache->len;
+       entry->log_len = cache->log_len;
+       entry->phys_len = cache->phys_len;
        entry->flags = cache->flags;
        cache->entries_pos++;
        cache->extents_mapped++;
@@ -2767,7 +2778,8 @@ static int emit_fiemap_extent(struct fiemap_extent_info 
*fieinfo,
        cache->cached = true;
        cache->offset = offset;
        cache->phys = phys;
-       cache->len = len;
+       cache->log_len = log_len;
+       cache->phys_len = phys_len;
        cache->flags = flags;
 
        return 0;
@@ -2793,7 +2805,8 @@ static int emit_last_fiemap_cache(struct 
fiemap_extent_info *fieinfo,
                return 0;
 
        ret = fiemap_fill_next_extent(fieinfo, cache->offset, cache->phys,
-                                     cache->len, 0, cache->flags);
+                                     cache->log_len, cache->phys_len,
+                                     cache->flags);
        cache->cached = false;
        if (ret > 0)
                ret = 0;
@@ -2987,13 +3000,15 @@ static int fiemap_process_hole(struct btrfs_inode 
*inode,
                        }
                        ret = emit_fiemap_extent(fieinfo, cache, prealloc_start,
                                                 disk_bytenr + extent_offset,
-                                                prealloc_len, prealloc_flags);
+                                                prealloc_len, prealloc_len,
+                                                prealloc_flags);
                        if (ret)
                                return ret;
                        extent_offset += prealloc_len;
                }
 
                ret = emit_fiemap_extent(fieinfo, cache, delalloc_start, 0,
+                                        delalloc_end + 1 - delalloc_start,
                                         delalloc_end + 1 - delalloc_start,
                                         FIEMAP_EXTENT_DELALLOC |
                                         FIEMAP_EXTENT_UNKNOWN);
@@ -3034,7 +3049,8 @@ static int fiemap_process_hole(struct btrfs_inode *inode,
                }
                ret = emit_fiemap_extent(fieinfo, cache, prealloc_start,
                                         disk_bytenr + extent_offset,
-                                        prealloc_len, prealloc_flags);
+                                        prealloc_len, prealloc_len,
+                                        prealloc_flags);
                if (ret)
                        return ret;
        }
@@ -3180,6 +3196,7 @@ int extent_fiemap(struct btrfs_inode *inode, struct 
fiemap_extent_info *fieinfo,
                u64 extent_offset = 0;
                u64 extent_gen;
                u64 disk_bytenr = 0;
+               u64 disk_size = 0;
                u64 flags = 0;
                int extent_type;
                u8 compression;
@@ -3242,7 +3259,7 @@ int extent_fiemap(struct btrfs_inode *inode, struct 
fiemap_extent_info *fieinfo,
                        flags |= FIEMAP_EXTENT_DATA_INLINE;
                        flags |= FIEMAP_EXTENT_NOT_ALIGNED;
                        ret = emit_fiemap_extent(fieinfo, &cache, key.offset, 0,
-                                                extent_len, flags);
+                                                extent_len, extent_len, flags);
                } else if (extent_type == BTRFS_FILE_EXTENT_PREALLOC) {
                        ret = fiemap_process_hole(inode, fieinfo, &cache,
                                                  &delalloc_cached_state,
@@ -3257,6 +3274,7 @@ int extent_fiemap(struct btrfs_inode *inode, struct 
fiemap_extent_info *fieinfo,
                                                  backref_ctx, 0, 0, 0,
                                                  key.offset, extent_end - 1);
                } else {
+                       disk_size = btrfs_file_extent_disk_num_bytes(leaf, ei);
                        /* We have a regular extent. */
                        if (fieinfo->fi_extents_max) {
                                ret = btrfs_is_data_extent_shared(inode,
@@ -3271,7 +3289,9 @@ int extent_fiemap(struct btrfs_inode *inode, struct 
fiemap_extent_info *fieinfo,
 
                        ret = emit_fiemap_extent(fieinfo, &cache, key.offset,
                                                 disk_bytenr + extent_offset,
-                                                extent_len, flags);
+                                                extent_len,
+                                                disk_size - extent_offset,
+                                                flags);
                }
 
                if (ret < 0) {
@@ -3309,7 +3329,7 @@ int extent_fiemap(struct btrfs_inode *inode, struct 
fiemap_extent_info *fieinfo,
                prev_extent_end = range_end;
        }
 
-       if (cache.cached && cache.offset + cache.len >= last_extent_end) {
+       if (cache.cached && cache.offset + cache.log_len >= last_extent_end) {
                const u64 i_size = i_size_read(&inode->vfs_inode);
 
                if (prev_extent_end < i_size) {
-- 
2.43.0



_______________________________________________
Linux-f2fs-devel mailing list
Linux-f2fs-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel

Reply via email to