io_uring-5.7-2020-05-08
-----BEGIN PGP SIGNATURE----- iQJEBAABCAAuFiEEwPw5LcreJtl1+l5K99NY+ylx4KYFAl62HvYQHGF4Ym9lQGtl cm5lbC5kawAKCRD301j7KXHgptEAEACbuLfgFok0Vw8j7KNW0WNNKlS2o6nXQlW5 cl95JsqYdSL+toiDPQnJFtdoaxMhzL90kbWZzvPTBj+yTpLzRX0YnwFqXwFfmrga gd/7SOM5C97F1LCPL+luhbgp5HUq+ZVH882KjMiOVLvjjAb4SeKSexQGoxeKvtcV Pg3xm+zsbKKvclRDEqhnZB1X93WFAIrufuKBuV5xMZar7lkeRS9zwBUHySXa00xF i7lbvDqtNn3itgNQd7VGSNCF5u4JxCUm73SumY3nDMFXBfvSNk0nUpFBpTYLjb7G 0XY71tfWrBlbk1sssqr1Dbs+pRuxJRj9FgtfNAMid7gcK0L9k6n7v08cFxkIz4Sv XPHisD6QCOz7pZ5JwfdAp9Ea5g9z+QsN0G1Owr18fSgWwlgvhJ9rdd4H0Of7rWVj mGyF5f+ZqoLD2UhaEmLgjQoSvzPlb6rsAUL9SxgpZkg/mk5l0j5tk32JS5bJL8h5 RTj0oeyqoVGKqnRy8heV/0z6TqcEtuNn/nOsht8adCgIUVpk95bkjTGBM900IK/X HhdJMqPlTEDXQic+ZxVYNHDTZFhq4UOVJkoDfEwIN971LZfUaiz8XZ6uG5m4rFqj iRmLN5XJNVNK52hNT1dLQyeQ4j3a5OnVGsvjZ33QLy2P6rCZd7yU6jKfsoL8JDEU uAzkaWqLjA== =YeXV -----END PGP SIGNATURE----- Merge tag 'io_uring-5.7-2020-05-08' of git://git.kernel.dk/linux-block Pull io_uring fixes from Jens Axboe: - Fix finish_wait() balancing in file cancelation (Xiaoguang) - Ensure early cleanup of resources in ring map failure (Xiaoguang) - Ensure IORING_OP_SLICE does the right file mode checks (Pavel) - Remove file opening from openat/openat2/statx, it's not needed and messes with O_PATH * tag 'io_uring-5.7-2020-05-08' of git://git.kernel.dk/linux-block: io_uring: don't use 'fd' for openat/openat2/statx splice: move f_mode checks to do_{splice,tee}() io_uring: handle -EFAULT properly in io_uring_setup() io_uring: fix mismatched finish_wait() calls in io_uring_cancel_files()
This commit is contained in:
Коммит
1d3962ae3b
|
@ -680,8 +680,6 @@ struct io_op_def {
|
|||
unsigned needs_mm : 1;
|
||||
/* needs req->file assigned */
|
||||
unsigned needs_file : 1;
|
||||
/* needs req->file assigned IFF fd is >= 0 */
|
||||
unsigned fd_non_neg : 1;
|
||||
/* hash wq insertion if file is a regular file */
|
||||
unsigned hash_reg_file : 1;
|
||||
/* unbound wq insertion if file is a non-regular file */
|
||||
|
@ -784,8 +782,6 @@ static const struct io_op_def io_op_defs[] = {
|
|||
.needs_file = 1,
|
||||
},
|
||||
[IORING_OP_OPENAT] = {
|
||||
.needs_file = 1,
|
||||
.fd_non_neg = 1,
|
||||
.file_table = 1,
|
||||
.needs_fs = 1,
|
||||
},
|
||||
|
@ -799,8 +795,6 @@ static const struct io_op_def io_op_defs[] = {
|
|||
},
|
||||
[IORING_OP_STATX] = {
|
||||
.needs_mm = 1,
|
||||
.needs_file = 1,
|
||||
.fd_non_neg = 1,
|
||||
.needs_fs = 1,
|
||||
.file_table = 1,
|
||||
},
|
||||
|
@ -837,8 +831,6 @@ static const struct io_op_def io_op_defs[] = {
|
|||
.buffer_select = 1,
|
||||
},
|
||||
[IORING_OP_OPENAT2] = {
|
||||
.needs_file = 1,
|
||||
.fd_non_neg = 1,
|
||||
.file_table = 1,
|
||||
.needs_fs = 1,
|
||||
},
|
||||
|
@ -5368,15 +5360,6 @@ static void io_wq_submit_work(struct io_wq_work **workptr)
|
|||
io_steal_work(req, workptr);
|
||||
}
|
||||
|
||||
static int io_req_needs_file(struct io_kiocb *req, int fd)
|
||||
{
|
||||
if (!io_op_defs[req->opcode].needs_file)
|
||||
return 0;
|
||||
if ((fd == -1 || fd == AT_FDCWD) && io_op_defs[req->opcode].fd_non_neg)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline struct file *io_file_from_index(struct io_ring_ctx *ctx,
|
||||
int index)
|
||||
{
|
||||
|
@ -5414,14 +5397,11 @@ static int io_file_get(struct io_submit_state *state, struct io_kiocb *req,
|
|||
}
|
||||
|
||||
static int io_req_set_file(struct io_submit_state *state, struct io_kiocb *req,
|
||||
int fd, unsigned int flags)
|
||||
int fd)
|
||||
{
|
||||
bool fixed;
|
||||
|
||||
if (!io_req_needs_file(req, fd))
|
||||
return 0;
|
||||
|
||||
fixed = (flags & IOSQE_FIXED_FILE);
|
||||
fixed = (req->flags & REQ_F_FIXED_FILE) != 0;
|
||||
if (unlikely(!fixed && req->needs_fixed_file))
|
||||
return -EBADF;
|
||||
|
||||
|
@ -5798,7 +5778,7 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
|
|||
struct io_submit_state *state, bool async)
|
||||
{
|
||||
unsigned int sqe_flags;
|
||||
int id, fd;
|
||||
int id;
|
||||
|
||||
/*
|
||||
* All io need record the previous position, if LINK vs DARIN,
|
||||
|
@ -5850,8 +5830,10 @@ static int io_init_req(struct io_ring_ctx *ctx, struct io_kiocb *req,
|
|||
IOSQE_ASYNC | IOSQE_FIXED_FILE |
|
||||
IOSQE_BUFFER_SELECT | IOSQE_IO_LINK);
|
||||
|
||||
fd = READ_ONCE(sqe->fd);
|
||||
return io_req_set_file(state, req, fd, sqe_flags);
|
||||
if (!io_op_defs[req->opcode].needs_file)
|
||||
return 0;
|
||||
|
||||
return io_req_set_file(state, req, READ_ONCE(sqe->fd));
|
||||
}
|
||||
|
||||
static int io_submit_sqes(struct io_ring_ctx *ctx, unsigned int nr,
|
||||
|
@ -7360,11 +7342,9 @@ static int io_uring_release(struct inode *inode, struct file *file)
|
|||
static void io_uring_cancel_files(struct io_ring_ctx *ctx,
|
||||
struct files_struct *files)
|
||||
{
|
||||
struct io_kiocb *req;
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
while (!list_empty_careful(&ctx->inflight_list)) {
|
||||
struct io_kiocb *cancel_req = NULL;
|
||||
struct io_kiocb *cancel_req = NULL, *req;
|
||||
DEFINE_WAIT(wait);
|
||||
|
||||
spin_lock_irq(&ctx->inflight_lock);
|
||||
list_for_each_entry(req, &ctx->inflight_list, inflight_entry) {
|
||||
|
@ -7404,6 +7384,7 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx,
|
|||
*/
|
||||
if (refcount_sub_and_test(2, &cancel_req->refs)) {
|
||||
io_put_req(cancel_req);
|
||||
finish_wait(&ctx->inflight_wait, &wait);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -7411,8 +7392,8 @@ static void io_uring_cancel_files(struct io_ring_ctx *ctx,
|
|||
io_wq_cancel_work(ctx->io_wq, &cancel_req->work);
|
||||
io_put_req(cancel_req);
|
||||
schedule();
|
||||
finish_wait(&ctx->inflight_wait, &wait);
|
||||
}
|
||||
finish_wait(&ctx->inflight_wait, &wait);
|
||||
}
|
||||
|
||||
static int io_uring_flush(struct file *file, void *data)
|
||||
|
@ -7761,7 +7742,8 @@ err:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int io_uring_create(unsigned entries, struct io_uring_params *p)
|
||||
static int io_uring_create(unsigned entries, struct io_uring_params *p,
|
||||
struct io_uring_params __user *params)
|
||||
{
|
||||
struct user_struct *user = NULL;
|
||||
struct io_ring_ctx *ctx;
|
||||
|
@ -7853,6 +7835,14 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p)
|
|||
p->cq_off.overflow = offsetof(struct io_rings, cq_overflow);
|
||||
p->cq_off.cqes = offsetof(struct io_rings, cqes);
|
||||
|
||||
p->features = IORING_FEAT_SINGLE_MMAP | IORING_FEAT_NODROP |
|
||||
IORING_FEAT_SUBMIT_STABLE | IORING_FEAT_RW_CUR_POS |
|
||||
IORING_FEAT_CUR_PERSONALITY | IORING_FEAT_FAST_POLL;
|
||||
|
||||
if (copy_to_user(params, p, sizeof(*p))) {
|
||||
ret = -EFAULT;
|
||||
goto err;
|
||||
}
|
||||
/*
|
||||
* Install ring fd as the very last thing, so we don't risk someone
|
||||
* having closed it before we finish setup
|
||||
|
@ -7861,9 +7851,6 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p)
|
|||
if (ret < 0)
|
||||
goto err;
|
||||
|
||||
p->features = IORING_FEAT_SINGLE_MMAP | IORING_FEAT_NODROP |
|
||||
IORING_FEAT_SUBMIT_STABLE | IORING_FEAT_RW_CUR_POS |
|
||||
IORING_FEAT_CUR_PERSONALITY | IORING_FEAT_FAST_POLL;
|
||||
trace_io_uring_create(ret, ctx, p->sq_entries, p->cq_entries, p->flags);
|
||||
return ret;
|
||||
err:
|
||||
|
@ -7879,7 +7866,6 @@ err:
|
|||
static long io_uring_setup(u32 entries, struct io_uring_params __user *params)
|
||||
{
|
||||
struct io_uring_params p;
|
||||
long ret;
|
||||
int i;
|
||||
|
||||
if (copy_from_user(&p, params, sizeof(p)))
|
||||
|
@ -7894,14 +7880,7 @@ static long io_uring_setup(u32 entries, struct io_uring_params __user *params)
|
|||
IORING_SETUP_CLAMP | IORING_SETUP_ATTACH_WQ))
|
||||
return -EINVAL;
|
||||
|
||||
ret = io_uring_create(entries, &p);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (copy_to_user(params, &p, sizeof(p)))
|
||||
return -EFAULT;
|
||||
|
||||
return ret;
|
||||
return io_uring_create(entries, &p, params);
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE2(io_uring_setup, u32, entries,
|
||||
|
|
45
fs/splice.c
45
fs/splice.c
|
@ -1118,6 +1118,10 @@ long do_splice(struct file *in, loff_t __user *off_in,
|
|||
loff_t offset;
|
||||
long ret;
|
||||
|
||||
if (unlikely(!(in->f_mode & FMODE_READ) ||
|
||||
!(out->f_mode & FMODE_WRITE)))
|
||||
return -EBADF;
|
||||
|
||||
ipipe = get_pipe_info(in);
|
||||
opipe = get_pipe_info(out);
|
||||
|
||||
|
@ -1125,12 +1129,6 @@ long do_splice(struct file *in, loff_t __user *off_in,
|
|||
if (off_in || off_out)
|
||||
return -ESPIPE;
|
||||
|
||||
if (!(in->f_mode & FMODE_READ))
|
||||
return -EBADF;
|
||||
|
||||
if (!(out->f_mode & FMODE_WRITE))
|
||||
return -EBADF;
|
||||
|
||||
/* Splicing to self would be fun, but... */
|
||||
if (ipipe == opipe)
|
||||
return -EINVAL;
|
||||
|
@ -1153,9 +1151,6 @@ long do_splice(struct file *in, loff_t __user *off_in,
|
|||
offset = out->f_pos;
|
||||
}
|
||||
|
||||
if (unlikely(!(out->f_mode & FMODE_WRITE)))
|
||||
return -EBADF;
|
||||
|
||||
if (unlikely(out->f_flags & O_APPEND))
|
||||
return -EINVAL;
|
||||
|
||||
|
@ -1440,15 +1435,11 @@ SYSCALL_DEFINE6(splice, int, fd_in, loff_t __user *, off_in,
|
|||
error = -EBADF;
|
||||
in = fdget(fd_in);
|
||||
if (in.file) {
|
||||
if (in.file->f_mode & FMODE_READ) {
|
||||
out = fdget(fd_out);
|
||||
if (out.file) {
|
||||
if (out.file->f_mode & FMODE_WRITE)
|
||||
error = do_splice(in.file, off_in,
|
||||
out.file, off_out,
|
||||
len, flags);
|
||||
fdput(out);
|
||||
}
|
||||
out = fdget(fd_out);
|
||||
if (out.file) {
|
||||
error = do_splice(in.file, off_in, out.file, off_out,
|
||||
len, flags);
|
||||
fdput(out);
|
||||
}
|
||||
fdput(in);
|
||||
}
|
||||
|
@ -1770,6 +1761,10 @@ static long do_tee(struct file *in, struct file *out, size_t len,
|
|||
struct pipe_inode_info *opipe = get_pipe_info(out);
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (unlikely(!(in->f_mode & FMODE_READ) ||
|
||||
!(out->f_mode & FMODE_WRITE)))
|
||||
return -EBADF;
|
||||
|
||||
/*
|
||||
* Duplicate the contents of ipipe to opipe without actually
|
||||
* copying the data.
|
||||
|
@ -1795,7 +1790,7 @@ static long do_tee(struct file *in, struct file *out, size_t len,
|
|||
|
||||
SYSCALL_DEFINE4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags)
|
||||
{
|
||||
struct fd in;
|
||||
struct fd in, out;
|
||||
int error;
|
||||
|
||||
if (unlikely(flags & ~SPLICE_F_ALL))
|
||||
|
@ -1807,14 +1802,10 @@ SYSCALL_DEFINE4(tee, int, fdin, int, fdout, size_t, len, unsigned int, flags)
|
|||
error = -EBADF;
|
||||
in = fdget(fdin);
|
||||
if (in.file) {
|
||||
if (in.file->f_mode & FMODE_READ) {
|
||||
struct fd out = fdget(fdout);
|
||||
if (out.file) {
|
||||
if (out.file->f_mode & FMODE_WRITE)
|
||||
error = do_tee(in.file, out.file,
|
||||
len, flags);
|
||||
fdput(out);
|
||||
}
|
||||
out = fdget(fdout);
|
||||
if (out.file) {
|
||||
error = do_tee(in.file, out.file, len, flags);
|
||||
fdput(out);
|
||||
}
|
||||
fdput(in);
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче