Commit 941919856c11d4dd11d4fcabb4dab58bd2b146bf

Authored by Tao Ma
Committed by Theodore Ts'o
1 parent 32f7f22c0b

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

... ... @@ -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,
... ... @@ -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 }
... ... @@ -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