diff options
author | 2015-10-15 11:34:49 -0700 | |
---|---|---|
committer | 2015-10-20 11:33:21 -0700 | |
commit | 67f8cf3cee6f398d05de8333c04fea2ddb59c805 (patch) | |
tree | 26e05e284cd06011e2f18cf3731fc92766860320 /fs/f2fs | |
parent | f2fs: flush dirty data for bmap (diff) | |
download | linux-67f8cf3cee6f398d05de8333c04fea2ddb59c805.tar.gz linux-67f8cf3cee6f398d05de8333c04fea2ddb59c805.tar.bz2 linux-67f8cf3cee6f398d05de8333c04fea2ddb59c805.zip |
f2fs: support fiemap for inline_data
There is a FIEMAP_EXTENT_INLINE_DATA, pointed out by Marc.
Reviewed-by: Chao Yu <chao2.yu@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
Diffstat (limited to 'fs/f2fs')
-rw-r--r-- | fs/f2fs/data.c | 6 | ||||
-rw-r--r-- | fs/f2fs/f2fs.h | 2 | ||||
-rw-r--r-- | fs/f2fs/inline.c | 36 |
3 files changed, 44 insertions, 0 deletions
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index b052e7c262ac..972eab7ac071 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -771,6 +771,12 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, if (ret) return ret; + if (f2fs_has_inline_data(inode)) { + ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len); + if (ret != -EAGAIN) + return ret; + } + mutex_lock(&inode->i_mutex); if (len >= isize) { diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index c3443da2f991..9db5500d63d9 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -2054,6 +2054,8 @@ void f2fs_delete_inline_entry(struct f2fs_dir_entry *, struct page *, bool f2fs_empty_inline_dir(struct inode *); int f2fs_read_inline_dir(struct file *, struct dir_context *, struct f2fs_str *); +int f2fs_inline_data_fiemap(struct inode *, + struct fiemap_extent_info *, __u64, __u64); /* * shrinker.c diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 3b18e23319c3..bda7126466c0 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -12,6 +12,7 @@ #include <linux/f2fs_fs.h> #include "f2fs.h" +#include "node.h" bool f2fs_may_inline_data(struct inode *inode) { @@ -570,3 +571,38 @@ int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx, f2fs_put_page(ipage, 1); return 0; } + +int f2fs_inline_data_fiemap(struct inode *inode, + struct fiemap_extent_info *fieinfo, __u64 start, __u64 len) +{ + __u64 byteaddr, ilen; + __u32 flags = FIEMAP_EXTENT_DATA_INLINE | FIEMAP_EXTENT_NOT_ALIGNED | + FIEMAP_EXTENT_LAST; + struct node_info ni; + struct page *ipage; + int err = 0; + + ipage = get_node_page(F2FS_I_SB(inode), inode->i_ino); + if (IS_ERR(ipage)) + return PTR_ERR(ipage); + + if (!f2fs_has_inline_data(inode)) { + err = -EAGAIN; + goto out; + } + + ilen = min_t(size_t, MAX_INLINE_DATA, i_size_read(inode)); + if (start >= ilen) + goto out; + if (start + len < ilen) + ilen = start + len; + ilen -= start; + + get_node_info(F2FS_I_SB(inode), inode->i_ino, &ni); + byteaddr = (__u64)ni.blk_addr << inode->i_sb->s_blocksize_bits; + byteaddr += (char *)inline_data_addr(ipage) - (char *)F2FS_INODE(ipage); + err = fiemap_fill_next_extent(fieinfo, start, byteaddr, ilen, flags); +out: + f2fs_put_page(ipage, 1); + return err; +} |