net/rxrpc/conn_client.c

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

File Facts

System
Linux kernel
Corpus path
net/rxrpc/conn_client.c
Extension
.c
Size
23466 bytes
Lines
834
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

idr_for_each_entry(&local->conn_ids, conn, id) {
			pr_err("AF_RXRPC: Leaked client conn %p {%d}\n",
			       conn, refcount_read(&conn->ref));
		}
		BUG();
	}

	idr_destroy(&local->conn_ids);
}

/*
 * Allocate a connection bundle.
 */
static struct rxrpc_bundle *rxrpc_alloc_bundle(struct rxrpc_call *call,
					       gfp_t gfp)
{
	static atomic_t rxrpc_bundle_id;
	struct rxrpc_bundle *bundle;

	bundle = kzalloc_obj(*bundle, gfp);
	if (bundle) {
		bundle->local		= call->local;
		bundle->peer		= rxrpc_get_peer(call->peer, rxrpc_peer_get_bundle);
		bundle->key		= key_get(call->key);
		bundle->security	= call->security;
		bundle->exclusive	= test_bit(RXRPC_CALL_EXCLUSIVE, &call->flags);
		bundle->upgrade		= test_bit(RXRPC_CALL_UPGRADE, &call->flags);
		bundle->service_id	= call->dest_srx.srx_service;
		bundle->security_level	= call->security_level;
		bundle->debug_id	= atomic_inc_return(&rxrpc_bundle_id);
		refcount_set(&bundle->ref, 1);
		atomic_set(&bundle->active, 1);
		INIT_LIST_HEAD(&bundle->waiting_calls);
		trace_rxrpc_bundle(bundle->debug_id, 1, rxrpc_bundle_new);

		write_lock(&bundle->local->rxnet->conn_lock);
		list_add_tail(&bundle->proc_link, &bundle->local->rxnet->bundle_proc_list);
		write_unlock(&bundle->local->rxnet->conn_lock);
	}
	return bundle;
}

struct rxrpc_bundle *rxrpc_get_bundle(struct rxrpc_bundle *bundle,
				      enum rxrpc_bundle_trace why)
{
	int r;

	__refcount_inc(&bundle->ref, &r);
	trace_rxrpc_bundle(bundle->debug_id, r + 1, why);
	return bundle;
}

static void rxrpc_free_bundle(struct rxrpc_bundle *bundle)
{
	trace_rxrpc_bundle(bundle->debug_id, refcount_read(&bundle->ref),
			   rxrpc_bundle_free);
	write_lock(&bundle->local->rxnet->conn_lock);
	list_del(&bundle->proc_link);
	write_unlock(&bundle->local->rxnet->conn_lock);
	rxrpc_put_peer(bundle->peer, rxrpc_peer_put_bundle);
	key_put(bundle->key);
	kfree(bundle);
}

void rxrpc_put_bundle(struct rxrpc_bundle *bundle, enum rxrpc_bundle_trace why)
{
	unsigned int id;
	bool dead;
	int r;

	if (bundle) {
		id = bundle->debug_id;
		dead = __refcount_dec_and_test(&bundle->ref, &r);
		trace_rxrpc_bundle(id, r - 1, why);
		if (dead)
			rxrpc_free_bundle(bundle);
	}
}

/*
 * Get rid of outstanding client connection preallocations when a local
 * endpoint is destroyed.
 */
void rxrpc_purge_client_connections(struct rxrpc_local *local)
{
	rxrpc_destroy_client_conn_ids(local);
}

/*
 * Allocate a client connection.

Annotation

Implementation Notes