Merge tag 'xfs-6.2-merge-8' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux
[platform/kernel/linux-starfive.git] / io_uring / rsrc.c
index 55d4ab9..18de10c 100644 (file)
@@ -170,10 +170,10 @@ static void __io_rsrc_put_work(struct io_rsrc_node *ref_node)
                if (prsrc->tag) {
                        if (ctx->flags & IORING_SETUP_IOPOLL) {
                                mutex_lock(&ctx->uring_lock);
-                               io_post_aux_cqe(ctx, prsrc->tag, 0, 0, true);
+                               io_post_aux_cqe(ctx, prsrc->tag, 0, 0);
                                mutex_unlock(&ctx->uring_lock);
                        } else {
-                               io_post_aux_cqe(ctx, prsrc->tag, 0, 0, true);
+                               io_post_aux_cqe(ctx, prsrc->tag, 0, 0);
                        }
                }
 
@@ -204,6 +204,14 @@ void io_rsrc_put_work(struct work_struct *work)
        }
 }
 
+void io_rsrc_put_tw(struct callback_head *cb)
+{
+       struct io_ring_ctx *ctx = container_of(cb, struct io_ring_ctx,
+                                              rsrc_put_tw);
+
+       io_rsrc_put_work(&ctx->rsrc_put_work.work);
+}
+
 void io_wait_rsrc_data(struct io_rsrc_data *data)
 {
        if (data && !atomic_dec_and_test(&data->refs))
@@ -242,8 +250,15 @@ static __cold void io_rsrc_node_ref_zero(struct percpu_ref *ref)
        }
        spin_unlock_irqrestore(&ctx->rsrc_ref_lock, flags);
 
-       if (first_add)
-               mod_delayed_work(system_wq, &ctx->rsrc_put_work, delay);
+       if (!first_add)
+               return;
+
+       if (ctx->submitter_task) {
+               if (!task_work_add(ctx->submitter_task, &ctx->rsrc_put_tw,
+                                  ctx->notify_method))
+                       return;
+       }
+       mod_delayed_work(system_wq, &ctx->rsrc_put_work, delay);
 }
 
 static struct io_rsrc_node *io_rsrc_node_alloc(void)
@@ -309,41 +324,41 @@ __cold static int io_rsrc_ref_quiesce(struct io_rsrc_data *data,
        /* As we may drop ->uring_lock, other task may have started quiesce */
        if (data->quiesce)
                return -ENXIO;
+       ret = io_rsrc_node_switch_start(ctx);
+       if (ret)
+               return ret;
+       io_rsrc_node_switch(ctx, data);
+
+       /* kill initial ref, already quiesced if zero */
+       if (atomic_dec_and_test(&data->refs))
+               return 0;
 
        data->quiesce = true;
+       mutex_unlock(&ctx->uring_lock);
        do {
-               ret = io_rsrc_node_switch_start(ctx);
-               if (ret)
+               ret = io_run_task_work_sig(ctx);
+               if (ret < 0) {
+                       atomic_inc(&data->refs);
+                       /* wait for all works potentially completing data->done */
+                       flush_delayed_work(&ctx->rsrc_put_work);
+                       reinit_completion(&data->done);
+                       mutex_lock(&ctx->uring_lock);
                        break;
-               io_rsrc_node_switch(ctx, data);
+               }
 
-               /* kill initial ref, already quiesced if zero */
-               if (atomic_dec_and_test(&data->refs))
-                       break;
-               mutex_unlock(&ctx->uring_lock);
                flush_delayed_work(&ctx->rsrc_put_work);
                ret = wait_for_completion_interruptible(&data->done);
                if (!ret) {
                        mutex_lock(&ctx->uring_lock);
-                       if (atomic_read(&data->refs) > 0) {
-                               /*
-                                * it has been revived by another thread while
-                                * we were unlocked
-                                */
-                               mutex_unlock(&ctx->uring_lock);
-                       } else {
+                       if (atomic_read(&data->refs) <= 0)
                                break;
-                       }
+                       /*
+                        * it has been revived by another thread while
+                        * we were unlocked
+                        */
+                       mutex_unlock(&ctx->uring_lock);
                }
-
-               atomic_inc(&data->refs);
-               /* wait for all works potentially completing data->done */
-               flush_delayed_work(&ctx->rsrc_put_work);
-               reinit_completion(&data->done);
-
-               ret = io_run_task_work_sig(ctx);
-               mutex_lock(&ctx->uring_lock);
-       } while (ret >= 0);
+       } while (1);
        data->quiesce = false;
 
        return ret;