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>
This commit is contained in:
Christoph Hellwig
2025-01-10 08:37:35 +01:00
committed by Jens Axboe
parent 09ccf5549d
commit dc909525da

View File

@@ -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)