Merge branch 'io_uring-5.8' into for-5.9/io_uring
authorJens Axboe <axboe@kernel.dk>
Fri, 24 Jul 2020 18:53:31 +0000 (12:53 -0600)
committerJens Axboe <axboe@kernel.dk>
Fri, 24 Jul 2020 18:53:31 +0000 (12:53 -0600)
Merge in io_uring-5.8 fixes, as changes/cleanups to how we do locked
mem accounting require a fixup, and only one of the spots are noticed
by git as the other merges cleanly. The flags fix from io_uring-5.8
also causes a merge conflict, the leak fix for recvmsg, the double poll
fix, and the link failure locking fix.

* io_uring-5.8:
  io_uring: fix lockup in io_fail_links()
  io_uring: fix ->work corruption with poll_add
  io_uring: missed req_init_async() for IOSQE_ASYNC
  io_uring: always allow drain/link/hardlink/async sqe flags
  io_uring: ensure double poll additions work with both request types
  io_uring: fix recvmsg memory leak with buffer selection
  io_uring: fix not initialised work->flags
  io_uring: fix missing msg_name assignment
  io_uring: account user memory freed when exit has been queued
  io_uring: fix memleak in io_sqe_files_register()
  io_uring: fix memleak in __io_sqe_files_update()
  io_uring: export cq overflow status to userspace

Signed-off-by: Jens Axboe <axboe@kernel.dk>
1  2 
fs/io_uring.c
include/uapi/linux/io_uring.h

diff --cc fs/io_uring.c
@@@ -4625,10 -4294,33 +4639,11 @@@ static void io_async_queue_proc(struct 
                               struct poll_table_struct *p)
  {
        struct io_poll_table *pt = container_of(p, struct io_poll_table, pt);
+       struct async_poll *apoll = pt->req->apoll;
  
-       __io_queue_proc(&pt->req->apoll->poll, pt, head);
+       __io_queue_proc(&apoll->poll, pt, head, &apoll->double_poll);
  }
  
 -static void io_sq_thread_drop_mm(struct io_ring_ctx *ctx)
 -{
 -      struct mm_struct *mm = current->mm;
 -
 -      if (mm) {
 -              kthread_unuse_mm(mm);
 -              mmput(mm);
 -      }
 -}
 -
 -static int io_sq_thread_acquire_mm(struct io_ring_ctx *ctx,
 -                                 struct io_kiocb *req)
 -{
 -      if (io_op_defs[req->opcode].needs_mm && !current->mm) {
 -              if (unlikely(!mmget_not_zero(ctx->sqo_mm)))
 -                      return -EFAULT;
 -              kthread_use_mm(ctx->sqo_mm);
 -      }
 -
 -      return 0;
 -}
 -
  static void io_async_task_func(struct callback_head *cb)
  {
        struct io_kiocb *req = container_of(cb, struct io_kiocb, task_work);
        }
  
        /* If req is still hashed, it cannot have been canceled. Don't check. */
 -      if (hash_hashed(&req->hash_node)) {
 +      if (hash_hashed(&req->hash_node))
                hash_del(&req->hash_node);
 -      } else {
 -              canceled = READ_ONCE(apoll->poll.canceled);
 -              if (canceled) {
 -                      io_cqring_fill_event(req, -ECANCELED);
 -                      io_commit_cqring(ctx);
 -              }
 -      }
  
+       io_poll_remove_double(req, apoll->double_poll);
        spin_unlock_irq(&ctx->completion_lock);
  
        /* restore ->work in case we need to retry again */
        if (req->flags & REQ_F_WORK_INITIALIZED)
                memcpy(&req->work, &apoll->work, sizeof(req->work));
 +
 +      if (!READ_ONCE(apoll->poll.canceled))
 +              __io_req_task_submit(req);
 +      else
 +              __io_req_task_cancel(req, -ECANCELED);
 +
+       kfree(apoll->double_poll);
        kfree(apoll);
 -
 -      if (!canceled) {
 -              __set_current_state(TASK_RUNNING);
 -              if (io_sq_thread_acquire_mm(ctx, req)) {
 -                      io_cqring_add_event(req, -EFAULT);
 -                      goto end_req;
 -              }
 -              mutex_lock(&ctx->uring_lock);
 -              __io_queue_sqe(req, NULL);
 -              mutex_unlock(&ctx->uring_lock);
 -      } else {
 -              io_cqring_ev_posted(ctx);
 -end_req:
 -              req_set_fail_links(req);
 -              io_double_put_req(req);
 -      }
  }
  
  static int io_async_wake(struct wait_queue_entry *wait, unsigned mode, int sync,
@@@ -7746,8 -7456,18 +7778,17 @@@ static void io_ring_ctx_wait_and_kill(s
        /* if we failed setting up the ctx, we might not have any rings */
        if (ctx->rings)
                io_cqring_overflow_flush(ctx, true);
 +      io_iopoll_try_reap_events(ctx);
        idr_for_each(&ctx->personality_idr, io_remove_personalities, ctx);
 -      if (ctx->account_mem)
 -              io_unaccount_mem(ctx->user,
 -                              ring_pages(ctx->sq_entries, ctx->cq_entries));
+       /*
+        * Do this upfront, so we won't have a grace period where the ring
+        * is closed but resources aren't reaped yet. This can cause
+        * spurious failure in setting up a new ring.
+        */
++      io_unaccount_mem(ctx, ring_pages(ctx->sq_entries, ctx->cq_entries),
++                       ACCT_LOCKED);
        INIT_WORK(&ctx->exit_work, io_ring_exit_work);
        queue_work(system_wq, &ctx->exit_work);
  }
Simple merge