Merge remote-tracking branch 'torvalds/master' into perf/core
[linux-2.6-microblaze.git] / fs / io_uring.c
index 5f82954..fa8794c 100644 (file)
@@ -783,6 +783,11 @@ struct io_task_work {
        task_work_func_t        func;
 };
 
+enum {
+       IORING_RSRC_FILE                = 0,
+       IORING_RSRC_BUFFER              = 1,
+};
+
 /*
  * NOTE! Each of the iocb union members has the file pointer
  * as the first entry in their struct definition. So you can
@@ -8228,6 +8233,7 @@ static int io_buffer_account_pin(struct io_ring_ctx *ctx, struct page **pages,
 {
        int i, ret;
 
+       imu->acct_pages = 0;
        for (i = 0; i < nr_pages; i++) {
                if (!PageCompound(pages[i])) {
                        imu->acct_pages++;
@@ -9039,11 +9045,16 @@ static void io_uring_clean_tctx(struct io_uring_task *tctx)
        struct io_tctx_node *node;
        unsigned long index;
 
-       tctx->io_wq = NULL;
        xa_for_each(&tctx->xa, index, node)
                io_uring_del_task_file(index);
-       if (wq)
+       if (wq) {
+               /*
+                * Must be after io_uring_del_task_file() (removes nodes under
+                * uring_lock) to avoid race with io_uring_try_cancel_iowq().
+                */
+               tctx->io_wq = NULL;
                io_wq_put_and_exit(wq);
+       }
 }
 
 static s64 tctx_inflight(struct io_uring_task *tctx, bool tracked)
@@ -9078,6 +9089,9 @@ static void io_uring_cancel_sqpoll(struct io_sq_data *sqd)
 
        if (!current->io_uring)
                return;
+       if (tctx->io_wq)
+               io_wq_exit_start(tctx->io_wq);
+
        WARN_ON_ONCE(!sqd || sqd->thread != current);
 
        atomic_inc(&tctx->in_idle);
@@ -9112,6 +9126,9 @@ void __io_uring_cancel(struct files_struct *files)
        DEFINE_WAIT(wait);
        s64 inflight;
 
+       if (tctx->io_wq)
+               io_wq_exit_start(tctx->io_wq);
+
        /* make sure overflow events are dropped */
        atomic_inc(&tctx->in_idle);
        do {
@@ -9659,7 +9676,8 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p,
                        IORING_FEAT_SUBMIT_STABLE | IORING_FEAT_RW_CUR_POS |
                        IORING_FEAT_CUR_PERSONALITY | IORING_FEAT_FAST_POLL |
                        IORING_FEAT_POLL_32BITS | IORING_FEAT_SQPOLL_NONFIXED |
-                       IORING_FEAT_EXT_ARG | IORING_FEAT_NATIVE_WORKERS;
+                       IORING_FEAT_EXT_ARG | IORING_FEAT_NATIVE_WORKERS |
+                       IORING_FEAT_RSRC_TAGS;
 
        if (copy_to_user(params, p, sizeof(*p))) {
                ret = -EFAULT;
@@ -9899,7 +9917,7 @@ static int io_register_files_update(struct io_ring_ctx *ctx, void __user *arg,
 }
 
 static int io_register_rsrc_update(struct io_ring_ctx *ctx, void __user *arg,
-                                  unsigned size)
+                                  unsigned size, unsigned type)
 {
        struct io_uring_rsrc_update2 up;
 
@@ -9907,13 +9925,13 @@ static int io_register_rsrc_update(struct io_ring_ctx *ctx, void __user *arg,
                return -EINVAL;
        if (copy_from_user(&up, arg, sizeof(up)))
                return -EFAULT;
-       if (!up.nr)
+       if (!up.nr || up.resv)
                return -EINVAL;
-       return __io_register_rsrc_update(ctx, up.type, &up, up.nr);
+       return __io_register_rsrc_update(ctx, type, &up, up.nr);
 }
 
 static int io_register_rsrc(struct io_ring_ctx *ctx, void __user *arg,
-                           unsigned int size)
+                           unsigned int size, unsigned int type)
 {
        struct io_uring_rsrc_register rr;
 
@@ -9924,10 +9942,10 @@ static int io_register_rsrc(struct io_ring_ctx *ctx, void __user *arg,
        memset(&rr, 0, sizeof(rr));
        if (copy_from_user(&rr, arg, size))
                return -EFAULT;
-       if (!rr.nr)
+       if (!rr.nr || rr.resv || rr.resv2)
                return -EINVAL;
 
-       switch (rr.type) {
+       switch (type) {
        case IORING_RSRC_FILE:
                return io_sqe_files_register(ctx, u64_to_user_ptr(rr.data),
                                             rr.nr, u64_to_user_ptr(rr.tags));
@@ -9949,8 +9967,10 @@ static bool io_register_op_must_quiesce(int op)
        case IORING_REGISTER_PROBE:
        case IORING_REGISTER_PERSONALITY:
        case IORING_UNREGISTER_PERSONALITY:
-       case IORING_REGISTER_RSRC:
-       case IORING_REGISTER_RSRC_UPDATE:
+       case IORING_REGISTER_FILES2:
+       case IORING_REGISTER_FILES_UPDATE2:
+       case IORING_REGISTER_BUFFERS2:
+       case IORING_REGISTER_BUFFERS_UPDATE:
                return false;
        default:
                return true;
@@ -10076,11 +10096,19 @@ static int __io_uring_register(struct io_ring_ctx *ctx, unsigned opcode,
        case IORING_REGISTER_RESTRICTIONS:
                ret = io_register_restrictions(ctx, arg, nr_args);
                break;
-       case IORING_REGISTER_RSRC:
-               ret = io_register_rsrc(ctx, arg, nr_args);
+       case IORING_REGISTER_FILES2:
+               ret = io_register_rsrc(ctx, arg, nr_args, IORING_RSRC_FILE);
+               break;
+       case IORING_REGISTER_FILES_UPDATE2:
+               ret = io_register_rsrc_update(ctx, arg, nr_args,
+                                             IORING_RSRC_FILE);
+               break;
+       case IORING_REGISTER_BUFFERS2:
+               ret = io_register_rsrc(ctx, arg, nr_args, IORING_RSRC_BUFFER);
                break;
-       case IORING_REGISTER_RSRC_UPDATE:
-               ret = io_register_rsrc_update(ctx, arg, nr_args);
+       case IORING_REGISTER_BUFFERS_UPDATE:
+               ret = io_register_rsrc_update(ctx, arg, nr_args,
+                                             IORING_RSRC_BUFFER);
                break;
        default:
                ret = -EINVAL;