Message ID | 20230731012626.6843-1-bo.wu@vivo.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [f2fs-dev,1/1] f2fs: move fiemap to use iomap framework | expand |
On 2023/7/31 9:26, Wu Bo wrote: > This patch has been tested with xfstests by running 'kvm-xfstests -c > f2fs -g auto' with and without this patch; no regressions were seen. > > Some tests fail both before and after, and the test results are: > f2fs/default: 683 tests, 9 failures, 226 skipped, 30297 seconds > Failures: generic/050 generic/064 generic/250 generic/252 generic/459 > generic/506 generic/563 generic/634 generic/635 Can you please take a look at gerneic/473 ? generic/473 1s ... - output mismatch (see /media/fstests/results//generic/473.out.bad) --- tests/generic/473.out 2022-11-10 08:42:19.231395230 +0000 +++ /media/fstests/results//generic/473.out.bad 2023-08-04 02:02:01.000000000 +0000 @@ -6,7 +6,7 @@ 1: [256..287]: hole Hole + Data 0: [0..127]: hole -1: [128..255]: data +1: [128..135]: data Hole + Data + Hole 0: [0..127]: hole ... (Run 'diff -u /media/fstests/tests/generic/473.out /media/fstests/results//generic/473.out.bad' to see the entire diff) Other concern is, it needs to test this implementation on compressed file, since the logic is a little bit complicated. +Cc Daeho Jeong Thanks,
On 2023/8/6 10:05, Chao Yu wrote: > On 2023/7/31 9:26, Wu Bo wrote: >> This patch has been tested with xfstests by running 'kvm-xfstests -c >> f2fs -g auto' with and without this patch; no regressions were seen. >> >> Some tests fail both before and after, and the test results are: >> f2fs/default: 683 tests, 9 failures, 226 skipped, 30297 seconds >> Failures: generic/050 generic/064 generic/250 generic/252 generic/459 >> generic/506 generic/563 generic/634 generic/635 > > Can you please take a look at gerneic/473 ? This generic/473 case is failed on xfs too. It's an issue of iomap. > > generic/473 1s ... - output mismatch (see > /media/fstests/results//generic/473.out.bad) > --- tests/generic/473.out 2022-11-10 08:42:19.231395230 +0000 > +++ /media/fstests/results//generic/473.out.bad 2023-08-04 > 02:02:01.000000000 +0000 > @@ -6,7 +6,7 @@ > 1: [256..287]: hole > Hole + Data > 0: [0..127]: hole > -1: [128..255]: data > +1: [128..135]: data > Hole + Data + Hole > 0: [0..127]: hole > ... > (Run 'diff -u /media/fstests/tests/generic/473.out > /media/fstests/results//generic/473.out.bad' to see the entire diff) The layout of the test file is: fiemap.473: EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS 0: [0..127]: hole 128 1: [128..255]: 5283840..5283967 128 0x1000 2: [256..383]: hole 128 3: [384..511]: 5283968..5284095 128 0x1000 And the test command is: xfs_io -c "fiemap -v 0 65k" fiemap.473 So the difference is about when to stop traversal the extents. The iomap stop when the length beyond it is requested from fiemap command: ... xfs_io-7399 [001] ..... 1385.656328: f2fs_map_blocks: dev = (254,48), ino = 5, file offset = 15, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0 xfs_io-7399 [001] ..... 1385.656328: f2fs_map_blocks: dev = (254,48), ino = 5, file offset = 16, start blkaddr = 0x3400, len = 0x1, flags = 2, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0 While previous logic is that stop traversal until next data extent is found: ... xfs_io-2194 [000] ..... 116.046690: f2fs_map_blocks: dev = (254,48), ino = 5, file offset = 15, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0 xfs_io-2194 [000] ..... 116.046690: f2fs_map_blocks: dev = (254,48), ino = 5, file offset = 16, start blkaddr = 0xa1400, len = 0x10, flags = 2, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0 xfs_io-2194 [000] ..... 116.046691: f2fs_map_blocks: dev = (254,48), ino = 5, file offset = 32, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0 ... xfs_io-2194 [000] ..... 116.046706: f2fs_map_blocks: dev = (254,48), ino = 5, file offset = 48, start blkaddr = 0xa1410, len = 0x10, flags = 2, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0 > > Other concern is, it needs to test this implementation on compressed > file, > since the logic is a little bit complicated. To be honest, all the complex logic is try to handle compressed file situation. I used enwiki8 dataset to test compressed file: mkfs.f2fs -f -O extra_attr,compression f2fs.img mount f2fs.img f2fs -o compress_algorithm=lz4,compress_log_size=3,compress_mode=user touch compressed_file f2fs_io setflags compression compressed_file cat enwiki8 > compressed_file f2fs_io compress compressed_file f2fs_io release_cblocks compressed_file xfs_io -c fiemap compressed_file | awk '{print $2 $3}' enwiki8 download url: http://mattmahoney.net/dc/enwik8.zip And the result is: --- a/orig +++ b/new @@ -1750,8 +1750,8 @@ [111872..111935]:323448..323511 [111936..111999]:323488..323551 [112000..112063]:323520..323583 -[112064..112087]:323560..323583 -[112088..112127]:53248..53287 +[112064..112095]:323560..323591 +[112096..112127]:53248..53279 [112128..112191]:53256..53319 [112192..112255]:53288..53351 [112256..112319]:53328..53391 @@ -2078,10 +2078,8 @@ [132800..132863]:65408..65471 [132864..132927]:65448..65511 [132928..132991]:65488..65551 -[132992..132999]:65528..65535 -[133000..133007]:65528..65535 -[133008..133039]:69632..69663 -[133040..133055]:hole +[132992..133007]:65528..65543 +[133008..133055]:69632..69679 [133056..133119]:69664..69727 [133120..133183]:69704..69767 [133184..133247]:69744..69807 The first diff is I count the space of COMPRESS_ADDR belong to the head of one compressed cluster while previous count at the rear of cluster. The secound diff show the previous print a 'hole' in one cluster. I think a compressed cluster should not include a 'hole', so there may have a bug before. Also, as discussed in this thread: https://lore.kernel.org/linux-f2fs-devel/ZJmBmt3WmUpWR3+2@casper.infradead.org/T/#t If f2fs can support async buffer write, the performance can be greatly improved when using io_uring. I think it's time to move f2fs to iomap framework. And really looking forward to hearing your opinion on this. Thanks
ping ... On 2023/8/7 10:38, Wu Bo wrote: > On 2023/8/6 10:05, Chao Yu wrote: > >> On 2023/7/31 9:26, Wu Bo wrote: >>> This patch has been tested with xfstests by running 'kvm-xfstests -c >>> f2fs -g auto' with and without this patch; no regressions were seen. >>> >>> Some tests fail both before and after, and the test results are: >>> f2fs/default: 683 tests, 9 failures, 226 skipped, 30297 seconds >>> Failures: generic/050 generic/064 generic/250 generic/252 generic/459 >>> generic/506 generic/563 generic/634 generic/635 >> Can you please take a look at gerneic/473 ? > This generic/473 case is failed on xfs too. It's an issue of iomap. > >> generic/473 1s ... - output mismatch (see >> /media/fstests/results//generic/473.out.bad) >> --- tests/generic/473.out 2022-11-10 08:42:19.231395230 +0000 >> +++ /media/fstests/results//generic/473.out.bad 2023-08-04 >> 02:02:01.000000000 +0000 >> @@ -6,7 +6,7 @@ >> 1: [256..287]: hole >> Hole + Data >> 0: [0..127]: hole >> -1: [128..255]: data >> +1: [128..135]: data >> Hole + Data + Hole >> 0: [0..127]: hole >> ... >> (Run 'diff -u /media/fstests/tests/generic/473.out >> /media/fstests/results//generic/473.out.bad' to see the entire diff) > The layout of the test file is: > fiemap.473: > EXT: FILE-OFFSET BLOCK-RANGE TOTAL FLAGS > 0: [0..127]: hole 128 > 1: [128..255]: 5283840..5283967 128 0x1000 > 2: [256..383]: hole 128 > 3: [384..511]: 5283968..5284095 128 0x1000 > > And the test command is: > xfs_io -c "fiemap -v 0 65k" fiemap.473 > > So the difference is about when to stop traversal the extents. > The iomap stop when the length beyond it is requested from fiemap command: > ... > xfs_io-7399 [001] ..... 1385.656328: f2fs_map_blocks: dev = (254,48), ino = 5, file offset = 15, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0 > xfs_io-7399 [001] ..... 1385.656328: f2fs_map_blocks: dev = (254,48), ino = 5, file offset = 16, start blkaddr = 0x3400, len = 0x1, flags = 2, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0 > > While previous logic is that stop traversal until next data extent is found: > ... > xfs_io-2194 [000] ..... 116.046690: f2fs_map_blocks: dev = (254,48), ino = 5, file offset = 15, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0 > xfs_io-2194 [000] ..... 116.046690: f2fs_map_blocks: dev = (254,48), ino = 5, file offset = 16, start blkaddr = 0xa1400, len = 0x10, flags = 2, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0 > xfs_io-2194 [000] ..... 116.046691: f2fs_map_blocks: dev = (254,48), ino = 5, file offset = 32, start blkaddr = 0x0, len = 0x0, flags = 0, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0 > ... > xfs_io-2194 [000] ..... 116.046706: f2fs_map_blocks: dev = (254,48), ino = 5, file offset = 48, start blkaddr = 0xa1410, len = 0x10, flags = 2, seg_type = 8, may_create = 0, multidevice = 0, flag = 1, err = 0 > >> Other concern is, it needs to test this implementation on compressed >> file, >> since the logic is a little bit complicated. > To be honest, all the complex logic is try to handle compressed file situation. > > I used enwiki8 dataset to test compressed file: > mkfs.f2fs -f -O extra_attr,compression f2fs.img > mount f2fs.img f2fs -o compress_algorithm=lz4,compress_log_size=3,compress_mode=user > touch compressed_file > f2fs_io setflags compression compressed_file > cat enwiki8 > compressed_file > f2fs_io compress compressed_file > f2fs_io release_cblocks compressed_file > xfs_io -c fiemap compressed_file | awk '{print $2 $3}' > > enwiki8 download url: http://mattmahoney.net/dc/enwik8.zip > > And the result is: > --- a/orig > +++ b/new > @@ -1750,8 +1750,8 @@ > [111872..111935]:323448..323511 > [111936..111999]:323488..323551 > [112000..112063]:323520..323583 > -[112064..112087]:323560..323583 > -[112088..112127]:53248..53287 > +[112064..112095]:323560..323591 > +[112096..112127]:53248..53279 > [112128..112191]:53256..53319 > [112192..112255]:53288..53351 > [112256..112319]:53328..53391 > @@ -2078,10 +2078,8 @@ > [132800..132863]:65408..65471 > [132864..132927]:65448..65511 > [132928..132991]:65488..65551 > -[132992..132999]:65528..65535 > -[133000..133007]:65528..65535 > -[133008..133039]:69632..69663 > -[133040..133055]:hole > +[132992..133007]:65528..65543 > +[133008..133055]:69632..69679 > [133056..133119]:69664..69727 > [133120..133183]:69704..69767 > [133184..133247]:69744..69807 > > The first diff is I count the space of COMPRESS_ADDR belong to the head of one > compressed cluster while previous count at the rear of cluster. > The secound diff show the previous print a 'hole' in one cluster. I think a > compressed cluster should not include a 'hole', so there may have a bug before. > > Also, as discussed in this thread: > https://lore.kernel.org/linux-f2fs-devel/ZJmBmt3WmUpWR3+2@casper.infradead.org/T/#t > If f2fs can support async buffer write, the performance can be greatly improved > when using io_uring. > > I think it's time to move f2fs to iomap framework. And really looking forward > to hearing your opinion on this. > > Thanks
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c index 5882afe71d82..2d0be051a875 100644 --- a/fs/f2fs/data.c +++ b/fs/f2fs/data.c @@ -1599,12 +1599,14 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag) unsigned int maxblocks = map->m_len; struct dnode_of_data dn; struct f2fs_sb_info *sbi = F2FS_I_SB(inode); + unsigned int cluster_size = F2FS_I(inode)->i_cluster_size; + unsigned int cluster_mask = cluster_size - 1; int mode = map->m_may_create ? ALLOC_NODE : LOOKUP_NODE; pgoff_t pgofs, end_offset, end; - int err = 0, ofs = 1; - unsigned int ofs_in_node, last_ofs_in_node; + int err = 0, ofs = 1, append = 0; + unsigned int ofs_in_node, last_ofs_in_node, ofs_in_cluster; blkcnt_t prealloc; - block_t blkaddr; + block_t blkaddr, start_addr; unsigned int start_pgofs; int bidx = 0; bool is_hole; @@ -1691,6 +1693,7 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag) map->m_flags |= F2FS_MAP_NEW; } else if (is_hole) { if (f2fs_compressed_file(inode) && + blkaddr == COMPRESS_ADDR && f2fs_sanity_check_cluster(&dn) && (flag != F2FS_GET_BLOCK_FIEMAP || IS_ENABLED(CONFIG_F2FS_CHECK_FS))) { @@ -1712,6 +1715,18 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag) *map->m_next_pgofs = pgofs + 1; goto sync_out; } + if (f2fs_compressed_file(inode) && + blkaddr == COMPRESS_ADDR) { + /* split consecutive cluster */ + if (map->m_len) { + dn.ofs_in_node--; + goto sync_out; + } + pgofs++; + dn.ofs_in_node++; + append = 1; + goto next_block; + } break; default: /* for defragment case */ @@ -1750,6 +1765,10 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag) goto sync_out; } + /* 1 cluster 1 extent, split consecutive cluster */ + if (append && !((dn.ofs_in_node + 1) & cluster_mask)) + goto sync_out; + skip: dn.ofs_in_node++; pgofs++; @@ -1832,6 +1851,20 @@ int f2fs_map_blocks(struct inode *inode, struct f2fs_map_blocks *map, int flag) if (map->m_next_extent) *map->m_next_extent = pgofs + 1; } + + if (flag == F2FS_GET_BLOCK_FIEMAP && f2fs_compressed_file(inode)) { + ofs_in_node = round_down(dn.ofs_in_node, cluster_size); + ofs_in_cluster = dn.ofs_in_node & cluster_mask; + start_addr = data_blkaddr(dn.inode, dn.node_page, ofs_in_node); + if (start_addr == COMPRESS_ADDR) { + map->m_flags |= F2FS_MAP_ENCODED; + map->m_len += append; + /* End of a cluster */ + if (blkaddr == NULL_ADDR || blkaddr == NEW_ADDR) + map->m_len += cluster_size - ofs_in_cluster; + } + } + f2fs_put_dnode(&dn); unlock_out: if (map->m_may_create) { @@ -1952,37 +1985,10 @@ static int f2fs_xattr_fiemap(struct inode *inode, return (err < 0 ? err : 0); } -static loff_t max_inode_blocks(struct inode *inode) -{ - loff_t result = ADDRS_PER_INODE(inode); - loff_t leaf_count = ADDRS_PER_BLOCK(inode); - - /* two direct node blocks */ - result += (leaf_count * 2); - - /* two indirect node blocks */ - leaf_count *= NIDS_PER_BLOCK; - result += (leaf_count * 2); - - /* one double indirect node block */ - leaf_count *= NIDS_PER_BLOCK; - result += leaf_count; - - return result; -} - int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, u64 start, u64 len) { - struct f2fs_map_blocks map; - sector_t start_blk, last_blk; - pgoff_t next_pgofs; - u64 logical = 0, phys = 0, size = 0; - u32 flags = 0; - int ret = 0; - bool compr_cluster = false, compr_appended; - unsigned int cluster_size = F2FS_I(inode)->i_cluster_size; - unsigned int count_in_cluster = 0; + int ret; loff_t maxbytes; if (fieinfo->fi_flags & FIEMAP_FLAG_CACHE) { @@ -1991,10 +1997,6 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, return ret; } - ret = fiemap_prep(inode, fieinfo, start, &len, FIEMAP_FLAG_XATTR); - if (ret) - return ret; - inode_lock(inode); maxbytes = max_file_blocks(inode) << F2FS_BLKSIZE_BITS; @@ -2011,110 +2013,9 @@ int f2fs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, goto out; } - if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode)) { - ret = f2fs_inline_data_fiemap(inode, fieinfo, start, len); - if (ret != -EAGAIN) - goto out; - } - - if (bytes_to_blks(inode, len) == 0) - len = blks_to_bytes(inode, 1); - - start_blk = bytes_to_blks(inode, start); - last_blk = bytes_to_blks(inode, start + len - 1); - -next: - memset(&map, 0, sizeof(map)); - map.m_lblk = start_blk; - map.m_len = bytes_to_blks(inode, len); - map.m_next_pgofs = &next_pgofs; - map.m_seg_type = NO_CHECK_TYPE; - - if (compr_cluster) { - map.m_lblk += 1; - map.m_len = cluster_size - count_in_cluster; - } - - ret = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_FIEMAP); - if (ret) - goto out; - - /* HOLE */ - if (!compr_cluster && !(map.m_flags & F2FS_MAP_FLAGS)) { - start_blk = next_pgofs; - - if (blks_to_bytes(inode, start_blk) < blks_to_bytes(inode, - max_inode_blocks(inode))) - goto prep_next; - - flags |= FIEMAP_EXTENT_LAST; - } - - compr_appended = false; - /* In a case of compressed cluster, append this to the last extent */ - if (compr_cluster && ((map.m_flags & F2FS_MAP_DELALLOC) || - !(map.m_flags & F2FS_MAP_FLAGS))) { - compr_appended = true; - goto skip_fill; - } - - if (size) { - flags |= FIEMAP_EXTENT_MERGED; - if (IS_ENCRYPTED(inode)) - flags |= FIEMAP_EXTENT_DATA_ENCRYPTED; - - ret = fiemap_fill_next_extent(fieinfo, logical, - phys, size, flags); - trace_f2fs_fiemap(inode, logical, phys, size, flags, ret); - if (ret) - goto out; - size = 0; - } - - if (start_blk > last_blk) - goto out; - -skip_fill: - if (map.m_pblk == COMPRESS_ADDR) { - compr_cluster = true; - count_in_cluster = 1; - } else if (compr_appended) { - unsigned int appended_blks = cluster_size - - count_in_cluster + 1; - size += blks_to_bytes(inode, appended_blks); - start_blk += appended_blks; - compr_cluster = false; - } else { - logical = blks_to_bytes(inode, start_blk); - phys = __is_valid_data_blkaddr(map.m_pblk) ? - blks_to_bytes(inode, map.m_pblk) : 0; - size = blks_to_bytes(inode, map.m_len); - flags = 0; - - if (compr_cluster) { - flags = FIEMAP_EXTENT_ENCODED; - count_in_cluster += map.m_len; - if (count_in_cluster == cluster_size) { - compr_cluster = false; - size += blks_to_bytes(inode, 1); - } - } else if (map.m_flags & F2FS_MAP_DELALLOC) { - flags = FIEMAP_EXTENT_UNWRITTEN; - } - - start_blk += bytes_to_blks(inode, size); - } + ret = iomap_fiemap(inode, fieinfo, start, len, &f2fs_iomap_report_ops); -prep_next: - cond_resched(); - if (fatal_signal_pending(current)) - ret = -EINTR; - else - goto next; out: - if (ret == 1) - ret = 0; - inode_unlock(inode); return ret; } @@ -4266,3 +4167,66 @@ static int f2fs_iomap_begin(struct inode *inode, loff_t offset, loff_t length, const struct iomap_ops f2fs_iomap_ops = { .iomap_begin = f2fs_iomap_begin, }; + +static int f2fs_iomap_begin_report(struct inode *inode, loff_t offset, + loff_t length, unsigned int flags, + struct iomap *iomap, struct iomap *srcmap) +{ + struct f2fs_map_blocks map = {0}; + pgoff_t next_pgofs = 0; + int err; + + if (f2fs_has_inline_data(inode) || f2fs_has_inline_dentry(inode)) { + err = f2fs_inline_data_fiemap(inode, iomap, offset, length); + if (err != -EAGAIN) + return err; + } + + map.m_lblk = bytes_to_blks(inode, offset); + map.m_len = bytes_to_blks(inode, offset + length - 1) - map.m_lblk + 1; + map.m_next_pgofs = &next_pgofs; + map.m_seg_type = NO_CHECK_TYPE; + err = f2fs_map_blocks(inode, &map, F2FS_GET_BLOCK_FIEMAP); + if (err) + return err; + /* + * When inline encryption is enabled, sometimes I/O to an encrypted file + * has to be broken up to guarantee DUN contiguity. Handle this by + * limiting the length of the mapping returned. + */ + map.m_len = fscrypt_limit_io_blocks(inode, map.m_lblk, map.m_len); + + if (WARN_ON_ONCE(map.m_pblk == COMPRESS_ADDR)) + return -EINVAL; + + iomap->offset = blks_to_bytes(inode, map.m_lblk); + if (map.m_flags & F2FS_MAP_FLAGS) + iomap->length = blks_to_bytes(inode, map.m_len); + else + iomap->length = blks_to_bytes(inode, next_pgofs) - + iomap->offset; + + if (map.m_pblk == NEW_ADDR) { + /* f2fs treat pre-alloc & delay-alloc blocks the same way */ + iomap->type = IOMAP_UNWRITTEN; + iomap->addr = IOMAP_NULL_ADDR; + } else if (map.m_pblk == NULL_ADDR) { + iomap->type = IOMAP_HOLE; + iomap->addr = IOMAP_NULL_ADDR; + } else { + iomap->type = IOMAP_MAPPED; + iomap->flags |= IOMAP_F_MERGED; + iomap->bdev = map.m_bdev; + iomap->addr = blks_to_bytes(inode, map.m_pblk); + } + + cond_resched(); + if (fatal_signal_pending(current)) + return -EINTR; + else + return 0; +} + +const struct iomap_ops f2fs_iomap_report_ops = { + .iomap_begin = f2fs_iomap_begin_report, +}; diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h index c7cb2177b252..64a2bf58bd67 100644 --- a/fs/f2fs/f2fs.h +++ b/fs/f2fs/f2fs.h @@ -25,6 +25,7 @@ #include <linux/quotaops.h> #include <linux/part_stat.h> #include <crypto/hash.h> +#include <linux/iomap.h> #include <linux/fscrypt.h> #include <linux/fsverity.h> @@ -680,8 +681,9 @@ struct extent_tree_info { #define F2FS_MAP_NEW (1U << 0) #define F2FS_MAP_MAPPED (1U << 1) #define F2FS_MAP_DELALLOC (1U << 2) +#define F2FS_MAP_ENCODED (1U << 3) #define F2FS_MAP_FLAGS (F2FS_MAP_NEW | F2FS_MAP_MAPPED |\ - F2FS_MAP_DELALLOC) + F2FS_MAP_DELALLOC | F2FS_MAP_ENCODED) struct f2fs_map_blocks { struct block_device *m_bdev; /* for multi-device dio */ @@ -4109,6 +4111,7 @@ extern const struct inode_operations f2fs_symlink_inode_operations; extern const struct inode_operations f2fs_encrypted_symlink_inode_operations; extern const struct inode_operations f2fs_special_inode_operations; extern struct kmem_cache *f2fs_inode_entry_slab; +extern const struct iomap_ops f2fs_iomap_report_ops; /* * inline.c @@ -4139,8 +4142,7 @@ bool f2fs_empty_inline_dir(struct inode *dir); int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx, struct fscrypt_str *fstr); int f2fs_inline_data_fiemap(struct inode *inode, - struct fiemap_extent_info *fieinfo, - __u64 start, __u64 len); + struct iomap *iomap, __u64 start, __u64 len); /* * shrinker.c diff --git a/fs/f2fs/inline.c b/fs/f2fs/inline.c index 4638fee16a91..c1afc3414231 100644 --- a/fs/f2fs/inline.c +++ b/fs/f2fs/inline.c @@ -767,11 +767,9 @@ int f2fs_read_inline_dir(struct file *file, struct dir_context *ctx, } int f2fs_inline_data_fiemap(struct inode *inode, - struct fiemap_extent_info *fieinfo, __u64 start, __u64 len) + struct iomap *iomap, __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; @@ -792,8 +790,14 @@ int f2fs_inline_data_fiemap(struct inode *inode, } ilen = min_t(size_t, MAX_INLINE_DATA(inode), i_size_read(inode)); - if (start >= ilen) + if (start >= ilen) { + /* stop iomap iterator */ + iomap->offset = start; + iomap->length = len; + iomap->addr = IOMAP_NULL_ADDR; + iomap->type = IOMAP_HOLE; goto out; + } if (start + len < ilen) ilen = start + len; ilen -= start; @@ -805,8 +809,12 @@ int f2fs_inline_data_fiemap(struct inode *inode, byteaddr = (__u64)ni.blk_addr << inode->i_sb->s_blocksize_bits; byteaddr += (char *)inline_data_addr(inode, ipage) - (char *)F2FS_INODE(ipage); - err = fiemap_fill_next_extent(fieinfo, start, byteaddr, ilen, flags); - trace_f2fs_fiemap(inode, start, byteaddr, ilen, flags, err); + iomap->addr = byteaddr; + iomap->type = IOMAP_INLINE; + iomap->flags = 0; + iomap->offset = start; + iomap->length = ilen; + out: f2fs_put_page(ipage, 1); return err;
This patch has been tested with xfstests by running 'kvm-xfstests -c f2fs -g auto' with and without this patch; no regressions were seen. Some tests fail both before and after, and the test results are: f2fs/default: 683 tests, 9 failures, 226 skipped, 30297 seconds Failures: generic/050 generic/064 generic/250 generic/252 generic/459 generic/506 generic/563 generic/634 generic/635 Signed-off-by: Wu Bo <bo.wu@vivo.com> --- fs/f2fs/data.c | 238 ++++++++++++++++++++--------------------------- fs/f2fs/f2fs.h | 8 +- fs/f2fs/inline.c | 20 ++-- 3 files changed, 120 insertions(+), 146 deletions(-)