io_uring/tctx.c

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

File Facts

System
Linux kernel
Corpus path
io_uring/tctx.c
Extension
.c
Size
9385 bytes
Lines
420
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

if (!hash) {
			mutex_unlock(&ctx->uring_lock);
			return ERR_PTR(-ENOMEM);
		}
		refcount_set(&hash->refs, 1);
		init_waitqueue_head(&hash->wait);
		ctx->hash_map = hash;
	}
	mutex_unlock(&ctx->uring_lock);

	data.hash = hash;
	data.task = task;

	/* Do QD, or 4 * CPUS, whatever is smallest */
	concurrency = min(ctx->sq_entries, 4 * num_online_cpus());

	return io_wq_create(concurrency, &data);
}

void __io_uring_free(struct task_struct *tsk)
{
	struct io_uring_task *tctx = tsk->io_uring;
	struct io_tctx_node *node;
	unsigned long index;

	/*
	 * Fault injection forcing allocation errors in the xa_store() path
	 * can lead to xa_empty() returning false, even though no actual
	 * node is stored in the xarray. Until that gets sorted out, attempt
	 * an iteration here and warn if any entries are found.
	 */
	if (tctx) {
		xa_for_each(&tctx->xa, index, node) {
			WARN_ON_ONCE(1);
			break;
		}
		WARN_ON_ONCE(tctx->io_wq);
		WARN_ON_ONCE(tctx->cached_refs);

		percpu_counter_destroy(&tctx->inflight);
		kfree(tctx);
		tsk->io_uring = NULL;
	}
	if (tsk->io_uring_restrict) {
		io_put_bpf_filters(tsk->io_uring_restrict);
		kfree(tsk->io_uring_restrict);
		tsk->io_uring_restrict = NULL;
	}
}

__cold struct io_uring_task *io_uring_alloc_task_context(struct task_struct *task,
							struct io_ring_ctx *ctx)
{
	struct io_uring_task *tctx;
	int ret;

	tctx = kzalloc_obj(*tctx);
	if (unlikely(!tctx))
		return ERR_PTR(-ENOMEM);

	ret = percpu_counter_init(&tctx->inflight, 0, GFP_KERNEL);
	if (unlikely(ret)) {
		kfree(tctx);
		return ERR_PTR(ret);
	}

	tctx->io_wq = io_init_wq_offload(ctx, task);
	if (IS_ERR(tctx->io_wq)) {
		ret = PTR_ERR(tctx->io_wq);
		percpu_counter_destroy(&tctx->inflight);
		kfree(tctx);
		return ERR_PTR(ret);
	}

	tctx->task = task;
	xa_init(&tctx->xa);
	init_waitqueue_head(&tctx->wait);
	atomic_set(&tctx->in_cancel, 0);
	atomic_set(&tctx->inflight_tracked, 0);
	mpscq_init(&tctx->task_list, &tctx->task_head);
	INIT_WORK(&tctx->fallback_work, io_tctx_fallback_work);
	init_task_work(&tctx->task_work, tctx_task_work);
	return tctx;
}

static int io_tctx_install_node(struct io_ring_ctx *ctx,
				struct io_uring_task *tctx)
{
	struct io_tctx_node *node;
	int ret;

Annotation

Implementation Notes