diff options
author | Gao Xiang <hsiangkao@linux.alibaba.com> | 2024-10-11 14:51:28 +0800 |
---|---|---|
committer | Gao Xiang <hsiangkao@linux.alibaba.com> | 2024-11-12 10:25:19 +0800 |
commit | 83a8836fa19a3930da72aaef553cbecd36a2966a (patch) | |
tree | 2bc5a9d957a63b3a13ac4d24870060f4532e09e0 /fs | |
parent | 59b723cd2adbac2a34fc8e12c74ae26ae45bf230 (diff) |
erofs: add SEEK_{DATA,HOLE} support
Many userspace programs (including erofs-utils itself) use SEEK_DATA /
SEEK_HOLE to parse hole extents in addition to FIEMAP.
Reviewed-by: Chao Yu <chao@kernel.org>
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20241011065128.2097377-1-hsiangkao@linux.alibaba.com
Diffstat (limited to 'fs')
-rw-r--r-- | fs/erofs/data.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/fs/erofs/data.c b/fs/erofs/data.c index 61debd799cf9..6355866220ff 100644 --- a/fs/erofs/data.c +++ b/fs/erofs/data.c @@ -473,8 +473,32 @@ static int erofs_file_mmap(struct file *file, struct vm_area_struct *vma) #define erofs_file_mmap generic_file_readonly_mmap #endif +static loff_t erofs_file_llseek(struct file *file, loff_t offset, int whence) +{ + struct inode *inode = file->f_mapping->host; + const struct iomap_ops *ops = &erofs_iomap_ops; + + if (erofs_inode_is_data_compressed(EROFS_I(inode)->datalayout)) +#ifdef CONFIG_EROFS_FS_ZIP + ops = &z_erofs_iomap_report_ops; +#else + return generic_file_llseek(file, offset, whence); +#endif + + if (whence == SEEK_HOLE) + offset = iomap_seek_hole(inode, offset, ops); + else if (whence == SEEK_DATA) + offset = iomap_seek_data(inode, offset, ops); + else + return generic_file_llseek(file, offset, whence); + + if (offset < 0) + return offset; + return vfs_setpos(file, offset, inode->i_sb->s_maxbytes); +} + const struct file_operations erofs_file_fops = { - .llseek = generic_file_llseek, + .llseek = erofs_file_llseek, .read_iter = erofs_file_read_iter, .mmap = erofs_file_mmap, .get_unmapped_area = thp_get_unmapped_area, |