Skip to content

Commit d3b6f23

Browse files
riteshharjanitytso
authored andcommitted
ext4: move ext4_fiemap to use iomap framework
This patch moves ext4_fiemap to use iomap framework. For xattr a new 'ext4_iomap_xattr_ops' is added. Reported-by: kbuild test robot <[email protected]> Reviewed-by: Jan Kara <[email protected]> Reviewed-by: Darrick J. Wong <[email protected]> Link: https://lore.kernel.org/r/b9f45c885814fcdd0631747ff0fe08886270828c.1582880246.git.riteshh@linux.ibm.com Signed-off-by: Ritesh Harjani <[email protected]> Signed-off-by: Theodore Ts'o <[email protected]>
1 parent b2c5764 commit d3b6f23

File tree

2 files changed

+48
-283
lines changed

2 files changed

+48
-283
lines changed

fs/ext4/extents.c

Lines changed: 48 additions & 242 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <linux/uaccess.h>
2929
#include <linux/fiemap.h>
3030
#include <linux/backing-dev.h>
31+
#include <linux/iomap.h>
3132
#include "ext4_jbd2.h"
3233
#include "ext4_extents.h"
3334
#include "xattr.h"
@@ -90,9 +91,6 @@ static int ext4_split_extent_at(handle_t *handle,
9091
int split_flag,
9192
int flags);
9293

93-
static int ext4_find_delayed_extent(struct inode *inode,
94-
struct extent_status *newes);
95-
9694
static int ext4_ext_trunc_restart_fn(struct inode *inode, int *dropped)
9795
{
9896
/*
@@ -2130,155 +2128,6 @@ int ext4_ext_insert_extent(handle_t *handle, struct inode *inode,
21302128
return err;
21312129
}
21322130

2133-
static int ext4_fill_fiemap_extents(struct inode *inode,
2134-
ext4_lblk_t block, ext4_lblk_t num,
2135-
struct fiemap_extent_info *fieinfo)
2136-
{
2137-
struct ext4_ext_path *path = NULL;
2138-
struct ext4_extent *ex;
2139-
struct extent_status es;
2140-
ext4_lblk_t next, next_del, start = 0, end = 0;
2141-
ext4_lblk_t last = block + num;
2142-
int exists, depth = 0, err = 0;
2143-
unsigned int flags = 0;
2144-
unsigned char blksize_bits = inode->i_sb->s_blocksize_bits;
2145-
2146-
while (block < last && block != EXT_MAX_BLOCKS) {
2147-
num = last - block;
2148-
/* find extent for this block */
2149-
down_read(&EXT4_I(inode)->i_data_sem);
2150-
2151-
path = ext4_find_extent(inode, block, &path, 0);
2152-
if (IS_ERR(path)) {
2153-
up_read(&EXT4_I(inode)->i_data_sem);
2154-
err = PTR_ERR(path);
2155-
path = NULL;
2156-
break;
2157-
}
2158-
2159-
depth = ext_depth(inode);
2160-
if (unlikely(path[depth].p_hdr == NULL)) {
2161-
up_read(&EXT4_I(inode)->i_data_sem);
2162-
EXT4_ERROR_INODE(inode, "path[%d].p_hdr == NULL", depth);
2163-
err = -EFSCORRUPTED;
2164-
break;
2165-
}
2166-
ex = path[depth].p_ext;
2167-
next = ext4_ext_next_allocated_block(path);
2168-
2169-
flags = 0;
2170-
exists = 0;
2171-
if (!ex) {
2172-
/* there is no extent yet, so try to allocate
2173-
* all requested space */
2174-
start = block;
2175-
end = block + num;
2176-
} else if (le32_to_cpu(ex->ee_block) > block) {
2177-
/* need to allocate space before found extent */
2178-
start = block;
2179-
end = le32_to_cpu(ex->ee_block);
2180-
if (block + num < end)
2181-
end = block + num;
2182-
} else if (block >= le32_to_cpu(ex->ee_block)
2183-
+ ext4_ext_get_actual_len(ex)) {
2184-
/* need to allocate space after found extent */
2185-
start = block;
2186-
end = block + num;
2187-
if (end >= next)
2188-
end = next;
2189-
} else if (block >= le32_to_cpu(ex->ee_block)) {
2190-
/*
2191-
* some part of requested space is covered
2192-
* by found extent
2193-
*/
2194-
start = block;
2195-
end = le32_to_cpu(ex->ee_block)
2196-
+ ext4_ext_get_actual_len(ex);
2197-
if (block + num < end)
2198-
end = block + num;
2199-
exists = 1;
2200-
} else {
2201-
BUG();
2202-
}
2203-
BUG_ON(end <= start);
2204-
2205-
if (!exists) {
2206-
es.es_lblk = start;
2207-
es.es_len = end - start;
2208-
es.es_pblk = 0;
2209-
} else {
2210-
es.es_lblk = le32_to_cpu(ex->ee_block);
2211-
es.es_len = ext4_ext_get_actual_len(ex);
2212-
es.es_pblk = ext4_ext_pblock(ex);
2213-
if (ext4_ext_is_unwritten(ex))
2214-
flags |= FIEMAP_EXTENT_UNWRITTEN;
2215-
}
2216-
2217-
/*
2218-
* Find delayed extent and update es accordingly. We call
2219-
* it even in !exists case to find out whether es is the
2220-
* last existing extent or not.
2221-
*/
2222-
next_del = ext4_find_delayed_extent(inode, &es);
2223-
if (!exists && next_del) {
2224-
exists = 1;
2225-
flags |= (FIEMAP_EXTENT_DELALLOC |
2226-
FIEMAP_EXTENT_UNKNOWN);
2227-
}
2228-
up_read(&EXT4_I(inode)->i_data_sem);
2229-
2230-
if (unlikely(es.es_len == 0)) {
2231-
EXT4_ERROR_INODE(inode, "es.es_len == 0");
2232-
err = -EFSCORRUPTED;
2233-
break;
2234-
}
2235-
2236-
/*
2237-
* This is possible iff next == next_del == EXT_MAX_BLOCKS.
2238-
* we need to check next == EXT_MAX_BLOCKS because it is
2239-
* possible that an extent is with unwritten and delayed
2240-
* status due to when an extent is delayed allocated and
2241-
* is allocated by fallocate status tree will track both of
2242-
* them in a extent.
2243-
*
2244-
* So we could return a unwritten and delayed extent, and
2245-
* its block is equal to 'next'.
2246-
*/
2247-
if (next == next_del && next == EXT_MAX_BLOCKS) {
2248-
flags |= FIEMAP_EXTENT_LAST;
2249-
if (unlikely(next_del != EXT_MAX_BLOCKS ||
2250-
next != EXT_MAX_BLOCKS)) {
2251-
EXT4_ERROR_INODE(inode,
2252-
"next extent == %u, next "
2253-
"delalloc extent = %u",
2254-
next, next_del);
2255-
err = -EFSCORRUPTED;
2256-
break;
2257-
}
2258-
}
2259-
2260-
if (exists) {
2261-
err = fiemap_fill_next_extent(fieinfo,
2262-
(__u64)es.es_lblk << blksize_bits,
2263-
(__u64)es.es_pblk << blksize_bits,
2264-
(__u64)es.es_len << blksize_bits,
2265-
flags);
2266-
if (err < 0)
2267-
break;
2268-
if (err == 1) {
2269-
err = 0;
2270-
break;
2271-
}
2272-
}
2273-
2274-
block = es.es_lblk + es.es_len;
2275-
}
2276-
2277-
ext4_ext_drop_refs(path);
2278-
kfree(path);
2279-
return err;
2280-
}
2281-
22822131
static int ext4_fill_es_cache_info(struct inode *inode,
22832132
ext4_lblk_t block, ext4_lblk_t num,
22842133
struct fiemap_extent_info *fieinfo)
@@ -4927,64 +4776,13 @@ int ext4_convert_unwritten_io_end_vec(handle_t *handle, ext4_io_end_t *io_end)
49274776
return ret < 0 ? ret : err;
49284777
}
49294778

4930-
/*
4931-
* If newes is not existing extent (newes->ec_pblk equals zero) find
4932-
* delayed extent at start of newes and update newes accordingly and
4933-
* return start of the next delayed extent.
4934-
*
4935-
* If newes is existing extent (newes->ec_pblk is not equal zero)
4936-
* return start of next delayed extent or EXT_MAX_BLOCKS if no delayed
4937-
* extent found. Leave newes unmodified.
4938-
*/
4939-
static int ext4_find_delayed_extent(struct inode *inode,
4940-
struct extent_status *newes)
4941-
{
4942-
struct extent_status es;
4943-
ext4_lblk_t block, next_del;
4944-
4945-
if (newes->es_pblk == 0) {
4946-
ext4_es_find_extent_range(inode, &ext4_es_is_delayed,
4947-
newes->es_lblk,
4948-
newes->es_lblk + newes->es_len - 1,
4949-
&es);
4950-
4951-
/*
4952-
* No extent in extent-tree contains block @newes->es_pblk,
4953-
* then the block may stay in 1)a hole or 2)delayed-extent.
4954-
*/
4955-
if (es.es_len == 0)
4956-
/* A hole found. */
4957-
return 0;
4958-
4959-
if (es.es_lblk > newes->es_lblk) {
4960-
/* A hole found. */
4961-
newes->es_len = min(es.es_lblk - newes->es_lblk,
4962-
newes->es_len);
4963-
return 0;
4964-
}
4965-
4966-
newes->es_len = es.es_lblk + es.es_len - newes->es_lblk;
4967-
}
4968-
4969-
block = newes->es_lblk + newes->es_len;
4970-
ext4_es_find_extent_range(inode, &ext4_es_is_delayed, block,
4971-
EXT_MAX_BLOCKS, &es);
4972-
if (es.es_len == 0)
4973-
next_del = EXT_MAX_BLOCKS;
4974-
else
4975-
next_del = es.es_lblk;
4976-
4977-
return next_del;
4978-
}
4979-
4980-
static int ext4_xattr_fiemap(struct inode *inode,
4981-
struct fiemap_extent_info *fieinfo)
4779+
static int ext4_iomap_xattr_fiemap(struct inode *inode, struct iomap *iomap)
49824780
{
49834781
__u64 physical = 0;
4984-
__u64 length;
4985-
__u32 flags = FIEMAP_EXTENT_LAST;
4782+
__u64 length = 0;
49864783
int blockbits = inode->i_sb->s_blocksize_bits;
49874784
int error = 0;
4785+
u16 iomap_type;
49884786

49894787
/* in-inode? */
49904788
if (ext4_test_inode_state(inode, EXT4_STATE_XATTR)) {
@@ -4999,40 +4797,49 @@ static int ext4_xattr_fiemap(struct inode *inode,
49994797
EXT4_I(inode)->i_extra_isize;
50004798
physical += offset;
50014799
length = EXT4_SB(inode->i_sb)->s_inode_size - offset;
5002-
flags |= FIEMAP_EXTENT_DATA_INLINE;
50034800
brelse(iloc.bh);
5004-
} else { /* external block */
4801+
iomap_type = IOMAP_INLINE;
4802+
} else if (EXT4_I(inode)->i_file_acl) { /* external block */
50054803
physical = (__u64)EXT4_I(inode)->i_file_acl << blockbits;
50064804
length = inode->i_sb->s_blocksize;
4805+
iomap_type = IOMAP_MAPPED;
4806+
} else {
4807+
/* no in-inode or external block for xattr, so return -ENOENT */
4808+
error = -ENOENT;
4809+
goto out;
50074810
}
50084811

5009-
if (physical)
5010-
error = fiemap_fill_next_extent(fieinfo, 0, physical,
5011-
length, flags);
5012-
return (error < 0 ? error : 0);
4812+
iomap->addr = physical;
4813+
iomap->offset = 0;
4814+
iomap->length = length;
4815+
iomap->type = iomap_type;
4816+
iomap->flags = 0;
4817+
out:
4818+
return error;
50134819
}
50144820

5015-
static int _ext4_fiemap(struct inode *inode,
5016-
struct fiemap_extent_info *fieinfo,
5017-
__u64 start, __u64 len,
5018-
int (*fill)(struct inode *, ext4_lblk_t,
5019-
ext4_lblk_t,
5020-
struct fiemap_extent_info *))
4821+
static int ext4_iomap_xattr_begin(struct inode *inode, loff_t offset,
4822+
loff_t length, unsigned flags,
4823+
struct iomap *iomap, struct iomap *srcmap)
50214824
{
5022-
ext4_lblk_t start_blk;
5023-
u32 ext4_fiemap_flags = FIEMAP_FLAG_SYNC|FIEMAP_FLAG_XATTR;
4825+
int error;
50244826

5025-
int error = 0;
5026-
5027-
if (ext4_has_inline_data(inode)) {
5028-
int has_inline = 1;
4827+
error = ext4_iomap_xattr_fiemap(inode, iomap);
4828+
if (error == 0 && (offset >= iomap->length))
4829+
error = -ENOENT;
4830+
return error;
4831+
}
50294832

5030-
error = ext4_inline_data_fiemap(inode, fieinfo, &has_inline,
5031-
start, len);
4833+
static const struct iomap_ops ext4_iomap_xattr_ops = {
4834+
.iomap_begin = ext4_iomap_xattr_begin,
4835+
};
50324836

5033-
if (has_inline)
5034-
return error;
5035-
}
4837+
static int _ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
4838+
__u64 start, __u64 len, bool from_es_cache)
4839+
{
4840+
ext4_lblk_t start_blk;
4841+
u32 ext4_fiemap_flags = FIEMAP_FLAG_SYNC | FIEMAP_FLAG_XATTR;
4842+
int error = 0;
50364843

50374844
if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) {
50384845
error = ext4_ext_precache(inode);
@@ -5041,19 +4848,19 @@ static int _ext4_fiemap(struct inode *inode,
50414848
fieinfo->fi_flags &= ~FIEMAP_FLAG_CACHE;
50424849
}
50434850

5044-
/* fallback to generic here if not in extents fmt */
5045-
if (!(ext4_test_inode_flag(inode, EXT4_INODE_EXTENTS)) &&
5046-
fill == ext4_fill_fiemap_extents)
5047-
return generic_block_fiemap(inode, fieinfo, start, len,
5048-
ext4_get_block);
5049-
5050-
if (fill == ext4_fill_es_cache_info)
4851+
if (from_es_cache)
50514852
ext4_fiemap_flags &= FIEMAP_FLAG_XATTR;
4853+
50524854
if (fiemap_check_flags(fieinfo, ext4_fiemap_flags))
50534855
return -EBADR;
50544856

50554857
if (fieinfo->fi_flags & FIEMAP_FLAG_XATTR) {
5056-
error = ext4_xattr_fiemap(inode, fieinfo);
4858+
fieinfo->fi_flags &= ~FIEMAP_FLAG_XATTR;
4859+
error = iomap_fiemap(inode, fieinfo, start, len,
4860+
&ext4_iomap_xattr_ops);
4861+
} else if (!from_es_cache) {
4862+
error = iomap_fiemap(inode, fieinfo, start, len,
4863+
&ext4_iomap_report_ops);
50574864
} else {
50584865
ext4_lblk_t len_blks;
50594866
__u64 last_blk;
@@ -5068,16 +4875,16 @@ static int _ext4_fiemap(struct inode *inode,
50684875
* Walk the extent tree gathering extent information
50694876
* and pushing extents back to the user.
50704877
*/
5071-
error = fill(inode, start_blk, len_blks, fieinfo);
4878+
error = ext4_fill_es_cache_info(inode, start_blk, len_blks,
4879+
fieinfo);
50724880
}
50734881
return error;
50744882
}
50754883

50764884
int ext4_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
50774885
__u64 start, __u64 len)
50784886
{
5079-
return _ext4_fiemap(inode, fieinfo, start, len,
5080-
ext4_fill_fiemap_extents);
4887+
return _ext4_fiemap(inode, fieinfo, start, len, false);
50814888
}
50824889

50834890
int ext4_get_es_cache(struct inode *inode, struct fiemap_extent_info *fieinfo,
@@ -5093,8 +4900,7 @@ int ext4_get_es_cache(struct inode *inode, struct fiemap_extent_info *fieinfo,
50934900
return 0;
50944901
}
50954902

5096-
return _ext4_fiemap(inode, fieinfo, start, len,
5097-
ext4_fill_es_cache_info);
4903+
return _ext4_fiemap(inode, fieinfo, start, len, true);
50984904
}
50994905

51004906

0 commit comments

Comments
 (0)