Add new function to target_type, so any dm devices may realize it Implement intermediate llseek_hole() on device-mapper layer, do some simple checks.
Feature: dm: implement SEEK_HOLE for dm-qcow2 and dm-ploop https://jira.vzint.dev/browse/PSBM-145746 Signed-off-by: Andrey Zhadchenko <andrey.zhadche...@virtuozzo.com> --- v2: fix return and goto inconsistency drivers/md/dm.c | 41 +++++++++++++++++++++++++++++++++++ include/linux/device-mapper.h | 4 ++++ 2 files changed, 45 insertions(+) diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 7e5c61a75eeb..d592c023b090 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -484,6 +484,45 @@ static int dm_blk_ioctl(struct block_device *bdev, fmode_t mode, return r; } +static loff_t dm_llseek_hole(struct block_device *bdev, loff_t offset, int whence) +{ + struct mapped_device *md = bdev->bd_disk->private_data; + struct dm_table *table; + struct dm_target *ti; + int srcu_idx; + loff_t ret; + + table = dm_get_live_table(md, &srcu_idx); + if (!table || !dm_table_get_size(table)) + return -ENOTTY; + + /* + * For now we only support devices that have a single target. + * But probably it is not hard to break it to a few requests to a different + * targets + */ + if (table->num_targets != 1) + return -EOPNOTSUPP; + + ti = dm_table_get_target(table, 0); + + if (dm_suspended_md(md)) { + ret = -EAGAIN; + goto out; + } + + if (!ti->type->llseek_hole) { + ret = -EINVAL; + goto out; + } + + ret = ti->type->llseek_hole(ti, offset, whence); + +out: + dm_put_live_table(md, srcu_idx); + return ret; +} + u64 dm_start_time_ns_from_clone(struct bio *bio) { return jiffies_to_nsecs(clone_to_tio(bio)->io->start_time); @@ -3255,6 +3294,7 @@ static const struct block_device_operations dm_blk_dops = { .getgeo = dm_blk_getgeo, .report_zones = dm_blk_report_zones, .pr_ops = &dm_pr_ops, + .llseek_hole = &dm_llseek_hole, .owner = THIS_MODULE }; @@ -3264,6 +3304,7 @@ static const struct block_device_operations dm_rq_blk_dops = { .ioctl = dm_blk_ioctl, .getgeo = dm_blk_getgeo, .pr_ops = &dm_pr_ops, + .llseek_hole = &dm_llseek_hole, .owner = THIS_MODULE }; diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 0e1f72680533..ddca72a1fac2 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -152,6 +152,9 @@ typedef size_t (*dm_dax_copy_iter_fn)(struct dm_target *ti, pgoff_t pgoff, typedef int (*dm_dax_zero_page_range_fn)(struct dm_target *ti, pgoff_t pgoff, size_t nr_pages); +typedef loff_t (*dm_llseek_hole_fn)(struct dm_target *ti, loff_t offset, + int whence); + void dm_error(const char *message); struct dm_dev { @@ -203,6 +206,7 @@ struct target_type { dm_dax_copy_iter_fn dax_copy_from_iter; dm_dax_copy_iter_fn dax_copy_to_iter; dm_dax_zero_page_range_fn dax_zero_page_range; + dm_llseek_hole_fn llseek_hole; /* For internal device-mapper use. */ struct list_head list; -- 2.39.3 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel