io_uring/timeout.c

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

File Facts

System
Linux kernel
Corpus path
io_uring/timeout.c
Extension
.c
Size
20086 bytes
Lines
756
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_timeout {
	struct file			*file;
	u32				off;
	u32				target_seq;
	u32				repeats;
	struct list_head		list;
	/* head of the link, used by linked timeouts only */
	struct io_kiocb			*head;
	/* for linked completions */
	struct io_kiocb			*prev;
};

struct io_timeout_rem {
	struct file			*file;
	u64				addr;

	/* timeout update */
	ktime_t				time;
	u32				flags;
	bool				ltimeout;
};

static clockid_t io_flags_to_clock(unsigned flags)
{
	switch (flags & IORING_TIMEOUT_CLOCK_MASK) {
	case IORING_TIMEOUT_BOOTTIME:
		return CLOCK_BOOTTIME;
	case IORING_TIMEOUT_REALTIME:
		return CLOCK_REALTIME;
	default:
		/* can't happen, vetted at prep time */
		WARN_ON_ONCE(1);
		fallthrough;
	case 0:
		return CLOCK_MONOTONIC;
	}
}

static int io_parse_user_time(ktime_t *time, u64 arg, unsigned flags)
{
	struct timespec64 ts;

	if (flags & IORING_TIMEOUT_IMMEDIATE_ARG) {
		*time = ns_to_ktime(arg);
		if (*time < 0)
			return -EINVAL;
		goto out;
	}

	if (get_timespec64(&ts, u64_to_user_ptr(arg)))
		return -EFAULT;
	if (ts.tv_sec < 0 || ts.tv_nsec < 0)
		return -EINVAL;
	*time = timespec64_to_ktime(ts);
out:
	if (flags & IORING_TIMEOUT_ABS)
		*time = timens_ktime_to_host(io_flags_to_clock(flags), *time);
	return 0;
}

static struct io_kiocb *__io_disarm_linked_timeout(struct io_kiocb *req,
						   struct io_kiocb *link);

static inline bool io_is_timeout_noseq(struct io_kiocb *req)
{
	struct io_timeout *timeout = io_kiocb_to_cmd(req, struct io_timeout);
	struct io_timeout_data *data = req->async_data;

	return !timeout->off || data->flags & IORING_TIMEOUT_MULTISHOT;
}

static inline void io_put_req(struct io_kiocb *req)
{
	if (req_ref_put_and_test(req)) {
		io_queue_next(req);
		io_free_req(req);
	}
}

static inline bool io_timeout_finish(struct io_timeout *timeout,
				     struct io_timeout_data *data)
{
	if (!(data->flags & IORING_TIMEOUT_MULTISHOT))
		return true;

	if (!timeout->off || (timeout->repeats && --timeout->repeats))
		return false;

	return true;
}

Annotation

Implementation Notes