Commit 23c94e1c authored by Martin Raiber's avatar Martin Raiber Committed by Miklos Szeredi

fuse: Switch to using async direct IO for FOPEN_DIRECT_IO

Switch to using the async directo IO code path in fuse_direct_read_iter()
and fuse_direct_write_iter().  This is especially important in connection
with loop devices with direct IO enabled as loop assumes async direct io is
actually async.
Signed-off-by: default avatarMartin Raiber <martin@urbackup.org>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 75126f55
...@@ -1436,10 +1436,26 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io, ...@@ -1436,10 +1436,26 @@ static ssize_t __fuse_direct_read(struct fuse_io_priv *io,
return res; return res;
} }
static ssize_t fuse_direct_IO(struct kiocb *iocb, struct iov_iter *iter);
static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to) static ssize_t fuse_direct_read_iter(struct kiocb *iocb, struct iov_iter *to)
{ {
ssize_t res;
if (!is_sync_kiocb(iocb) && iocb->ki_flags & IOCB_DIRECT) {
struct file *file = iocb->ki_filp;
if (is_bad_inode(file_inode(file)))
return -EIO;
res = fuse_direct_IO(iocb, to);
} else {
struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb); struct fuse_io_priv io = FUSE_IO_PRIV_SYNC(iocb);
return __fuse_direct_read(&io, to, &iocb->ki_pos);
res = __fuse_direct_read(&io, to, &iocb->ki_pos);
}
return res;
} }
static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
...@@ -1454,8 +1470,14 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from) ...@@ -1454,8 +1470,14 @@ static ssize_t fuse_direct_write_iter(struct kiocb *iocb, struct iov_iter *from)
/* Don't allow parallel writes to the same file */ /* Don't allow parallel writes to the same file */
inode_lock(inode); inode_lock(inode);
res = generic_write_checks(iocb, from); res = generic_write_checks(iocb, from);
if (res > 0) if (res > 0) {
res = fuse_direct_io(&io, from, &iocb->ki_pos, FUSE_DIO_WRITE); if (!is_sync_kiocb(iocb) && iocb->ki_flags & IOCB_DIRECT) {
res = fuse_direct_IO(iocb, from);
} else {
res = fuse_direct_io(&io, from, &iocb->ki_pos,
FUSE_DIO_WRITE);
}
}
fuse_invalidate_attr(inode); fuse_invalidate_attr(inode);
if (res > 0) if (res > 0)
fuse_write_update_size(inode, iocb->ki_pos); fuse_write_update_size(inode, iocb->ki_pos);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment