Example #1
0
/*
 * set up an incoming call
 * - called in process context with IRQs enabled
 */
struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
				       struct rxrpc_connection *conn,
				       struct rxrpc_header *hdr,
				       gfp_t gfp)
{
	struct rxrpc_call *call, *candidate;
	struct rb_node **p, *parent;
	__be32 call_id;

	_enter(",%d,,%x", conn->debug_id, gfp);

	ASSERT(rx != NULL);

	candidate = rxrpc_alloc_call(gfp);
	if (!candidate)
		return ERR_PTR(-EBUSY);

	candidate->socket = rx;
	candidate->conn = conn;
	candidate->cid = hdr->cid;
	candidate->call_id = hdr->callNumber;
	candidate->channel = ntohl(hdr->cid) & RXRPC_CHANNELMASK;
	candidate->rx_data_post = 0;
	candidate->state = RXRPC_CALL_SERVER_ACCEPTING;
	if (conn->security_ix > 0)
		candidate->state = RXRPC_CALL_SERVER_SECURING;

	write_lock_bh(&conn->lock);

	/* set the channel for this call */
	call = conn->channels[candidate->channel];
	_debug("channel[%u] is %p", candidate->channel, call);
	if (call && call->call_id == hdr->callNumber) {
		/* already set; must've been a duplicate packet */
		_debug("extant call [%d]", call->state);
		ASSERTCMP(call->conn, ==, conn);

		read_lock(&call->state_lock);
		switch (call->state) {
		case RXRPC_CALL_LOCALLY_ABORTED:
			if (!test_and_set_bit(RXRPC_CALL_ABORT, &call->events))
				rxrpc_queue_call(call);
		case RXRPC_CALL_REMOTELY_ABORTED:
			read_unlock(&call->state_lock);
			goto aborted_call;
		default:
			rxrpc_get_call(call);
			read_unlock(&call->state_lock);
			goto extant_call;
		}
	}
Example #2
0
/*
 * Allocate a new client call.
 */
static struct rxrpc_call *rxrpc_alloc_client_call(struct sockaddr_rxrpc *srx,
						  gfp_t gfp)
{
	struct rxrpc_call *call;
	ktime_t now;

	_enter("");

	call = rxrpc_alloc_call(gfp);
	if (!call)
		return ERR_PTR(-ENOMEM);
	call->state = RXRPC_CALL_CLIENT_AWAIT_CONN;
	call->service_id = srx->srx_service;
	call->tx_phase = true;
	now = ktime_get_real();
	call->acks_latest_ts = now;
	call->cong_tstamp = now;

	_leave(" = %p", call);
	return call;
}
Example #3
0
/*
 * allocate a new client call and attempt to get a connection slot for it
 */
static struct rxrpc_call *rxrpc_alloc_client_call(
	struct rxrpc_sock *rx,
	struct rxrpc_transport *trans,
	struct rxrpc_conn_bundle *bundle,
	gfp_t gfp)
{
	struct rxrpc_call *call;
	int ret;

	_enter("");

	ASSERT(rx != NULL);
	ASSERT(trans != NULL);
	ASSERT(bundle != NULL);

	call = rxrpc_alloc_call(gfp);
	if (!call)
		return ERR_PTR(-ENOMEM);

	sock_hold(&rx->sk);
	call->socket = rx;
	call->rx_data_post = 1;

	ret = rxrpc_connect_call(rx, trans, bundle, call, gfp);
	if (ret < 0) {
		kmem_cache_free(rxrpc_call_jar, call);
		return ERR_PTR(ret);
	}

	spin_lock(&call->conn->trans->peer->lock);
	list_add(&call->error_link, &call->conn->trans->peer->error_targets);
	spin_unlock(&call->conn->trans->peer->lock);

	call->lifetimer.expires = jiffies + rxrpc_call_max_lifetime * HZ;
	add_timer(&call->lifetimer);

	_leave(" = %p", call);
	return call;
}
Example #4
0
/*
 * Preallocate a single service call, connection and peer and, if possible,
 * give them a user ID and attach the user's side of the ID to them.
 */
static int rxrpc_service_prealloc_one(struct rxrpc_sock *rx,
				      struct rxrpc_backlog *b,
				      rxrpc_notify_rx_t notify_rx,
				      rxrpc_user_attach_call_t user_attach_call,
				      unsigned long user_call_ID, gfp_t gfp)
{
	const void *here = __builtin_return_address(0);
	struct rxrpc_call *call;
	struct rxrpc_net *rxnet = rxrpc_net(sock_net(&rx->sk));
	int max, tmp;
	unsigned int size = RXRPC_BACKLOG_MAX;
	unsigned int head, tail, call_head, call_tail;

	max = rx->sk.sk_max_ack_backlog;
	tmp = rx->sk.sk_ack_backlog;
	if (tmp >= max) {
		_leave(" = -ENOBUFS [full %u]", max);
		return -ENOBUFS;
	}
	max -= tmp;

	/* We don't need more conns and peers than we have calls, but on the
	 * other hand, we shouldn't ever use more peers than conns or conns
	 * than calls.
	 */
	call_head = b->call_backlog_head;
	call_tail = READ_ONCE(b->call_backlog_tail);
	tmp = CIRC_CNT(call_head, call_tail, size);
	if (tmp >= max) {
		_leave(" = -ENOBUFS [enough %u]", tmp);
		return -ENOBUFS;
	}
	max = tmp + 1;

	head = b->peer_backlog_head;
	tail = READ_ONCE(b->peer_backlog_tail);
	if (CIRC_CNT(head, tail, size) < max) {
		struct rxrpc_peer *peer = rxrpc_alloc_peer(rx->local, gfp);
		if (!peer)
			return -ENOMEM;
		b->peer_backlog[head] = peer;
		smp_store_release(&b->peer_backlog_head,
				  (head + 1) & (size - 1));
	}

	head = b->conn_backlog_head;
	tail = READ_ONCE(b->conn_backlog_tail);
	if (CIRC_CNT(head, tail, size) < max) {
		struct rxrpc_connection *conn;

		conn = rxrpc_prealloc_service_connection(rxnet, gfp);
		if (!conn)
			return -ENOMEM;
		b->conn_backlog[head] = conn;
		smp_store_release(&b->conn_backlog_head,
				  (head + 1) & (size - 1));

		trace_rxrpc_conn(conn, rxrpc_conn_new_service,
				 atomic_read(&conn->usage), here);
	}

	/* Now it gets complicated, because calls get registered with the
	 * socket here, particularly if a user ID is preassigned by the user.
	 */
	call = rxrpc_alloc_call(gfp);
	if (!call)
		return -ENOMEM;
	call->flags |= (1 << RXRPC_CALL_IS_SERVICE);
	call->state = RXRPC_CALL_SERVER_PREALLOC;

	trace_rxrpc_call(call, rxrpc_call_new_service,
			 atomic_read(&call->usage),
			 here, (const void *)user_call_ID);

	write_lock(&rx->call_lock);
	if (user_attach_call) {
		struct rxrpc_call *xcall;
		struct rb_node *parent, **pp;

		/* Check the user ID isn't already in use */
		pp = &rx->calls.rb_node;
		parent = NULL;
		while (*pp) {
			parent = *pp;
			xcall = rb_entry(parent, struct rxrpc_call, sock_node);
			if (user_call_ID < call->user_call_ID)
				pp = &(*pp)->rb_left;
			else if (user_call_ID > call->user_call_ID)
				pp = &(*pp)->rb_right;
			else
				goto id_in_use;
		}

		call->user_call_ID = user_call_ID;
		call->notify_rx = notify_rx;
		rxrpc_get_call(call, rxrpc_call_got_kernel);
		user_attach_call(call, user_call_ID);
		rxrpc_get_call(call, rxrpc_call_got_userid);
		rb_link_node(&call->sock_node, parent, pp);
		rb_insert_color(&call->sock_node, &rx->calls);
		set_bit(RXRPC_CALL_HAS_USERID, &call->flags);
	}

	list_add(&call->sock_link, &rx->sock_calls);

	write_unlock(&rx->call_lock);

	write_lock(&rxnet->call_lock);
	list_add_tail(&call->link, &rxnet->calls);
	write_unlock(&rxnet->call_lock);

	b->call_backlog[call_head] = call;
	smp_store_release(&b->call_backlog_head, (call_head + 1) & (size - 1));
	_leave(" = 0 [%d -> %lx]", call->debug_id, user_call_ID);
	return 0;

id_in_use:
	write_unlock(&rx->call_lock);
	rxrpc_cleanup_call(call);
	_leave(" = -EBADSLT");
	return -EBADSLT;
}