io_uring/rsrc.c

Source file repositories/reference/linux-study-clean/io_uring/rsrc.c

File Facts

System
Linux kernel
Corpus path
io_uring/rsrc.c
Extension
.c
Size
39671 bytes
Lines
1709
Domain
Kernel Services
Bucket
io_uring
Inferred role
Kernel Services: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Shared kernel service surface used by multiple subsystems, including helpers, cryptography, virtualization support, and async I/O infrastructure.

Dependency Surface

Detected Declarations

Annotated Snippet

struct io_rsrc_update {
	struct file			*file;
	u64				arg;
	u32				nr_args;
	u32				offset;
};

static struct io_rsrc_node *io_sqe_buffer_register(struct io_ring_ctx *ctx,
						   struct iovec *iov);

static int hpage_acct_ref(struct io_ring_ctx *ctx, struct page *hpage,
			  bool *acct_new)
{
	unsigned long key = (unsigned long) hpage;
	unsigned long count;
	void *entry;
	int ret;

	lockdep_assert_held(&ctx->uring_lock);

	entry = xa_load(&ctx->hpage_acct, key);
	if (entry) {
		*acct_new = false;
		count = xa_to_value(entry) + 1;
	} else {
		ret = xa_reserve(&ctx->hpage_acct, key, GFP_KERNEL_ACCOUNT);
		if (ret)
			return ret;
		*acct_new = true;
		count = 1;
	}
	xa_store(&ctx->hpage_acct, key, xa_mk_value(count), GFP_KERNEL_ACCOUNT);
	return 0;
}

static bool hpage_acct_unref(struct io_ring_ctx *ctx, struct page *hpage)
{
	unsigned long key = (unsigned long) hpage;
	unsigned long count;
	void *entry;

	lockdep_assert_held(&ctx->uring_lock);

	entry = xa_load(&ctx->hpage_acct, key);
	if (WARN_ON_ONCE(!entry))
		return false;
	count = xa_to_value(entry);
	if (count == 1) {
		xa_erase(&ctx->hpage_acct, key);
		return true;
	}
	xa_store(&ctx->hpage_acct, key, xa_mk_value(count - 1), GFP_KERNEL_ACCOUNT);
	return false;
}

/* only define max */
#define IORING_MAX_FIXED_FILES	(1U << 20)
#define IORING_MAX_REG_BUFFERS	(1U << 14)

#define IO_CACHED_BVECS_SEGS	32

int __io_account_mem(struct user_struct *user, unsigned long nr_pages)
{
	unsigned long page_limit, cur_pages, new_pages;

	if (!nr_pages)
		return 0;

	/* Don't allow more pages than we can safely lock */
	page_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;

	cur_pages = atomic_long_read(&user->locked_vm);
	do {
		new_pages = cur_pages + nr_pages;
		if (new_pages > page_limit)
			return -ENOMEM;
	} while (!atomic_long_try_cmpxchg(&user->locked_vm,
					  &cur_pages, new_pages));
	return 0;
}

void io_unaccount_mem(struct user_struct *user, struct mm_struct *mm_account,
		      unsigned long nr_pages)
{
	if (user)
		__io_unaccount_mem(user, nr_pages);

	if (mm_account)
		atomic64_sub(nr_pages, &mm_account->pinned_vm);
}

Annotation

Implementation Notes