io_uring/openclose.c

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

File Facts

System
Linux kernel
Corpus path
io_uring/openclose.c
Extension
.c
Size
10737 bytes
Lines
449
Domain
Kernel Services
Bucket
io_uring
Inferred role
Kernel Services: implementation source
Status
source 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_open {
	struct file			*file;
	int				dfd;
	u32				file_slot;
	struct delayed_filename		filename;
	struct open_how			how;
	unsigned long			nofile;
};

struct io_close {
	struct file			*file;
	int				fd;
	u32				file_slot;
};

struct io_fixed_install {
	struct file			*file;
	unsigned int			o_flags;
};

static bool io_openat_force_async(struct io_open *open)
{
	/*
	 * Don't bother trying for O_TRUNC, O_CREAT, or O_TMPFILE open,
	 * it'll always -EAGAIN. Note that we test for __O_TMPFILE because
	 * O_TMPFILE includes O_DIRECTORY, which isn't a flag we need to force
	 * async for.
	 */
	return open->how.flags & (O_TRUNC | O_CREAT | __O_TMPFILE);
}

static int __io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
{
	struct io_open *open = io_kiocb_to_cmd(req, struct io_open);
	const char __user *fname;
	int ret;

	if (unlikely(sqe->buf_index))
		return -EINVAL;
	if (unlikely(req->flags & REQ_F_FIXED_FILE))
		return -EBADF;

	/* open.how should be already initialised */
	if (!(open->how.flags & O_PATH) && force_o_largefile())
		open->how.flags |= O_LARGEFILE;

	open->dfd = READ_ONCE(sqe->fd);
	fname = u64_to_user_ptr(READ_ONCE(sqe->addr));
	ret = delayed_getname(&open->filename, fname);
	if (unlikely(ret))
		return ret;
	req->flags |= REQ_F_NEED_CLEANUP;

	open->file_slot = READ_ONCE(sqe->file_index);
	if (open->file_slot && (open->how.flags & O_CLOEXEC))
		return -EINVAL;

	open->nofile = rlimit(RLIMIT_NOFILE);
	if (io_openat_force_async(open))
		req->flags |= REQ_F_FORCE_ASYNC;
	return 0;
}

void io_openat_bpf_populate(struct io_uring_bpf_ctx *bctx, struct io_kiocb *req)
{
	struct io_open *open = io_kiocb_to_cmd(req, struct io_open);

	bctx->open.flags = open->how.flags;
	bctx->open.mode = open->how.mode;
	bctx->open.resolve = open->how.resolve;
}

int io_openat_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
{
	struct io_open *open = io_kiocb_to_cmd(req, struct io_open);
	u64 mode = READ_ONCE(sqe->len);
	u64 flags = READ_ONCE(sqe->open_flags);

	open->how = build_open_how(flags, mode);
	return __io_openat_prep(req, sqe);
}

int io_openat2_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
{
	struct io_open *open = io_kiocb_to_cmd(req, struct io_open);
	struct open_how __user *how;
	size_t len;
	int ret;

	how = u64_to_user_ptr(READ_ONCE(sqe->addr2));

Annotation

Implementation Notes