kernel/bpf/bpf_local_storage.c

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

File Facts

System
Linux kernel
Corpus path
kernel/bpf/bpf_local_storage.c
Extension
.c
Size
25350 bytes
Lines
878
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

if (value) {
			/* No need to call check_and_init_map_value as memory is zero init */
			copy_map_value(&smap->map, SDATA(selem)->data, value);
			if (swap_uptrs)
				bpf_obj_swap_uptrs(smap->map.record, SDATA(selem)->data, value);
		}
		return selem;
	}

	mem_uncharge(smap, owner, smap->elem_size);

	return NULL;
}

static void bpf_local_storage_free_trace_rcu(struct rcu_head *rcu)
{
	struct bpf_local_storage *local_storage;

	/*
	 * RCU Tasks Trace grace period implies RCU grace period, do
	 * kfree() directly.
	 */
	local_storage = container_of(rcu, struct bpf_local_storage, rcu);
	kfree(local_storage);
}

static void bpf_local_storage_free(struct bpf_local_storage *local_storage,
				   bool reuse_now)
{
	if (!local_storage)
		return;

	if (reuse_now) {
		kfree_rcu(local_storage, rcu);
		return;
	}

	call_rcu_tasks_trace(&local_storage->rcu,
			     bpf_local_storage_free_trace_rcu);
}

static void bpf_selem_free_trace_rcu(struct rcu_head *rcu)
{
	struct bpf_local_storage_elem *selem;
	struct bpf_local_storage_map *smap;

	selem = container_of(rcu, struct bpf_local_storage_elem, rcu);
	/* The bpf_local_storage_map_free will wait for rcu_barrier */
	smap = rcu_dereference_check(SDATA(selem)->smap, 1);

	if (smap)
		bpf_obj_free_fields(smap->map.record, SDATA(selem)->data);
	/*
	 * RCU Tasks Trace grace period implies RCU grace period, do
	 * kfree() directly.
	 */
	kfree(selem);
}

void bpf_selem_free(struct bpf_local_storage_elem *selem,
		    bool reuse_now)
{
	struct bpf_local_storage_map *smap;

	smap = rcu_dereference_check(SDATA(selem)->smap, 1);

	if (reuse_now) {
		if (smap)
			bpf_obj_free_fields(smap->map.record, SDATA(selem)->data);
		kfree_rcu(selem, rcu);
		return;
	}

	call_rcu_tasks_trace(&selem->rcu, bpf_selem_free_trace_rcu);
}

static void bpf_selem_free_list(struct hlist_head *list, bool reuse_now)
{
	struct bpf_local_storage_elem *selem;
	struct hlist_node *n;

	/* The "_safe" iteration is needed.
	 * The loop is not removing the selem from the list
	 * but bpf_selem_free will use the selem->rcu_head
	 * which is union-ized with the selem->free_node.
	 */
	hlist_for_each_entry_safe(selem, n, list, free_node)
		bpf_selem_free(selem, reuse_now);
}

Annotation

Implementation Notes