diff options
author | Tao Ma <boyu.mt@taobao.com> | 2012-12-10 14:06:02 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2012-12-10 14:06:02 -0500 |
commit | 941919856c11d4dd11d4fcabb4dab58bd2b146bf (patch) | |
tree | dcb06b13ca094575d9f32e49371560c1c956c874 /fs | |
parent | 32f7f22c0b52e8189fef83986b16dc7abe95f2c4 (diff) |
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>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/extents.c | 9 | ||||
-rw-r--r-- | fs/ext4/inline.c | 35 | ||||
-rw-r--r-- | fs/ext4/xattr.h | 10 |
3 files changed, 54 insertions, 0 deletions
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c index f2659f51b23d..70dc6fc53a00 100644 --- a/fs/ext4/extents.c +++ b/fs/ext4/extents.c | |||
@@ -4802,6 +4802,15 @@ int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, | |||
4802 | ext4_lblk_t start_blk; | 4802 | ext4_lblk_t start_blk; |
4803 | int error = 0; | 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 | /* fallback to generic here if not in extents fmt */ | 4814 | /* fallback to generic here if not in extents fmt */ |
4806 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) | 4815 | if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS))) |
4807 | return generic_block_fiemap(inode, fieinfo, start, len, | 4816 | return generic_block_fiemap(inode, fieinfo, start, len, |
diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c index fc3629980925..bf5f77803885 100644 --- a/fs/ext4/inline.c +++ b/fs/ext4/inline.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "ext4.h" | 15 | #include "ext4.h" |
16 | #include "xattr.h" | 16 | #include "xattr.h" |
17 | #include "truncate.h" | 17 | #include "truncate.h" |
18 | #include <linux/fiemap.h> | ||
18 | 19 | ||
19 | #define EXT4_XATTR_SYSTEM_DATA "data" | 20 | #define EXT4_XATTR_SYSTEM_DATA "data" |
20 | #define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS)) | 21 | #define EXT4_MIN_INLINE_DATA_SIZE ((sizeof(__le32) * EXT4_N_BLOCKS)) |
@@ -1680,3 +1681,37 @@ int ext4_destroy_inline_data(handle_t *handle, struct inode *inode) | |||
1680 | 1681 | ||
1681 | return ret; | 1682 | return ret; |
1682 | } | 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); | ||
1717 | } | ||
diff --git a/fs/ext4/xattr.h b/fs/ext4/xattr.h index f6c3ca6dae46..5c7e55edfe6c 100644 --- a/fs/ext4/xattr.h +++ b/fs/ext4/xattr.h | |||
@@ -184,6 +184,9 @@ extern int empty_inline_dir(struct inode *dir, int *has_inline_data); | |||
184 | extern struct buffer_head *ext4_get_first_inline_block(struct inode *inode, | 184 | extern struct buffer_head *ext4_get_first_inline_block(struct inode *inode, |
185 | struct ext4_dir_entry_2 **parent_de, | 185 | struct ext4_dir_entry_2 **parent_de, |
186 | int *retval); | 186 | int *retval); |
187 | extern int ext4_inline_data_fiemap(struct inode *inode, | ||
188 | struct fiemap_extent_info *fieinfo, | ||
189 | int *has_inline); | ||
187 | # else /* CONFIG_EXT4_FS_XATTR */ | 190 | # else /* CONFIG_EXT4_FS_XATTR */ |
188 | 191 | ||
189 | static inline int | 192 | static inline int |
@@ -398,6 +401,13 @@ ext4_get_first_inline_block(struct inode *inode, | |||
398 | { | 401 | { |
399 | return NULL; | 402 | return NULL; |
400 | } | 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; | ||
410 | } | ||
401 | # endif /* CONFIG_EXT4_FS_XATTR */ | 411 | # endif /* CONFIG_EXT4_FS_XATTR */ |
402 | 412 | ||
403 | #ifdef CONFIG_EXT4_FS_SECURITY | 413 | #ifdef CONFIG_EXT4_FS_SECURITY |