[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20240328203910.2370087-3-stefanha@redhat.com>
Date: Thu, 28 Mar 2024 16:39:03 -0400
From: Stefan Hajnoczi <stefanha@...hat.com>
To: linux-block@...r.kernel.org
Cc: linux-kernel@...r.kernel.org,
eblake@...hat.com,
Alasdair Kergon <agk@...hat.com>,
Mikulas Patocka <mpatocka@...hat.com>,
dm-devel@...ts.linux.dev,
David Teigland <teigland@...hat.com>,
Mike Snitzer <snitzer@...nel.org>,
Jens Axboe <axboe@...nel.dk>,
Christoph Hellwig <hch@....de>,
Joe Thornber <ejt@...hat.com>,
Stefan Hajnoczi <stefanha@...hat.com>
Subject: [RFC 2/9] loop: add llseek(SEEK_HOLE/SEEK_DATA) support
Signed-off-by: Stefan Hajnoczi <stefanha@...hat.com>
---
Open issues:
- The file offset is updated on both the blkdev file and the backing
file. Is there a way to avoid updating the backing file offset so the
file opened by userspace is not affected?
- Should this run in the worker or use the cgroups?
---
drivers/block/loop.c | 36 ++++++++++++++++++++++++++++++------
1 file changed, 30 insertions(+), 6 deletions(-)
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index 28a95fd366fea..6a89375de82e8 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -750,6 +750,29 @@ static void loop_sysfs_exit(struct loop_device *lo)
&loop_attribute_group);
}
+static loff_t lo_seek_hole_data(struct block_device *bdev, loff_t offset,
+ int whence)
+{
+ /* TODO need to activate cgroups or use worker? */
+ /* TODO locking? */
+ struct loop_device *lo = bdev->bd_disk->private_data;
+ struct file *file = lo->lo_backing_file;
+
+ if (lo->lo_offset > 0)
+ offset += lo->lo_offset; /* TODO underflow/overflow? */
+
+ /* TODO backing file offset is modified! */
+ offset = vfs_llseek(file, offset, whence);
+ if (offset < 0)
+ return offset;
+
+ if (lo->lo_offset > 0)
+ offset -= lo->lo_offset; /* TODO underflow/overflow? */
+ if (lo->lo_sizelimit > 0 && offset > lo->lo_sizelimit)
+ offset = lo->lo_sizelimit;
+ return offset;
+}
+
static void loop_config_discard(struct loop_device *lo,
struct queue_limits *lim)
{
@@ -1751,13 +1774,14 @@ static void lo_free_disk(struct gendisk *disk)
}
static const struct block_device_operations lo_fops = {
- .owner = THIS_MODULE,
- .release = lo_release,
- .ioctl = lo_ioctl,
+ .owner = THIS_MODULE,
+ .release = lo_release,
+ .ioctl = lo_ioctl,
#ifdef CONFIG_COMPAT
- .compat_ioctl = lo_compat_ioctl,
+ .compat_ioctl = lo_compat_ioctl,
#endif
- .free_disk = lo_free_disk,
+ .free_disk = lo_free_disk,
+ .seek_hole_data = lo_seek_hole_data,
};
/*
@@ -2140,7 +2164,7 @@ static int loop_control_remove(int idx)
pr_warn_once("deleting an unspecified loop device is not supported.\n");
return -EINVAL;
}
-
+
/* Hide this loop device for serialization. */
ret = mutex_lock_killable(&loop_ctl_mutex);
if (ret)
--
2.44.0
Powered by blists - more mailing lists