Commit 941919856c11d4dd11d4fcabb4dab58bd2b146bf
Committed by
Theodore Ts'o
1 parent
32f7f22c0b
Exists in
master
and in
20 other branches
ext4: let fiemap work with inline data
fiemap is used to find the disk layout of a file, as for inline data, let us just pretend like a file with just one extent. Signed-off-by: Tao Ma <boyu.mt@taobao.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Showing 3 changed files with 54 additions and 0 deletions Side-by-side Diff
fs/ext4/extents.c
... | ... | @@ -4802,6 +4802,15 @@ |
4802 | 4802 | ext4_lblk_t start_blk; |
4803 | 4803 | int error = 0; |
4804 | 4804 | |
4805 | + if (ext4_has_inline_data(inode)) { | |
4806 | + int has_inline = 1; | |
4807 | + | |
4808 | + error = ext4_inline_data_fiemap(inode, fieinfo, &has_inline); | |
4809 | + | |
4810 | + if (has_inline) | |
4811 | + return error; | |
4812 | + } | |
4813 | + | |
4805 | 4814 | /* fallback to generic here if not in extents fmt */ |
4806 | 4815 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) |
4807 | 4816 | return generic_block_fiemap(inode, fieinfo, start, len, |
fs/ext4/inline.c
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | #include "ext4.h" |
16 | 16 | #include "xattr.h" |
17 | 17 | #include "truncate.h" |
18 | +#include <linux/fiemap.h> | |
18 | 19 | |
19 | 20 | #define EXT4_XATTR_SYSTEM_DATA "data" |
20 | 21 | #define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS)) |
... | ... | @@ -1679,5 +1680,39 @@ |
1679 | 1680 | up_write(&EXT4_I(inode)->xattr_sem); |
1680 | 1681 | |
1681 | 1682 | return ret; |
1683 | +} | |
1684 | + | |
1685 | +int ext4_inline_data_fiemap(struct inode *inode, | |
1686 | + struct fiemap_extent_info *fieinfo, | |
1687 | + int *has_inline) | |
1688 | +{ | |
1689 | + __u64 physical = 0; | |
1690 | + __u64 length; | |
1691 | + __u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_LAST; | |
1692 | + int error = 0; | |
1693 | + struct ext4_iloc iloc; | |
1694 | + | |
1695 | + down_read(&EXT4_I(inode)->xattr_sem); | |
1696 | + if (!ext4_has_inline_data(inode)) { | |
1697 | + *has_inline = 0; | |
1698 | + goto out; | |
1699 | + } | |
1700 | + | |
1701 | + error = ext4_get_inode_loc(inode, &iloc); | |
1702 | + if (error) | |
1703 | + goto out; | |
1704 | + | |
1705 | + physical = iloc.bh->b_blocknr << inode->i_sb->s_blocksize_bits; | |
1706 | + physical += (char *)ext4_raw_inode(&iloc) - iloc.bh->b_data; | |
1707 | + physical += offsetof(struct ext4_inode, i_block); | |
1708 | + length = i_size_read(inode); | |
1709 | + | |
1710 | + if (physical) | |
1711 | + error = fiemap_fill_next_extent(fieinfo, 0, physical, | |
1712 | + length, flags); | |
1713 | + brelse(iloc.bh); | |
1714 | +out: | |
1715 | + up_read(&EXT4_I(inode)->xattr_sem); | |
1716 | + return (error < 0 ? error : 0); | |
1682 | 1717 | } |
fs/ext4/xattr.h
... | ... | @@ -184,6 +184,9 @@ |
184 | 184 | extern struct buffer_head *ext4_get_first_inline_block(struct inode *inode, |
185 | 185 | struct ext4_dir_entry_2 **parent_de, |
186 | 186 | int *retval); |
187 | +extern int ext4_inline_data_fiemap(struct inode *inode, | |
188 | + struct fiemap_extent_info *fieinfo, | |
189 | + int *has_inline); | |
187 | 190 | # else /* CONFIG_EXT4_FS_XATTR */ |
188 | 191 | |
189 | 192 | static inline int |
... | ... | @@ -397,6 +400,13 @@ |
397 | 400 | int *retval) |
398 | 401 | { |
399 | 402 | return NULL; |
403 | +} | |
404 | + | |
405 | +static inline int ext4_inline_data_fiemap(struct inode *inode, | |
406 | + struct fiemap_extent_info *fieinfo, | |
407 | + int *has_inline) | |
408 | +{ | |
409 | + return 0; | |
400 | 410 | } |
401 | 411 | # endif /* CONFIG_EXT4_FS_XATTR */ |
402 | 412 |