net/unix/unix_bpf.c

Source file repositories/reference/linux-study-clean/net/unix/unix_bpf.c

File Facts

System
Linux kernel
Corpus path
net/unix/unix_bpf.c
Extension
.c
Size
5597 bytes
Lines
206
Domain
Networking Core
Bucket
Sockets, Protocols, Packet Path, And Network Policy
Inferred role
Networking Core: implementation source
Status
source 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

sk_psock_queue_empty(psock)) {
		mutex_unlock(&u->iolock);
		sk_psock_put(sk, psock);
		return __unix_recvmsg(sk, msg, len, flags);
	}

msg_bytes_ready:
	copied = sk_msg_recvmsg(sk, psock, msg, len, flags);
	if (!copied) {
		long timeo;
		int data;

		timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
		data = unix_msg_wait_data(sk, psock, timeo);
		if (data) {
			if (!sk_psock_queue_empty(psock))
				goto msg_bytes_ready;
			mutex_unlock(&u->iolock);
			sk_psock_put(sk, psock);
			return __unix_recvmsg(sk, msg, len, flags);
		}
		copied = -EAGAIN;
	}
	mutex_unlock(&u->iolock);
	sk_psock_put(sk, psock);
	return copied;
}

static struct proto *unix_dgram_prot_saved __read_mostly;
static DEFINE_SPINLOCK(unix_dgram_prot_lock);
static struct proto unix_dgram_bpf_prot;

static struct proto *unix_stream_prot_saved __read_mostly;
static DEFINE_SPINLOCK(unix_stream_prot_lock);
static struct proto unix_stream_bpf_prot;

static void unix_dgram_bpf_rebuild_protos(struct proto *prot, const struct proto *base)
{
	*prot        = *base;
	prot->close  = sock_map_close;
	prot->recvmsg = unix_bpf_recvmsg;
	prot->sock_is_readable = sk_msg_is_readable;
}

static void unix_stream_bpf_rebuild_protos(struct proto *prot,
					   const struct proto *base)
{
	*prot        = *base;
	prot->close  = sock_map_close;
	prot->recvmsg = unix_bpf_recvmsg;
	prot->sock_is_readable = sk_msg_is_readable;
	prot->unhash  = sock_map_unhash;
}

static void unix_dgram_bpf_check_needs_rebuild(struct proto *ops)
{
	if (unlikely(ops != smp_load_acquire(&unix_dgram_prot_saved))) {
		spin_lock_bh(&unix_dgram_prot_lock);
		if (likely(ops != unix_dgram_prot_saved)) {
			unix_dgram_bpf_rebuild_protos(&unix_dgram_bpf_prot, ops);
			smp_store_release(&unix_dgram_prot_saved, ops);
		}
		spin_unlock_bh(&unix_dgram_prot_lock);
	}
}

static void unix_stream_bpf_check_needs_rebuild(struct proto *ops)
{
	if (unlikely(ops != smp_load_acquire(&unix_stream_prot_saved))) {
		spin_lock_bh(&unix_stream_prot_lock);
		if (likely(ops != unix_stream_prot_saved)) {
			unix_stream_bpf_rebuild_protos(&unix_stream_bpf_prot, ops);
			smp_store_release(&unix_stream_prot_saved, ops);
		}
		spin_unlock_bh(&unix_stream_prot_lock);
	}
}

int unix_dgram_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
{
	if (sk->sk_type != SOCK_DGRAM)
		return -EOPNOTSUPP;

	if (restore) {
		sk->sk_write_space = psock->saved_write_space;
		sock_replace_proto(sk, psock->sk_proto);
		return 0;
	}

	unix_dgram_bpf_check_needs_rebuild(psock->sk_proto);

Annotation

Implementation Notes