net/rxrpc/local_object.c

Source file repositories/reference/linux-study-clean/net/rxrpc/local_object.c

File Facts

System
Linux kernel
Corpus path
net/rxrpc/local_object.c
Extension
.c
Size
12560 bytes
Lines
487
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

if (srx->srx_service) {
			local = NULL;
			goto addr_in_use;
		}

		/* Found a match.  We want to replace a dying object.
		 * Attempting to bind the transport socket may still fail if
		 * we're attempting to use a local address that the dying
		 * object is still using.
		 */
		if (!rxrpc_use_local(local, rxrpc_local_use_lookup))
			break;

		goto found;
	}

	local = rxrpc_alloc_local(net, srx);
	if (!local)
		goto nomem;

	ret = rxrpc_open_socket(local, net);
	if (ret < 0)
		goto sock_error;

	if (cursor) {
		hlist_replace_rcu(cursor, &local->link);
		cursor->pprev = NULL;
	} else {
		hlist_add_head_rcu(&local->link, &rxnet->local_endpoints);
	}

found:
	mutex_unlock(&rxnet->local_mutex);
	_leave(" = %p", local);
	return local;

nomem:
	ret = -ENOMEM;
sock_error:
	mutex_unlock(&rxnet->local_mutex);
	if (local)
		call_rcu(&local->rcu, rxrpc_local_rcu);
	_leave(" = %d", ret);
	return ERR_PTR(ret);

addr_in_use:
	mutex_unlock(&rxnet->local_mutex);
	_leave(" = -EADDRINUSE");
	return ERR_PTR(-EADDRINUSE);
}

/*
 * Get a ref on a local endpoint.
 */
struct rxrpc_local *rxrpc_get_local(struct rxrpc_local *local,
				    enum rxrpc_local_trace why)
{
	int r, u;

	u = atomic_read(&local->active_users);
	__refcount_inc(&local->ref, &r);
	trace_rxrpc_local(local->debug_id, why, r + 1, u);
	return local;
}

/*
 * Get a ref on a local endpoint unless its usage has already reached 0.
 */
struct rxrpc_local *rxrpc_get_local_maybe(struct rxrpc_local *local,
					  enum rxrpc_local_trace why)
{
	int r, u;

	if (local && __refcount_inc_not_zero(&local->ref, &r)) {
		u = atomic_read(&local->active_users);
		trace_rxrpc_local(local->debug_id, why, r + 1, u);
		return local;
	}

	return NULL;
}

/*
 * Drop a ref on a local endpoint.
 */
void rxrpc_put_local(struct rxrpc_local *local, enum rxrpc_local_trace why)
{
	unsigned int debug_id;
	bool dead;
	int r, u;

Annotation

Implementation Notes