tools/testing/selftests/ublk/kublk.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/ublk/kublk.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/ublk/kublk.c
Extension
.c
Size
58361 bytes
Lines
2381
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

struct ublk_thread_info {
	struct ublk_dev 	*dev;
	pthread_t		thread;
	unsigned		idx;
	sem_t 			*ready;
	cpu_set_t 		*affinity;
	unsigned long long	extra_flags;
	unsigned char		(*q_thread_map)[UBLK_MAX_QUEUES];
};

static void ublk_thread_set_sched_affinity(const struct ublk_thread_info *info)
{
	if (pthread_setaffinity_np(pthread_self(), sizeof(*info->affinity), info->affinity) < 0)
		ublk_err("ublk dev %u thread %u set affinity failed",
				info->dev->dev_info.dev_id, info->idx);
}

static void ublk_batch_setup_queues(struct ublk_thread *t)
{
	int i;

	for (i = 0; i < t->dev->dev_info.nr_hw_queues; i++) {
		struct ublk_queue *q = &t->dev->q[i];
		int ret;

		/*
		 * Only prepare io commands in the mapped thread context,
		 * otherwise io command buffer index may not work as expected
		 */
		if (t->q_map[i] == 0)
			continue;

		if (q->tgt_ops->pre_fetch_io)
			q->tgt_ops->pre_fetch_io(t, q, 0, true);

		ret = ublk_batch_queue_prep_io_cmds(t, q);
		ublk_assert(ret >= 0);
	}
}

static __attribute__((noinline)) int __ublk_io_handler_fn(struct ublk_thread_info *info)
{
	struct ublk_thread t = {
		.dev = info->dev,
		.idx = info->idx,
	};
	int dev_id = info->dev->dev_info.dev_id;
	int ret;

	/* Copy per-thread queue mapping into thread-local variable */
	if (info->q_thread_map)
		memcpy(t.q_map, info->q_thread_map[info->idx], sizeof(t.q_map));

	ret = ublk_thread_init(&t, info->extra_flags);
	if (ret) {
		ublk_err("ublk dev %d thread %u init failed\n",
				dev_id, t.idx);
		return ret;
	}
	sem_post(info->ready);

	ublk_dbg(UBLK_DBG_THREAD, "tid %d: ublk dev %d thread %u started\n",
			gettid(), dev_id, t.idx);

	if (!ublk_thread_batch_io(&t)) {
		/* submit all io commands to ublk driver */
		ublk_submit_fetch_commands(&t);
	} else {
		ublk_batch_setup_queues(&t);
		ublk_batch_start_fetch(&t);
	}

	do {
		if (ublk_process_io(&t) < 0)
			break;
	} while (1);

	ublk_dbg(UBLK_DBG_THREAD, "tid %d: ublk dev %d thread %d exiting\n",
		 gettid(), dev_id, t.idx);
	ublk_thread_deinit(&t);
	return 0;
}

static void *ublk_io_handler_fn(void *data)
{
	struct ublk_thread_info *info = data;

	/*
	 * IO perf is sensitive with queue pthread affinity on NUMA machine
	 *

Annotation

Implementation Notes