@@ -58,6 +58,13 @@ If this flag is set, the kernel will sync the file before mapping extents.
If this flag is set, the extents returned will describe the inodes
extended attribute lookup tree, instead of its data tree.
+* FIEMAP_FLAG_ONDISK
+If this flag is set, fe_length returns size of blocks allocated on the disk,
+rather than actual data length contained in extent.
+
+For example, if extent have the FIEMAP_EXTENT_ENCODED flag set and
+the data are compressed, then actual data size contained by extent
+differs from blocks allocated on disk.
Extent Mapping
--------------
@@ -4488,10 +4488,17 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
if (!test_bit(EXTENT_FLAG_COMPRESSED, &em->flags))
offset_in_extent = em_start - em->start;
em_end = extent_map_end(em);
- em_len = em_end - em_start;
disko = 0;
flags = 0;
+ if (fieinfo->fi_flags & FIEMAP_FLAG_ONDISK &&
+ em->block_start != EXTENT_MAP_INLINE &&
+ em->block_len != (u64)-1) {
+
+ em_len = em->block_len;
+ } else
+ em_len = em_end - em_start;
+
/*
* bump off for our next call to get_extent
*/
@@ -8744,7 +8744,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
return ret;
}
-#define BTRFS_FIEMAP_FLAGS (FIEMAP_FLAG_SYNC)
+#define BTRFS_FIEMAP_FLAGS (FIEMAP_FLAG_SYNC|FIEMAP_FLAG_ONDISK)
static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
__u64 start, __u64 len)
@@ -41,8 +41,12 @@ struct fiemap {
#define FIEMAP_FLAG_SYNC 0x00000001 /* sync file data before map */
#define FIEMAP_FLAG_XATTR 0x00000002 /* map extended attribute tree */
#define FIEMAP_FLAG_CACHE 0x00000004 /* request caching of the extents */
+#define FIEMAP_FLAG_ONDISK 0x00000008 /* return size of blocks allocated
+ * on disk, rather than actual
+ * data length in extent */
-#define FIEMAP_FLAGS_COMPAT (FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR)
+#define FIEMAP_FLAGS_COMPAT (FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR | \
+ FIEMAP_FLAG_ONDISK)
#define FIEMAP_EXTENT_LAST 0x00000001 /* Last extent in file. */
#define FIEMAP_EXTENT_UNKNOWN 0x00000002 /* Data location unknown. */
Simple patch which allows you to query with FIEMAP ioctl for disk blocks allocated per extent. It's done when you set new FIEMAP flag : * FIEMAP_FLAG_ONDISK If this flag is set, fe_length returns size of blocks allocated on the disk, rather than actual data length contained in extent. Here is also userspace POC code: https://github.com/adrb/public/blob/master/linux/tools/fiemap.c Signed-off-by: Adrian Brzezinski <linux-btrfs@adrb.pl> --- Documentation/filesystems/fiemap.txt | 7 +++++++ fs/btrfs/extent_io.c | 9 ++++++++- fs/btrfs/inode.c | 2 +- include/uapi/linux/fiemap.h | 6 +++++- 4 files changed, 21 insertions(+), 3 deletions(-)