Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rxrpc, afs: Allow afs to pin rxrpc_peer objects

Change rxrpc's API such that:

(1) A new function, rxrpc_kernel_lookup_peer(), is provided to look up an
rxrpc_peer record for a remote address and a corresponding function,
rxrpc_kernel_put_peer(), is provided to dispose of it again.

(2) When setting up a call, the rxrpc_peer object used during a call is
now passed in rather than being set up by rxrpc_connect_call(). For
afs, this meenat passing it to rxrpc_kernel_begin_call() rather than
the full address (the service ID then has to be passed in as a
separate parameter).

(3) A new function, rxrpc_kernel_remote_addr(), is added so that afs can
get a pointer to the transport address for display purposed, and
another, rxrpc_kernel_remote_srx(), to gain a pointer to the full
rxrpc address.

(4) The function to retrieve the RTT from a call, rxrpc_kernel_get_srtt(),
is then altered to take a peer. This now returns the RTT or -1 if
there are insufficient samples.

(5) Rename rxrpc_kernel_get_peer() to rxrpc_kernel_call_get_peer().

(6) Provide a new function, rxrpc_kernel_get_peer(), to get a ref on a
peer the caller already has.

This allows the afs filesystem to pin the rxrpc_peer records that it is
using, allowing faster lookups and pointer comparisons rather than
comparing sockaddr_rxrpc contents. It also makes it easier to get hold of
the RTT. The following changes are made to afs:

(1) The addr_list struct's addrs[] elements now hold a peer struct pointer
and a service ID rather than a sockaddr_rxrpc.

(2) When displaying the transport address, rxrpc_kernel_remote_addr() is
used.

(3) The port arg is removed from afs_alloc_addrlist() since it's always
overridden.

(4) afs_merge_fs_addr4() and afs_merge_fs_addr6() do peer lookup and may
now return an error that must be handled.

(5) afs_find_server() now takes a peer pointer to specify the address.

(6) afs_find_server(), afs_compare_fs_alists() and afs_merge_fs_addr[46]{}
now do peer pointer comparison rather than address comparison.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org

+274 -239
+66 -59
fs/afs/addr_list.c
··· 13 13 #include "internal.h" 14 14 #include "afs_fs.h" 15 15 16 + static void afs_free_addrlist(struct rcu_head *rcu) 17 + { 18 + struct afs_addr_list *alist = container_of(rcu, struct afs_addr_list, rcu); 19 + unsigned int i; 20 + 21 + for (i = 0; i < alist->nr_addrs; i++) 22 + rxrpc_kernel_put_peer(alist->addrs[i].peer); 23 + } 24 + 16 25 /* 17 26 * Release an address list. 18 27 */ 19 28 void afs_put_addrlist(struct afs_addr_list *alist) 20 29 { 21 30 if (alist && refcount_dec_and_test(&alist->usage)) 22 - kfree_rcu(alist, rcu); 31 + call_rcu(&alist->rcu, afs_free_addrlist); 23 32 } 24 33 25 34 /* 26 35 * Allocate an address list. 27 36 */ 28 - struct afs_addr_list *afs_alloc_addrlist(unsigned int nr, 29 - unsigned short service, 30 - unsigned short port) 37 + struct afs_addr_list *afs_alloc_addrlist(unsigned int nr, u16 service_id) 31 38 { 32 39 struct afs_addr_list *alist; 33 40 unsigned int i; 34 41 35 - _enter("%u,%u,%u", nr, service, port); 42 + _enter("%u,%u", nr, service_id); 36 43 37 44 if (nr > AFS_MAX_ADDRESSES) 38 45 nr = AFS_MAX_ADDRESSES; ··· 51 44 refcount_set(&alist->usage, 1); 52 45 alist->max_addrs = nr; 53 46 54 - for (i = 0; i < nr; i++) { 55 - struct sockaddr_rxrpc *srx = &alist->addrs[i].srx; 56 - srx->srx_family = AF_RXRPC; 57 - srx->srx_service = service; 58 - srx->transport_type = SOCK_DGRAM; 59 - srx->transport_len = sizeof(srx->transport.sin6); 60 - srx->transport.sin6.sin6_family = AF_INET6; 61 - srx->transport.sin6.sin6_port = htons(port); 62 - } 63 - 47 + for (i = 0; i < nr; i++) 48 + alist->addrs[i].service_id = service_id; 64 49 return alist; 65 50 } 66 51 ··· 125 126 if (!vllist->servers[0].server) 126 127 goto error_vl; 127 128 128 - alist = afs_alloc_addrlist(nr, service, AFS_VL_PORT); 129 + alist = afs_alloc_addrlist(nr, service); 129 130 if (!alist) 130 131 goto error; 131 132 ··· 196 197 } 197 198 198 199 if (family == AF_INET) 199 - afs_merge_fs_addr4(alist, x[0], xport); 200 + ret = afs_merge_fs_addr4(net, alist, x[0], xport); 200 201 else 201 - afs_merge_fs_addr6(alist, x, xport); 202 + ret = afs_merge_fs_addr6(net, alist, x, xport); 203 + if (ret < 0) 204 + goto error; 202 205 203 206 } while (p < end); 204 207 ··· 272 271 /* 273 272 * Merge an IPv4 entry into a fileserver address list. 274 273 */ 275 - void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr, u16 port) 274 + int afs_merge_fs_addr4(struct afs_net *net, struct afs_addr_list *alist, 275 + __be32 xdr, u16 port) 276 276 { 277 - struct sockaddr_rxrpc *srx; 278 - u32 addr = ntohl(xdr); 277 + struct sockaddr_rxrpc srx; 278 + struct rxrpc_peer *peer; 279 279 int i; 280 280 281 281 if (alist->nr_addrs >= alist->max_addrs) 282 - return; 282 + return 0; 283 + 284 + srx.srx_family = AF_RXRPC; 285 + srx.transport_type = SOCK_DGRAM; 286 + srx.transport_len = sizeof(srx.transport.sin); 287 + srx.transport.sin.sin_family = AF_INET; 288 + srx.transport.sin.sin_port = htons(port); 289 + srx.transport.sin.sin_addr.s_addr = xdr; 290 + 291 + peer = rxrpc_kernel_lookup_peer(net->socket, &srx, GFP_KERNEL); 292 + if (!peer) 293 + return -ENOMEM; 283 294 284 295 for (i = 0; i < alist->nr_ipv4; i++) { 285 - struct sockaddr_in *a = &alist->addrs[i].srx.transport.sin; 286 - u32 a_addr = ntohl(a->sin_addr.s_addr); 287 - u16 a_port = ntohs(a->sin_port); 288 - 289 - if (addr == a_addr && port == a_port) 290 - return; 291 - if (addr == a_addr && port < a_port) 292 - break; 293 - if (addr < a_addr) 296 + if (peer == alist->addrs[i].peer) { 297 + rxrpc_kernel_put_peer(peer); 298 + return 0; 299 + } 300 + if (peer <= alist->addrs[i].peer) 294 301 break; 295 302 } 296 303 ··· 307 298 alist->addrs + i, 308 299 sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); 309 300 310 - srx = &alist->addrs[i].srx; 311 - srx->srx_family = AF_RXRPC; 312 - srx->transport_type = SOCK_DGRAM; 313 - srx->transport_len = sizeof(srx->transport.sin); 314 - srx->transport.sin.sin_family = AF_INET; 315 - srx->transport.sin.sin_port = htons(port); 316 - srx->transport.sin.sin_addr.s_addr = xdr; 301 + alist->addrs[i].peer = peer; 317 302 alist->nr_ipv4++; 318 303 alist->nr_addrs++; 304 + return 0; 319 305 } 320 306 321 307 /* 322 308 * Merge an IPv6 entry into a fileserver address list. 323 309 */ 324 - void afs_merge_fs_addr6(struct afs_addr_list *alist, __be32 *xdr, u16 port) 310 + int afs_merge_fs_addr6(struct afs_net *net, struct afs_addr_list *alist, 311 + __be32 *xdr, u16 port) 325 312 { 326 - struct sockaddr_rxrpc *srx; 327 - int i, diff; 313 + struct sockaddr_rxrpc srx; 314 + struct rxrpc_peer *peer; 315 + int i; 328 316 329 317 if (alist->nr_addrs >= alist->max_addrs) 330 - return; 318 + return 0; 319 + 320 + srx.srx_family = AF_RXRPC; 321 + srx.transport_type = SOCK_DGRAM; 322 + srx.transport_len = sizeof(srx.transport.sin6); 323 + srx.transport.sin6.sin6_family = AF_INET6; 324 + srx.transport.sin6.sin6_port = htons(port); 325 + memcpy(&srx.transport.sin6.sin6_addr, xdr, 16); 326 + 327 + peer = rxrpc_kernel_lookup_peer(net->socket, &srx, GFP_KERNEL); 328 + if (!peer) 329 + return -ENOMEM; 331 330 332 331 for (i = alist->nr_ipv4; i < alist->nr_addrs; i++) { 333 - struct sockaddr_in6 *a = &alist->addrs[i].srx.transport.sin6; 334 - u16 a_port = ntohs(a->sin6_port); 335 - 336 - diff = memcmp(xdr, &a->sin6_addr, 16); 337 - if (diff == 0 && port == a_port) 338 - return; 339 - if (diff == 0 && port < a_port) 340 - break; 341 - if (diff < 0) 332 + if (peer == alist->addrs[i].peer) { 333 + rxrpc_kernel_put_peer(peer); 334 + return 0; 335 + } 336 + if (peer <= alist->addrs[i].peer) 342 337 break; 343 338 } 344 339 ··· 350 337 memmove(alist->addrs + i + 1, 351 338 alist->addrs + i, 352 339 sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); 353 - 354 - srx = &alist->addrs[i].srx; 355 - srx->srx_family = AF_RXRPC; 356 - srx->transport_type = SOCK_DGRAM; 357 - srx->transport_len = sizeof(srx->transport.sin6); 358 - srx->transport.sin6.sin6_family = AF_INET6; 359 - srx->transport.sin6.sin6_port = htons(port); 360 - memcpy(&srx->transport.sin6.sin6_addr, xdr, 16); 340 + alist->addrs[i].peer = peer; 361 341 alist->nr_addrs++; 342 + return 0; 362 343 } 363 344 364 345 /*
+3 -2
fs/afs/cmservice.c
··· 146 146 { 147 147 struct sockaddr_rxrpc srx; 148 148 struct afs_server *server; 149 + struct rxrpc_peer *peer; 149 150 150 - rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx); 151 + peer = rxrpc_kernel_get_call_peer(call->net->socket, call->rxcall); 151 152 152 - server = afs_find_server(call->net, &srx); 153 + server = afs_find_server(call->net, peer); 153 154 if (!server) { 154 155 trace_afs_cm_no_server(call, &srx); 155 156 return 0;
+6 -5
fs/afs/fs_probe.c
··· 101 101 void afs_fileserver_probe_result(struct afs_call *call) 102 102 { 103 103 struct afs_addr_list *alist = call->alist; 104 + struct afs_address *addr = &alist->addrs[call->addr_ix]; 104 105 struct afs_server *server = call->server; 105 106 unsigned int index = call->addr_ix; 106 107 unsigned int rtt_us = 0, cap0; ··· 154 153 if (call->service_id == YFS_FS_SERVICE) { 155 154 server->probe.is_yfs = true; 156 155 set_bit(AFS_SERVER_FL_IS_YFS, &server->flags); 157 - alist->addrs[index].srx.srx_service = call->service_id; 156 + addr->service_id = call->service_id; 158 157 } else { 159 158 server->probe.not_yfs = true; 160 159 if (!server->probe.is_yfs) { 161 160 clear_bit(AFS_SERVER_FL_IS_YFS, &server->flags); 162 - alist->addrs[index].srx.srx_service = call->service_id; 161 + addr->service_id = call->service_id; 163 162 } 164 163 cap0 = ntohl(call->tmp); 165 164 if (cap0 & AFS3_VICED_CAPABILITY_64BITFILES) ··· 168 167 clear_bit(AFS_SERVER_FL_HAS_FS64, &server->flags); 169 168 } 170 169 171 - rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us); 170 + rtt_us = rxrpc_kernel_get_srtt(addr->peer); 172 171 if (rtt_us < server->probe.rtt) { 173 172 server->probe.rtt = rtt_us; 174 173 server->rtt = rtt_us; ··· 182 181 out: 183 182 spin_unlock(&server->probe_lock); 184 183 185 - _debug("probe %pU [%u] %pISpc rtt=%u ret=%d", 186 - &server->uuid, index, &alist->addrs[index].srx.transport, 184 + _debug("probe %pU [%u] %pISpc rtt=%d ret=%d", 185 + &server->uuid, index, rxrpc_kernel_remote_addr(alist->addrs[index].peer), 187 186 rtt_us, ret); 188 187 189 188 return afs_done_one_fs_probe(call->net, server);
+14 -12
fs/afs/internal.h
··· 72 72 AFS_CALL_COMPLETE, /* Completed or failed */ 73 73 }; 74 74 75 + struct afs_address { 76 + struct rxrpc_peer *peer; 77 + u16 service_id; 78 + }; 79 + 75 80 /* 76 81 * List of server addresses. 77 82 */ ··· 92 87 enum dns_lookup_status status:8; 93 88 unsigned long failed; /* Mask of addrs that failed locally/ICMP */ 94 89 unsigned long responded; /* Mask of addrs that responded */ 95 - struct { 96 - struct sockaddr_rxrpc srx; 97 - } addrs[] __counted_by(max_addrs); 90 + struct afs_address addrs[] __counted_by(max_addrs); 98 91 #define AFS_MAX_ADDRESSES ((unsigned int)(sizeof(unsigned long) * 8)) 99 92 }; 100 93 ··· 423 420 atomic_t probe_outstanding; 424 421 spinlock_t probe_lock; 425 422 struct { 426 - unsigned int rtt; /* RTT in uS */ 423 + unsigned int rtt; /* Best RTT in uS (or UINT_MAX) */ 427 424 u32 abort_code; 428 425 short error; 429 426 unsigned short flags; ··· 540 537 atomic_t probe_outstanding; 541 538 spinlock_t probe_lock; 542 539 struct { 543 - unsigned int rtt; /* RTT in uS */ 540 + unsigned int rtt; /* Best RTT in uS (or UINT_MAX) */ 544 541 u32 abort_code; 545 542 short error; 546 543 bool responded:1; ··· 967 964 refcount_inc(&alist->usage); 968 965 return alist; 969 966 } 970 - extern struct afs_addr_list *afs_alloc_addrlist(unsigned int, 971 - unsigned short, 972 - unsigned short); 967 + extern struct afs_addr_list *afs_alloc_addrlist(unsigned int nr, u16 service_id); 973 968 extern void afs_put_addrlist(struct afs_addr_list *); 974 969 extern struct afs_vlserver_list *afs_parse_text_addrs(struct afs_net *, 975 970 const char *, size_t, char, ··· 978 977 extern bool afs_iterate_addresses(struct afs_addr_cursor *); 979 978 extern int afs_end_cursor(struct afs_addr_cursor *); 980 979 981 - extern void afs_merge_fs_addr4(struct afs_addr_list *, __be32, u16); 982 - extern void afs_merge_fs_addr6(struct afs_addr_list *, __be32 *, u16); 980 + extern int afs_merge_fs_addr4(struct afs_net *net, struct afs_addr_list *addr, 981 + __be32 xdr, u16 port); 982 + extern int afs_merge_fs_addr6(struct afs_net *net, struct afs_addr_list *addr, 983 + __be32 *xdr, u16 port); 983 984 984 985 /* 985 986 * callback.c ··· 1408 1405 */ 1409 1406 extern spinlock_t afs_server_peer_lock; 1410 1407 1411 - extern struct afs_server *afs_find_server(struct afs_net *, 1412 - const struct sockaddr_rxrpc *); 1408 + extern struct afs_server *afs_find_server(struct afs_net *, const struct rxrpc_peer *); 1413 1409 extern struct afs_server *afs_find_server_by_uuid(struct afs_net *, const uuid_t *); 1414 1410 extern struct afs_server *afs_lookup_server(struct afs_cell *, struct key *, const uuid_t *, u32); 1415 1411 extern struct afs_server *afs_get_server(struct afs_server *, enum afs_server_trace);
+5 -4
fs/afs/proc.c
··· 307 307 for (i = 0; i < alist->nr_addrs; i++) 308 308 seq_printf(m, " %c %pISpc\n", 309 309 alist->preferred == i ? '>' : '-', 310 - &alist->addrs[i].srx.transport); 310 + rxrpc_kernel_remote_addr(alist->addrs[i].peer)); 311 311 } 312 312 seq_printf(m, " info: fl=%lx rtt=%d\n", vlserver->flags, vlserver->rtt); 313 313 seq_printf(m, " probe: fl=%x e=%d ac=%d out=%d\n", ··· 398 398 seq_printf(m, " - ALIST v=%u rsp=%lx f=%lx\n", 399 399 alist->version, alist->responded, alist->failed); 400 400 for (i = 0; i < alist->nr_addrs; i++) 401 - seq_printf(m, " [%x] %pISpc%s\n", 402 - i, &alist->addrs[i].srx.transport, 403 - alist->preferred == i ? "*" : ""); 401 + seq_printf(m, " [%x] %pISpc%s rtt=%d\n", 402 + i, rxrpc_kernel_remote_addr(alist->addrs[i].peer), 403 + alist->preferred == i ? "*" : "", 404 + rxrpc_kernel_get_srtt(alist->addrs[i].peer)); 404 405 return 0; 405 406 } 406 407
+3 -3
fs/afs/rotate.c
··· 113 113 struct afs_server *server; 114 114 struct afs_vnode *vnode = op->file[0].vnode; 115 115 struct afs_error e; 116 - u32 rtt; 116 + unsigned int rtt; 117 117 int error = op->ac.error, i; 118 118 119 119 _enter("%lx[%d],%lx[%d],%d,%d", ··· 420 420 } 421 421 422 422 op->index = -1; 423 - rtt = U32_MAX; 423 + rtt = UINT_MAX; 424 424 for (i = 0; i < op->server_list->nr_servers; i++) { 425 425 struct afs_server *s = op->server_list->servers[i].server; 426 426 ··· 488 488 489 489 _debug("address [%u] %u/%u %pISp", 490 490 op->index, op->ac.index, op->ac.alist->nr_addrs, 491 - &op->ac.alist->addrs[op->ac.index].srx.transport); 491 + rxrpc_kernel_remote_addr(op->ac.alist->addrs[op->ac.index].peer)); 492 492 493 493 _leave(" = t"); 494 494 return true;
+6 -4
fs/afs/rxrpc.c
··· 296 296 */ 297 297 void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp) 298 298 { 299 - struct sockaddr_rxrpc *srx = &ac->alist->addrs[ac->index].srx; 299 + struct afs_address *addr = &ac->alist->addrs[ac->index]; 300 + struct rxrpc_peer *peer = addr->peer; 300 301 struct rxrpc_call *rxcall; 301 302 struct msghdr msg; 302 303 struct kvec iov[1]; ··· 305 304 s64 tx_total_len; 306 305 int ret; 307 306 308 - _enter(",{%pISp},", &srx->transport); 307 + _enter(",{%pISp},", rxrpc_kernel_remote_addr(addr->peer)); 309 308 310 309 ASSERT(call->type != NULL); 311 310 ASSERT(call->type->name != NULL); ··· 334 333 } 335 334 336 335 /* create a call */ 337 - rxcall = rxrpc_kernel_begin_call(call->net->socket, srx, call->key, 336 + rxcall = rxrpc_kernel_begin_call(call->net->socket, peer, call->key, 338 337 (unsigned long)call, 339 338 tx_total_len, 340 339 call->max_lifespan, ··· 342 341 (call->async ? 343 342 afs_wake_up_async_call : 344 343 afs_wake_up_call_waiter), 344 + addr->service_id, 345 345 call->upgrade, 346 346 (call->intr ? RXRPC_PREINTERRUPTIBLE : 347 347 RXRPC_UNINTERRUPTIBLE), ··· 463 461 max = m + 1; 464 462 pr_notice("kAFS: Peer reported %s failure on %s [%pISp]\n", 465 463 msg, call->type->name, 466 - &call->alist->addrs[call->addr_ix].srx.transport); 464 + rxrpc_kernel_remote_addr(call->alist->addrs[call->addr_ix].peer)); 467 465 } 468 466 } 469 467
+7 -34
fs/afs/server.c
··· 21 21 /* 22 22 * Find a server by one of its addresses. 23 23 */ 24 - struct afs_server *afs_find_server(struct afs_net *net, 25 - const struct sockaddr_rxrpc *srx) 24 + struct afs_server *afs_find_server(struct afs_net *net, const struct rxrpc_peer *peer) 26 25 { 27 26 const struct afs_addr_list *alist; 28 27 struct afs_server *server = NULL; 29 28 unsigned int i; 30 - int seq = 1, diff; 29 + int seq = 1; 31 30 32 31 rcu_read_lock(); 33 32 ··· 37 38 seq++; /* 2 on the 1st/lockless path, otherwise odd */ 38 39 read_seqbegin_or_lock(&net->fs_addr_lock, &seq); 39 40 40 - if (srx->transport.family == AF_INET6) { 41 - const struct sockaddr_in6 *a = &srx->transport.sin6, *b; 42 - hlist_for_each_entry_rcu(server, &net->fs_addresses6, addr6_link) { 43 - alist = rcu_dereference(server->addresses); 44 - for (i = alist->nr_ipv4; i < alist->nr_addrs; i++) { 45 - b = &alist->addrs[i].srx.transport.sin6; 46 - diff = ((u16 __force)a->sin6_port - 47 - (u16 __force)b->sin6_port); 48 - if (diff == 0) 49 - diff = memcmp(&a->sin6_addr, 50 - &b->sin6_addr, 51 - sizeof(struct in6_addr)); 52 - if (diff == 0) 53 - goto found; 54 - } 55 - } 56 - } else { 57 - const struct sockaddr_in *a = &srx->transport.sin, *b; 58 - hlist_for_each_entry_rcu(server, &net->fs_addresses4, addr4_link) { 59 - alist = rcu_dereference(server->addresses); 60 - for (i = 0; i < alist->nr_ipv4; i++) { 61 - b = &alist->addrs[i].srx.transport.sin; 62 - diff = ((u16 __force)a->sin_port - 63 - (u16 __force)b->sin_port); 64 - if (diff == 0) 65 - diff = ((u32 __force)a->sin_addr.s_addr - 66 - (u32 __force)b->sin_addr.s_addr); 67 - if (diff == 0) 68 - goto found; 69 - } 70 - } 41 + hlist_for_each_entry_rcu(server, &net->fs_addresses6, addr6_link) { 42 + alist = rcu_dereference(server->addresses); 43 + for (i = 0; i < alist->nr_addrs; i++) 44 + if (alist->addrs[i].peer == peer) 45 + goto found; 71 46 } 72 47 73 48 server = NULL;
+3 -52
fs/afs/vl_alias.c
··· 33 33 } 34 34 35 35 /* 36 - * Compare two addresses. 37 - */ 38 - static int afs_compare_addrs(const struct sockaddr_rxrpc *srx_a, 39 - const struct sockaddr_rxrpc *srx_b) 40 - { 41 - short port_a, port_b; 42 - int addr_a, addr_b, diff; 43 - 44 - diff = (short)srx_a->transport_type - (short)srx_b->transport_type; 45 - if (diff) 46 - goto out; 47 - 48 - switch (srx_a->transport_type) { 49 - case AF_INET: { 50 - const struct sockaddr_in *a = &srx_a->transport.sin; 51 - const struct sockaddr_in *b = &srx_b->transport.sin; 52 - addr_a = ntohl(a->sin_addr.s_addr); 53 - addr_b = ntohl(b->sin_addr.s_addr); 54 - diff = addr_a - addr_b; 55 - if (diff == 0) { 56 - port_a = ntohs(a->sin_port); 57 - port_b = ntohs(b->sin_port); 58 - diff = port_a - port_b; 59 - } 60 - break; 61 - } 62 - 63 - case AF_INET6: { 64 - const struct sockaddr_in6 *a = &srx_a->transport.sin6; 65 - const struct sockaddr_in6 *b = &srx_b->transport.sin6; 66 - diff = memcmp(&a->sin6_addr, &b->sin6_addr, 16); 67 - if (diff == 0) { 68 - port_a = ntohs(a->sin6_port); 69 - port_b = ntohs(b->sin6_port); 70 - diff = port_a - port_b; 71 - } 72 - break; 73 - } 74 - 75 - default: 76 - WARN_ON(1); 77 - diff = 1; 78 - } 79 - 80 - out: 81 - return diff; 82 - } 83 - 84 - /* 85 36 * Compare the address lists of a pair of fileservers. 86 37 */ 87 38 static int afs_compare_fs_alists(const struct afs_server *server_a, ··· 45 94 lb = rcu_dereference(server_b->addresses); 46 95 47 96 while (a < la->nr_addrs && b < lb->nr_addrs) { 48 - const struct sockaddr_rxrpc *srx_a = &la->addrs[a].srx; 49 - const struct sockaddr_rxrpc *srx_b = &lb->addrs[b].srx; 50 - int diff = afs_compare_addrs(srx_a, srx_b); 97 + unsigned long pa = (unsigned long)la->addrs[a].peer; 98 + unsigned long pb = (unsigned long)lb->addrs[b].peer; 99 + long diff = pa - pb; 51 100 52 101 if (diff < 0) { 53 102 a++;
+10 -5
fs/afs/vl_list.c
··· 83 83 /* 84 84 * Build a VL server address list from a DNS queried server list. 85 85 */ 86 - static struct afs_addr_list *afs_extract_vl_addrs(const u8 **_b, const u8 *end, 86 + static struct afs_addr_list *afs_extract_vl_addrs(struct afs_net *net, 87 + const u8 **_b, const u8 *end, 87 88 u8 nr_addrs, u16 port) 88 89 { 89 90 struct afs_addr_list *alist; 90 91 const u8 *b = *_b; 91 92 int ret = -EINVAL; 92 93 93 - alist = afs_alloc_addrlist(nr_addrs, VL_SERVICE, port); 94 + alist = afs_alloc_addrlist(nr_addrs, VL_SERVICE); 94 95 if (!alist) 95 96 return ERR_PTR(-ENOMEM); 96 97 if (nr_addrs == 0) ··· 110 109 goto error; 111 110 } 112 111 memcpy(x, b, 4); 113 - afs_merge_fs_addr4(alist, x[0], port); 112 + ret = afs_merge_fs_addr4(net, alist, x[0], port); 113 + if (ret < 0) 114 + goto error; 114 115 b += 4; 115 116 break; 116 117 ··· 122 119 goto error; 123 120 } 124 121 memcpy(x, b, 16); 125 - afs_merge_fs_addr6(alist, x, port); 122 + ret = afs_merge_fs_addr6(net, alist, x, port); 123 + if (ret < 0) 124 + goto error; 126 125 b += 16; 127 126 break; 128 127 ··· 252 247 /* Extract the addresses - note that we can't skip this as we 253 248 * have to advance the payload pointer. 254 249 */ 255 - addrs = afs_extract_vl_addrs(&b, end, bs.nr_addrs, bs.port); 250 + addrs = afs_extract_vl_addrs(cell->net, &b, end, bs.nr_addrs, bs.port); 256 251 if (IS_ERR(addrs)) { 257 252 ret = PTR_ERR(addrs); 258 253 goto error_2;
+7 -5
fs/afs/vl_probe.c
··· 48 48 { 49 49 struct afs_addr_list *alist = call->alist; 50 50 struct afs_vlserver *server = call->vlserver; 51 + struct afs_address *addr = &alist->addrs[call->addr_ix]; 51 52 unsigned int server_index = call->server_index; 52 53 unsigned int rtt_us = 0; 53 54 unsigned int index = call->addr_ix; ··· 107 106 if (call->service_id == YFS_VL_SERVICE) { 108 107 server->probe.flags |= AFS_VLSERVER_PROBE_IS_YFS; 109 108 set_bit(AFS_VLSERVER_FL_IS_YFS, &server->flags); 110 - alist->addrs[index].srx.srx_service = call->service_id; 109 + addr->service_id = call->service_id; 111 110 } else { 112 111 server->probe.flags |= AFS_VLSERVER_PROBE_NOT_YFS; 113 112 if (!(server->probe.flags & AFS_VLSERVER_PROBE_IS_YFS)) { 114 113 clear_bit(AFS_VLSERVER_FL_IS_YFS, &server->flags); 115 - alist->addrs[index].srx.srx_service = call->service_id; 114 + addr->service_id = call->service_id; 116 115 } 117 116 } 118 117 119 - rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us); 118 + rtt_us = rxrpc_kernel_get_srtt(addr->peer); 120 119 if (rtt_us < server->probe.rtt) { 121 120 server->probe.rtt = rtt_us; 122 121 server->rtt = rtt_us; ··· 131 130 out: 132 131 spin_unlock(&server->probe_lock); 133 132 134 - _debug("probe [%u][%u] %pISpc rtt=%u ret=%d", 135 - server_index, index, &alist->addrs[index].srx.transport, rtt_us, ret); 133 + _debug("probe [%u][%u] %pISpc rtt=%d ret=%d", 134 + server_index, index, rxrpc_kernel_remote_addr(addr->peer), 135 + rtt_us, ret); 136 136 137 137 afs_done_one_vl_probe(server, have_result); 138 138 }
+3 -3
fs/afs/vl_rotate.c
··· 92 92 struct afs_addr_list *alist; 93 93 struct afs_vlserver *vlserver; 94 94 struct afs_error e; 95 - u32 rtt; 95 + unsigned int rtt; 96 96 int error = vc->ac.error, i; 97 97 98 98 _enter("%lx[%d],%lx[%d],%d,%d", ··· 194 194 goto selected_server; 195 195 196 196 vc->index = -1; 197 - rtt = U32_MAX; 197 + rtt = UINT_MAX; 198 198 for (i = 0; i < vc->server_list->nr_servers; i++) { 199 199 struct afs_vlserver *s = vc->server_list->servers[i].server; 200 200 ··· 249 249 250 250 _debug("VL address %d/%d", vc->ac.index, vc->ac.alist->nr_addrs); 251 251 252 - _leave(" = t %pISpc", &vc->ac.alist->addrs[vc->ac.index].srx.transport); 252 + _leave(" = t %pISpc", rxrpc_kernel_remote_addr(vc->ac.alist->addrs[vc->ac.index].peer)); 253 253 return true; 254 254 255 255 next_server:
+15 -7
fs/afs/vlclient.c
··· 208 208 count = ntohl(*bp); 209 209 210 210 nentries = min(nentries, count); 211 - alist = afs_alloc_addrlist(nentries, FS_SERVICE, AFS_FS_PORT); 211 + alist = afs_alloc_addrlist(nentries, FS_SERVICE); 212 212 if (!alist) 213 213 return -ENOMEM; 214 214 alist->version = uniquifier; ··· 230 230 alist = call->ret_alist; 231 231 bp = call->buffer; 232 232 count = min(call->count, 4U); 233 - for (i = 0; i < count; i++) 234 - if (alist->nr_addrs < call->count2) 235 - afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT); 233 + for (i = 0; i < count; i++) { 234 + if (alist->nr_addrs < call->count2) { 235 + ret = afs_merge_fs_addr4(call->net, alist, *bp++, AFS_FS_PORT); 236 + if (ret < 0) 237 + return ret; 238 + } 239 + } 236 240 237 241 call->count -= count; 238 242 if (call->count > 0) ··· 454 450 if (call->count > YFS_MAXENDPOINTS) 455 451 return afs_protocol_error(call, afs_eproto_yvl_fsendpt_num); 456 452 457 - alist = afs_alloc_addrlist(call->count, FS_SERVICE, AFS_FS_PORT); 453 + alist = afs_alloc_addrlist(call->count, FS_SERVICE); 458 454 if (!alist) 459 455 return -ENOMEM; 460 456 alist->version = uniquifier; ··· 492 488 if (ntohl(bp[0]) != sizeof(__be32) * 2) 493 489 return afs_protocol_error( 494 490 call, afs_eproto_yvl_fsendpt4_len); 495 - afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2])); 491 + ret = afs_merge_fs_addr4(call->net, alist, bp[1], ntohl(bp[2])); 492 + if (ret < 0) 493 + return ret; 496 494 bp += 3; 497 495 break; 498 496 case YFS_ENDPOINT_IPV6: 499 497 if (ntohl(bp[0]) != sizeof(__be32) * 5) 500 498 return afs_protocol_error( 501 499 call, afs_eproto_yvl_fsendpt6_len); 502 - afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5])); 500 + ret = afs_merge_fs_addr6(call->net, alist, bp + 1, ntohl(bp[5])); 501 + if (ret < 0) 502 + return ret; 503 503 bp += 6; 504 504 break; 505 505 default:
+11 -4
include/net/af_rxrpc.h
··· 15 15 struct sock; 16 16 struct socket; 17 17 struct rxrpc_call; 18 + struct rxrpc_peer; 18 19 enum rxrpc_abort_reason; 19 20 20 21 enum rxrpc_interruptibility { ··· 42 41 rxrpc_notify_new_call_t, 43 42 rxrpc_discard_new_call_t); 44 43 struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, 45 - struct sockaddr_rxrpc *srx, 44 + struct rxrpc_peer *peer, 46 45 struct key *key, 47 46 unsigned long user_call_ID, 48 47 s64 tx_total_len, 49 48 u32 hard_timeout, 50 49 gfp_t gfp, 51 50 rxrpc_notify_rx_t notify_rx, 51 + u16 service_id, 52 52 bool upgrade, 53 53 enum rxrpc_interruptibility interruptibility, 54 54 unsigned int debug_id); ··· 62 60 u32, int, enum rxrpc_abort_reason); 63 61 void rxrpc_kernel_shutdown_call(struct socket *sock, struct rxrpc_call *call); 64 62 void rxrpc_kernel_put_call(struct socket *sock, struct rxrpc_call *call); 65 - void rxrpc_kernel_get_peer(struct socket *, struct rxrpc_call *, 66 - struct sockaddr_rxrpc *); 67 - bool rxrpc_kernel_get_srtt(struct socket *, struct rxrpc_call *, u32 *); 63 + struct rxrpc_peer *rxrpc_kernel_lookup_peer(struct socket *sock, 64 + struct sockaddr_rxrpc *srx, gfp_t gfp); 65 + void rxrpc_kernel_put_peer(struct rxrpc_peer *peer); 66 + struct rxrpc_peer *rxrpc_kernel_get_peer(struct rxrpc_peer *peer); 67 + struct rxrpc_peer *rxrpc_kernel_get_call_peer(struct socket *sock, struct rxrpc_call *call); 68 + const struct sockaddr_rxrpc *rxrpc_kernel_remote_srx(const struct rxrpc_peer *peer); 69 + const struct sockaddr *rxrpc_kernel_remote_addr(const struct rxrpc_peer *peer); 70 + unsigned int rxrpc_kernel_get_srtt(const struct rxrpc_peer *); 68 71 int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t, 69 72 rxrpc_user_attach_call_t, unsigned long, gfp_t, 70 73 unsigned int);
+3
include/trace/events/rxrpc.h
··· 178 178 #define rxrpc_peer_traces \ 179 179 EM(rxrpc_peer_free, "FREE ") \ 180 180 EM(rxrpc_peer_get_accept, "GET accept ") \ 181 + EM(rxrpc_peer_get_application, "GET app ") \ 181 182 EM(rxrpc_peer_get_bundle, "GET bundle ") \ 183 + EM(rxrpc_peer_get_call, "GET call ") \ 182 184 EM(rxrpc_peer_get_client_conn, "GET cln-conn") \ 183 185 EM(rxrpc_peer_get_input, "GET input ") \ 184 186 EM(rxrpc_peer_get_input_error, "GET inpt-err") \ ··· 189 187 EM(rxrpc_peer_get_service_conn, "GET srv-conn") \ 190 188 EM(rxrpc_peer_new_client, "NEW client ") \ 191 189 EM(rxrpc_peer_new_prealloc, "NEW prealloc") \ 190 + EM(rxrpc_peer_put_application, "PUT app ") \ 192 191 EM(rxrpc_peer_put_bundle, "PUT bundle ") \ 193 192 EM(rxrpc_peer_put_call, "PUT call ") \ 194 193 EM(rxrpc_peer_put_conn, "PUT conn ") \
+54 -8
net/rxrpc/af_rxrpc.c
··· 259 259 } 260 260 261 261 /** 262 + * rxrpc_kernel_lookup_peer - Obtain remote transport endpoint for an address 263 + * @sock: The socket through which it will be accessed 264 + * @srx: The network address 265 + * @gfp: Allocation flags 266 + * 267 + * Lookup or create a remote transport endpoint record for the specified 268 + * address and return it with a ref held. 269 + */ 270 + struct rxrpc_peer *rxrpc_kernel_lookup_peer(struct socket *sock, 271 + struct sockaddr_rxrpc *srx, gfp_t gfp) 272 + { 273 + struct rxrpc_sock *rx = rxrpc_sk(sock->sk); 274 + int ret; 275 + 276 + ret = rxrpc_validate_address(rx, srx, sizeof(*srx)); 277 + if (ret < 0) 278 + return ERR_PTR(ret); 279 + 280 + return rxrpc_lookup_peer(rx->local, srx, gfp); 281 + } 282 + EXPORT_SYMBOL(rxrpc_kernel_lookup_peer); 283 + 284 + /** 285 + * rxrpc_kernel_get_peer - Get a reference on a peer 286 + * @peer: The peer to get a reference on. 287 + * 288 + * Get a record for the remote peer in a call. 289 + */ 290 + struct rxrpc_peer *rxrpc_kernel_get_peer(struct rxrpc_peer *peer) 291 + { 292 + return peer ? rxrpc_get_peer(peer, rxrpc_peer_get_application) : NULL; 293 + } 294 + EXPORT_SYMBOL(rxrpc_kernel_get_peer); 295 + 296 + /** 297 + * rxrpc_kernel_put_peer - Allow a kernel app to drop a peer reference 298 + * @peer: The peer to drop a ref on 299 + */ 300 + void rxrpc_kernel_put_peer(struct rxrpc_peer *peer) 301 + { 302 + rxrpc_put_peer(peer, rxrpc_peer_put_application); 303 + } 304 + EXPORT_SYMBOL(rxrpc_kernel_put_peer); 305 + 306 + /** 262 307 * rxrpc_kernel_begin_call - Allow a kernel service to begin a call 263 308 * @sock: The socket on which to make the call 264 - * @srx: The address of the peer to contact 309 + * @peer: The peer to contact 265 310 * @key: The security context to use (defaults to socket setting) 266 311 * @user_call_ID: The ID to use 267 312 * @tx_total_len: Total length of data to transmit during the call (or -1) 268 313 * @hard_timeout: The maximum lifespan of the call in sec 269 314 * @gfp: The allocation constraints 270 315 * @notify_rx: Where to send notifications instead of socket queue 316 + * @service_id: The ID of the service to contact 271 317 * @upgrade: Request service upgrade for call 272 318 * @interruptibility: The call is interruptible, or can be canceled. 273 319 * @debug_id: The debug ID for tracing to be assigned to the call ··· 326 280 * supplying @srx and @key. 327 281 */ 328 282 struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, 329 - struct sockaddr_rxrpc *srx, 283 + struct rxrpc_peer *peer, 330 284 struct key *key, 331 285 unsigned long user_call_ID, 332 286 s64 tx_total_len, 333 287 u32 hard_timeout, 334 288 gfp_t gfp, 335 289 rxrpc_notify_rx_t notify_rx, 290 + u16 service_id, 336 291 bool upgrade, 337 292 enum rxrpc_interruptibility interruptibility, 338 293 unsigned int debug_id) ··· 342 295 struct rxrpc_call_params p; 343 296 struct rxrpc_call *call; 344 297 struct rxrpc_sock *rx = rxrpc_sk(sock->sk); 345 - int ret; 346 298 347 299 _enter(",,%x,%lx", key_serial(key), user_call_ID); 348 300 349 - ret = rxrpc_validate_address(rx, srx, sizeof(*srx)); 350 - if (ret < 0) 351 - return ERR_PTR(ret); 301 + if (WARN_ON_ONCE(peer->local != rx->local)) 302 + return ERR_PTR(-EIO); 352 303 353 304 lock_sock(&rx->sk); 354 305 ··· 364 319 365 320 memset(&cp, 0, sizeof(cp)); 366 321 cp.local = rx->local; 322 + cp.peer = peer; 367 323 cp.key = key; 368 324 cp.security_level = rx->min_sec_level; 369 325 cp.exclusive = false; 370 326 cp.upgrade = upgrade; 371 - cp.service_id = srx->srx_service; 372 - call = rxrpc_new_client_call(rx, &cp, srx, &p, gfp, debug_id); 327 + cp.service_id = service_id; 328 + call = rxrpc_new_client_call(rx, &cp, &p, gfp, debug_id); 373 329 /* The socket has been unlocked. */ 374 330 if (!IS_ERR(call)) { 375 331 call->notify_rx = notify_rx;
+1 -1
net/rxrpc/ar-internal.h
··· 364 364 365 365 struct rxrpc_conn_parameters { 366 366 struct rxrpc_local *local; /* Representation of local endpoint */ 367 + struct rxrpc_peer *peer; /* Representation of remote endpoint */ 367 368 struct key *key; /* Security details */ 368 369 bool exclusive; /* T if conn is exclusive */ 369 370 bool upgrade; /* T if service ID can be upgraded */ ··· 868 867 struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *, gfp_t, unsigned int); 869 868 struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *, 870 869 struct rxrpc_conn_parameters *, 871 - struct sockaddr_rxrpc *, 872 870 struct rxrpc_call_params *, gfp_t, 873 871 unsigned int); 874 872 void rxrpc_start_call_timer(struct rxrpc_call *call);
+9 -8
net/rxrpc/call_object.c
··· 193 193 * Allocate a new client call. 194 194 */ 195 195 static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx, 196 - struct sockaddr_rxrpc *srx, 197 196 struct rxrpc_conn_parameters *cp, 198 197 struct rxrpc_call_params *p, 199 198 gfp_t gfp, ··· 210 211 now = ktime_get_real(); 211 212 call->acks_latest_ts = now; 212 213 call->cong_tstamp = now; 213 - call->dest_srx = *srx; 214 + call->dest_srx = cp->peer->srx; 215 + call->dest_srx.srx_service = cp->service_id; 214 216 call->interruptibility = p->interruptibility; 215 217 call->tx_total_len = p->tx_total_len; 216 218 call->key = key_get(cp->key); 219 + call->peer = rxrpc_get_peer(cp->peer, rxrpc_peer_get_call); 217 220 call->local = rxrpc_get_local(cp->local, rxrpc_local_get_call); 218 221 call->security_level = cp->security_level; 219 222 if (p->kernel) ··· 307 306 308 307 _enter("{%d,%lx},", call->debug_id, call->user_call_ID); 309 308 310 - call->peer = rxrpc_lookup_peer(local, &call->dest_srx, gfp); 311 - if (!call->peer) 312 - goto error; 313 - 314 309 ret = rxrpc_look_up_bundle(call, gfp); 315 310 if (ret < 0) 316 311 goto error; ··· 331 334 */ 332 335 struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, 333 336 struct rxrpc_conn_parameters *cp, 334 - struct sockaddr_rxrpc *srx, 335 337 struct rxrpc_call_params *p, 336 338 gfp_t gfp, 337 339 unsigned int debug_id) ··· 345 349 346 350 _enter("%p,%lx", rx, p->user_call_ID); 347 351 352 + if (WARN_ON_ONCE(!cp->peer)) { 353 + release_sock(&rx->sk); 354 + return ERR_PTR(-EIO); 355 + } 356 + 348 357 limiter = rxrpc_get_call_slot(p, gfp); 349 358 if (!limiter) { 350 359 release_sock(&rx->sk); 351 360 return ERR_PTR(-ERESTARTSYS); 352 361 } 353 362 354 - call = rxrpc_alloc_client_call(rx, srx, cp, p, gfp, debug_id); 363 + call = rxrpc_alloc_client_call(rx, cp, p, gfp, debug_id); 355 364 if (IS_ERR(call)) { 356 365 release_sock(&rx->sk); 357 366 up(limiter);
+38 -22
net/rxrpc/peer_object.c
··· 22 22 #include <net/ip6_route.h> 23 23 #include "ar-internal.h" 24 24 25 + static const struct sockaddr_rxrpc rxrpc_null_addr; 26 + 25 27 /* 26 28 * Hash a peer key. 27 29 */ ··· 459 457 } 460 458 461 459 /** 462 - * rxrpc_kernel_get_peer - Get the peer address of a call 460 + * rxrpc_kernel_get_call_peer - Get the peer address of a call 463 461 * @sock: The socket on which the call is in progress. 464 462 * @call: The call to query 465 - * @_srx: Where to place the result 466 463 * 467 - * Get the address of the remote peer in a call. 464 + * Get a record for the remote peer in a call. 468 465 */ 469 - void rxrpc_kernel_get_peer(struct socket *sock, struct rxrpc_call *call, 470 - struct sockaddr_rxrpc *_srx) 466 + struct rxrpc_peer *rxrpc_kernel_get_call_peer(struct socket *sock, struct rxrpc_call *call) 471 467 { 472 - *_srx = call->peer->srx; 468 + return call->peer; 473 469 } 474 - EXPORT_SYMBOL(rxrpc_kernel_get_peer); 470 + EXPORT_SYMBOL(rxrpc_kernel_get_call_peer); 475 471 476 472 /** 477 473 * rxrpc_kernel_get_srtt - Get a call's peer smoothed RTT 478 - * @sock: The socket on which the call is in progress. 479 - * @call: The call to query 480 - * @_srtt: Where to store the SRTT value. 474 + * @peer: The peer to query 481 475 * 482 - * Get the call's peer smoothed RTT in uS. 476 + * Get the call's peer smoothed RTT in uS or UINT_MAX if we have no samples. 483 477 */ 484 - bool rxrpc_kernel_get_srtt(struct socket *sock, struct rxrpc_call *call, 485 - u32 *_srtt) 478 + unsigned int rxrpc_kernel_get_srtt(const struct rxrpc_peer *peer) 486 479 { 487 - struct rxrpc_peer *peer = call->peer; 488 - 489 - if (peer->rtt_count == 0) { 490 - *_srtt = 1000000; /* 1S */ 491 - return false; 492 - } 493 - 494 - *_srtt = call->peer->srtt_us >> 3; 495 - return true; 480 + return peer->rtt_count > 0 ? peer->srtt_us >> 3 : UINT_MAX; 496 481 } 497 482 EXPORT_SYMBOL(rxrpc_kernel_get_srtt); 483 + 484 + /** 485 + * rxrpc_kernel_remote_srx - Get the address of a peer 486 + * @peer: The peer to query 487 + * 488 + * Get a pointer to the address from a peer record. The caller is responsible 489 + * for making sure that the address is not deallocated. 490 + */ 491 + const struct sockaddr_rxrpc *rxrpc_kernel_remote_srx(const struct rxrpc_peer *peer) 492 + { 493 + return peer ? &peer->srx : &rxrpc_null_addr; 494 + } 495 + EXPORT_SYMBOL(rxrpc_kernel_remote_srx); 496 + 497 + /** 498 + * rxrpc_kernel_remote_addr - Get the peer transport address of a call 499 + * @peer: The peer to query 500 + * 501 + * Get a pointer to the transport address from a peer record. The caller is 502 + * responsible for making sure that the address is not deallocated. 503 + */ 504 + const struct sockaddr *rxrpc_kernel_remote_addr(const struct rxrpc_peer *peer) 505 + { 506 + return (const struct sockaddr *) 507 + (peer ? &peer->srx.transport : &rxrpc_null_addr.transport); 508 + } 509 + EXPORT_SYMBOL(rxrpc_kernel_remote_addr);
+10 -1
net/rxrpc/sendmsg.c
··· 572 572 __acquires(&call->user_mutex) 573 573 { 574 574 struct rxrpc_conn_parameters cp; 575 + struct rxrpc_peer *peer; 575 576 struct rxrpc_call *call; 576 577 struct key *key; 577 578 ··· 585 584 return ERR_PTR(-EDESTADDRREQ); 586 585 } 587 586 587 + peer = rxrpc_lookup_peer(rx->local, srx, GFP_KERNEL); 588 + if (!peer) { 589 + release_sock(&rx->sk); 590 + return ERR_PTR(-ENOMEM); 591 + } 592 + 588 593 key = rx->key; 589 594 if (key && !rx->key->payload.data[0]) 590 595 key = NULL; 591 596 592 597 memset(&cp, 0, sizeof(cp)); 593 598 cp.local = rx->local; 599 + cp.peer = peer; 594 600 cp.key = rx->key; 595 601 cp.security_level = rx->min_sec_level; 596 602 cp.exclusive = rx->exclusive | p->exclusive; 597 603 cp.upgrade = p->upgrade; 598 604 cp.service_id = srx->srx_service; 599 - call = rxrpc_new_client_call(rx, &cp, srx, &p->call, GFP_KERNEL, 605 + call = rxrpc_new_client_call(rx, &cp, &p->call, GFP_KERNEL, 600 606 atomic_inc_return(&rxrpc_debug_id)); 601 607 /* The socket is now unlocked */ 602 608 609 + rxrpc_put_peer(peer, rxrpc_peer_put_application); 603 610 _leave(" = %p\n", call); 604 611 return call; 605 612 }