aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2016-04-04 09:00:34 -0400
committerDavid Howells <dhowells@redhat.com>2016-06-15 05:15:16 -0400
commitf66d7490196055cb9fb058f8936d19111a6231b9 (patch)
tree915553b7124caf0a18c22db24e2ee1c60cafcc96
parentfe77d5fc5ab33bb088cf8448767a77fdc32e08d1 (diff)
rxrpc: Use the peer record to distribute network errors
Use the peer record to distribute network errors rather than the transport object (which I want to get rid of). An error from a particular peer terminates all calls on that peer. For future consideration: (1) For ICMP-induced errors it might be worth trying to extract the RxRPC header from the offending packet, if one is returned attached to the ICMP packet, to better direct the error. This may be overkill, though, since an ICMP packet would be expected to be relating to the destination port, machine or network. RxRPC ABORT and BUSY packets give notice at RxRPC level. (2) To also abort connection-level communications (such as CHALLENGE packets) where indicted by an error - but that requires some revamping of the connection event handling first. Signed-off-by: David Howells <dhowells@redhat.com>
-rw-r--r--net/rxrpc/ar-internal.h16
-rw-r--r--net/rxrpc/call_event.c15
-rw-r--r--net/rxrpc/call_object.c6
-rw-r--r--net/rxrpc/output.c4
-rw-r--r--net/rxrpc/peer_event.c109
-rw-r--r--net/rxrpc/peer_object.c6
-rw-r--r--net/rxrpc/transport.c17
7 files changed, 79 insertions, 94 deletions
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index 1e5c15632f49..a63bb7518fb5 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -189,7 +189,6 @@ struct rxrpc_local {
189 rwlock_t services_lock; /* lock for services list */ 189 rwlock_t services_lock; /* lock for services list */
190 atomic_t usage; 190 atomic_t usage;
191 int debug_id; /* debug ID for printks */ 191 int debug_id; /* debug ID for printks */
192 volatile char error_rcvd; /* T if received ICMP error outstanding */
193 struct sockaddr_rxrpc srx; /* local address */ 192 struct sockaddr_rxrpc srx; /* local address */
194}; 193};
195 194
@@ -203,14 +202,16 @@ struct rxrpc_peer {
203 unsigned long hash_key; 202 unsigned long hash_key;
204 struct hlist_node hash_link; 203 struct hlist_node hash_link;
205 struct rxrpc_local *local; 204 struct rxrpc_local *local;
206 struct list_head error_targets; /* targets for net error distribution */ 205 struct hlist_head error_targets; /* targets for net error distribution */
206 struct work_struct error_distributor;
207 spinlock_t lock; /* access lock */ 207 spinlock_t lock; /* access lock */
208 unsigned int if_mtu; /* interface MTU for this peer */ 208 unsigned int if_mtu; /* interface MTU for this peer */
209 unsigned int mtu; /* network MTU for this peer */ 209 unsigned int mtu; /* network MTU for this peer */
210 unsigned int maxdata; /* data size (MTU - hdrsize) */ 210 unsigned int maxdata; /* data size (MTU - hdrsize) */
211 unsigned short hdrsize; /* header size (IP + UDP + RxRPC) */ 211 unsigned short hdrsize; /* header size (IP + UDP + RxRPC) */
212 int debug_id; /* debug ID for printks */ 212 int debug_id; /* debug ID for printks */
213 int net_error; /* network error distributed */ 213 int error_report; /* Net (+0) or local (+1000000) to distribute */
214#define RXRPC_LOCAL_ERROR_OFFSET 1000000
214 struct sockaddr_rxrpc srx; /* remote address */ 215 struct sockaddr_rxrpc srx; /* remote address */
215 216
216 /* calculated RTT cache */ 217 /* calculated RTT cache */
@@ -229,12 +230,10 @@ struct rxrpc_peer {
229struct rxrpc_transport { 230struct rxrpc_transport {
230 struct rxrpc_local *local; /* local transport endpoint */ 231 struct rxrpc_local *local; /* local transport endpoint */
231 struct rxrpc_peer *peer; /* remote transport endpoint */ 232 struct rxrpc_peer *peer; /* remote transport endpoint */
232 struct work_struct error_handler; /* network error distributor */
233 struct rb_root bundles; /* client connection bundles on this transport */ 233 struct rb_root bundles; /* client connection bundles on this transport */
234 struct rb_root client_conns; /* client connections on this transport */ 234 struct rb_root client_conns; /* client connections on this transport */
235 struct rb_root server_conns; /* server connections on this transport */ 235 struct rb_root server_conns; /* server connections on this transport */
236 struct list_head link; /* link in master session list */ 236 struct list_head link; /* link in master session list */
237 struct sk_buff_head error_queue; /* error packets awaiting processing */
238 unsigned long put_time; /* time at which to reap */ 237 unsigned long put_time; /* time at which to reap */
239 spinlock_t client_lock; /* client connection allocation lock */ 238 spinlock_t client_lock; /* client connection allocation lock */
240 rwlock_t conn_lock; /* lock for active/dead connections */ 239 rwlock_t conn_lock; /* lock for active/dead connections */
@@ -393,7 +392,7 @@ struct rxrpc_call {
393 struct work_struct destroyer; /* call destroyer */ 392 struct work_struct destroyer; /* call destroyer */
394 struct work_struct processor; /* packet processor and ACK generator */ 393 struct work_struct processor; /* packet processor and ACK generator */
395 struct list_head link; /* link in master call list */ 394 struct list_head link; /* link in master call list */
396 struct list_head error_link; /* link in error distribution list */ 395 struct hlist_node error_link; /* link in error distribution list */
397 struct list_head accept_link; /* calls awaiting acceptance */ 396 struct list_head accept_link; /* calls awaiting acceptance */
398 struct rb_node sock_node; /* node in socket call tree */ 397 struct rb_node sock_node; /* node in socket call tree */
399 struct rb_node conn_node; /* node in connection call tree */ 398 struct rb_node conn_node; /* node in connection call tree */
@@ -411,7 +410,8 @@ struct rxrpc_call {
411 atomic_t sequence; /* Tx data packet sequence counter */ 410 atomic_t sequence; /* Tx data packet sequence counter */
412 u32 local_abort; /* local abort code */ 411 u32 local_abort; /* local abort code */
413 u32 remote_abort; /* remote abort code */ 412 u32 remote_abort; /* remote abort code */
414 int error; /* local error incurred */ 413 int error_report; /* Network error (ICMP/local transport) */
414 int error; /* Local error incurred */
415 enum rxrpc_call_state state : 8; /* current state of call */ 415 enum rxrpc_call_state state : 8; /* current state of call */
416 int debug_id; /* debug ID for printks */ 416 int debug_id; /* debug ID for printks */
417 u8 channel; /* connection channel occupied by this call */ 417 u8 channel; /* connection channel occupied by this call */
@@ -609,7 +609,7 @@ int rxrpc_do_sendmsg(struct rxrpc_sock *, struct msghdr *, size_t);
609 * peer_event.c 609 * peer_event.c
610 */ 610 */
611void rxrpc_error_report(struct sock *); 611void rxrpc_error_report(struct sock *);
612void rxrpc_UDP_error_handler(struct work_struct *); 612void rxrpc_peer_error_distributor(struct work_struct *);
613 613
614/* 614/*
615 * peer_object.c 615 * peer_object.c
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
index 18381783c2b1..e610b106c913 100644
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -864,17 +864,24 @@ void rxrpc_process_call(struct work_struct *work)
864 } 864 }
865 865
866 if (test_bit(RXRPC_CALL_EV_RCVD_ERROR, &call->events)) { 866 if (test_bit(RXRPC_CALL_EV_RCVD_ERROR, &call->events)) {
867 enum rxrpc_skb_mark mark;
867 int error; 868 int error;
868 869
869 clear_bit(RXRPC_CALL_EV_CONN_ABORT, &call->events); 870 clear_bit(RXRPC_CALL_EV_CONN_ABORT, &call->events);
870 clear_bit(RXRPC_CALL_EV_REJECT_BUSY, &call->events); 871 clear_bit(RXRPC_CALL_EV_REJECT_BUSY, &call->events);
871 clear_bit(RXRPC_CALL_EV_ABORT, &call->events); 872 clear_bit(RXRPC_CALL_EV_ABORT, &call->events);
872 873
873 error = call->conn->trans->peer->net_error; 874 error = call->error_report;
874 _debug("post net error %d", error); 875 if (error < RXRPC_LOCAL_ERROR_OFFSET) {
876 mark = RXRPC_SKB_MARK_NET_ERROR;
877 _debug("post net error %d", error);
878 } else {
879 mark = RXRPC_SKB_MARK_LOCAL_ERROR;
880 error -= RXRPC_LOCAL_ERROR_OFFSET;
881 _debug("post net local error %d", error);
882 }
875 883
876 if (rxrpc_post_message(call, RXRPC_SKB_MARK_NET_ERROR, 884 if (rxrpc_post_message(call, mark, error, true) < 0)
877 error, true) < 0)
878 goto no_mem; 885 goto no_mem;
879 clear_bit(RXRPC_CALL_EV_RCVD_ERROR, &call->events); 886 clear_bit(RXRPC_CALL_EV_RCVD_ERROR, &call->events);
880 goto kill_ACKs; 887 goto kill_ACKs;
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index 68125dc4cb7c..8b4d47b3ccac 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -334,7 +334,7 @@ static struct rxrpc_call *rxrpc_alloc_client_call(
334 rxrpc_call_hash_add(call); 334 rxrpc_call_hash_add(call);
335 335
336 spin_lock(&call->conn->trans->peer->lock); 336 spin_lock(&call->conn->trans->peer->lock);
337 list_add(&call->error_link, &call->conn->trans->peer->error_targets); 337 hlist_add_head(&call->error_link, &call->conn->trans->peer->error_targets);
338 spin_unlock(&call->conn->trans->peer->lock); 338 spin_unlock(&call->conn->trans->peer->lock);
339 339
340 call->lifetimer.expires = jiffies + rxrpc_max_call_lifetime; 340 call->lifetimer.expires = jiffies + rxrpc_max_call_lifetime;
@@ -516,7 +516,7 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx,
516 write_unlock_bh(&conn->lock); 516 write_unlock_bh(&conn->lock);
517 517
518 spin_lock(&conn->trans->peer->lock); 518 spin_lock(&conn->trans->peer->lock);
519 list_add(&call->error_link, &conn->trans->peer->error_targets); 519 hlist_add_head(&call->error_link, &conn->trans->peer->error_targets);
520 spin_unlock(&conn->trans->peer->lock); 520 spin_unlock(&conn->trans->peer->lock);
521 521
522 write_lock_bh(&rxrpc_call_lock); 522 write_lock_bh(&rxrpc_call_lock);
@@ -812,7 +812,7 @@ static void rxrpc_cleanup_call(struct rxrpc_call *call)
812 812
813 if (call->conn) { 813 if (call->conn) {
814 spin_lock(&call->conn->trans->peer->lock); 814 spin_lock(&call->conn->trans->peer->lock);
815 list_del(&call->error_link); 815 hlist_del_init(&call->error_link);
816 spin_unlock(&call->conn->trans->peer->lock); 816 spin_unlock(&call->conn->trans->peer->lock);
817 817
818 write_lock_bh(&call->conn->lock); 818 write_lock_bh(&call->conn->lock);
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index 2e3c4064e29c..e6fb3863b0bc 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -707,7 +707,9 @@ out:
707call_aborted: 707call_aborted:
708 rxrpc_free_skb(skb); 708 rxrpc_free_skb(skb);
709 if (call->state == RXRPC_CALL_NETWORK_ERROR) 709 if (call->state == RXRPC_CALL_NETWORK_ERROR)
710 ret = call->conn->trans->peer->net_error; 710 ret = call->error_report < RXRPC_LOCAL_ERROR_OFFSET ?
711 call->error_report :
712 call->error_report - RXRPC_LOCAL_ERROR_OFFSET;
711 else 713 else
712 ret = -ECONNABORTED; 714 ret = -ECONNABORTED;
713 _leave(" = %d", ret); 715 _leave(" = %d", ret);
diff --git a/net/rxrpc/peer_event.c b/net/rxrpc/peer_event.c
index 31c440acd8c9..8940674b5e08 100644
--- a/net/rxrpc/peer_event.c
+++ b/net/rxrpc/peer_event.c
@@ -1,4 +1,4 @@
1/* Error message handling (ICMP) 1/* Peer event handling, typically ICMP messages.
2 * 2 *
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
@@ -22,6 +22,8 @@
22#include <net/ip.h> 22#include <net/ip.h>
23#include "ar-internal.h" 23#include "ar-internal.h"
24 24
25static void rxrpc_store_error(struct rxrpc_peer *, struct sock_exterr_skb *);
26
25/* 27/*
26 * Find the peer associated with an ICMP packet. 28 * Find the peer associated with an ICMP packet.
27 */ 29 */
@@ -111,12 +113,11 @@ static void rxrpc_adjust_mtu(struct rxrpc_peer *peer, struct sock_exterr_skb *se
111} 113}
112 114
113/* 115/*
114 * handle an error received on the local endpoint 116 * Handle an error received on the local endpoint.
115 */ 117 */
116void rxrpc_error_report(struct sock *sk) 118void rxrpc_error_report(struct sock *sk)
117{ 119{
118 struct sock_exterr_skb *serr; 120 struct sock_exterr_skb *serr;
119 struct rxrpc_transport *trans;
120 struct rxrpc_local *local = sk->sk_user_data; 121 struct rxrpc_local *local = sk->sk_user_data;
121 struct rxrpc_peer *peer; 122 struct rxrpc_peer *peer;
122 struct sk_buff *skb; 123 struct sk_buff *skb;
@@ -148,57 +149,37 @@ void rxrpc_error_report(struct sock *sk)
148 return; 149 return;
149 } 150 }
150 151
151 trans = rxrpc_find_transport(local, peer);
152 if (!trans) {
153 rcu_read_unlock();
154 rxrpc_put_peer(peer);
155 rxrpc_free_skb(skb);
156 _leave(" [no trans]");
157 return;
158 }
159
160 if ((serr->ee.ee_origin == SO_EE_ORIGIN_ICMP && 152 if ((serr->ee.ee_origin == SO_EE_ORIGIN_ICMP &&
161 serr->ee.ee_type == ICMP_DEST_UNREACH && 153 serr->ee.ee_type == ICMP_DEST_UNREACH &&
162 serr->ee.ee_code == ICMP_FRAG_NEEDED)) { 154 serr->ee.ee_code == ICMP_FRAG_NEEDED)) {
163 rxrpc_adjust_mtu(peer, serr); 155 rxrpc_adjust_mtu(peer, serr);
156 rcu_read_unlock();
164 rxrpc_free_skb(skb); 157 rxrpc_free_skb(skb);
165 skb = NULL; 158 rxrpc_put_peer(peer);
166 goto out; 159 _leave(" [MTU update]");
160 return;
167 } 161 }
168 162
169out: 163 rxrpc_store_error(peer, serr);
170 rcu_read_unlock(); 164 rcu_read_unlock();
171 rxrpc_put_peer(peer); 165 rxrpc_free_skb(skb);
172 166
173 if (skb) { 167 /* The ref we obtained is passed off to the work item */
174 /* pass the transport ref to error_handler to release */ 168 rxrpc_queue_work(&peer->error_distributor);
175 skb_queue_tail(&trans->error_queue, skb);
176 rxrpc_queue_work(&trans->error_handler);
177 } else {
178 rxrpc_put_transport(trans);
179 }
180 _leave(""); 169 _leave("");
181} 170}
182 171
183/* 172/*
184 * deal with UDP error messages 173 * Map an error report to error codes on the peer record.
185 */ 174 */
186void rxrpc_UDP_error_handler(struct work_struct *work) 175static void rxrpc_store_error(struct rxrpc_peer *peer,
176 struct sock_exterr_skb *serr)
187{ 177{
188 struct sock_extended_err *ee; 178 struct sock_extended_err *ee;
189 struct sock_exterr_skb *serr;
190 struct rxrpc_transport *trans =
191 container_of(work, struct rxrpc_transport, error_handler);
192 struct sk_buff *skb;
193 int err; 179 int err;
194 180
195 _enter(""); 181 _enter("");
196 182
197 skb = skb_dequeue(&trans->error_queue);
198 if (!skb)
199 return;
200
201 serr = SKB_EXT_ERR(skb);
202 ee = &serr->ee; 183 ee = &serr->ee;
203 184
204 _net("Rx Error o=%d t=%d c=%d e=%d", 185 _net("Rx Error o=%d t=%d c=%d e=%d",
@@ -244,47 +225,57 @@ void rxrpc_UDP_error_handler(struct work_struct *work)
244 } 225 }
245 break; 226 break;
246 227
228 case SO_EE_ORIGIN_NONE:
247 case SO_EE_ORIGIN_LOCAL: 229 case SO_EE_ORIGIN_LOCAL:
248 _proto("Rx Received local error { error=%d }", err); 230 _proto("Rx Received local error { error=%d }", err);
231 err += RXRPC_LOCAL_ERROR_OFFSET;
249 break; 232 break;
250 233
251 case SO_EE_ORIGIN_NONE:
252 case SO_EE_ORIGIN_ICMP6: 234 case SO_EE_ORIGIN_ICMP6:
253 default: 235 default:
254 _proto("Rx Received error report { orig=%u }", ee->ee_origin); 236 _proto("Rx Received error report { orig=%u }", ee->ee_origin);
255 break; 237 break;
256 } 238 }
257 239
258 /* terminate all the affected calls if there's an unrecoverable 240 peer->error_report = err;
259 * error */ 241}
260 if (err) { 242
261 struct rxrpc_call *call, *_n; 243/*
244 * Distribute an error that occurred on a peer
245 */
246void rxrpc_peer_error_distributor(struct work_struct *work)
247{
248 struct rxrpc_peer *peer =
249 container_of(work, struct rxrpc_peer, error_distributor);
250 struct rxrpc_call *call;
251 int error_report;
252
253 _enter("");
262 254
263 _debug("ISSUE ERROR %d", err); 255 error_report = READ_ONCE(peer->error_report);
264 256
265 spin_lock_bh(&trans->peer->lock); 257 _debug("ISSUE ERROR %d", error_report);
266 trans->peer->net_error = err;
267 258
268 list_for_each_entry_safe(call, _n, &trans->peer->error_targets, 259 spin_lock_bh(&peer->lock);
269 error_link) {
270 write_lock(&call->state_lock);
271 if (call->state != RXRPC_CALL_COMPLETE &&
272 call->state < RXRPC_CALL_NETWORK_ERROR) {
273 call->state = RXRPC_CALL_NETWORK_ERROR;
274 set_bit(RXRPC_CALL_EV_RCVD_ERROR, &call->events);
275 rxrpc_queue_call(call);
276 }
277 write_unlock(&call->state_lock);
278 list_del_init(&call->error_link);
279 }
280 260
281 spin_unlock_bh(&trans->peer->lock); 261 while (!hlist_empty(&peer->error_targets)) {
262 call = hlist_entry(peer->error_targets.first,
263 struct rxrpc_call, error_link);
264 hlist_del_init(&call->error_link);
265
266 write_lock(&call->state_lock);
267 if (call->state != RXRPC_CALL_COMPLETE &&
268 call->state < RXRPC_CALL_NETWORK_ERROR) {
269 call->error_report = error_report;
270 call->state = RXRPC_CALL_NETWORK_ERROR;
271 set_bit(RXRPC_CALL_EV_RCVD_ERROR, &call->events);
272 rxrpc_queue_call(call);
273 }
274 write_unlock(&call->state_lock);
282 } 275 }
283 276
284 if (!skb_queue_empty(&trans->error_queue)) 277 spin_unlock_bh(&peer->lock);
285 rxrpc_queue_work(&trans->error_handler);
286 278
287 rxrpc_free_skb(skb); 279 rxrpc_put_peer(peer);
288 rxrpc_put_transport(trans);
289 _leave(""); 280 _leave("");
290} 281}
diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c
index 7fc50dc7d333..faf222c21698 100644
--- a/net/rxrpc/peer_object.c
+++ b/net/rxrpc/peer_object.c
@@ -182,7 +182,9 @@ struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *local, gfp_t gfp)
182 if (peer) { 182 if (peer) {
183 atomic_set(&peer->usage, 1); 183 atomic_set(&peer->usage, 1);
184 peer->local = local; 184 peer->local = local;
185 INIT_LIST_HEAD(&peer->error_targets); 185 INIT_HLIST_HEAD(&peer->error_targets);
186 INIT_WORK(&peer->error_distributor,
187 &rxrpc_peer_error_distributor);
186 spin_lock_init(&peer->lock); 188 spin_lock_init(&peer->lock);
187 peer->debug_id = atomic_inc_return(&rxrpc_debug_id); 189 peer->debug_id = atomic_inc_return(&rxrpc_debug_id);
188 } 190 }
@@ -298,7 +300,7 @@ struct rxrpc_peer *rxrpc_lookup_peer(struct rxrpc_local *local,
298 */ 300 */
299void __rxrpc_put_peer(struct rxrpc_peer *peer) 301void __rxrpc_put_peer(struct rxrpc_peer *peer)
300{ 302{
301 ASSERT(list_empty(&peer->error_targets)); 303 ASSERT(hlist_empty(&peer->error_targets));
302 304
303 spin_lock(&rxrpc_peer_hash_lock); 305 spin_lock(&rxrpc_peer_hash_lock);
304 hash_del_rcu(&peer->hash_link); 306 hash_del_rcu(&peer->hash_link);
diff --git a/net/rxrpc/transport.c b/net/rxrpc/transport.c
index d33387dec0ce..24c71218a6f8 100644
--- a/net/rxrpc/transport.c
+++ b/net/rxrpc/transport.c
@@ -49,26 +49,11 @@ static struct rxrpc_transport *rxrpc_alloc_transport(struct rxrpc_local *local,
49 trans->bundles = RB_ROOT; 49 trans->bundles = RB_ROOT;
50 trans->client_conns = RB_ROOT; 50 trans->client_conns = RB_ROOT;
51 trans->server_conns = RB_ROOT; 51 trans->server_conns = RB_ROOT;
52 skb_queue_head_init(&trans->error_queue);
53 spin_lock_init(&trans->client_lock); 52 spin_lock_init(&trans->client_lock);
54 rwlock_init(&trans->conn_lock); 53 rwlock_init(&trans->conn_lock);
55 atomic_set(&trans->usage, 1); 54 atomic_set(&trans->usage, 1);
56 trans->conn_idcounter = peer->srx.srx_service << 16; 55 trans->conn_idcounter = peer->srx.srx_service << 16;
57 trans->debug_id = atomic_inc_return(&rxrpc_debug_id); 56 trans->debug_id = atomic_inc_return(&rxrpc_debug_id);
58
59 if (peer->srx.transport.family == AF_INET) {
60 switch (peer->srx.transport_type) {
61 case SOCK_DGRAM:
62 INIT_WORK(&trans->error_handler,
63 rxrpc_UDP_error_handler);
64 break;
65 default:
66 BUG();
67 break;
68 }
69 } else {
70 BUG();
71 }
72 } 57 }
73 58
74 _leave(" = %p", trans); 59 _leave(" = %p", trans);
@@ -210,8 +195,6 @@ static void rxrpc_cleanup_transport(struct rxrpc_transport *trans)
210{ 195{
211 _net("DESTROY TRANS %d", trans->debug_id); 196 _net("DESTROY TRANS %d", trans->debug_id);
212 197
213 rxrpc_purge_queue(&trans->error_queue);
214
215 rxrpc_put_local(trans->local); 198 rxrpc_put_local(trans->local);
216 rxrpc_put_peer(trans->peer); 199 rxrpc_put_peer(trans->peer);
217 kfree(trans); 200 kfree(trans);