io_uring/rw.c

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

File Facts

System
Linux kernel
Corpus path
io_uring/rw.c
Extension
.c
Size
36678 bytes
Lines
1398
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_rw {
	/* NOTE: kiocb has the file as the first member, so don't do it here */
	struct kiocb			kiocb;
	u64				addr;
	u32				len;
	rwf_t				flags;
};

static bool io_file_supports_nowait(struct io_kiocb *req, __poll_t mask)
{
	/* If FMODE_NOWAIT is set for a file, we're golden */
	if (req->flags & REQ_F_SUPPORT_NOWAIT)
		return true;
	/* No FMODE_NOWAIT, if we can poll, check the status */
	if (io_file_can_poll(req)) {
		struct poll_table_struct pt = { ._key = mask };

		return vfs_poll(req->file, &pt) & mask;
	}
	/* No FMODE_NOWAIT support, and file isn't pollable. Tough luck. */
	return false;
}

static int io_iov_compat_buffer_select_prep(struct io_rw *rw)
{
	struct compat_iovec __user *uiov = u64_to_user_ptr(rw->addr);
	struct compat_iovec iov;

	if (copy_from_user(&iov, uiov, sizeof(iov)))
		return -EFAULT;
	rw->len = iov.iov_len;
	return 0;
}

static int io_iov_buffer_select_prep(struct io_kiocb *req)
{
	struct iovec __user *uiov;
	struct iovec iov;
	struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);

	if (rw->len != 1)
		return -EINVAL;

	if (io_is_compat(req->ctx))
		return io_iov_compat_buffer_select_prep(rw);

	uiov = u64_to_user_ptr(rw->addr);
	if (copy_from_user(&iov, uiov, sizeof(*uiov)))
		return -EFAULT;
	rw->len = iov.iov_len;
	return 0;
}

static int io_import_vec(int ddir, struct io_kiocb *req,
			 struct io_async_rw *io,
			 const struct iovec __user *uvec,
			 size_t uvec_segs)
{
	int ret, nr_segs;
	struct iovec *iov;

	if (io->vec.iovec) {
		nr_segs = io->vec.nr;
		iov = io->vec.iovec;
	} else {
		nr_segs = 1;
		iov = &io->fast_iov;
	}

	ret = __import_iovec(ddir, uvec, uvec_segs, nr_segs, &iov, &io->iter,
			     io_is_compat(req->ctx));
	if (unlikely(ret < 0))
		return ret;
	if (iov) {
		req->flags |= REQ_F_NEED_CLEANUP;
		io_vec_reset_iovec(&io->vec, iov, io->iter.nr_segs);
	}
	return 0;
}

static int __io_import_rw_buffer(int ddir, struct io_kiocb *req,
				 struct io_async_rw *io, struct io_br_sel *sel,
				 unsigned int issue_flags)
{
	const struct io_issue_def *def = &io_issue_defs[req->opcode];
	struct io_rw *rw = io_kiocb_to_cmd(req, struct io_rw);
	size_t sqe_len = rw->len;

	sel->addr = u64_to_user_ptr(rw->addr);
	if (def->vectored && !(req->flags & REQ_F_BUFFER_SELECT))

Annotation

Implementation Notes