summaryrefslogtreecommitdiffstats
path: root/drivers/block/loop.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2025-01-10 08:37:35 +0100
committerJens Axboe <axboe@kernel.dk>2025-01-10 15:31:50 +0100
commitdc909525daec7c7c5d628683c99d26e281c1a7bb (patch)
treea9d7ac339415c9917dc8862acbf23f8ce75a0118 /drivers/block/loop.c
parentloop: only write back pagecache when starting to to use direct I/O (diff)
downloadlinux-dc909525daec7c7c5d628683c99d26e281c1a7bb.tar.xz
linux-dc909525daec7c7c5d628683c99d26e281c1a7bb.zip
loop: open code the direct I/O flag update in loop_set_dio
loop_set_dio is different from the other (__)loop_update_dio callers in that it doesn't take any implicit conditions into account and wants to update the direct I/O flag to the user passed in value and fail if that can't be done. Open code the logic here to prepare for simplifying the other direct I/O flag updates and to make the error handling less convoluted. Signed-off-by: Christoph Hellwig <hch@lst.de> Link: https://lore.kernel.org/r/20250110073750.1582447-6-hch@lst.de Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'drivers/block/loop.c')
-rw-r--r--drivers/block/loop.c28
1 files changed, 20 insertions, 8 deletions
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index cf80cdf5e440..6eb6d901151c 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1455,16 +1455,28 @@ static int loop_set_capacity(struct loop_device *lo)
static int loop_set_dio(struct loop_device *lo, unsigned long arg)
{
- int error = -ENXIO;
- if (lo->lo_state != Lo_bound)
- goto out;
+ bool use_dio = !!arg;
- __loop_update_dio(lo, !!arg);
- if (lo->use_dio == !!arg)
+ if (lo->lo_state != Lo_bound)
+ return -ENXIO;
+ if (use_dio == lo->use_dio)
return 0;
- error = -EINVAL;
- out:
- return error;
+
+ if (use_dio) {
+ if (!lo_can_use_dio(lo))
+ return -EINVAL;
+ /* flush dirty pages before starting to use direct I/O */
+ vfs_fsync(lo->lo_backing_file, 0);
+ }
+
+ blk_mq_freeze_queue(lo->lo_queue);
+ lo->use_dio = use_dio;
+ if (use_dio)
+ lo->lo_flags |= LO_FLAGS_DIRECT_IO;
+ else
+ lo->lo_flags &= ~LO_FLAGS_DIRECT_IO;
+ blk_mq_unfreeze_queue(lo->lo_queue);
+ return 0;
}
static int loop_set_block_size(struct loop_device *lo, unsigned long arg)