io_uring/rsrc: add empty flag in rsrc_node
[linux-block.git] / io_uring / rsrc.h
index 2b8743645efcbd5d29709fbd2ecff2b6d51e86f3..f3fe455c6c712fc91cca1d29aaf037aa66f38ac3 100644 (file)
@@ -4,6 +4,10 @@
 
 #include <net/af_unix.h>
 
+#include "alloc_cache.h"
+
+#define IO_NODE_ALLOC_CACHE_MAX 32
+
 #define IO_RSRC_TAG_TABLE_SHIFT        (PAGE_SHIFT - 3)
 #define IO_RSRC_TAG_TABLE_MAX  (1U << IO_RSRC_TAG_TABLE_SHIFT)
 #define IO_RSRC_TAG_TABLE_MASK (IO_RSRC_TAG_TABLE_MAX - 1)
@@ -14,7 +18,6 @@ enum {
 };
 
 struct io_rsrc_put {
-       struct list_head list;
        u64 tag;
        union {
                void *rsrc;
@@ -31,18 +34,18 @@ struct io_rsrc_data {
        u64                             **tags;
        unsigned int                    nr;
        rsrc_put_fn                     *do_put;
-       atomic_t                        refs;
-       struct completion               done;
        bool                            quiesce;
 };
 
 struct io_rsrc_node {
-       struct percpu_ref               refs;
+       union {
+               struct io_cache_entry           cache;
+               struct io_rsrc_data             *rsrc_data;
+       };
+       int                             refs;
+       bool                            empty;
        struct list_head                node;
-       struct list_head                rsrc_list;
-       struct io_rsrc_data             *rsrc_data;
-       struct llist_node               llist;
-       bool                            done;
+       struct io_rsrc_put              item;
 };
 
 struct io_mapped_ubuf {
@@ -54,16 +57,11 @@ struct io_mapped_ubuf {
 };
 
 void io_rsrc_put_tw(struct callback_head *cb);
+void io_rsrc_node_ref_zero(struct io_rsrc_node *node);
 void io_rsrc_put_work(struct work_struct *work);
-void io_rsrc_refs_refill(struct io_ring_ctx *ctx);
-void io_wait_rsrc_data(struct io_rsrc_data *data);
-void io_rsrc_node_destroy(struct io_rsrc_node *ref_node);
-void io_rsrc_refs_drop(struct io_ring_ctx *ctx);
-int io_rsrc_node_switch_start(struct io_ring_ctx *ctx);
-int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx,
-                         struct io_rsrc_node *node, void *rsrc);
-void io_rsrc_node_switch(struct io_ring_ctx *ctx,
-                        struct io_rsrc_data *data_to_kill);
+void io_rsrc_node_destroy(struct io_ring_ctx *ctx, struct io_rsrc_node *ref_node);
+struct io_rsrc_node *io_rsrc_node_alloc(struct io_ring_ctx *ctx);
+int io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx, void *rsrc);
 
 int io_import_fixed(int ddir, struct iov_iter *iter,
                           struct io_mapped_ubuf *imu,
@@ -107,36 +105,24 @@ int io_register_rsrc_update(struct io_ring_ctx *ctx, void __user *arg,
 int io_register_rsrc(struct io_ring_ctx *ctx, void __user *arg,
                        unsigned int size, unsigned int type);
 
-static inline void io_rsrc_put_node(struct io_rsrc_node *node, int nr)
+static inline void io_put_rsrc_node(struct io_ring_ctx *ctx, struct io_rsrc_node *node)
 {
-       percpu_ref_put_many(&node->refs, nr);
-}
+       lockdep_assert_held(&ctx->uring_lock);
 
-static inline void io_req_put_rsrc(struct io_kiocb *req)
-{
-       if (req->rsrc_node)
-               io_rsrc_put_node(req->rsrc_node, 1);
+       if (node && !--node->refs)
+               io_rsrc_node_ref_zero(node);
 }
 
 static inline void io_req_put_rsrc_locked(struct io_kiocb *req,
                                          struct io_ring_ctx *ctx)
-       __must_hold(&ctx->uring_lock)
 {
-       struct io_rsrc_node *node = req->rsrc_node;
-
-       if (node) {
-               if (node == ctx->rsrc_node)
-                       ctx->rsrc_cached_refs++;
-               else
-                       io_rsrc_put_node(node, 1);
-       }
+       io_put_rsrc_node(ctx, req->rsrc_node);
 }
 
-static inline void io_charge_rsrc_node(struct io_ring_ctx *ctx)
+static inline void io_charge_rsrc_node(struct io_ring_ctx *ctx,
+                                      struct io_rsrc_node *node)
 {
-       ctx->rsrc_cached_refs--;
-       if (unlikely(ctx->rsrc_cached_refs < 0))
-               io_rsrc_refs_refill(ctx);
+       node->refs++;
 }
 
 static inline void io_req_set_rsrc_node(struct io_kiocb *req,
@@ -144,15 +130,13 @@ static inline void io_req_set_rsrc_node(struct io_kiocb *req,
                                        unsigned int issue_flags)
 {
        if (!req->rsrc_node) {
-               req->rsrc_node = ctx->rsrc_node;
+               io_ring_submit_lock(ctx, issue_flags);
 
-               if (!(issue_flags & IO_URING_F_UNLOCKED)) {
-                       lockdep_assert_held(&ctx->uring_lock);
+               lockdep_assert_held(&ctx->uring_lock);
 
-                       io_charge_rsrc_node(ctx);
-               } else {
-                       percpu_ref_get(&req->rsrc_node->refs);
-               }
+               req->rsrc_node = ctx->rsrc_node;
+               io_charge_rsrc_node(ctx, ctx->rsrc_node);
+               io_ring_submit_unlock(ctx, issue_flags);
        }
 }
 
@@ -164,6 +148,12 @@ static inline u64 *io_get_tag_slot(struct io_rsrc_data *data, unsigned int idx)
        return &data->tags[table_idx][off];
 }
 
+static inline int io_rsrc_init(struct io_ring_ctx *ctx)
+{
+       ctx->rsrc_node = io_rsrc_node_alloc(ctx);
+       return ctx->rsrc_node ? 0 : -ENOMEM;
+}
+
 int io_files_update(struct io_kiocb *req, unsigned int issue_flags);
 int io_files_update_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);