Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

erofs: add fiemap support with iomap

This adds fiemap support for both uncompressed files and compressed
files by using iomap infrastructure.

Link: https://lore.kernel.org/r/20210813052931.203280-3-hsiangkao@linux.alibaba.com
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>

+59 -1
+14 -1
fs/erofs/data.c
··· 5 5 */ 6 6 #include "internal.h" 7 7 #include <linux/prefetch.h> 8 - #include <linux/iomap.h> 9 8 #include <linux/dax.h> 10 9 #include <trace/events/erofs.h> 11 10 ··· 150 151 .iomap_begin = erofs_iomap_begin, 151 152 .iomap_end = erofs_iomap_end, 152 153 }; 154 + 155 + int erofs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 156 + u64 start, u64 len) 157 + { 158 + if (erofs_inode_is_data_compressed(EROFS_I(inode)->datalayout)) { 159 + #ifdef CONFIG_EROFS_FS_ZIP 160 + return iomap_fiemap(inode, fieinfo, start, len, 161 + &z_erofs_iomap_report_ops); 162 + #else 163 + return -EOPNOTSUPP; 164 + #endif 165 + } 166 + return iomap_fiemap(inode, fieinfo, start, len, &erofs_iomap_ops); 167 + } 153 168 154 169 /* 155 170 * since we dont have write or truncate flows, so no inode
+1
fs/erofs/inode.c
··· 365 365 .getattr = erofs_getattr, 366 366 .listxattr = erofs_listxattr, 367 367 .get_acl = erofs_get_acl, 368 + .fiemap = erofs_fiemap, 368 369 }; 369 370 370 371 const struct inode_operations erofs_symlink_iops = {
+5
fs/erofs/internal.h
··· 15 15 #include <linux/magic.h> 16 16 #include <linux/slab.h> 17 17 #include <linux/vmalloc.h> 18 + #include <linux/iomap.h> 18 19 #include "erofs_fs.h" 19 20 20 21 /* redefine pr_fmt "erofs: " */ ··· 364 363 #define EROFS_GET_BLOCKS_FIEMAP 0x0002 365 364 366 365 /* zmap.c */ 366 + extern const struct iomap_ops z_erofs_iomap_report_ops; 367 + 367 368 #ifdef CONFIG_EROFS_FS_ZIP 368 369 int z_erofs_fill_inode(struct inode *inode); 369 370 int z_erofs_map_blocks_iter(struct inode *inode, ··· 384 381 /* data.c */ 385 382 extern const struct file_operations erofs_file_fops; 386 383 struct page *erofs_get_meta_page(struct super_block *sb, erofs_blk_t blkaddr); 384 + int erofs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo, 385 + u64 start, u64 len); 387 386 388 387 /* inode.c */ 389 388 static inline unsigned long erofs_inode_hash(erofs_nid_t nid)
+1
fs/erofs/namei.c
··· 245 245 .getattr = erofs_getattr, 246 246 .listxattr = erofs_listxattr, 247 247 .get_acl = erofs_get_acl, 248 + .fiemap = erofs_fiemap, 248 249 };
+38
fs/erofs/zmap.c
··· 675 675 DBG_BUGON(err < 0 && err != -ENOMEM); 676 676 return err; 677 677 } 678 + 679 + static int z_erofs_iomap_begin_report(struct inode *inode, loff_t offset, 680 + loff_t length, unsigned int flags, 681 + struct iomap *iomap, struct iomap *srcmap) 682 + { 683 + int ret; 684 + struct erofs_map_blocks map = { .m_la = offset }; 685 + 686 + ret = z_erofs_map_blocks_iter(inode, &map, EROFS_GET_BLOCKS_FIEMAP); 687 + if (map.mpage) 688 + put_page(map.mpage); 689 + if (ret < 0) 690 + return ret; 691 + 692 + iomap->bdev = inode->i_sb->s_bdev; 693 + iomap->offset = map.m_la; 694 + iomap->length = map.m_llen; 695 + if (map.m_flags & EROFS_MAP_MAPPED) { 696 + iomap->type = IOMAP_MAPPED; 697 + iomap->addr = map.m_pa; 698 + } else { 699 + iomap->type = IOMAP_HOLE; 700 + iomap->addr = IOMAP_NULL_ADDR; 701 + /* 702 + * No strict rule how to describe extents for post EOF, yet 703 + * we need do like below. Otherwise, iomap itself will get 704 + * into an endless loop on post EOF. 705 + */ 706 + if (iomap->offset >= inode->i_size) 707 + iomap->length = length + map.m_la - offset; 708 + } 709 + iomap->flags = 0; 710 + return 0; 711 + } 712 + 713 + const struct iomap_ops z_erofs_iomap_report_ops = { 714 + .iomap_begin = z_erofs_iomap_begin_report, 715 + };