162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci#ifndef IOU_RSRC_H
362306a36Sopenharmony_ci#define IOU_RSRC_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#include <net/af_unix.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include "alloc_cache.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#define IO_NODE_ALLOC_CACHE_MAX 32
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#define IO_RSRC_TAG_TABLE_SHIFT	(PAGE_SHIFT - 3)
1262306a36Sopenharmony_ci#define IO_RSRC_TAG_TABLE_MAX	(1U << IO_RSRC_TAG_TABLE_SHIFT)
1362306a36Sopenharmony_ci#define IO_RSRC_TAG_TABLE_MASK	(IO_RSRC_TAG_TABLE_MAX - 1)
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_cienum {
1662306a36Sopenharmony_ci	IORING_RSRC_FILE		= 0,
1762306a36Sopenharmony_ci	IORING_RSRC_BUFFER		= 1,
1862306a36Sopenharmony_ci};
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistruct io_rsrc_put {
2162306a36Sopenharmony_ci	u64 tag;
2262306a36Sopenharmony_ci	union {
2362306a36Sopenharmony_ci		void *rsrc;
2462306a36Sopenharmony_ci		struct file *file;
2562306a36Sopenharmony_ci		struct io_mapped_ubuf *buf;
2662306a36Sopenharmony_ci	};
2762306a36Sopenharmony_ci};
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_citypedef void (rsrc_put_fn)(struct io_ring_ctx *ctx, struct io_rsrc_put *prsrc);
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_cistruct io_rsrc_data {
3262306a36Sopenharmony_ci	struct io_ring_ctx		*ctx;
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	u64				**tags;
3562306a36Sopenharmony_ci	unsigned int			nr;
3662306a36Sopenharmony_ci	u16				rsrc_type;
3762306a36Sopenharmony_ci	bool				quiesce;
3862306a36Sopenharmony_ci};
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistruct io_rsrc_node {
4162306a36Sopenharmony_ci	union {
4262306a36Sopenharmony_ci		struct io_cache_entry		cache;
4362306a36Sopenharmony_ci		struct io_ring_ctx		*ctx;
4462306a36Sopenharmony_ci	};
4562306a36Sopenharmony_ci	int				refs;
4662306a36Sopenharmony_ci	bool				empty;
4762306a36Sopenharmony_ci	u16				type;
4862306a36Sopenharmony_ci	struct list_head		node;
4962306a36Sopenharmony_ci	struct io_rsrc_put		item;
5062306a36Sopenharmony_ci};
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cistruct io_mapped_ubuf {
5362306a36Sopenharmony_ci	u64		ubuf;
5462306a36Sopenharmony_ci	u64		ubuf_end;
5562306a36Sopenharmony_ci	unsigned int	nr_bvecs;
5662306a36Sopenharmony_ci	unsigned long	acct_pages;
5762306a36Sopenharmony_ci	struct bio_vec	bvec[] __counted_by(nr_bvecs);
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_civoid io_rsrc_node_ref_zero(struct io_rsrc_node *node);
6162306a36Sopenharmony_civoid io_rsrc_node_destroy(struct io_ring_ctx *ctx, struct io_rsrc_node *ref_node);
6262306a36Sopenharmony_cistruct io_rsrc_node *io_rsrc_node_alloc(struct io_ring_ctx *ctx);
6362306a36Sopenharmony_ciint io_queue_rsrc_removal(struct io_rsrc_data *data, unsigned idx, void *rsrc);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ciint io_import_fixed(int ddir, struct iov_iter *iter,
6662306a36Sopenharmony_ci			   struct io_mapped_ubuf *imu,
6762306a36Sopenharmony_ci			   u64 buf_addr, size_t len);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_civoid __io_sqe_buffers_unregister(struct io_ring_ctx *ctx);
7062306a36Sopenharmony_ciint io_sqe_buffers_unregister(struct io_ring_ctx *ctx);
7162306a36Sopenharmony_ciint io_sqe_buffers_register(struct io_ring_ctx *ctx, void __user *arg,
7262306a36Sopenharmony_ci			    unsigned int nr_args, u64 __user *tags);
7362306a36Sopenharmony_civoid __io_sqe_files_unregister(struct io_ring_ctx *ctx);
7462306a36Sopenharmony_ciint io_sqe_files_unregister(struct io_ring_ctx *ctx);
7562306a36Sopenharmony_ciint io_sqe_files_register(struct io_ring_ctx *ctx, void __user *arg,
7662306a36Sopenharmony_ci			  unsigned nr_args, u64 __user *tags);
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ciint io_register_files_update(struct io_ring_ctx *ctx, void __user *arg,
7962306a36Sopenharmony_ci			     unsigned nr_args);
8062306a36Sopenharmony_ciint io_register_rsrc_update(struct io_ring_ctx *ctx, void __user *arg,
8162306a36Sopenharmony_ci			    unsigned size, unsigned type);
8262306a36Sopenharmony_ciint io_register_rsrc(struct io_ring_ctx *ctx, void __user *arg,
8362306a36Sopenharmony_ci			unsigned int size, unsigned int type);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_cistatic inline void io_put_rsrc_node(struct io_ring_ctx *ctx, struct io_rsrc_node *node)
8662306a36Sopenharmony_ci{
8762306a36Sopenharmony_ci	lockdep_assert_held(&ctx->uring_lock);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	if (node && !--node->refs)
9062306a36Sopenharmony_ci		io_rsrc_node_ref_zero(node);
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic inline void io_req_put_rsrc_locked(struct io_kiocb *req,
9462306a36Sopenharmony_ci					  struct io_ring_ctx *ctx)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	io_put_rsrc_node(ctx, req->rsrc_node);
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic inline void io_charge_rsrc_node(struct io_ring_ctx *ctx,
10062306a36Sopenharmony_ci				       struct io_rsrc_node *node)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	node->refs++;
10362306a36Sopenharmony_ci}
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_cistatic inline void io_req_set_rsrc_node(struct io_kiocb *req,
10662306a36Sopenharmony_ci					struct io_ring_ctx *ctx,
10762306a36Sopenharmony_ci					unsigned int issue_flags)
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci	if (!req->rsrc_node) {
11062306a36Sopenharmony_ci		io_ring_submit_lock(ctx, issue_flags);
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci		lockdep_assert_held(&ctx->uring_lock);
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci		req->rsrc_node = ctx->rsrc_node;
11562306a36Sopenharmony_ci		io_charge_rsrc_node(ctx, ctx->rsrc_node);
11662306a36Sopenharmony_ci		io_ring_submit_unlock(ctx, issue_flags);
11762306a36Sopenharmony_ci	}
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistatic inline u64 *io_get_tag_slot(struct io_rsrc_data *data, unsigned int idx)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	unsigned int off = idx & IO_RSRC_TAG_TABLE_MASK;
12362306a36Sopenharmony_ci	unsigned int table_idx = idx >> IO_RSRC_TAG_TABLE_SHIFT;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	return &data->tags[table_idx][off];
12662306a36Sopenharmony_ci}
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_cistatic inline int io_rsrc_init(struct io_ring_ctx *ctx)
12962306a36Sopenharmony_ci{
13062306a36Sopenharmony_ci	ctx->rsrc_node = io_rsrc_node_alloc(ctx);
13162306a36Sopenharmony_ci	return ctx->rsrc_node ? 0 : -ENOMEM;
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ciint io_files_update(struct io_kiocb *req, unsigned int issue_flags);
13562306a36Sopenharmony_ciint io_files_update_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ciint __io_account_mem(struct user_struct *user, unsigned long nr_pages);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_cistatic inline void __io_unaccount_mem(struct user_struct *user,
14062306a36Sopenharmony_ci				      unsigned long nr_pages)
14162306a36Sopenharmony_ci{
14262306a36Sopenharmony_ci	atomic_long_sub(nr_pages, &user->locked_vm);
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci#endif
146