Commit a2d79c71 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-5.3/io_uring-20190711' of git://git.kernel.dk/linux-block

Pull io_uring updates from Jens Axboe:
 "This contains:

   - Support for recvmsg/sendmsg as first class opcodes.

     I don't envision going much further down this path, as there are
     plans in progress to support potentially any system call in an
     async fashion through io_uring. But I think it does make sense to
     have certain core ops available directly, especially those that can
     support a "try this non-blocking" flag/mode. (me)

   - Handle generic short reads automatically.

     This can happen fairly easily if parts of the buffered read is
     cached. Since the application needs to issue another request for
     the remainder, just do this internally and save kernel/user
     roundtrip while providing a nicer more robust API. (me)

   - Support for linked SQEs.

     This allows SQEs to depend on each other, enabling an application
     to eg queue a read-from-this-file,write-to-that-file pair. (me)

   - Fix race in stopping SQ thread (Jackie)"

* tag 'for-5.3/io_uring-20190711' of git://git.kernel.dk/linux-block:
  io_uring: fix io_sq_thread_stop running in front of io_sq_thread
  io_uring: add support for recvmsg()
  io_uring: add support for sendmsg()
  io_uring: add support for sqe links
  io_uring: punt short reads to async context
  uio: make import_iovec()/compat_import_iovec() return bytes on success
parents 964a4eac a4c0b3de
...@@ -1479,8 +1479,9 @@ static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb) ...@@ -1479,8 +1479,9 @@ static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb)
return 0; return 0;
} }
static int aio_setup_rw(int rw, const struct iocb *iocb, struct iovec **iovec, static ssize_t aio_setup_rw(int rw, const struct iocb *iocb,
bool vectored, bool compat, struct iov_iter *iter) struct iovec **iovec, bool vectored, bool compat,
struct iov_iter *iter)
{ {
void __user *buf = (void __user *)(uintptr_t)iocb->aio_buf; void __user *buf = (void __user *)(uintptr_t)iocb->aio_buf;
size_t len = iocb->aio_nbytes; size_t len = iocb->aio_nbytes;
...@@ -1537,7 +1538,7 @@ static int aio_read(struct kiocb *req, const struct iocb *iocb, ...@@ -1537,7 +1538,7 @@ static int aio_read(struct kiocb *req, const struct iocb *iocb,
return -EINVAL; return -EINVAL;
ret = aio_setup_rw(READ, iocb, &iovec, vectored, compat, &iter); ret = aio_setup_rw(READ, iocb, &iovec, vectored, compat, &iter);
if (ret) if (ret < 0)
return ret; return ret;
ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter)); ret = rw_verify_area(READ, file, &req->ki_pos, iov_iter_count(&iter));
if (!ret) if (!ret)
...@@ -1565,7 +1566,7 @@ static int aio_write(struct kiocb *req, const struct iocb *iocb, ...@@ -1565,7 +1566,7 @@ static int aio_write(struct kiocb *req, const struct iocb *iocb,
return -EINVAL; return -EINVAL;
ret = aio_setup_rw(WRITE, iocb, &iovec, vectored, compat, &iter); ret = aio_setup_rw(WRITE, iocb, &iovec, vectored, compat, &iter);
if (ret) if (ret < 0)
return ret; return ret;
ret = rw_verify_area(WRITE, file, &req->ki_pos, iov_iter_count(&iter)); ret = rw_verify_area(WRITE, file, &req->ki_pos, iov_iter_count(&iter));
if (!ret) { if (!ret) {
......
This diff is collapsed.
...@@ -1356,7 +1356,7 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov, ...@@ -1356,7 +1356,7 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov,
struct iovec iovstack[UIO_FASTIOV]; struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov = iovstack; struct iovec *iov = iovstack;
struct iov_iter iter; struct iov_iter iter;
long error; ssize_t error;
struct fd f; struct fd f;
int type; int type;
...@@ -1367,7 +1367,7 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov, ...@@ -1367,7 +1367,7 @@ SYSCALL_DEFINE4(vmsplice, int, fd, const struct iovec __user *, uiov,
error = import_iovec(type, uiov, nr_segs, error = import_iovec(type, uiov, nr_segs,
ARRAY_SIZE(iovstack), &iov, &iter); ARRAY_SIZE(iovstack), &iov, &iter);
if (!error) { if (error >= 0) {
error = do_vmsplice(f.file, &iter, flags); error = do_vmsplice(f.file, &iter, flags);
kfree(iov); kfree(iov);
} }
...@@ -1382,7 +1382,7 @@ COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, io ...@@ -1382,7 +1382,7 @@ COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, io
struct iovec iovstack[UIO_FASTIOV]; struct iovec iovstack[UIO_FASTIOV];
struct iovec *iov = iovstack; struct iovec *iov = iovstack;
struct iov_iter iter; struct iov_iter iter;
long error; ssize_t error;
struct fd f; struct fd f;
int type; int type;
...@@ -1393,7 +1393,7 @@ COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, io ...@@ -1393,7 +1393,7 @@ COMPAT_SYSCALL_DEFINE4(vmsplice, int, fd, const struct compat_iovec __user *, io
error = compat_import_iovec(type, iov32, nr_segs, error = compat_import_iovec(type, iov32, nr_segs,
ARRAY_SIZE(iovstack), &iov, &iter); ARRAY_SIZE(iovstack), &iov, &iter);
if (!error) { if (error >= 0) {
error = do_vmsplice(f.file, &iter, flags); error = do_vmsplice(f.file, &iter, flags);
kfree(iov); kfree(iov);
} }
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
struct pid; struct pid;
struct cred; struct cred;
struct socket;
#define __sockaddr_check_size(size) \ #define __sockaddr_check_size(size) \
BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage))) BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage)))
...@@ -374,6 +375,12 @@ extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, ...@@ -374,6 +375,12 @@ extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg,
extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg,
unsigned int vlen, unsigned int flags, unsigned int vlen, unsigned int flags,
bool forbid_cmsg_compat); bool forbid_cmsg_compat);
extern long __sys_sendmsg_sock(struct socket *sock,
struct user_msghdr __user *msg,
unsigned int flags);
extern long __sys_recvmsg_sock(struct socket *sock,
struct user_msghdr __user *msg,
unsigned int flags);
/* helpers which do the actual work for syscalls */ /* helpers which do the actual work for syscalls */
extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size, extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size,
......
...@@ -267,13 +267,13 @@ bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, struct ...@@ -267,13 +267,13 @@ bool csum_and_copy_from_iter_full(void *addr, size_t bytes, __wsum *csum, struct
size_t hash_and_copy_to_iter(const void *addr, size_t bytes, void *hashp, size_t hash_and_copy_to_iter(const void *addr, size_t bytes, void *hashp,
struct iov_iter *i); struct iov_iter *i);
int import_iovec(int type, const struct iovec __user * uvector, ssize_t import_iovec(int type, const struct iovec __user * uvector,
unsigned nr_segs, unsigned fast_segs, unsigned nr_segs, unsigned fast_segs,
struct iovec **iov, struct iov_iter *i); struct iovec **iov, struct iov_iter *i);
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
struct compat_iovec; struct compat_iovec;
int compat_import_iovec(int type, const struct compat_iovec __user * uvector, ssize_t compat_import_iovec(int type, const struct compat_iovec __user * uvector,
unsigned nr_segs, unsigned fast_segs, unsigned nr_segs, unsigned fast_segs,
struct iovec **iov, struct iov_iter *i); struct iovec **iov, struct iov_iter *i);
#endif #endif
......
...@@ -27,6 +27,7 @@ struct io_uring_sqe { ...@@ -27,6 +27,7 @@ struct io_uring_sqe {
__u32 fsync_flags; __u32 fsync_flags;
__u16 poll_events; __u16 poll_events;
__u32 sync_range_flags; __u32 sync_range_flags;
__u32 msg_flags;
}; };
__u64 user_data; /* data to be passed back at completion time */ __u64 user_data; /* data to be passed back at completion time */
union { union {
...@@ -40,6 +41,7 @@ struct io_uring_sqe { ...@@ -40,6 +41,7 @@ struct io_uring_sqe {
*/ */
#define IOSQE_FIXED_FILE (1U << 0) /* use fixed fileset */ #define IOSQE_FIXED_FILE (1U << 0) /* use fixed fileset */
#define IOSQE_IO_DRAIN (1U << 1) /* issue after inflight IO */ #define IOSQE_IO_DRAIN (1U << 1) /* issue after inflight IO */
#define IOSQE_IO_LINK (1U << 2) /* links next sqe */
/* /*
* io_uring_setup() flags * io_uring_setup() flags
...@@ -57,6 +59,8 @@ struct io_uring_sqe { ...@@ -57,6 +59,8 @@ struct io_uring_sqe {
#define IORING_OP_POLL_ADD 6 #define IORING_OP_POLL_ADD 6
#define IORING_OP_POLL_REMOVE 7 #define IORING_OP_POLL_REMOVE 7
#define IORING_OP_SYNC_FILE_RANGE 8 #define IORING_OP_SYNC_FILE_RANGE 8
#define IORING_OP_SENDMSG 9
#define IORING_OP_RECVMSG 10
/* /*
* sqe->fsync_flags * sqe->fsync_flags
......
...@@ -1634,9 +1634,9 @@ EXPORT_SYMBOL(dup_iter); ...@@ -1634,9 +1634,9 @@ EXPORT_SYMBOL(dup_iter);
* on-stack array was used or not (and regardless of whether this function * on-stack array was used or not (and regardless of whether this function
* returns an error or not). * returns an error or not).
* *
* Return: 0 on success or negative error code on error. * Return: Negative error code on error, bytes imported on success
*/ */
int import_iovec(int type, const struct iovec __user * uvector, ssize_t import_iovec(int type, const struct iovec __user * uvector,
unsigned nr_segs, unsigned fast_segs, unsigned nr_segs, unsigned fast_segs,
struct iovec **iov, struct iov_iter *i) struct iovec **iov, struct iov_iter *i)
{ {
...@@ -1652,14 +1652,15 @@ int import_iovec(int type, const struct iovec __user * uvector, ...@@ -1652,14 +1652,15 @@ int import_iovec(int type, const struct iovec __user * uvector,
} }
iov_iter_init(i, type, p, nr_segs, n); iov_iter_init(i, type, p, nr_segs, n);
*iov = p == *iov ? NULL : p; *iov = p == *iov ? NULL : p;
return 0; return n;
} }
EXPORT_SYMBOL(import_iovec); EXPORT_SYMBOL(import_iovec);
#ifdef CONFIG_COMPAT #ifdef CONFIG_COMPAT
#include <linux/compat.h> #include <linux/compat.h>
int compat_import_iovec(int type, const struct compat_iovec __user * uvector, ssize_t compat_import_iovec(int type,
const struct compat_iovec __user * uvector,
unsigned nr_segs, unsigned fast_segs, unsigned nr_segs, unsigned fast_segs,
struct iovec **iov, struct iov_iter *i) struct iovec **iov, struct iov_iter *i)
{ {
...@@ -1675,7 +1676,7 @@ int compat_import_iovec(int type, const struct compat_iovec __user * uvector, ...@@ -1675,7 +1676,7 @@ int compat_import_iovec(int type, const struct compat_iovec __user * uvector,
} }
iov_iter_init(i, type, p, nr_segs, n); iov_iter_init(i, type, p, nr_segs, n);
*iov = p == *iov ? NULL : p; *iov = p == *iov ? NULL : p;
return 0; return n;
} }
#endif #endif
......
...@@ -80,9 +80,10 @@ int get_compat_msghdr(struct msghdr *kmsg, ...@@ -80,9 +80,10 @@ int get_compat_msghdr(struct msghdr *kmsg,
kmsg->msg_iocb = NULL; kmsg->msg_iocb = NULL;
return compat_import_iovec(save_addr ? READ : WRITE, err = compat_import_iovec(save_addr ? READ : WRITE,
compat_ptr(msg.msg_iov), msg.msg_iovlen, compat_ptr(msg.msg_iov), msg.msg_iovlen,
UIO_FASTIOV, iov, &kmsg->msg_iter); UIO_FASTIOV, iov, &kmsg->msg_iter);
return err < 0 ? err : 0;
} }
/* Bleech... */ /* Bleech... */
......
...@@ -2222,9 +2222,10 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, ...@@ -2222,9 +2222,10 @@ static int copy_msghdr_from_user(struct msghdr *kmsg,
kmsg->msg_iocb = NULL; kmsg->msg_iocb = NULL;
return import_iovec(save_addr ? READ : WRITE, err = import_iovec(save_addr ? READ : WRITE,
msg.msg_iov, msg.msg_iovlen, msg.msg_iov, msg.msg_iovlen,
UIO_FASTIOV, iov, &kmsg->msg_iter); UIO_FASTIOV, iov, &kmsg->msg_iter);
return err < 0 ? err : 0;
} }
static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg, static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
...@@ -2326,6 +2327,13 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg, ...@@ -2326,6 +2327,13 @@ static int ___sys_sendmsg(struct socket *sock, struct user_msghdr __user *msg,
/* /*
* BSD sendmsg interface * BSD sendmsg interface
*/ */
long __sys_sendmsg_sock(struct socket *sock, struct user_msghdr __user *msg,
unsigned int flags)
{
struct msghdr msg_sys;
return ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL, 0);
}
long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags, long __sys_sendmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
bool forbid_cmsg_compat) bool forbid_cmsg_compat)
...@@ -2500,6 +2508,14 @@ static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg, ...@@ -2500,6 +2508,14 @@ static int ___sys_recvmsg(struct socket *sock, struct user_msghdr __user *msg,
* BSD recvmsg interface * BSD recvmsg interface
*/ */
long __sys_recvmsg_sock(struct socket *sock, struct user_msghdr __user *msg,
unsigned int flags)
{
struct msghdr msg_sys;
return ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
}
long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags, long __sys_recvmsg(int fd, struct user_msghdr __user *msg, unsigned int flags,
bool forbid_cmsg_compat) bool forbid_cmsg_compat)
{ {
......
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