]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
erofs: add SEEK_{DATA,HOLE} support
authorGao Xiang <hsiangkao@linux.alibaba.com>
Fri, 11 Oct 2024 06:51:28 +0000 (14:51 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Tue, 12 Nov 2024 02:25:19 +0000 (10:25 +0800)
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
fs/erofs/data.c

index 61debd799cf90436f2294f8e7990ca37a34b855d..6355866220ffc82048c59c5d02d85fc914d52741 100644 (file)
@@ -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,