diff options
author | Christoph Hellwig <hch@lst.de> | 2025-01-10 08:37:35 +0100 |
---|---|---|
committer | Jens Axboe <axboe@kernel.dk> | 2025-01-10 15:31:50 +0100 |
commit | dc909525daec7c7c5d628683c99d26e281c1a7bb (patch) | |
tree | a9d7ac339415c9917dc8862acbf23f8ce75a0118 /drivers/block/loop.c | |
parent | loop: only write back pagecache when starting to to use direct I/O (diff) | |
download | linux-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.c | 28 |
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) |