kernel/bpf/cgroup_iter.c

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

File Facts

System
Linux kernel
Corpus path
kernel/bpf/cgroup_iter.c
Extension
.c
Size
10670 bytes
Lines
376
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
Inferred role
Core OS: implementation source
Status
source 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

struct bpf_iter__cgroup {
	__bpf_md_ptr(struct bpf_iter_meta *, meta);
	__bpf_md_ptr(struct cgroup *, cgroup);
};

struct cgroup_iter_priv {
	struct cgroup_subsys_state *start_css;
	bool visited_all;
	bool terminate;
	int order;
};

static void *cgroup_iter_seq_start(struct seq_file *seq, loff_t *pos)
{
	struct cgroup_iter_priv *p = seq->private;

	cgroup_lock();

	/* cgroup_iter doesn't support read across multiple sessions. */
	if (*pos > 0) {
		if (p->visited_all)
			return NULL;

		/* Haven't visited all, but because cgroup_mutex has dropped,
		 * return -EOPNOTSUPP to indicate incomplete iteration.
		 */
		return ERR_PTR(-EOPNOTSUPP);
	}

	++*pos;
	p->terminate = false;
	p->visited_all = false;
	if (p->order == BPF_CGROUP_ITER_DESCENDANTS_PRE)
		return css_next_descendant_pre(NULL, p->start_css);
	else if (p->order == BPF_CGROUP_ITER_DESCENDANTS_POST)
		return css_next_descendant_post(NULL, p->start_css);
	else if (p->order == BPF_CGROUP_ITER_CHILDREN)
		return css_next_child(NULL, p->start_css);
	else /* BPF_CGROUP_ITER_SELF_ONLY and BPF_CGROUP_ITER_ANCESTORS_UP */
		return p->start_css;
}

static int __cgroup_iter_seq_show(struct seq_file *seq,
				  struct cgroup_subsys_state *css, int in_stop);

static void cgroup_iter_seq_stop(struct seq_file *seq, void *v)
{
	struct cgroup_iter_priv *p = seq->private;

	cgroup_unlock();

	/* pass NULL to the prog for post-processing */
	if (!v) {
		__cgroup_iter_seq_show(seq, NULL, true);
		p->visited_all = true;
	}
}

static void *cgroup_iter_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
	struct cgroup_subsys_state *curr = (struct cgroup_subsys_state *)v;
	struct cgroup_iter_priv *p = seq->private;

	++*pos;
	if (p->terminate)
		return NULL;

	if (p->order == BPF_CGROUP_ITER_DESCENDANTS_PRE)
		return css_next_descendant_pre(curr, p->start_css);
	else if (p->order == BPF_CGROUP_ITER_DESCENDANTS_POST)
		return css_next_descendant_post(curr, p->start_css);
	else if (p->order == BPF_CGROUP_ITER_ANCESTORS_UP)
		return curr->parent;
	else if (p->order == BPF_CGROUP_ITER_CHILDREN)
		return css_next_child(curr, p->start_css);
	else  /* BPF_CGROUP_ITER_SELF_ONLY */
		return NULL;
}

static int __cgroup_iter_seq_show(struct seq_file *seq,
				  struct cgroup_subsys_state *css, int in_stop)
{
	struct cgroup_iter_priv *p = seq->private;
	struct bpf_iter__cgroup ctx;
	struct bpf_iter_meta meta;
	struct bpf_prog *prog;
	int ret = 0;

	/* cgroup is dead, skip this element */
	if (css && cgroup_is_dead(css->cgroup))

Annotation

Implementation Notes