mirror of
https://github.com/torvalds/linux.git
synced 2024-11-30 08:01:59 +00:00
RxRPC development
-----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEqG5UsNXhtOCrfGQP+7dXa6fLC2sFAl9X6OcACgkQ+7dXa6fL C2s3Dg/9FyGc4Na08Rc5q8K2TSVhsx1dqBscf/t3gIulCaShbbRRFAb4UecrxOTn GV/eekGVejh/a+cCCVjMGFNP2FxyW9WTFoxINaTFp+bdGURdo8MOJTCTc/1Sgflb M7s+2mubYHfHLw4/VUR8tCAhODPC0JUTiDnkZqXZxA8SizUPAkNZySH7OfgW9PjA PFy/lB5IbR9mU64FWMALU2Rs09Gav/KRA+/X8fyE80i1MgYAz82U7x/EQa0XCmdR B61VObK8z9/o7Juu8GzM01k8b5zoWraHph0e/BdFaEN1KY5phPdPyerGa67GcgwX imnvcW4N75QBlHhE8C34eKnbIaNIPUR9ZNJdEgnA29CPOtP87rSPaeNNn4ISyF8r TnGGpAeBHMahrY2dhKK0lIv9Gbwd1j+OAlrL9O+j4KTaKZc9CqnXLzKp3ugXDeex RzHptlsc0I0bQ8ZeCA1jS9OFmypaRtYabE9DSrPS2Epbb8SdcCE4ZTXabB3A/ytk HBle/MfGcQN9yFAJpDJ/0Bj6PmUZgohVS7qMrZi+JV99vkNPebxxxEvoiM5il2km 3DXPrD3rv9/qg8F6xVHYkWXVxZk6FCMe8/sg9VKUfOhmwEiFBkXv2IwTP/s3nN0g 0h46rXAzjWXY8YMZzsgBHVe/Vp2MfJGsx9hyO1JppRbxGb1PVeU= =f+/X -----END PGP SIGNATURE----- Merge tag 'rxrpc-next-20200908' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs David Howells says: ==================== rxrpc: Allow more calls to same peer Here are some development patches for AF_RXRPC that allow more simultaneous calls to be made to the same peer with the same security parameters. The current code allows a maximum of 4 simultaneous calls, which limits the afs filesystem to that many simultaneous threads. This increases the limit to 16. To make this work, the way client connections are limited has to be changed (incoming call/connection limits are unaffected) as the current code depends on queuing calls on a connection and then pushing the connection through a queue. The limit is on the number of available connections. This is changed such that there's a limit[*] on the total number of calls systemwide across all namespaces, but the limit on the number of client connections is removed. Once a call is allowed to proceed, it finds a bundle of connections and tries to grab a call slot. If there's a spare call slot, fine, otherwise it will wait. If there's already a waiter, it will try to create another connection in the bundle, unless the limit of 4 is reached (4 calls per connection, giving 16). A number of things throttle someone trying to set up endless connections: - Calls that fail immediately have their conns deleted immediately, - Calls that don't fail immediately have to wait for a timeout, - Connections normally get automatically reaped if they haven't been used for 2m, but this is sped up to 2s if the number of connections rises over 900. This number is tunable by sysctl. [*] Technically two limits - kernel sockets and userspace rxrpc sockets are accounted separately. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
56bbc22d83
@ -68,21 +68,14 @@ enum rxrpc_client_trace {
|
||||
rxrpc_client_chan_activate,
|
||||
rxrpc_client_chan_disconnect,
|
||||
rxrpc_client_chan_pass,
|
||||
rxrpc_client_chan_unstarted,
|
||||
rxrpc_client_chan_wait_failed,
|
||||
rxrpc_client_cleanup,
|
||||
rxrpc_client_count,
|
||||
rxrpc_client_discard,
|
||||
rxrpc_client_duplicate,
|
||||
rxrpc_client_exposed,
|
||||
rxrpc_client_replace,
|
||||
rxrpc_client_to_active,
|
||||
rxrpc_client_to_culled,
|
||||
rxrpc_client_to_idle,
|
||||
rxrpc_client_to_inactive,
|
||||
rxrpc_client_to_upgrade,
|
||||
rxrpc_client_to_waiting,
|
||||
rxrpc_client_uncount,
|
||||
};
|
||||
|
||||
enum rxrpc_call_trace {
|
||||
@ -271,29 +264,14 @@ enum rxrpc_tx_point {
|
||||
EM(rxrpc_client_chan_activate, "ChActv") \
|
||||
EM(rxrpc_client_chan_disconnect, "ChDisc") \
|
||||
EM(rxrpc_client_chan_pass, "ChPass") \
|
||||
EM(rxrpc_client_chan_unstarted, "ChUnst") \
|
||||
EM(rxrpc_client_chan_wait_failed, "ChWtFl") \
|
||||
EM(rxrpc_client_cleanup, "Clean ") \
|
||||
EM(rxrpc_client_count, "Count ") \
|
||||
EM(rxrpc_client_discard, "Discar") \
|
||||
EM(rxrpc_client_duplicate, "Duplic") \
|
||||
EM(rxrpc_client_exposed, "Expose") \
|
||||
EM(rxrpc_client_replace, "Replac") \
|
||||
EM(rxrpc_client_to_active, "->Actv") \
|
||||
EM(rxrpc_client_to_culled, "->Cull") \
|
||||
EM(rxrpc_client_to_idle, "->Idle") \
|
||||
EM(rxrpc_client_to_inactive, "->Inac") \
|
||||
EM(rxrpc_client_to_upgrade, "->Upgd") \
|
||||
EM(rxrpc_client_to_waiting, "->Wait") \
|
||||
E_(rxrpc_client_uncount, "Uncoun")
|
||||
|
||||
#define rxrpc_conn_cache_states \
|
||||
EM(RXRPC_CONN_CLIENT_INACTIVE, "Inac") \
|
||||
EM(RXRPC_CONN_CLIENT_WAITING, "Wait") \
|
||||
EM(RXRPC_CONN_CLIENT_ACTIVE, "Actv") \
|
||||
EM(RXRPC_CONN_CLIENT_UPGRADE, "Upgd") \
|
||||
EM(RXRPC_CONN_CLIENT_CULLED, "Cull") \
|
||||
E_(RXRPC_CONN_CLIENT_IDLE, "Idle") \
|
||||
E_(rxrpc_client_to_idle, "->Idle")
|
||||
|
||||
#define rxrpc_call_traces \
|
||||
EM(rxrpc_call_connected, "CON") \
|
||||
@ -594,23 +572,20 @@ TRACE_EVENT(rxrpc_client,
|
||||
__field(int, channel )
|
||||
__field(int, usage )
|
||||
__field(enum rxrpc_client_trace, op )
|
||||
__field(enum rxrpc_conn_cache_state, cs )
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->conn = conn->debug_id;
|
||||
__entry->conn = conn ? conn->debug_id : 0;
|
||||
__entry->channel = channel;
|
||||
__entry->usage = atomic_read(&conn->usage);
|
||||
__entry->usage = conn ? atomic_read(&conn->usage) : -2;
|
||||
__entry->op = op;
|
||||
__entry->cid = conn->proto.cid;
|
||||
__entry->cs = conn->cache_state;
|
||||
),
|
||||
|
||||
TP_printk("C=%08x h=%2d %s %s i=%08x u=%d",
|
||||
TP_printk("C=%08x h=%2d %s i=%08x u=%d",
|
||||
__entry->conn,
|
||||
__entry->channel,
|
||||
__print_symbolic(__entry->op, rxrpc_client_traces),
|
||||
__print_symbolic(__entry->cs, rxrpc_conn_cache_states),
|
||||
__entry->cid,
|
||||
__entry->usage)
|
||||
);
|
||||
|
@ -308,9 +308,10 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
|
||||
key = NULL; /* a no-security key */
|
||||
|
||||
memset(&p, 0, sizeof(p));
|
||||
p.user_call_ID = user_call_ID;
|
||||
p.tx_total_len = tx_total_len;
|
||||
p.interruptibility = interruptibility;
|
||||
p.user_call_ID = user_call_ID;
|
||||
p.tx_total_len = tx_total_len;
|
||||
p.interruptibility = interruptibility;
|
||||
p.kernel = true;
|
||||
|
||||
memset(&cp, 0, sizeof(cp));
|
||||
cp.local = rx->local;
|
||||
|
@ -76,14 +76,12 @@ struct rxrpc_net {
|
||||
struct work_struct service_conn_reaper;
|
||||
struct timer_list service_conn_reap_timer;
|
||||
|
||||
unsigned int nr_client_conns;
|
||||
unsigned int nr_active_client_conns;
|
||||
bool kill_all_client_conns;
|
||||
bool live;
|
||||
|
||||
bool kill_all_client_conns;
|
||||
atomic_t nr_client_conns;
|
||||
spinlock_t client_conn_cache_lock; /* Lock for ->*_client_conns */
|
||||
spinlock_t client_conn_discard_lock; /* Prevent multiple discarders */
|
||||
struct list_head waiting_client_conns;
|
||||
struct list_head active_client_conns;
|
||||
struct list_head idle_client_conns;
|
||||
struct work_struct client_conn_reaper;
|
||||
struct timer_list client_conn_reap_timer;
|
||||
@ -275,8 +273,8 @@ struct rxrpc_local {
|
||||
struct rw_semaphore defrag_sem; /* control re-enablement of IP DF bit */
|
||||
struct sk_buff_head reject_queue; /* packets awaiting rejection */
|
||||
struct sk_buff_head event_queue; /* endpoint event packets awaiting processing */
|
||||
struct rb_root client_conns; /* Client connections by socket params */
|
||||
spinlock_t client_conns_lock; /* Lock for client_conns */
|
||||
struct rb_root client_bundles; /* Client connection bundles by socket params */
|
||||
spinlock_t client_bundles_lock; /* Lock for client_bundles */
|
||||
spinlock_t lock; /* access lock */
|
||||
rwlock_t services_lock; /* lock for services list */
|
||||
int debug_id; /* debug ID for printks */
|
||||
@ -353,10 +351,7 @@ struct rxrpc_conn_parameters {
|
||||
enum rxrpc_conn_flag {
|
||||
RXRPC_CONN_HAS_IDR, /* Has a client conn ID assigned */
|
||||
RXRPC_CONN_IN_SERVICE_CONNS, /* Conn is in peer->service_conns */
|
||||
RXRPC_CONN_IN_CLIENT_CONNS, /* Conn is in local->client_conns */
|
||||
RXRPC_CONN_EXPOSED, /* Conn has extra ref for exposure */
|
||||
RXRPC_CONN_DONT_REUSE, /* Don't reuse this connection */
|
||||
RXRPC_CONN_COUNTED, /* Counted by rxrpc_nr_client_conns */
|
||||
RXRPC_CONN_PROBING_FOR_UPGRADE, /* Probing for service upgrade */
|
||||
RXRPC_CONN_FINAL_ACK_0, /* Need final ACK for channel 0 */
|
||||
RXRPC_CONN_FINAL_ACK_1, /* Need final ACK for channel 1 */
|
||||
@ -376,19 +371,6 @@ enum rxrpc_conn_event {
|
||||
RXRPC_CONN_EV_CHALLENGE, /* Send challenge packet */
|
||||
};
|
||||
|
||||
/*
|
||||
* The connection cache state.
|
||||
*/
|
||||
enum rxrpc_conn_cache_state {
|
||||
RXRPC_CONN_CLIENT_INACTIVE, /* Conn is not yet listed */
|
||||
RXRPC_CONN_CLIENT_WAITING, /* Conn is on wait list, waiting for capacity */
|
||||
RXRPC_CONN_CLIENT_ACTIVE, /* Conn is on active list, doing calls */
|
||||
RXRPC_CONN_CLIENT_UPGRADE, /* Conn is on active list, probing for upgrade */
|
||||
RXRPC_CONN_CLIENT_CULLED, /* Conn is culled and delisted, doing calls */
|
||||
RXRPC_CONN_CLIENT_IDLE, /* Conn is on idle list, doing mostly nothing */
|
||||
RXRPC_CONN__NR_CACHE_STATES
|
||||
};
|
||||
|
||||
/*
|
||||
* The connection protocol state.
|
||||
*/
|
||||
@ -404,6 +386,23 @@ enum rxrpc_conn_proto_state {
|
||||
RXRPC_CONN__NR_STATES
|
||||
};
|
||||
|
||||
/*
|
||||
* RxRPC client connection bundle.
|
||||
*/
|
||||
struct rxrpc_bundle {
|
||||
struct rxrpc_conn_parameters params;
|
||||
atomic_t usage;
|
||||
unsigned int debug_id;
|
||||
bool try_upgrade; /* True if the bundle is attempting upgrade */
|
||||
bool alloc_conn; /* True if someone's getting a conn */
|
||||
unsigned short alloc_error; /* Error from last conn allocation */
|
||||
spinlock_t channel_lock;
|
||||
struct rb_node local_node; /* Node in local->client_conns */
|
||||
struct list_head waiting_calls; /* Calls waiting for channels */
|
||||
unsigned long avail_chans; /* Mask of available channels */
|
||||
struct rxrpc_connection *conns[4]; /* The connections in the bundle (max 4) */
|
||||
};
|
||||
|
||||
/*
|
||||
* RxRPC connection definition
|
||||
* - matched by { local, peer, epoch, conn_id, direction }
|
||||
@ -417,10 +416,7 @@ struct rxrpc_connection {
|
||||
struct rcu_head rcu;
|
||||
struct list_head cache_link;
|
||||
|
||||
spinlock_t channel_lock;
|
||||
unsigned char active_chans; /* Mask of active channels */
|
||||
#define RXRPC_ACTIVE_CHANS_MASK ((1 << RXRPC_MAXCALLS) - 1)
|
||||
struct list_head waiting_calls; /* Calls waiting for channels */
|
||||
unsigned char act_chans; /* Mask of active channels */
|
||||
struct rxrpc_channel {
|
||||
unsigned long final_ack_at; /* Time at which to issue final ACK */
|
||||
struct rxrpc_call __rcu *call; /* Active call */
|
||||
@ -437,10 +433,8 @@ struct rxrpc_connection {
|
||||
|
||||
struct timer_list timer; /* Conn event timer */
|
||||
struct work_struct processor; /* connection event processor */
|
||||
union {
|
||||
struct rb_node client_node; /* Node in local->client_conns */
|
||||
struct rb_node service_node; /* Node in peer->service_conns */
|
||||
};
|
||||
struct rxrpc_bundle *bundle; /* Client connection bundle */
|
||||
struct rb_node service_node; /* Node in peer->service_conns */
|
||||
struct list_head proc_link; /* link in procfs list */
|
||||
struct list_head link; /* link in master connection list */
|
||||
struct sk_buff_head rx_queue; /* received conn-level packets */
|
||||
@ -452,7 +446,6 @@ struct rxrpc_connection {
|
||||
unsigned long events;
|
||||
unsigned long idle_timestamp; /* Time at which last became idle */
|
||||
spinlock_t state_lock; /* state-change lock */
|
||||
enum rxrpc_conn_cache_state cache_state;
|
||||
enum rxrpc_conn_proto_state state; /* current state of connection */
|
||||
u32 abort_code; /* Abort code of connection abort */
|
||||
int debug_id; /* debug ID for printks */
|
||||
@ -464,6 +457,7 @@ struct rxrpc_connection {
|
||||
u8 security_size; /* security header size */
|
||||
u8 security_ix; /* security type */
|
||||
u8 out_clientflag; /* RXRPC_CLIENT_INITIATED if we are client */
|
||||
u8 bundle_shift; /* Index into bundle->avail_chans */
|
||||
short error; /* Local error code */
|
||||
};
|
||||
|
||||
@ -493,6 +487,8 @@ enum rxrpc_call_flag {
|
||||
RXRPC_CALL_RX_HEARD, /* The peer responded at least once to this call */
|
||||
RXRPC_CALL_RX_UNDERRUN, /* Got data underrun */
|
||||
RXRPC_CALL_DISCONNECTED, /* The call has been disconnected */
|
||||
RXRPC_CALL_KERNEL, /* The call was made by the kernel */
|
||||
RXRPC_CALL_UPGRADE, /* Service upgrade was requested for the call */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -577,7 +573,7 @@ struct rxrpc_call {
|
||||
struct work_struct processor; /* Event processor */
|
||||
rxrpc_notify_rx_t notify_rx; /* kernel service Rx notification function */
|
||||
struct list_head link; /* link in master call list */
|
||||
struct list_head chan_wait_link; /* Link in conn->waiting_calls */
|
||||
struct list_head chan_wait_link; /* Link in conn->bundle->waiting_calls */
|
||||
struct hlist_node error_link; /* link in error distribution list */
|
||||
struct list_head accept_link; /* Link in rx->acceptq */
|
||||
struct list_head recvmsg_link; /* Link in rx->recvmsg_q */
|
||||
@ -727,6 +723,7 @@ struct rxrpc_call_params {
|
||||
u32 normal; /* Max time since last call packet (msec) */
|
||||
} timeouts;
|
||||
u8 nr_timeouts; /* Number of timeouts specified */
|
||||
bool kernel; /* T if kernel is making the call */
|
||||
enum rxrpc_interruptibility interruptibility; /* How is interruptible is the call? */
|
||||
};
|
||||
|
||||
@ -815,18 +812,19 @@ static inline bool rxrpc_is_client_call(const struct rxrpc_call *call)
|
||||
/*
|
||||
* conn_client.c
|
||||
*/
|
||||
extern unsigned int rxrpc_max_client_connections;
|
||||
extern unsigned int rxrpc_reap_client_connections;
|
||||
extern unsigned long rxrpc_conn_idle_client_expiry;
|
||||
extern unsigned long rxrpc_conn_idle_client_fast_expiry;
|
||||
extern struct idr rxrpc_client_conn_ids;
|
||||
|
||||
void rxrpc_destroy_client_conn_ids(void);
|
||||
struct rxrpc_bundle *rxrpc_get_bundle(struct rxrpc_bundle *);
|
||||
void rxrpc_put_bundle(struct rxrpc_bundle *);
|
||||
int rxrpc_connect_call(struct rxrpc_sock *, struct rxrpc_call *,
|
||||
struct rxrpc_conn_parameters *, struct sockaddr_rxrpc *,
|
||||
gfp_t);
|
||||
void rxrpc_expose_client_call(struct rxrpc_call *);
|
||||
void rxrpc_disconnect_client_call(struct rxrpc_call *);
|
||||
void rxrpc_disconnect_client_call(struct rxrpc_bundle *, struct rxrpc_call *);
|
||||
void rxrpc_put_client_conn(struct rxrpc_connection *);
|
||||
void rxrpc_discard_expired_client_conns(struct work_struct *);
|
||||
void rxrpc_destroy_all_client_connections(struct rxrpc_net *);
|
||||
@ -852,7 +850,7 @@ void rxrpc_disconnect_call(struct rxrpc_call *);
|
||||
void rxrpc_kill_connection(struct rxrpc_connection *);
|
||||
bool rxrpc_queue_conn(struct rxrpc_connection *);
|
||||
void rxrpc_see_connection(struct rxrpc_connection *);
|
||||
void rxrpc_get_connection(struct rxrpc_connection *);
|
||||
struct rxrpc_connection *rxrpc_get_connection(struct rxrpc_connection *);
|
||||
struct rxrpc_connection *rxrpc_get_connection_maybe(struct rxrpc_connection *);
|
||||
void rxrpc_put_service_conn(struct rxrpc_connection *);
|
||||
void rxrpc_service_connection_reaper(struct work_struct *);
|
||||
|
@ -41,6 +41,11 @@ const char *const rxrpc_call_completions[NR__RXRPC_CALL_COMPLETIONS] = {
|
||||
|
||||
struct kmem_cache *rxrpc_call_jar;
|
||||
|
||||
static struct semaphore rxrpc_call_limiter =
|
||||
__SEMAPHORE_INITIALIZER(rxrpc_call_limiter, 1000);
|
||||
static struct semaphore rxrpc_kernel_call_limiter =
|
||||
__SEMAPHORE_INITIALIZER(rxrpc_kernel_call_limiter, 1000);
|
||||
|
||||
static void rxrpc_call_timer_expired(struct timer_list *t)
|
||||
{
|
||||
struct rxrpc_call *call = from_timer(call, t, timer);
|
||||
@ -209,6 +214,34 @@ static void rxrpc_start_call_timer(struct rxrpc_call *call)
|
||||
call->timer.expires = now;
|
||||
}
|
||||
|
||||
/*
|
||||
* Wait for a call slot to become available.
|
||||
*/
|
||||
static struct semaphore *rxrpc_get_call_slot(struct rxrpc_call_params *p, gfp_t gfp)
|
||||
{
|
||||
struct semaphore *limiter = &rxrpc_call_limiter;
|
||||
|
||||
if (p->kernel)
|
||||
limiter = &rxrpc_kernel_call_limiter;
|
||||
if (p->interruptibility == RXRPC_UNINTERRUPTIBLE) {
|
||||
down(limiter);
|
||||
return limiter;
|
||||
}
|
||||
return down_interruptible(limiter) < 0 ? NULL : limiter;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release a call slot.
|
||||
*/
|
||||
static void rxrpc_put_call_slot(struct rxrpc_call *call)
|
||||
{
|
||||
struct semaphore *limiter = &rxrpc_call_limiter;
|
||||
|
||||
if (test_bit(RXRPC_CALL_KERNEL, &call->flags))
|
||||
limiter = &rxrpc_kernel_call_limiter;
|
||||
up(limiter);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up a call for the given parameters.
|
||||
* - Called with the socket lock held, which it must release.
|
||||
@ -225,15 +258,21 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
|
||||
{
|
||||
struct rxrpc_call *call, *xcall;
|
||||
struct rxrpc_net *rxnet;
|
||||
struct semaphore *limiter;
|
||||
struct rb_node *parent, **pp;
|
||||
const void *here = __builtin_return_address(0);
|
||||
int ret;
|
||||
|
||||
_enter("%p,%lx", rx, p->user_call_ID);
|
||||
|
||||
limiter = rxrpc_get_call_slot(p, gfp);
|
||||
if (!limiter)
|
||||
return ERR_PTR(-ERESTARTSYS);
|
||||
|
||||
call = rxrpc_alloc_client_call(rx, srx, gfp, debug_id);
|
||||
if (IS_ERR(call)) {
|
||||
release_sock(&rx->sk);
|
||||
up(limiter);
|
||||
_leave(" = %ld", PTR_ERR(call));
|
||||
return call;
|
||||
}
|
||||
@ -243,6 +282,8 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
|
||||
trace_rxrpc_call(call->debug_id, rxrpc_call_new_client,
|
||||
atomic_read(&call->usage),
|
||||
here, (const void *)p->user_call_ID);
|
||||
if (p->kernel)
|
||||
__set_bit(RXRPC_CALL_KERNEL, &call->flags);
|
||||
|
||||
/* We need to protect a partially set up call against the user as we
|
||||
* will be acting outside the socket lock.
|
||||
@ -471,6 +512,8 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
|
||||
BUG();
|
||||
spin_unlock_bh(&call->lock);
|
||||
|
||||
rxrpc_put_call_slot(call);
|
||||
|
||||
del_timer_sync(&call->timer);
|
||||
|
||||
/* Make sure we don't get any more notifications */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -157,12 +157,12 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn,
|
||||
|
||||
_enter("{%d},%x", conn->debug_id, conn->abort_code);
|
||||
|
||||
spin_lock(&conn->channel_lock);
|
||||
spin_lock(&conn->bundle->channel_lock);
|
||||
|
||||
for (i = 0; i < RXRPC_MAXCALLS; i++) {
|
||||
call = rcu_dereference_protected(
|
||||
conn->channels[i].call,
|
||||
lockdep_is_held(&conn->channel_lock));
|
||||
lockdep_is_held(&conn->bundle->channel_lock));
|
||||
if (call) {
|
||||
if (compl == RXRPC_CALL_LOCALLY_ABORTED)
|
||||
trace_rxrpc_abort(call->debug_id,
|
||||
@ -179,7 +179,7 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn,
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&conn->channel_lock);
|
||||
spin_unlock(&conn->bundle->channel_lock);
|
||||
_leave("");
|
||||
}
|
||||
|
||||
@ -210,6 +210,7 @@ static int rxrpc_abort_connection(struct rxrpc_connection *conn,
|
||||
conn->error = error;
|
||||
conn->abort_code = abort_code;
|
||||
conn->state = RXRPC_CONN_LOCALLY_ABORTED;
|
||||
set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags);
|
||||
spin_unlock_bh(&conn->state_lock);
|
||||
|
||||
msg.msg_name = &conn->params.peer->srx.transport;
|
||||
@ -319,6 +320,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
|
||||
conn->error = -ECONNABORTED;
|
||||
conn->abort_code = abort_code;
|
||||
conn->state = RXRPC_CONN_REMOTELY_ABORTED;
|
||||
set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags);
|
||||
rxrpc_abort_calls(conn, RXRPC_CALL_REMOTELY_ABORTED, sp->hdr.serial);
|
||||
return -ECONNABORTED;
|
||||
|
||||
@ -339,7 +341,7 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
spin_lock(&conn->channel_lock);
|
||||
spin_lock(&conn->bundle->channel_lock);
|
||||
spin_lock(&conn->state_lock);
|
||||
|
||||
if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING) {
|
||||
@ -349,12 +351,12 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
|
||||
rxrpc_call_is_secure(
|
||||
rcu_dereference_protected(
|
||||
conn->channels[loop].call,
|
||||
lockdep_is_held(&conn->channel_lock)));
|
||||
lockdep_is_held(&conn->bundle->channel_lock)));
|
||||
} else {
|
||||
spin_unlock(&conn->state_lock);
|
||||
}
|
||||
|
||||
spin_unlock(&conn->channel_lock);
|
||||
spin_unlock(&conn->bundle->channel_lock);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
|
@ -41,8 +41,6 @@ struct rxrpc_connection *rxrpc_alloc_connection(gfp_t gfp)
|
||||
conn = kzalloc(sizeof(struct rxrpc_connection), gfp);
|
||||
if (conn) {
|
||||
INIT_LIST_HEAD(&conn->cache_link);
|
||||
spin_lock_init(&conn->channel_lock);
|
||||
INIT_LIST_HEAD(&conn->waiting_calls);
|
||||
timer_setup(&conn->timer, &rxrpc_connection_timer, 0);
|
||||
INIT_WORK(&conn->processor, &rxrpc_process_connection);
|
||||
INIT_LIST_HEAD(&conn->proc_link);
|
||||
@ -219,11 +217,11 @@ void rxrpc_disconnect_call(struct rxrpc_call *call)
|
||||
}
|
||||
|
||||
if (rxrpc_is_client_call(call))
|
||||
return rxrpc_disconnect_client_call(call);
|
||||
return rxrpc_disconnect_client_call(conn->bundle, call);
|
||||
|
||||
spin_lock(&conn->channel_lock);
|
||||
spin_lock(&conn->bundle->channel_lock);
|
||||
__rxrpc_disconnect_call(conn, call);
|
||||
spin_unlock(&conn->channel_lock);
|
||||
spin_unlock(&conn->bundle->channel_lock);
|
||||
|
||||
set_bit(RXRPC_CALL_DISCONNECTED, &call->flags);
|
||||
conn->idle_timestamp = jiffies;
|
||||
@ -292,12 +290,13 @@ void rxrpc_see_connection(struct rxrpc_connection *conn)
|
||||
/*
|
||||
* Get a ref on a connection.
|
||||
*/
|
||||
void rxrpc_get_connection(struct rxrpc_connection *conn)
|
||||
struct rxrpc_connection *rxrpc_get_connection(struct rxrpc_connection *conn)
|
||||
{
|
||||
const void *here = __builtin_return_address(0);
|
||||
int n = atomic_inc_return(&conn->usage);
|
||||
|
||||
trace_rxrpc_conn(conn->debug_id, rxrpc_conn_got, n, here);
|
||||
return conn;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -365,6 +364,7 @@ static void rxrpc_destroy_connection(struct rcu_head *rcu)
|
||||
conn->security->clear(conn);
|
||||
key_put(conn->params.key);
|
||||
key_put(conn->server_key);
|
||||
rxrpc_put_bundle(conn->bundle);
|
||||
rxrpc_put_peer(conn->params.peer);
|
||||
|
||||
if (atomic_dec_and_test(&conn->params.local->rxnet->nr_conns))
|
||||
|
@ -8,6 +8,12 @@
|
||||
#include <linux/slab.h>
|
||||
#include "ar-internal.h"
|
||||
|
||||
static struct rxrpc_bundle rxrpc_service_dummy_bundle = {
|
||||
.usage = ATOMIC_INIT(1),
|
||||
.debug_id = UINT_MAX,
|
||||
.channel_lock = __SPIN_LOCK_UNLOCKED(&rxrpc_service_dummy_bundle.channel_lock),
|
||||
};
|
||||
|
||||
/*
|
||||
* Find a service connection under RCU conditions.
|
||||
*
|
||||
@ -127,6 +133,7 @@ struct rxrpc_connection *rxrpc_prealloc_service_connection(struct rxrpc_net *rxn
|
||||
*/
|
||||
conn->state = RXRPC_CONN_SERVICE_PREALLOC;
|
||||
atomic_set(&conn->usage, 2);
|
||||
conn->bundle = rxrpc_get_bundle(&rxrpc_service_dummy_bundle);
|
||||
|
||||
atomic_inc(&rxnet->nr_conns);
|
||||
write_lock(&rxnet->conn_lock);
|
||||
|
@ -86,8 +86,8 @@ static struct rxrpc_local *rxrpc_alloc_local(struct rxrpc_net *rxnet,
|
||||
init_rwsem(&local->defrag_sem);
|
||||
skb_queue_head_init(&local->reject_queue);
|
||||
skb_queue_head_init(&local->event_queue);
|
||||
local->client_conns = RB_ROOT;
|
||||
spin_lock_init(&local->client_conns_lock);
|
||||
local->client_bundles = RB_ROOT;
|
||||
spin_lock_init(&local->client_bundles_lock);
|
||||
spin_lock_init(&local->lock);
|
||||
rwlock_init(&local->services_lock);
|
||||
local->debug_id = atomic_inc_return(&rxrpc_debug_id);
|
||||
|
@ -62,13 +62,10 @@ static __net_init int rxrpc_init_net(struct net *net)
|
||||
timer_setup(&rxnet->service_conn_reap_timer,
|
||||
rxrpc_service_conn_reap_timeout, 0);
|
||||
|
||||
rxnet->nr_client_conns = 0;
|
||||
rxnet->nr_active_client_conns = 0;
|
||||
atomic_set(&rxnet->nr_client_conns, 0);
|
||||
rxnet->kill_all_client_conns = false;
|
||||
spin_lock_init(&rxnet->client_conn_cache_lock);
|
||||
spin_lock_init(&rxnet->client_conn_discard_lock);
|
||||
INIT_LIST_HEAD(&rxnet->waiting_client_conns);
|
||||
INIT_LIST_HEAD(&rxnet->active_client_conns);
|
||||
INIT_LIST_HEAD(&rxnet->idle_client_conns);
|
||||
INIT_WORK(&rxnet->client_conn_reaper,
|
||||
rxrpc_discard_expired_client_conns);
|
||||
|
@ -357,6 +357,12 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
|
||||
|
||||
_enter(",{%d}", skb->len);
|
||||
|
||||
if (hlist_unhashed(&call->error_link)) {
|
||||
spin_lock_bh(&call->peer->lock);
|
||||
hlist_add_head_rcu(&call->error_link, &call->peer->error_targets);
|
||||
spin_unlock_bh(&call->peer->lock);
|
||||
}
|
||||
|
||||
/* Each transmission of a Tx packet needs a new serial number */
|
||||
serial = atomic_inc_return(&conn->serial);
|
||||
|
||||
|
@ -165,7 +165,7 @@ static int rxrpc_connection_seq_show(struct seq_file *seq, void *v)
|
||||
"Proto Local "
|
||||
" Remote "
|
||||
" SvID ConnID End Use State Key "
|
||||
" Serial ISerial\n"
|
||||
" Serial ISerial CallId0 CallId1 CallId2 CallId3\n"
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1169,7 +1169,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
|
||||
if (response->encrypted.checksum != csum)
|
||||
goto protocol_error_free;
|
||||
|
||||
spin_lock(&conn->channel_lock);
|
||||
spin_lock(&conn->bundle->channel_lock);
|
||||
for (i = 0; i < RXRPC_MAXCALLS; i++) {
|
||||
struct rxrpc_call *call;
|
||||
u32 call_id = ntohl(response->encrypted.call_id[i]);
|
||||
@ -1186,13 +1186,13 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
|
||||
if (call_id > conn->channels[i].call_counter) {
|
||||
call = rcu_dereference_protected(
|
||||
conn->channels[i].call,
|
||||
lockdep_is_held(&conn->channel_lock));
|
||||
lockdep_is_held(&conn->bundle->channel_lock));
|
||||
if (call && call->state < RXRPC_CALL_COMPLETE)
|
||||
goto protocol_error_unlock;
|
||||
conn->channels[i].call_counter = call_id;
|
||||
}
|
||||
}
|
||||
spin_unlock(&conn->channel_lock);
|
||||
spin_unlock(&conn->bundle->channel_lock);
|
||||
|
||||
eproto = tracepoint_string("rxkad_rsp_seq");
|
||||
abort_code = RXKADOUTOFSEQUENCE;
|
||||
@ -1219,7 +1219,7 @@ static int rxkad_verify_response(struct rxrpc_connection *conn,
|
||||
return 0;
|
||||
|
||||
protocol_error_unlock:
|
||||
spin_unlock(&conn->channel_lock);
|
||||
spin_unlock(&conn->bundle->channel_lock);
|
||||
protocol_error_free:
|
||||
kfree(ticket);
|
||||
protocol_error:
|
||||
|
@ -73,14 +73,6 @@ static struct ctl_table rxrpc_sysctl_table[] = {
|
||||
},
|
||||
|
||||
/* Non-time values */
|
||||
{
|
||||
.procname = "max_client_conns",
|
||||
.data = &rxrpc_max_client_connections,
|
||||
.maxlen = sizeof(unsigned int),
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = (void *)&rxrpc_reap_client_connections,
|
||||
},
|
||||
{
|
||||
.procname = "reap_client_conns",
|
||||
.data = &rxrpc_reap_client_connections,
|
||||
@ -88,7 +80,7 @@ static struct ctl_table rxrpc_sysctl_table[] = {
|
||||
.mode = 0644,
|
||||
.proc_handler = proc_dointvec_minmax,
|
||||
.extra1 = (void *)SYSCTL_ONE,
|
||||
.extra2 = (void *)&rxrpc_max_client_connections,
|
||||
.extra2 = (void *)&n_65535,
|
||||
},
|
||||
{
|
||||
.procname = "max_backlog",
|
||||
|
Loading…
Reference in New Issue
Block a user