net/core/sysctl_net_core.c

Source file repositories/reference/linux-study-clean/net/core/sysctl_net_core.c

File Facts

System
Linux kernel
Corpus path
net/core/sysctl_net_core.c
Extension
.c
Size
20393 bytes
Lines
850
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

Networking stack implementation surface: socket APIs, protocol dispatch, packet flow, routing, filtering, and network namespaces.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!mask) {
			mask = kzalloc(cpumask_size(), GFP_KERNEL);
			net->core.rps_default_mask = mask;
		}
		err = -ENOMEM;
		if (!mask)
			goto done;

		err = cpumask_parse(buffer, mask);
		if (err)
			goto done;

		err = rps_cpumask_housekeeping(mask);
		if (err)
			goto done;
	} else {
		err = dump_cpumask(buffer, lenp, ppos,
				   mask ?: cpu_none_mask);
	}

done:
	mutex_unlock(&rps_default_mask_mutex);
	return err;
}

static int rps_sock_flow_sysctl(const struct ctl_table *table, int write,
				void *buffer, size_t *lenp, loff_t *ppos)
{
	struct rps_sock_flow_table *o_sock_table, *sock_table;
	static DEFINE_MUTEX(sock_flow_mutex);
	rps_tag_ptr o_tag_ptr, tag_ptr;
	unsigned int orig_size, size;
	struct ctl_table tmp = {
		.data = &size,
		.maxlen = sizeof(size),
		.mode = table->mode
	};
	void *tofree = NULL;
	int ret, i;
	u8 log;

	mutex_lock(&sock_flow_mutex);

	o_tag_ptr = tag_ptr = net_hotdata.rps_sock_flow_table;

	size = o_tag_ptr ? rps_tag_to_mask(o_tag_ptr) + 1 : 0;
	o_sock_table = rps_tag_to_table(o_tag_ptr);
	orig_size = size;

	ret = proc_dointvec(&tmp, write, buffer, lenp, ppos);

	if (!write)
		goto unlock;

	if (size) {
		if (size > 1<<29) {
			/* Enforce limit to prevent overflow */
			mutex_unlock(&sock_flow_mutex);
			return -EINVAL;
		}
		sock_table = o_sock_table;
		size = roundup_pow_of_two(size);
		if (size != orig_size) {
			sock_table = vmalloc_huge(size * sizeof(*sock_table),
						  GFP_KERNEL);
			if (!sock_table) {
				mutex_unlock(&sock_flow_mutex);
				return -ENOMEM;
			}
			net_hotdata.rps_cpu_mask =
				roundup_pow_of_two(nr_cpu_ids) - 1;
			log = ilog2(size);
			tag_ptr = (rps_tag_ptr)sock_table | log;
		}

		for (i = 0; i < size; i++)
			sock_table[i].ent = RPS_NO_CPU;
	} else {
		sock_table = NULL;
		tag_ptr = 0UL;
	}
	if (tag_ptr != o_tag_ptr) {
		smp_store_release(&net_hotdata.rps_sock_flow_table, tag_ptr);
		if (sock_table) {
			static_branch_inc(&rps_needed);
			static_branch_inc(&rfs_needed);
		}
		if (o_sock_table) {
			static_branch_dec(&rps_needed);
			static_branch_dec(&rfs_needed);

Annotation

Implementation Notes