From: Nadav Amit <[email protected]>

iouring with userfaultfd cannot currently be used fixed buffers since
userfaultfd does not provide read_iter(). This is required to allow
asynchronous (queued) reads from userfaultfd.

To support async-reads of userfaultfd provide read_iter() instead of
read().

Cc: Jens Axboe <[email protected]>
Cc: Andrea Arcangeli <[email protected]>
Cc: Peter Xu <[email protected]>
Cc: Alexander Viro <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Signed-off-by: Nadav Amit <[email protected]>
---
 fs/userfaultfd.c | 18 ++++++++++--------
 1 file changed, 10 insertions(+), 8 deletions(-)

diff --git a/fs/userfaultfd.c b/fs/userfaultfd.c
index b6a04e526025..6333b4632742 100644
--- a/fs/userfaultfd.c
+++ b/fs/userfaultfd.c
@@ -1195,9 +1195,9 @@ static ssize_t userfaultfd_ctx_read(struct 
userfaultfd_ctx *ctx, int no_wait,
        return ret;
 }
 
-static ssize_t userfaultfd_read(struct file *file, char __user *buf,
-                               size_t count, loff_t *ppos)
+static ssize_t userfaultfd_read_iter(struct kiocb *iocb, struct iov_iter *to)
 {
+       struct file *file = iocb->ki_filp;
        struct userfaultfd_ctx *ctx = file->private_data;
        ssize_t _ret, ret = 0;
        struct uffd_msg msg;
@@ -1207,16 +1207,18 @@ static ssize_t userfaultfd_read(struct file *file, char 
__user *buf,
                return -EINVAL;
 
        for (;;) {
-               if (count < sizeof(msg))
+               if (iov_iter_count(to) < sizeof(msg))
                        return ret ? ret : -EINVAL;
                _ret = userfaultfd_ctx_read(ctx, no_wait, &msg);
                if (_ret < 0)
                        return ret ? ret : _ret;
-               if (copy_to_user((__u64 __user *) buf, &msg, sizeof(msg)))
-                       return ret ? ret : -EFAULT;
+
+               _ret = copy_to_iter(&msg, sizeof(msg), to);
+               if (_ret != sizeof(msg))
+                       return ret ? ret : -EINVAL;
+
                ret += sizeof(msg);
-               buf += sizeof(msg);
-               count -= sizeof(msg);
+
                /*
                 * Allow to read more than one fault at time but only
                 * block if waiting for the very first one.
@@ -1980,7 +1982,7 @@ static const struct file_operations userfaultfd_fops = {
 #endif
        .release        = userfaultfd_release,
        .poll           = userfaultfd_poll,
-       .read           = userfaultfd_read,
+       .read_iter      = userfaultfd_read_iter,
        .unlocked_ioctl = userfaultfd_ioctl,
        .compat_ioctl   = compat_ptr_ioctl,
        .llseek         = noop_llseek,
-- 
2.25.1

Reply via email to