summaryrefslogtreecommitdiff
path: root/fs/read_write.c
diff options
context:
space:
mode:
authorJohn Garry <john.g.garry@oracle.com>2024-10-19 12:51:07 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-12-05 14:01:11 +0100
commitcfe3e04e9a5704aac92aaa2b45706850d96af0b9 (patch)
tree97ba109623ed22b5790a83c9aa1a0f1a08616503 /fs/read_write.c
parent78de864e8af3649b03f905e206e6f06f3aa4c006 (diff)
downloadlinux-cfe3e04e9a5704aac92aaa2b45706850d96af0b9.tar.gz
linux-cfe3e04e9a5704aac92aaa2b45706850d96af0b9.tar.bz2
linux-cfe3e04e9a5704aac92aaa2b45706850d96af0b9.zip
fs/block: Check for IOCB_DIRECT in generic_atomic_write_valid()
[ Upstream commit c3be7ebbbce5201e151f17e28a6c807602f369c9 ] Currently FMODE_CAN_ATOMIC_WRITE is set if the bdev can atomic write and the file is open for direct IO. This does not work if the file is not opened for direct IO, yet fcntl(O_DIRECT) is used on the fd later. Change to check for direct IO on a per-IO basis in generic_atomic_write_valid(). Since we want to report -EOPNOTSUPP for non-direct IO for an atomic write, change to return an error code. Relocate the block fops atomic write checks to the common write path, as to catch non-direct IO. Fixes: c34fc6f26ab8 ("fs: Initial atomic write support") Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: John Garry <john.g.garry@oracle.com> Link: https://lore.kernel.org/r/20241019125113.369994-3-john.g.garry@oracle.com Signed-off-by: Jens Axboe <axboe@kernel.dk> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'fs/read_write.c')
-rw-r--r--fs/read_write.c13
1 files changed, 8 insertions, 5 deletions
diff --git a/fs/read_write.c b/fs/read_write.c
index 2c3263530828..befec0b5c537 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -1830,18 +1830,21 @@ int generic_file_rw_checks(struct file *file_in, struct file *file_out)
return 0;
}
-bool generic_atomic_write_valid(struct kiocb *iocb, struct iov_iter *iter)
+int generic_atomic_write_valid(struct kiocb *iocb, struct iov_iter *iter)
{
size_t len = iov_iter_count(iter);
if (!iter_is_ubuf(iter))
- return false;
+ return -EINVAL;
if (!is_power_of_2(len))
- return false;
+ return -EINVAL;
if (!IS_ALIGNED(iocb->ki_pos, len))
- return false;
+ return -EINVAL;
- return true;
+ if (!(iocb->ki_flags & IOCB_DIRECT))
+ return -EOPNOTSUPP;
+
+ return 0;
}