From nobody Tue Dec 16 05:37:31 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7C44EC4167B for ; Wed, 13 Dec 2023 13:51:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1379336AbjLMNvD (ORCPT ); Wed, 13 Dec 2023 08:51:03 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43596 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1379318AbjLMNue (ORCPT ); Wed, 13 Dec 2023 08:50:34 -0500 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CC5DF12C for ; Wed, 13 Dec 2023 05:50:28 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1702475427; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=q6Lp8rfctSKWrF/kxpDTZ66NjpDrrMBQkxfGUgvl4+Q=; b=aBWnsyl6mtir47qPdsKVjsbyNx0UtTvgHeJeRrfdGK15K28t3U1eCe2878XpRBzy0Bhp3g aS676j48zKTHEoGND6Pd5tw9j+kStoLOHi5PduBr6FzKAU7qIRGNXz6qGNdc9Pt3Owckqr qpOKkLl6T2Y3Y9rBD/mOq3YLO0KeHDA= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-404-CZPYmNY9NO2U5V9dt3ph4A-1; Wed, 13 Dec 2023 08:50:21 -0500 X-MC-Unique: CZPYmNY9NO2U5V9dt3ph4A-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 79D423C2A1CD; Wed, 13 Dec 2023 13:50:21 +0000 (UTC) Received: from warthog.procyon.org.com (unknown [10.42.28.2]) by smtp.corp.redhat.com (Postfix) with ESMTP id 5DA591121306; Wed, 13 Dec 2023 13:50:20 +0000 (UTC) From: David Howells To: Marc Dionne Cc: David Howells , linux-afs@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 09/40] rxrpc, afs: Allow afs to pin rxrpc_peer objects Date: Wed, 13 Dec 2023 13:49:31 +0000 Message-ID: <20231213135003.367397-10-dhowells@redhat.com> In-Reply-To: <20231213135003.367397-1-dhowells@redhat.com> References: <20231213135003.367397-1-dhowells@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.3 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" 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 cc: Marc Dionne cc: linux-afs@lists.infradead.org --- Notes: Changes =3D=3D=3D=3D=3D=3D=3D ver #2) - Add a couple of missing symbol exports. fs/afs/addr_list.c | 125 ++++++++++++++++++----------------- fs/afs/cmservice.c | 5 +- fs/afs/fs_probe.c | 11 +-- fs/afs/internal.h | 26 ++++---- fs/afs/proc.c | 9 +-- fs/afs/rotate.c | 6 +- fs/afs/rxrpc.c | 10 +-- fs/afs/server.c | 41 ++---------- fs/afs/vl_alias.c | 55 +-------------- fs/afs/vl_list.c | 15 +++-- fs/afs/vl_probe.c | 12 ++-- fs/afs/vl_rotate.c | 6 +- fs/afs/vlclient.c | 22 ++++-- include/net/af_rxrpc.h | 15 +++-- include/trace/events/rxrpc.h | 3 + net/rxrpc/af_rxrpc.c | 62 ++++++++++++++--- net/rxrpc/ar-internal.h | 2 +- net/rxrpc/call_object.c | 17 ++--- net/rxrpc/peer_object.c | 58 ++++++++++------ net/rxrpc/sendmsg.c | 11 ++- 20 files changed, 273 insertions(+), 238 deletions(-) diff --git a/fs/afs/addr_list.c b/fs/afs/addr_list.c index ac05a59e9d46..519821f5aedc 100644 --- a/fs/afs/addr_list.c +++ b/fs/afs/addr_list.c @@ -13,26 +13,33 @@ #include "internal.h" #include "afs_fs.h" =20 +static void afs_free_addrlist(struct rcu_head *rcu) +{ + struct afs_addr_list *alist =3D container_of(rcu, struct afs_addr_list, r= cu); + unsigned int i; + + for (i =3D 0; i < alist->nr_addrs; i++) + rxrpc_kernel_put_peer(alist->addrs[i].peer); +} + /* * Release an address list. */ void afs_put_addrlist(struct afs_addr_list *alist) { if (alist && refcount_dec_and_test(&alist->usage)) - kfree_rcu(alist, rcu); + call_rcu(&alist->rcu, afs_free_addrlist); } =20 /* * Allocate an address list. */ -struct afs_addr_list *afs_alloc_addrlist(unsigned int nr, - unsigned short service, - unsigned short port) +struct afs_addr_list *afs_alloc_addrlist(unsigned int nr, u16 service_id) { struct afs_addr_list *alist; unsigned int i; =20 - _enter("%u,%u,%u", nr, service, port); + _enter("%u,%u", nr, service_id); =20 if (nr > AFS_MAX_ADDRESSES) nr =3D AFS_MAX_ADDRESSES; @@ -44,16 +51,8 @@ struct afs_addr_list *afs_alloc_addrlist(unsigned int nr, refcount_set(&alist->usage, 1); alist->max_addrs =3D nr; =20 - for (i =3D 0; i < nr; i++) { - struct sockaddr_rxrpc *srx =3D &alist->addrs[i].srx; - srx->srx_family =3D AF_RXRPC; - srx->srx_service =3D service; - srx->transport_type =3D SOCK_DGRAM; - srx->transport_len =3D sizeof(srx->transport.sin6); - srx->transport.sin6.sin6_family =3D AF_INET6; - srx->transport.sin6.sin6_port =3D htons(port); - } - + for (i =3D 0; i < nr; i++) + alist->addrs[i].service_id =3D service_id; return alist; } =20 @@ -126,7 +125,7 @@ struct afs_vlserver_list *afs_parse_text_addrs(struct a= fs_net *net, if (!vllist->servers[0].server) goto error_vl; =20 - alist =3D afs_alloc_addrlist(nr, service, AFS_VL_PORT); + alist =3D afs_alloc_addrlist(nr, service); if (!alist) goto error; =20 @@ -197,9 +196,11 @@ struct afs_vlserver_list *afs_parse_text_addrs(struct = afs_net *net, } =20 if (family =3D=3D AF_INET) - afs_merge_fs_addr4(alist, x[0], xport); + ret =3D afs_merge_fs_addr4(net, alist, x[0], xport); else - afs_merge_fs_addr6(alist, x, xport); + ret =3D afs_merge_fs_addr6(net, alist, x, xport); + if (ret < 0) + goto error; =20 } while (p < end); =20 @@ -271,25 +272,33 @@ struct afs_vlserver_list *afs_dns_query(struct afs_ce= ll *cell, time64_t *_expiry /* * Merge an IPv4 entry into a fileserver address list. */ -void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr, u16 port) +int afs_merge_fs_addr4(struct afs_net *net, struct afs_addr_list *alist, + __be32 xdr, u16 port) { - struct sockaddr_rxrpc *srx; - u32 addr =3D ntohl(xdr); + struct sockaddr_rxrpc srx; + struct rxrpc_peer *peer; int i; =20 if (alist->nr_addrs >=3D alist->max_addrs) - return; + return 0; =20 - for (i =3D 0; i < alist->nr_ipv4; i++) { - struct sockaddr_in *a =3D &alist->addrs[i].srx.transport.sin; - u32 a_addr =3D ntohl(a->sin_addr.s_addr); - u16 a_port =3D ntohs(a->sin_port); + srx.srx_family =3D AF_RXRPC; + srx.transport_type =3D SOCK_DGRAM; + srx.transport_len =3D sizeof(srx.transport.sin); + srx.transport.sin.sin_family =3D AF_INET; + srx.transport.sin.sin_port =3D htons(port); + srx.transport.sin.sin_addr.s_addr =3D xdr; =20 - if (addr =3D=3D a_addr && port =3D=3D a_port) - return; - if (addr =3D=3D a_addr && port < a_port) - break; - if (addr < a_addr) + peer =3D rxrpc_kernel_lookup_peer(net->socket, &srx, GFP_KERNEL); + if (!peer) + return -ENOMEM; + + for (i =3D 0; i < alist->nr_ipv4; i++) { + if (peer =3D=3D alist->addrs[i].peer) { + rxrpc_kernel_put_peer(peer); + return 0; + } + if (peer <=3D alist->addrs[i].peer) break; } =20 @@ -298,38 +307,42 @@ void afs_merge_fs_addr4(struct afs_addr_list *alist, = __be32 xdr, u16 port) alist->addrs + i, sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); =20 - srx =3D &alist->addrs[i].srx; - srx->srx_family =3D AF_RXRPC; - srx->transport_type =3D SOCK_DGRAM; - srx->transport_len =3D sizeof(srx->transport.sin); - srx->transport.sin.sin_family =3D AF_INET; - srx->transport.sin.sin_port =3D htons(port); - srx->transport.sin.sin_addr.s_addr =3D xdr; + alist->addrs[i].peer =3D peer; alist->nr_ipv4++; alist->nr_addrs++; + return 0; } =20 /* * Merge an IPv6 entry into a fileserver address list. */ -void afs_merge_fs_addr6(struct afs_addr_list *alist, __be32 *xdr, u16 port) +int afs_merge_fs_addr6(struct afs_net *net, struct afs_addr_list *alist, + __be32 *xdr, u16 port) { - struct sockaddr_rxrpc *srx; - int i, diff; + struct sockaddr_rxrpc srx; + struct rxrpc_peer *peer; + int i; =20 if (alist->nr_addrs >=3D alist->max_addrs) - return; + return 0; =20 - for (i =3D alist->nr_ipv4; i < alist->nr_addrs; i++) { - struct sockaddr_in6 *a =3D &alist->addrs[i].srx.transport.sin6; - u16 a_port =3D ntohs(a->sin6_port); + srx.srx_family =3D AF_RXRPC; + srx.transport_type =3D SOCK_DGRAM; + srx.transport_len =3D sizeof(srx.transport.sin6); + srx.transport.sin6.sin6_family =3D AF_INET6; + srx.transport.sin6.sin6_port =3D htons(port); + memcpy(&srx.transport.sin6.sin6_addr, xdr, 16); =20 - diff =3D memcmp(xdr, &a->sin6_addr, 16); - if (diff =3D=3D 0 && port =3D=3D a_port) - return; - if (diff =3D=3D 0 && port < a_port) - break; - if (diff < 0) + peer =3D rxrpc_kernel_lookup_peer(net->socket, &srx, GFP_KERNEL); + if (!peer) + return -ENOMEM; + + for (i =3D alist->nr_ipv4; i < alist->nr_addrs; i++) { + if (peer =3D=3D alist->addrs[i].peer) { + rxrpc_kernel_put_peer(peer); + return 0; + } + if (peer <=3D alist->addrs[i].peer) break; } =20 @@ -337,15 +350,9 @@ void afs_merge_fs_addr6(struct afs_addr_list *alist, _= _be32 *xdr, u16 port) memmove(alist->addrs + i + 1, alist->addrs + i, sizeof(alist->addrs[0]) * (alist->nr_addrs - i)); - - srx =3D &alist->addrs[i].srx; - srx->srx_family =3D AF_RXRPC; - srx->transport_type =3D SOCK_DGRAM; - srx->transport_len =3D sizeof(srx->transport.sin6); - srx->transport.sin6.sin6_family =3D AF_INET6; - srx->transport.sin6.sin6_port =3D htons(port); - memcpy(&srx->transport.sin6.sin6_addr, xdr, 16); + alist->addrs[i].peer =3D peer; alist->nr_addrs++; + return 0; } =20 /* diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index d4ddb20d6732..99a3f20bc786 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c @@ -146,10 +146,11 @@ static int afs_find_cm_server_by_peer(struct afs_call= *call) { struct sockaddr_rxrpc srx; struct afs_server *server; + struct rxrpc_peer *peer; =20 - rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx); + peer =3D rxrpc_kernel_get_call_peer(call->net->socket, call->rxcall); =20 - server =3D afs_find_server(call->net, &srx); + server =3D afs_find_server(call->net, peer); if (!server) { trace_afs_cm_no_server(call, &srx); return 0; diff --git a/fs/afs/fs_probe.c b/fs/afs/fs_probe.c index 3dd24842f277..58d28b82571e 100644 --- a/fs/afs/fs_probe.c +++ b/fs/afs/fs_probe.c @@ -101,6 +101,7 @@ static void afs_fs_probe_not_done(struct afs_net *net, void afs_fileserver_probe_result(struct afs_call *call) { struct afs_addr_list *alist =3D call->alist; + struct afs_address *addr =3D &alist->addrs[call->addr_ix]; struct afs_server *server =3D call->server; unsigned int index =3D call->addr_ix; unsigned int rtt_us =3D 0, cap0; @@ -153,12 +154,12 @@ void afs_fileserver_probe_result(struct afs_call *cal= l) if (call->service_id =3D=3D YFS_FS_SERVICE) { server->probe.is_yfs =3D true; set_bit(AFS_SERVER_FL_IS_YFS, &server->flags); - alist->addrs[index].srx.srx_service =3D call->service_id; + addr->service_id =3D call->service_id; } else { server->probe.not_yfs =3D true; if (!server->probe.is_yfs) { clear_bit(AFS_SERVER_FL_IS_YFS, &server->flags); - alist->addrs[index].srx.srx_service =3D call->service_id; + addr->service_id =3D call->service_id; } cap0 =3D ntohl(call->tmp); if (cap0 & AFS3_VICED_CAPABILITY_64BITFILES) @@ -167,7 +168,7 @@ void afs_fileserver_probe_result(struct afs_call *call) clear_bit(AFS_SERVER_FL_HAS_FS64, &server->flags); } =20 - rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us); + rtt_us =3D rxrpc_kernel_get_srtt(addr->peer); if (rtt_us < server->probe.rtt) { server->probe.rtt =3D rtt_us; server->rtt =3D rtt_us; @@ -181,8 +182,8 @@ void afs_fileserver_probe_result(struct afs_call *call) out: spin_unlock(&server->probe_lock); =20 - _debug("probe %pU [%u] %pISpc rtt=3D%u ret=3D%d", - &server->uuid, index, &alist->addrs[index].srx.transport, + _debug("probe %pU [%u] %pISpc rtt=3D%d ret=3D%d", + &server->uuid, index, rxrpc_kernel_remote_addr(alist->addrs[index]= .peer), rtt_us, ret); =20 return afs_done_one_fs_probe(call->net, server); diff --git a/fs/afs/internal.h b/fs/afs/internal.h index e2adb314ab6a..ec08b4a7e499 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -72,6 +72,11 @@ enum afs_call_state { AFS_CALL_COMPLETE, /* Completed or failed */ }; =20 +struct afs_address { + struct rxrpc_peer *peer; + u16 service_id; +}; + /* * List of server addresses. */ @@ -87,9 +92,7 @@ struct afs_addr_list { enum dns_lookup_status status:8; unsigned long failed; /* Mask of addrs that failed locally/ICMP */ unsigned long responded; /* Mask of addrs that responded */ - struct { - struct sockaddr_rxrpc srx; - } addrs[] __counted_by(max_addrs); + struct afs_address addrs[] __counted_by(max_addrs); #define AFS_MAX_ADDRESSES ((unsigned int)(sizeof(unsigned long) * 8)) }; =20 @@ -420,7 +423,7 @@ struct afs_vlserver { atomic_t probe_outstanding; spinlock_t probe_lock; struct { - unsigned int rtt; /* RTT in uS */ + unsigned int rtt; /* Best RTT in uS (or UINT_MAX) */ u32 abort_code; short error; unsigned short flags; @@ -537,7 +540,7 @@ struct afs_server { atomic_t probe_outstanding; spinlock_t probe_lock; struct { - unsigned int rtt; /* RTT in uS */ + unsigned int rtt; /* Best RTT in uS (or UINT_MAX) */ u32 abort_code; short error; bool responded:1; @@ -964,9 +967,7 @@ static inline struct afs_addr_list *afs_get_addrlist(st= ruct afs_addr_list *alist refcount_inc(&alist->usage); return alist; } -extern struct afs_addr_list *afs_alloc_addrlist(unsigned int, - unsigned short, - unsigned short); +extern struct afs_addr_list *afs_alloc_addrlist(unsigned int nr, u16 servi= ce_id); extern void afs_put_addrlist(struct afs_addr_list *); extern struct afs_vlserver_list *afs_parse_text_addrs(struct afs_net *, const char *, size_t, char, @@ -977,8 +978,10 @@ extern struct afs_vlserver_list *afs_dns_query(struct = afs_cell *, time64_t *); extern bool afs_iterate_addresses(struct afs_addr_cursor *); extern int afs_end_cursor(struct afs_addr_cursor *); =20 -extern void afs_merge_fs_addr4(struct afs_addr_list *, __be32, u16); -extern void afs_merge_fs_addr6(struct afs_addr_list *, __be32 *, u16); +extern int afs_merge_fs_addr4(struct afs_net *net, struct afs_addr_list *a= ddr, + __be32 xdr, u16 port); +extern int afs_merge_fs_addr6(struct afs_net *net, struct afs_addr_list *a= ddr, + __be32 *xdr, u16 port); =20 /* * callback.c @@ -1405,8 +1408,7 @@ extern void __exit afs_clean_up_permit_cache(void); */ extern spinlock_t afs_server_peer_lock; =20 -extern struct afs_server *afs_find_server(struct afs_net *, - const struct sockaddr_rxrpc *); +extern struct afs_server *afs_find_server(struct afs_net *, const struct r= xrpc_peer *); extern struct afs_server *afs_find_server_by_uuid(struct afs_net *, const = uuid_t *); extern struct afs_server *afs_lookup_server(struct afs_cell *, struct key = *, const uuid_t *, u32); extern struct afs_server *afs_get_server(struct afs_server *, enum afs_ser= ver_trace); diff --git a/fs/afs/proc.c b/fs/afs/proc.c index ab9cd986cfd9..8a65a06908d2 100644 --- a/fs/afs/proc.c +++ b/fs/afs/proc.c @@ -307,7 +307,7 @@ static int afs_proc_cell_vlservers_show(struct seq_file= *m, void *v) for (i =3D 0; i < alist->nr_addrs; i++) seq_printf(m, " %c %pISpc\n", alist->preferred =3D=3D i ? '>' : '-', - &alist->addrs[i].srx.transport); + rxrpc_kernel_remote_addr(alist->addrs[i].peer)); } seq_printf(m, " info: fl=3D%lx rtt=3D%d\n", vlserver->flags, vlserver->rt= t); seq_printf(m, " probe: fl=3D%x e=3D%d ac=3D%d out=3D%d\n", @@ -398,9 +398,10 @@ static int afs_proc_servers_show(struct seq_file *m, v= oid *v) seq_printf(m, " - ALIST v=3D%u rsp=3D%lx f=3D%lx\n", alist->version, alist->responded, alist->failed); for (i =3D 0; i < alist->nr_addrs; i++) - seq_printf(m, " [%x] %pISpc%s\n", - i, &alist->addrs[i].srx.transport, - alist->preferred =3D=3D i ? "*" : ""); + seq_printf(m, " [%x] %pISpc%s rtt=3D%d\n", + i, rxrpc_kernel_remote_addr(alist->addrs[i].peer), + alist->preferred =3D=3D i ? "*" : "", + rxrpc_kernel_get_srtt(alist->addrs[i].peer)); return 0; } =20 diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c index 46081e5da6f5..59aed7a6dd11 100644 --- a/fs/afs/rotate.c +++ b/fs/afs/rotate.c @@ -113,7 +113,7 @@ bool afs_select_fileserver(struct afs_operation *op) struct afs_server *server; struct afs_vnode *vnode =3D op->file[0].vnode; struct afs_error e; - u32 rtt; + unsigned int rtt; int error =3D op->ac.error, i; =20 _enter("%lx[%d],%lx[%d],%d,%d", @@ -420,7 +420,7 @@ bool afs_select_fileserver(struct afs_operation *op) } =20 op->index =3D -1; - rtt =3D U32_MAX; + rtt =3D UINT_MAX; for (i =3D 0; i < op->server_list->nr_servers; i++) { struct afs_server *s =3D op->server_list->servers[i].server; =20 @@ -488,7 +488,7 @@ bool afs_select_fileserver(struct afs_operation *op) =20 _debug("address [%u] %u/%u %pISp", op->index, op->ac.index, op->ac.alist->nr_addrs, - &op->ac.alist->addrs[op->ac.index].srx.transport); + rxrpc_kernel_remote_addr(op->ac.alist->addrs[op->ac.index].peer)); =20 _leave(" =3D t"); return true; diff --git a/fs/afs/rxrpc.c b/fs/afs/rxrpc.c index 181317126e43..2603db03b7ff 100644 --- a/fs/afs/rxrpc.c +++ b/fs/afs/rxrpc.c @@ -296,7 +296,8 @@ static void afs_notify_end_request_tx(struct sock *sock, */ void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_= t gfp) { - struct sockaddr_rxrpc *srx =3D &ac->alist->addrs[ac->index].srx; + struct afs_address *addr =3D &ac->alist->addrs[ac->index]; + struct rxrpc_peer *peer =3D addr->peer; struct rxrpc_call *rxcall; struct msghdr msg; struct kvec iov[1]; @@ -304,7 +305,7 @@ void afs_make_call(struct afs_addr_cursor *ac, struct a= fs_call *call, gfp_t gfp) s64 tx_total_len; int ret; =20 - _enter(",{%pISp},", &srx->transport); + _enter(",{%pISp},", rxrpc_kernel_remote_addr(addr->peer)); =20 ASSERT(call->type !=3D NULL); ASSERT(call->type->name !=3D NULL); @@ -333,7 +334,7 @@ void afs_make_call(struct afs_addr_cursor *ac, struct a= fs_call *call, gfp_t gfp) } =20 /* create a call */ - rxcall =3D rxrpc_kernel_begin_call(call->net->socket, srx, call->key, + rxcall =3D rxrpc_kernel_begin_call(call->net->socket, peer, call->key, (unsigned long)call, tx_total_len, call->max_lifespan, @@ -341,6 +342,7 @@ void afs_make_call(struct afs_addr_cursor *ac, struct a= fs_call *call, gfp_t gfp) (call->async ? afs_wake_up_async_call : afs_wake_up_call_waiter), + addr->service_id, call->upgrade, (call->intr ? RXRPC_PREINTERRUPTIBLE : RXRPC_UNINTERRUPTIBLE), @@ -461,7 +463,7 @@ static void afs_log_error(struct afs_call *call, s32 re= mote_abort) max =3D m + 1; pr_notice("kAFS: Peer reported %s failure on %s [%pISp]\n", msg, call->type->name, - &call->alist->addrs[call->addr_ix].srx.transport); + rxrpc_kernel_remote_addr(call->alist->addrs[call->addr_ix].peer)); } } =20 diff --git a/fs/afs/server.c b/fs/afs/server.c index b8e2d211d4a1..5b5fa94005c9 100644 --- a/fs/afs/server.c +++ b/fs/afs/server.c @@ -21,13 +21,12 @@ static void __afs_put_server(struct afs_net *, struct a= fs_server *); /* * Find a server by one of its addresses. */ -struct afs_server *afs_find_server(struct afs_net *net, - const struct sockaddr_rxrpc *srx) +struct afs_server *afs_find_server(struct afs_net *net, const struct rxrpc= _peer *peer) { const struct afs_addr_list *alist; struct afs_server *server =3D NULL; unsigned int i; - int seq =3D 1, diff; + int seq =3D 1; =20 rcu_read_lock(); =20 @@ -38,37 +37,11 @@ struct afs_server *afs_find_server(struct afs_net *net, seq++; /* 2 on the 1st/lockless path, otherwise odd */ read_seqbegin_or_lock(&net->fs_addr_lock, &seq); =20 - if (srx->transport.family =3D=3D AF_INET6) { - const struct sockaddr_in6 *a =3D &srx->transport.sin6, *b; - hlist_for_each_entry_rcu(server, &net->fs_addresses6, addr6_link) { - alist =3D rcu_dereference(server->addresses); - for (i =3D alist->nr_ipv4; i < alist->nr_addrs; i++) { - b =3D &alist->addrs[i].srx.transport.sin6; - diff =3D ((u16 __force)a->sin6_port - - (u16 __force)b->sin6_port); - if (diff =3D=3D 0) - diff =3D memcmp(&a->sin6_addr, - &b->sin6_addr, - sizeof(struct in6_addr)); - if (diff =3D=3D 0) - goto found; - } - } - } else { - const struct sockaddr_in *a =3D &srx->transport.sin, *b; - hlist_for_each_entry_rcu(server, &net->fs_addresses4, addr4_link) { - alist =3D rcu_dereference(server->addresses); - for (i =3D 0; i < alist->nr_ipv4; i++) { - b =3D &alist->addrs[i].srx.transport.sin; - diff =3D ((u16 __force)a->sin_port - - (u16 __force)b->sin_port); - if (diff =3D=3D 0) - diff =3D ((u32 __force)a->sin_addr.s_addr - - (u32 __force)b->sin_addr.s_addr); - if (diff =3D=3D 0) - goto found; - } - } + hlist_for_each_entry_rcu(server, &net->fs_addresses6, addr6_link) { + alist =3D rcu_dereference(server->addresses); + for (i =3D 0; i < alist->nr_addrs; i++) + if (alist->addrs[i].peer =3D=3D peer) + goto found; } =20 server =3D NULL; diff --git a/fs/afs/vl_alias.c b/fs/afs/vl_alias.c index d3c0df70a1a5..6fdf9f1bedc0 100644 --- a/fs/afs/vl_alias.c +++ b/fs/afs/vl_alias.c @@ -32,55 +32,6 @@ static struct afs_volume *afs_sample_volume(struct afs_c= ell *cell, struct key *k return volume; } =20 -/* - * Compare two addresses. - */ -static int afs_compare_addrs(const struct sockaddr_rxrpc *srx_a, - const struct sockaddr_rxrpc *srx_b) -{ - short port_a, port_b; - int addr_a, addr_b, diff; - - diff =3D (short)srx_a->transport_type - (short)srx_b->transport_type; - if (diff) - goto out; - - switch (srx_a->transport_type) { - case AF_INET: { - const struct sockaddr_in *a =3D &srx_a->transport.sin; - const struct sockaddr_in *b =3D &srx_b->transport.sin; - addr_a =3D ntohl(a->sin_addr.s_addr); - addr_b =3D ntohl(b->sin_addr.s_addr); - diff =3D addr_a - addr_b; - if (diff =3D=3D 0) { - port_a =3D ntohs(a->sin_port); - port_b =3D ntohs(b->sin_port); - diff =3D port_a - port_b; - } - break; - } - - case AF_INET6: { - const struct sockaddr_in6 *a =3D &srx_a->transport.sin6; - const struct sockaddr_in6 *b =3D &srx_b->transport.sin6; - diff =3D memcmp(&a->sin6_addr, &b->sin6_addr, 16); - if (diff =3D=3D 0) { - port_a =3D ntohs(a->sin6_port); - port_b =3D ntohs(b->sin6_port); - diff =3D port_a - port_b; - } - break; - } - - default: - WARN_ON(1); - diff =3D 1; - } - -out: - return diff; -} - /* * Compare the address lists of a pair of fileservers. */ @@ -94,9 +45,9 @@ static int afs_compare_fs_alists(const struct afs_server = *server_a, lb =3D rcu_dereference(server_b->addresses); =20 while (a < la->nr_addrs && b < lb->nr_addrs) { - const struct sockaddr_rxrpc *srx_a =3D &la->addrs[a].srx; - const struct sockaddr_rxrpc *srx_b =3D &lb->addrs[b].srx; - int diff =3D afs_compare_addrs(srx_a, srx_b); + unsigned long pa =3D (unsigned long)la->addrs[a].peer; + unsigned long pb =3D (unsigned long)lb->addrs[b].peer; + long diff =3D pa - pb; =20 if (diff < 0) { a++; diff --git a/fs/afs/vl_list.c b/fs/afs/vl_list.c index acc48216136a..ba89140eee9e 100644 --- a/fs/afs/vl_list.c +++ b/fs/afs/vl_list.c @@ -83,14 +83,15 @@ static u16 afs_extract_le16(const u8 **_b) /* * Build a VL server address list from a DNS queried server list. */ -static struct afs_addr_list *afs_extract_vl_addrs(const u8 **_b, const u8 = *end, +static struct afs_addr_list *afs_extract_vl_addrs(struct afs_net *net, + const u8 **_b, const u8 *end, u8 nr_addrs, u16 port) { struct afs_addr_list *alist; const u8 *b =3D *_b; int ret =3D -EINVAL; =20 - alist =3D afs_alloc_addrlist(nr_addrs, VL_SERVICE, port); + alist =3D afs_alloc_addrlist(nr_addrs, VL_SERVICE); if (!alist) return ERR_PTR(-ENOMEM); if (nr_addrs =3D=3D 0) @@ -109,7 +110,9 @@ static struct afs_addr_list *afs_extract_vl_addrs(const= u8 **_b, const u8 *end, goto error; } memcpy(x, b, 4); - afs_merge_fs_addr4(alist, x[0], port); + ret =3D afs_merge_fs_addr4(net, alist, x[0], port); + if (ret < 0) + goto error; b +=3D 4; break; =20 @@ -119,7 +122,9 @@ static struct afs_addr_list *afs_extract_vl_addrs(const= u8 **_b, const u8 *end, goto error; } memcpy(x, b, 16); - afs_merge_fs_addr6(alist, x, port); + ret =3D afs_merge_fs_addr6(net, alist, x, port); + if (ret < 0) + goto error; b +=3D 16; break; =20 @@ -247,7 +252,7 @@ struct afs_vlserver_list *afs_extract_vlserver_list(str= uct afs_cell *cell, /* Extract the addresses - note that we can't skip this as we * have to advance the payload pointer. */ - addrs =3D afs_extract_vl_addrs(&b, end, bs.nr_addrs, bs.port); + addrs =3D afs_extract_vl_addrs(cell->net, &b, end, bs.nr_addrs, bs.port); if (IS_ERR(addrs)) { ret =3D PTR_ERR(addrs); goto error_2; diff --git a/fs/afs/vl_probe.c b/fs/afs/vl_probe.c index bdd9372e3fb2..9551aef07cee 100644 --- a/fs/afs/vl_probe.c +++ b/fs/afs/vl_probe.c @@ -48,6 +48,7 @@ void afs_vlserver_probe_result(struct afs_call *call) { struct afs_addr_list *alist =3D call->alist; struct afs_vlserver *server =3D call->vlserver; + struct afs_address *addr =3D &alist->addrs[call->addr_ix]; unsigned int server_index =3D call->server_index; unsigned int rtt_us =3D 0; unsigned int index =3D call->addr_ix; @@ -106,16 +107,16 @@ void afs_vlserver_probe_result(struct afs_call *call) if (call->service_id =3D=3D YFS_VL_SERVICE) { server->probe.flags |=3D AFS_VLSERVER_PROBE_IS_YFS; set_bit(AFS_VLSERVER_FL_IS_YFS, &server->flags); - alist->addrs[index].srx.srx_service =3D call->service_id; + addr->service_id =3D call->service_id; } else { server->probe.flags |=3D AFS_VLSERVER_PROBE_NOT_YFS; if (!(server->probe.flags & AFS_VLSERVER_PROBE_IS_YFS)) { clear_bit(AFS_VLSERVER_FL_IS_YFS, &server->flags); - alist->addrs[index].srx.srx_service =3D call->service_id; + addr->service_id =3D call->service_id; } } =20 - rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us); + rtt_us =3D rxrpc_kernel_get_srtt(addr->peer); if (rtt_us < server->probe.rtt) { server->probe.rtt =3D rtt_us; server->rtt =3D rtt_us; @@ -130,8 +131,9 @@ void afs_vlserver_probe_result(struct afs_call *call) out: spin_unlock(&server->probe_lock); =20 - _debug("probe [%u][%u] %pISpc rtt=3D%u ret=3D%d", - server_index, index, &alist->addrs[index].srx.transport, rtt_us, r= et); + _debug("probe [%u][%u] %pISpc rtt=3D%d ret=3D%d", + server_index, index, rxrpc_kernel_remote_addr(addr->peer), + rtt_us, ret); =20 afs_done_one_vl_probe(server, have_result); } diff --git a/fs/afs/vl_rotate.c b/fs/afs/vl_rotate.c index e52b9d4c8a0a..f8f255c966ae 100644 --- a/fs/afs/vl_rotate.c +++ b/fs/afs/vl_rotate.c @@ -92,7 +92,7 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc) struct afs_addr_list *alist; struct afs_vlserver *vlserver; struct afs_error e; - u32 rtt; + unsigned int rtt; int error =3D vc->ac.error, i; =20 _enter("%lx[%d],%lx[%d],%d,%d", @@ -194,7 +194,7 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc) goto selected_server; =20 vc->index =3D -1; - rtt =3D U32_MAX; + rtt =3D UINT_MAX; for (i =3D 0; i < vc->server_list->nr_servers; i++) { struct afs_vlserver *s =3D vc->server_list->servers[i].server; =20 @@ -249,7 +249,7 @@ bool afs_select_vlserver(struct afs_vl_cursor *vc) =20 _debug("VL address %d/%d", vc->ac.index, vc->ac.alist->nr_addrs); =20 - _leave(" =3D t %pISpc", &vc->ac.alist->addrs[vc->ac.index].srx.transport); + _leave(" =3D t %pISpc", rxrpc_kernel_remote_addr(vc->ac.alist->addrs[vc->= ac.index].peer)); return true; =20 next_server: diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c index 00fca3c66ba6..41e7932d75c6 100644 --- a/fs/afs/vlclient.c +++ b/fs/afs/vlclient.c @@ -208,7 +208,7 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call *= call) count =3D ntohl(*bp); =20 nentries =3D min(nentries, count); - alist =3D afs_alloc_addrlist(nentries, FS_SERVICE, AFS_FS_PORT); + alist =3D afs_alloc_addrlist(nentries, FS_SERVICE); if (!alist) return -ENOMEM; alist->version =3D uniquifier; @@ -230,9 +230,13 @@ static int afs_deliver_vl_get_addrs_u(struct afs_call = *call) alist =3D call->ret_alist; bp =3D call->buffer; count =3D min(call->count, 4U); - for (i =3D 0; i < count; i++) - if (alist->nr_addrs < call->count2) - afs_merge_fs_addr4(alist, *bp++, AFS_FS_PORT); + for (i =3D 0; i < count; i++) { + if (alist->nr_addrs < call->count2) { + ret =3D afs_merge_fs_addr4(call->net, alist, *bp++, AFS_FS_PORT); + if (ret < 0) + return ret; + } + } =20 call->count -=3D count; if (call->count > 0) @@ -450,7 +454,7 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs_c= all *call) if (call->count > YFS_MAXENDPOINTS) return afs_protocol_error(call, afs_eproto_yvl_fsendpt_num); =20 - alist =3D afs_alloc_addrlist(call->count, FS_SERVICE, AFS_FS_PORT); + alist =3D afs_alloc_addrlist(call->count, FS_SERVICE); if (!alist) return -ENOMEM; alist->version =3D uniquifier; @@ -488,14 +492,18 @@ static int afs_deliver_yfsvl_get_endpoints(struct afs= _call *call) if (ntohl(bp[0]) !=3D sizeof(__be32) * 2) return afs_protocol_error( call, afs_eproto_yvl_fsendpt4_len); - afs_merge_fs_addr4(alist, bp[1], ntohl(bp[2])); + ret =3D afs_merge_fs_addr4(call->net, alist, bp[1], ntohl(bp[2])); + if (ret < 0) + return ret; bp +=3D 3; break; case YFS_ENDPOINT_IPV6: if (ntohl(bp[0]) !=3D sizeof(__be32) * 5) return afs_protocol_error( call, afs_eproto_yvl_fsendpt6_len); - afs_merge_fs_addr6(alist, bp + 1, ntohl(bp[5])); + ret =3D afs_merge_fs_addr6(call->net, alist, bp + 1, ntohl(bp[5])); + if (ret < 0) + return ret; bp +=3D 6; break; default: diff --git a/include/net/af_rxrpc.h b/include/net/af_rxrpc.h index 5531dd08061e..0754c463224a 100644 --- a/include/net/af_rxrpc.h +++ b/include/net/af_rxrpc.h @@ -15,6 +15,7 @@ struct key; struct sock; struct socket; struct rxrpc_call; +struct rxrpc_peer; enum rxrpc_abort_reason; =20 enum rxrpc_interruptibility { @@ -41,13 +42,14 @@ void rxrpc_kernel_new_call_notification(struct socket *, rxrpc_notify_new_call_t, rxrpc_discard_new_call_t); struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, - struct sockaddr_rxrpc *srx, + struct rxrpc_peer *peer, struct key *key, unsigned long user_call_ID, s64 tx_total_len, u32 hard_timeout, gfp_t gfp, rxrpc_notify_rx_t notify_rx, + u16 service_id, bool upgrade, enum rxrpc_interruptibility interruptibility, unsigned int debug_id); @@ -60,9 +62,14 @@ bool rxrpc_kernel_abort_call(struct socket *, struct rxr= pc_call *, u32, int, enum rxrpc_abort_reason); void rxrpc_kernel_shutdown_call(struct socket *sock, struct rxrpc_call *ca= ll); void rxrpc_kernel_put_call(struct socket *sock, struct rxrpc_call *call); -void rxrpc_kernel_get_peer(struct socket *, struct rxrpc_call *, - struct sockaddr_rxrpc *); -bool rxrpc_kernel_get_srtt(struct socket *, struct rxrpc_call *, u32 *); +struct rxrpc_peer *rxrpc_kernel_lookup_peer(struct socket *sock, + struct sockaddr_rxrpc *srx, gfp_t gfp); +void rxrpc_kernel_put_peer(struct rxrpc_peer *peer); +struct rxrpc_peer *rxrpc_kernel_get_peer(struct rxrpc_peer *peer); +struct rxrpc_peer *rxrpc_kernel_get_call_peer(struct socket *sock, struct = rxrpc_call *call); +const struct sockaddr_rxrpc *rxrpc_kernel_remote_srx(const struct rxrpc_pe= er *peer); +const struct sockaddr *rxrpc_kernel_remote_addr(const struct rxrpc_peer *p= eer); +unsigned int rxrpc_kernel_get_srtt(const struct rxrpc_peer *); int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t, rxrpc_user_attach_call_t, unsigned long, gfp_t, unsigned int); diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h index f7e537f64db4..4c1ef7b3705c 100644 --- a/include/trace/events/rxrpc.h +++ b/include/trace/events/rxrpc.h @@ -178,7 +178,9 @@ #define rxrpc_peer_traces \ EM(rxrpc_peer_free, "FREE ") \ EM(rxrpc_peer_get_accept, "GET accept ") \ + EM(rxrpc_peer_get_application, "GET app ") \ EM(rxrpc_peer_get_bundle, "GET bundle ") \ + EM(rxrpc_peer_get_call, "GET call ") \ EM(rxrpc_peer_get_client_conn, "GET cln-conn") \ EM(rxrpc_peer_get_input, "GET input ") \ EM(rxrpc_peer_get_input_error, "GET inpt-err") \ @@ -187,6 +189,7 @@ EM(rxrpc_peer_get_service_conn, "GET srv-conn") \ EM(rxrpc_peer_new_client, "NEW client ") \ EM(rxrpc_peer_new_prealloc, "NEW prealloc") \ + EM(rxrpc_peer_put_application, "PUT app ") \ EM(rxrpc_peer_put_bundle, "PUT bundle ") \ EM(rxrpc_peer_put_call, "PUT call ") \ EM(rxrpc_peer_put_conn, "PUT conn ") \ diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index fa8aec78f63d..465bfe5eb061 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c @@ -258,16 +258,62 @@ static int rxrpc_listen(struct socket *sock, int back= log) return ret; } =20 +/** + * rxrpc_kernel_lookup_peer - Obtain remote transport endpoint for an addr= ess + * @sock: The socket through which it will be accessed + * @srx: The network address + * @gfp: Allocation flags + * + * Lookup or create a remote transport endpoint record for the specified + * address and return it with a ref held. + */ +struct rxrpc_peer *rxrpc_kernel_lookup_peer(struct socket *sock, + struct sockaddr_rxrpc *srx, gfp_t gfp) +{ + struct rxrpc_sock *rx =3D rxrpc_sk(sock->sk); + int ret; + + ret =3D rxrpc_validate_address(rx, srx, sizeof(*srx)); + if (ret < 0) + return ERR_PTR(ret); + + return rxrpc_lookup_peer(rx->local, srx, gfp); +} +EXPORT_SYMBOL(rxrpc_kernel_lookup_peer); + +/** + * rxrpc_kernel_get_peer - Get a reference on a peer + * @peer: The peer to get a reference on. + * + * Get a record for the remote peer in a call. + */ +struct rxrpc_peer *rxrpc_kernel_get_peer(struct rxrpc_peer *peer) +{ + return peer ? rxrpc_get_peer(peer, rxrpc_peer_get_application) : NULL; +} +EXPORT_SYMBOL(rxrpc_kernel_get_peer); + +/** + * rxrpc_kernel_put_peer - Allow a kernel app to drop a peer reference + * @peer: The peer to drop a ref on + */ +void rxrpc_kernel_put_peer(struct rxrpc_peer *peer) +{ + rxrpc_put_peer(peer, rxrpc_peer_put_application); +} +EXPORT_SYMBOL(rxrpc_kernel_put_peer); + /** * rxrpc_kernel_begin_call - Allow a kernel service to begin a call * @sock: The socket on which to make the call - * @srx: The address of the peer to contact + * @peer: The peer to contact * @key: The security context to use (defaults to socket setting) * @user_call_ID: The ID to use * @tx_total_len: Total length of data to transmit during the call (or -1) * @hard_timeout: The maximum lifespan of the call in sec * @gfp: The allocation constraints * @notify_rx: Where to send notifications instead of socket queue + * @service_id: The ID of the service to contact * @upgrade: Request service upgrade for call * @interruptibility: The call is interruptible, or can be canceled. * @debug_id: The debug ID for tracing to be assigned to the call @@ -280,13 +326,14 @@ static int rxrpc_listen(struct socket *sock, int back= log) * supplying @srx and @key. */ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock, - struct sockaddr_rxrpc *srx, + struct rxrpc_peer *peer, struct key *key, unsigned long user_call_ID, s64 tx_total_len, u32 hard_timeout, gfp_t gfp, rxrpc_notify_rx_t notify_rx, + u16 service_id, bool upgrade, enum rxrpc_interruptibility interruptibility, unsigned int debug_id) @@ -295,13 +342,11 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct soc= ket *sock, struct rxrpc_call_params p; struct rxrpc_call *call; struct rxrpc_sock *rx =3D rxrpc_sk(sock->sk); - int ret; =20 _enter(",,%x,%lx", key_serial(key), user_call_ID); =20 - ret =3D rxrpc_validate_address(rx, srx, sizeof(*srx)); - if (ret < 0) - return ERR_PTR(ret); + if (WARN_ON_ONCE(peer->local !=3D rx->local)) + return ERR_PTR(-EIO); =20 lock_sock(&rx->sk); =20 @@ -319,12 +364,13 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct soc= ket *sock, =20 memset(&cp, 0, sizeof(cp)); cp.local =3D rx->local; + cp.peer =3D peer; cp.key =3D key; cp.security_level =3D rx->min_sec_level; cp.exclusive =3D false; cp.upgrade =3D upgrade; - cp.service_id =3D srx->srx_service; - call =3D rxrpc_new_client_call(rx, &cp, srx, &p, gfp, debug_id); + cp.service_id =3D service_id; + call =3D rxrpc_new_client_call(rx, &cp, &p, gfp, debug_id); /* The socket has been unlocked. */ if (!IS_ERR(call)) { call->notify_rx =3D notify_rx; diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index e8e14c6f904d..8eea7a487380 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h @@ -364,6 +364,7 @@ struct rxrpc_conn_proto { =20 struct rxrpc_conn_parameters { struct rxrpc_local *local; /* Representation of local endpoint */ + struct rxrpc_peer *peer; /* Representation of remote endpoint */ struct key *key; /* Security details */ bool exclusive; /* T if conn is exclusive */ bool upgrade; /* T if service ID can be upgraded */ @@ -867,7 +868,6 @@ struct rxrpc_call *rxrpc_find_call_by_user_ID(struct rx= rpc_sock *, unsigned long struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *, gfp_t, unsigned i= nt); struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *, struct rxrpc_conn_parameters *, - struct sockaddr_rxrpc *, struct rxrpc_call_params *, gfp_t, unsigned int); void rxrpc_start_call_timer(struct rxrpc_call *call); diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c index 773eecd1e979..beea25ac88f5 100644 --- a/net/rxrpc/call_object.c +++ b/net/rxrpc/call_object.c @@ -193,7 +193,6 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *= rx, gfp_t gfp, * Allocate a new client call. */ static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx, - struct sockaddr_rxrpc *srx, struct rxrpc_conn_parameters *cp, struct rxrpc_call_params *p, gfp_t gfp, @@ -211,10 +210,12 @@ static struct rxrpc_call *rxrpc_alloc_client_call(str= uct rxrpc_sock *rx, now =3D ktime_get_real(); call->acks_latest_ts =3D now; call->cong_tstamp =3D now; - call->dest_srx =3D *srx; + call->dest_srx =3D cp->peer->srx; + call->dest_srx.srx_service =3D cp->service_id; call->interruptibility =3D p->interruptibility; call->tx_total_len =3D p->tx_total_len; call->key =3D key_get(cp->key); + call->peer =3D rxrpc_get_peer(cp->peer, rxrpc_peer_get_call); call->local =3D rxrpc_get_local(cp->local, rxrpc_local_get_call); call->security_level =3D cp->security_level; if (p->kernel) @@ -306,10 +307,6 @@ static int rxrpc_connect_call(struct rxrpc_call *call,= gfp_t gfp) =20 _enter("{%d,%lx},", call->debug_id, call->user_call_ID); =20 - call->peer =3D rxrpc_lookup_peer(local, &call->dest_srx, gfp); - if (!call->peer) - goto error; - ret =3D rxrpc_look_up_bundle(call, gfp); if (ret < 0) goto error; @@ -334,7 +331,6 @@ static int rxrpc_connect_call(struct rxrpc_call *call, = gfp_t gfp) */ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx, struct rxrpc_conn_parameters *cp, - struct sockaddr_rxrpc *srx, struct rxrpc_call_params *p, gfp_t gfp, unsigned int debug_id) @@ -349,13 +345,18 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc= _sock *rx, =20 _enter("%p,%lx", rx, p->user_call_ID); =20 + if (WARN_ON_ONCE(!cp->peer)) { + release_sock(&rx->sk); + return ERR_PTR(-EIO); + } + limiter =3D rxrpc_get_call_slot(p, gfp); if (!limiter) { release_sock(&rx->sk); return ERR_PTR(-ERESTARTSYS); } =20 - call =3D rxrpc_alloc_client_call(rx, srx, cp, p, gfp, debug_id); + call =3D rxrpc_alloc_client_call(rx, cp, p, gfp, debug_id); if (IS_ERR(call)) { release_sock(&rx->sk); up(limiter); diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c index 8d7a715a0bb1..49dcda67a0d5 100644 --- a/net/rxrpc/peer_object.c +++ b/net/rxrpc/peer_object.c @@ -22,6 +22,8 @@ #include #include "ar-internal.h" =20 +static const struct sockaddr_rxrpc rxrpc_null_addr; + /* * Hash a peer key. */ @@ -457,39 +459,53 @@ void rxrpc_destroy_all_peers(struct rxrpc_net *rxnet) } =20 /** - * rxrpc_kernel_get_peer - Get the peer address of a call + * rxrpc_kernel_get_call_peer - Get the peer address of a call * @sock: The socket on which the call is in progress. * @call: The call to query - * @_srx: Where to place the result * - * Get the address of the remote peer in a call. + * Get a record for the remote peer in a call. */ -void rxrpc_kernel_get_peer(struct socket *sock, struct rxrpc_call *call, - struct sockaddr_rxrpc *_srx) +struct rxrpc_peer *rxrpc_kernel_get_call_peer(struct socket *sock, struct = rxrpc_call *call) { - *_srx =3D call->peer->srx; + return call->peer; } -EXPORT_SYMBOL(rxrpc_kernel_get_peer); +EXPORT_SYMBOL(rxrpc_kernel_get_call_peer); =20 /** * rxrpc_kernel_get_srtt - Get a call's peer smoothed RTT - * @sock: The socket on which the call is in progress. - * @call: The call to query - * @_srtt: Where to store the SRTT value. + * @peer: The peer to query * - * Get the call's peer smoothed RTT in uS. + * Get the call's peer smoothed RTT in uS or UINT_MAX if we have no sample= s. */ -bool rxrpc_kernel_get_srtt(struct socket *sock, struct rxrpc_call *call, - u32 *_srtt) +unsigned int rxrpc_kernel_get_srtt(const struct rxrpc_peer *peer) { - struct rxrpc_peer *peer =3D call->peer; + return peer->rtt_count > 0 ? peer->srtt_us >> 3 : UINT_MAX; +} +EXPORT_SYMBOL(rxrpc_kernel_get_srtt); =20 - if (peer->rtt_count =3D=3D 0) { - *_srtt =3D 1000000; /* 1S */ - return false; - } +/** + * rxrpc_kernel_remote_srx - Get the address of a peer + * @peer: The peer to query + * + * Get a pointer to the address from a peer record. The caller is respons= ible + * for making sure that the address is not deallocated. + */ +const struct sockaddr_rxrpc *rxrpc_kernel_remote_srx(const struct rxrpc_pe= er *peer) +{ + return peer ? &peer->srx : &rxrpc_null_addr; +} +EXPORT_SYMBOL(rxrpc_kernel_remote_srx); =20 - *_srtt =3D call->peer->srtt_us >> 3; - return true; +/** + * rxrpc_kernel_remote_addr - Get the peer transport address of a call + * @peer: The peer to query + * + * Get a pointer to the transport address from a peer record. The caller = is + * responsible for making sure that the address is not deallocated. + */ +const struct sockaddr *rxrpc_kernel_remote_addr(const struct rxrpc_peer *p= eer) +{ + return (const struct sockaddr *) + (peer ? &peer->srx.transport : &rxrpc_null_addr.transport); } -EXPORT_SYMBOL(rxrpc_kernel_get_srtt); +EXPORT_SYMBOL(rxrpc_kernel_remote_addr); diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index 8e0b94714e84..5677d5690a02 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c @@ -572,6 +572,7 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx= , struct msghdr *msg, __acquires(&call->user_mutex) { struct rxrpc_conn_parameters cp; + struct rxrpc_peer *peer; struct rxrpc_call *call; struct key *key; =20 @@ -584,21 +585,29 @@ rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *= rx, struct msghdr *msg, return ERR_PTR(-EDESTADDRREQ); } =20 + peer =3D rxrpc_lookup_peer(rx->local, srx, GFP_KERNEL); + if (!peer) { + release_sock(&rx->sk); + return ERR_PTR(-ENOMEM); + } + key =3D rx->key; if (key && !rx->key->payload.data[0]) key =3D NULL; =20 memset(&cp, 0, sizeof(cp)); cp.local =3D rx->local; + cp.peer =3D peer; cp.key =3D rx->key; cp.security_level =3D rx->min_sec_level; cp.exclusive =3D rx->exclusive | p->exclusive; cp.upgrade =3D p->upgrade; cp.service_id =3D srx->srx_service; - call =3D rxrpc_new_client_call(rx, &cp, srx, &p->call, GFP_KERNEL, + call =3D rxrpc_new_client_call(rx, &cp, &p->call, GFP_KERNEL, atomic_inc_return(&rxrpc_debug_id)); /* The socket is now unlocked */ =20 + rxrpc_put_peer(peer, rxrpc_peer_put_application); _leave(" =3D %p\n", call); return call; }