kernel/bpf/bpf_iter.c

Source file repositories/reference/linux-study-clean/kernel/bpf/bpf_iter.c

File Facts

System
Linux kernel
Corpus path
kernel/bpf/bpf_iter.c
Extension
.c
Size
19345 bytes
Lines
828
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
Inferred role
Core OS: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

const struct file_operations bpf_iter_fops = {
	.open		= iter_open,
	.read		= bpf_seq_read,
	.release	= iter_release,
};

/* The argument reg_info will be cached in bpf_iter_target_info.
 * The common practice is to declare target reg_info as
 * a const static variable and passed as an argument to
 * bpf_iter_reg_target().
 */
int bpf_iter_reg_target(const struct bpf_iter_reg *reg_info)
{
	struct bpf_iter_target_info *tinfo;

	tinfo = kzalloc_obj(*tinfo);
	if (!tinfo)
		return -ENOMEM;

	tinfo->reg_info = reg_info;
	INIT_LIST_HEAD(&tinfo->list);

	mutex_lock(&targets_mutex);
	list_add(&tinfo->list, &targets);
	mutex_unlock(&targets_mutex);

	return 0;
}

void bpf_iter_unreg_target(const struct bpf_iter_reg *reg_info)
{
	struct bpf_iter_target_info *tinfo;
	bool found = false;

	mutex_lock(&targets_mutex);
	list_for_each_entry(tinfo, &targets, list) {
		if (reg_info == tinfo->reg_info) {
			list_del(&tinfo->list);
			kfree(tinfo);
			found = true;
			break;
		}
	}
	mutex_unlock(&targets_mutex);

	WARN_ON(found == false);
}

static void cache_btf_id(struct bpf_iter_target_info *tinfo,
			 struct bpf_prog *prog)
{
	tinfo->btf_id = prog->aux->attach_btf_id;
}

int bpf_iter_prog_supported(struct bpf_prog *prog)
{
	const char *attach_fname = prog->aux->attach_func_name;
	struct bpf_iter_target_info *tinfo = NULL, *iter;
	u32 prog_btf_id = prog->aux->attach_btf_id;
	const char *prefix = BPF_ITER_FUNC_PREFIX;
	int prefix_len = strlen(prefix);

	if (strncmp(attach_fname, prefix, prefix_len))
		return -EINVAL;

	mutex_lock(&targets_mutex);
	list_for_each_entry(iter, &targets, list) {
		if (iter->btf_id && iter->btf_id == prog_btf_id) {
			tinfo = iter;
			break;
		}
		if (!strcmp(attach_fname + prefix_len, iter->reg_info->target)) {
			cache_btf_id(iter, prog);
			tinfo = iter;
			break;
		}
	}
	mutex_unlock(&targets_mutex);

	if (!tinfo)
		return -EINVAL;

	return bpf_prog_ctx_arg_info_init(prog, tinfo->reg_info->ctx_arg_info,
					  tinfo->reg_info->ctx_arg_info_size);
}

const struct bpf_func_proto *
bpf_iter_get_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
{
	const struct bpf_iter_target_info *tinfo;

Annotation

Implementation Notes