Skip to content

Commit 72904d7

Browse files
committed
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 <[email protected]> cc: Marc Dionne <[email protected]> cc: [email protected]
1 parent 07f3502 commit 72904d7

File tree

20 files changed

+273
-238
lines changed

20 files changed

+273
-238
lines changed

fs/afs/addr_list.c

Lines changed: 66 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,33 @@
1313
#include "internal.h"
1414
#include "afs_fs.h"
1515

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+
1625
/*
1726
* Release an address list.
1827
*/
1928
void afs_put_addrlist(struct afs_addr_list *alist)
2029
{
2130
if (alist && refcount_dec_and_test(&alist->usage))
22-
kfree_rcu(alist, rcu);
31+
call_rcu(&alist->rcu, afs_free_addrlist);
2332
}
2433

2534
/*
2635
* Allocate an address list.
2736
*/
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)
3138
{
3239
struct afs_addr_list *alist;
3340
unsigned int i;
3441

35-
_enter("%u,%u,%u", nr, service, port);
42+
_enter("%u,%u", nr, service_id);
3643

3744
if (nr > AFS_MAX_ADDRESSES)
3845
nr = AFS_MAX_ADDRESSES;
@@ -44,16 +51,8 @@ struct afs_addr_list *afs_alloc_addrlist(unsigned int nr,
4451
refcount_set(&alist->usage, 1);
4552
alist->max_addrs = nr;
4653

47-
for (i = 0; i < nr; i++) {
48-
struct sockaddr_rxrpc *srx = &alist->addrs[i].srx;
49-
srx->srx_family = AF_RXRPC;
50-
srx->srx_service = service;
51-
srx->transport_type = SOCK_DGRAM;
52-
srx->transport_len = sizeof(srx->transport.sin6);
53-
srx->transport.sin6.sin6_family = AF_INET6;
54-
srx->transport.sin6.sin6_port = htons(port);
55-
}
56-
54+
for (i = 0; i < nr; i++)
55+
alist->addrs[i].service_id = service_id;
5756
return alist;
5857
}
5958

@@ -126,7 +125,7 @@ struct afs_vlserver_list *afs_parse_text_addrs(struct afs_net *net,
126125
if (!vllist->servers[0].server)
127126
goto error_vl;
128127

129-
alist = afs_alloc_addrlist(nr, service, AFS_VL_PORT);
128+
alist = afs_alloc_addrlist(nr, service);
130129
if (!alist)
131130
goto error;
132131

@@ -197,9 +196,11 @@ struct afs_vlserver_list *afs_parse_text_addrs(struct afs_net *net,
197196
}
198197

199198
if (family == AF_INET)
200-
afs_merge_fs_addr4(alist, x[0], xport);
199+
ret = afs_merge_fs_addr4(net, alist, x[0], xport);
201200
else
202-
afs_merge_fs_addr6(alist, x, xport);
201+
ret = afs_merge_fs_addr6(net, alist, x, xport);
202+
if (ret < 0)
203+
goto error;
203204

204205
} while (p < end);
205206

@@ -271,25 +272,33 @@ struct afs_vlserver_list *afs_dns_query(struct afs_cell *cell, time64_t *_expiry
271272
/*
272273
* Merge an IPv4 entry into a fileserver address list.
273274
*/
274-
void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr, u16 port)
275+
int afs_merge_fs_addr4(struct afs_net *net, struct afs_addr_list *alist,
276+
__be32 xdr, u16 port)
275277
{
276-
struct sockaddr_rxrpc *srx;
277-
u32 addr = ntohl(xdr);
278+
struct sockaddr_rxrpc srx;
279+
struct rxrpc_peer *peer;
278280
int i;
279281

280282
if (alist->nr_addrs >= alist->max_addrs)
281-
return;
283+
return 0;
282284

283-
for (i = 0; i < alist->nr_ipv4; i++) {
284-
struct sockaddr_in *a = &alist->addrs[i].srx.transport.sin;
285-
u32 a_addr = ntohl(a->sin_addr.s_addr);
286-
u16 a_port = ntohs(a->sin_port);
285+
srx.srx_family = AF_RXRPC;
286+
srx.transport_type = SOCK_DGRAM;
287+
srx.transport_len = sizeof(srx.transport.sin);
288+
srx.transport.sin.sin_family = AF_INET;
289+
srx.transport.sin.sin_port = htons(port);
290+
srx.transport.sin.sin_addr.s_addr = xdr;
287291

288-
if (addr == a_addr && port == a_port)
289-
return;
290-
if (addr == a_addr && port < a_port)
291-
break;
292-
if (addr < a_addr)
292+
peer = rxrpc_kernel_lookup_peer(net->socket, &srx, GFP_KERNEL);
293+
if (!peer)
294+
return -ENOMEM;
295+
296+
for (i = 0; i < alist->nr_ipv4; i++) {
297+
if (peer == alist->addrs[i].peer) {
298+
rxrpc_kernel_put_peer(peer);
299+
return 0;
300+
}
301+
if (peer <= alist->addrs[i].peer)
293302
break;
294303
}
295304

@@ -298,54 +307,52 @@ void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr, u16 port)
298307
alist->addrs + i,
299308
sizeof(alist->addrs[0]) * (alist->nr_addrs - i));
300309

301-
srx = &alist->addrs[i].srx;
302-
srx->srx_family = AF_RXRPC;
303-
srx->transport_type = SOCK_DGRAM;
304-
srx->transport_len = sizeof(srx->transport.sin);
305-
srx->transport.sin.sin_family = AF_INET;
306-
srx->transport.sin.sin_port = htons(port);
307-
srx->transport.sin.sin_addr.s_addr = xdr;
310+
alist->addrs[i].peer = peer;
308311
alist->nr_ipv4++;
309312
alist->nr_addrs++;
313+
return 0;
310314
}
311315

312316
/*
313317
* Merge an IPv6 entry into a fileserver address list.
314318
*/
315-
void afs_merge_fs_addr6(struct afs_addr_list *alist, __be32 *xdr, u16 port)
319+
int afs_merge_fs_addr6(struct afs_net *net, struct afs_addr_list *alist,
320+
__be32 *xdr, u16 port)
316321
{
317-
struct sockaddr_rxrpc *srx;
318-
int i, diff;
322+
struct sockaddr_rxrpc srx;
323+
struct rxrpc_peer *peer;
324+
int i;
319325

320326
if (alist->nr_addrs >= alist->max_addrs)
321-
return;
327+
return 0;
322328

323-
for (i = alist->nr_ipv4; i < alist->nr_addrs; i++) {
324-
struct sockaddr_in6 *a = &alist->addrs[i].srx.transport.sin6;
325-
u16 a_port = ntohs(a->sin6_port);
329+
srx.srx_family = AF_RXRPC;
330+
srx.transport_type = SOCK_DGRAM;
331+
srx.transport_len = sizeof(srx.transport.sin6);
332+
srx.transport.sin6.sin6_family = AF_INET6;
333+
srx.transport.sin6.sin6_port = htons(port);
334+
memcpy(&srx.transport.sin6.sin6_addr, xdr, 16);
326335

327-
diff = memcmp(xdr, &a->sin6_addr, 16);
328-
if (diff == 0 && port == a_port)
329-
return;
330-
if (diff == 0 && port < a_port)
331-
break;
332-
if (diff < 0)
336+
peer = rxrpc_kernel_lookup_peer(net->socket, &srx, GFP_KERNEL);
337+
if (!peer)
338+
return -ENOMEM;
339+
340+
for (i = alist->nr_ipv4; i < alist->nr_addrs; i++) {
341+
if (peer == alist->addrs[i].peer) {
342+
rxrpc_kernel_put_peer(peer);
343+
return 0;
344+
}
345+
if (peer <= alist->addrs[i].peer)
333346
break;
334347
}
335348

336349
if (i < alist->nr_addrs)
337350
memmove(alist->addrs + i + 1,
338351
alist->addrs + i,
339352
sizeof(alist->addrs[0]) * (alist->nr_addrs - i));
340-
341-
srx = &alist->addrs[i].srx;
342-
srx->srx_family = AF_RXRPC;
343-
srx->transport_type = SOCK_DGRAM;
344-
srx->transport_len = sizeof(srx->transport.sin6);
345-
srx->transport.sin6.sin6_family = AF_INET6;
346-
srx->transport.sin6.sin6_port = htons(port);
347-
memcpy(&srx->transport.sin6.sin6_addr, xdr, 16);
353+
alist->addrs[i].peer = peer;
348354
alist->nr_addrs++;
355+
return 0;
349356
}
350357

351358
/*

fs/afs/cmservice.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,11 @@ static int afs_find_cm_server_by_peer(struct afs_call *call)
146146
{
147147
struct sockaddr_rxrpc srx;
148148
struct afs_server *server;
149+
struct rxrpc_peer *peer;
149150

150-
rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
151+
peer = rxrpc_kernel_get_call_peer(call->net->socket, call->rxcall);
151152

152-
server = afs_find_server(call->net, &srx);
153+
server = afs_find_server(call->net, peer);
153154
if (!server) {
154155
trace_afs_cm_no_server(call, &srx);
155156
return 0;

fs/afs/fs_probe.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ static void afs_fs_probe_not_done(struct afs_net *net,
101101
void afs_fileserver_probe_result(struct afs_call *call)
102102
{
103103
struct afs_addr_list *alist = call->alist;
104+
struct afs_address *addr = &alist->addrs[call->addr_ix];
104105
struct afs_server *server = call->server;
105106
unsigned int index = call->addr_ix;
106107
unsigned int rtt_us = 0, cap0;
@@ -153,12 +154,12 @@ void afs_fileserver_probe_result(struct afs_call *call)
153154
if (call->service_id == YFS_FS_SERVICE) {
154155
server->probe.is_yfs = true;
155156
set_bit(AFS_SERVER_FL_IS_YFS, &server->flags);
156-
alist->addrs[index].srx.srx_service = call->service_id;
157+
addr->service_id = call->service_id;
157158
} else {
158159
server->probe.not_yfs = true;
159160
if (!server->probe.is_yfs) {
160161
clear_bit(AFS_SERVER_FL_IS_YFS, &server->flags);
161-
alist->addrs[index].srx.srx_service = call->service_id;
162+
addr->service_id = call->service_id;
162163
}
163164
cap0 = ntohl(call->tmp);
164165
if (cap0 & AFS3_VICED_CAPABILITY_64BITFILES)
@@ -167,7 +168,7 @@ void afs_fileserver_probe_result(struct afs_call *call)
167168
clear_bit(AFS_SERVER_FL_HAS_FS64, &server->flags);
168169
}
169170

170-
rxrpc_kernel_get_srtt(call->net->socket, call->rxcall, &rtt_us);
171+
rtt_us = rxrpc_kernel_get_srtt(addr->peer);
171172
if (rtt_us < server->probe.rtt) {
172173
server->probe.rtt = rtt_us;
173174
server->rtt = rtt_us;
@@ -181,8 +182,8 @@ void afs_fileserver_probe_result(struct afs_call *call)
181182
out:
182183
spin_unlock(&server->probe_lock);
183184

184-
_debug("probe %pU [%u] %pISpc rtt=%u ret=%d",
185-
&server->uuid, index, &alist->addrs[index].srx.transport,
185+
_debug("probe %pU [%u] %pISpc rtt=%d ret=%d",
186+
&server->uuid, index, rxrpc_kernel_remote_addr(alist->addrs[index].peer),
186187
rtt_us, ret);
187188

188189
return afs_done_one_fs_probe(call->net, server);

fs/afs/internal.h

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,11 @@ enum afs_call_state {
7272
AFS_CALL_COMPLETE, /* Completed or failed */
7373
};
7474

75+
struct afs_address {
76+
struct rxrpc_peer *peer;
77+
u16 service_id;
78+
};
79+
7580
/*
7681
* List of server addresses.
7782
*/
@@ -87,9 +92,7 @@ struct afs_addr_list {
8792
enum dns_lookup_status status:8;
8893
unsigned long failed; /* Mask of addrs that failed locally/ICMP */
8994
unsigned long responded; /* Mask of addrs that responded */
90-
struct {
91-
struct sockaddr_rxrpc srx;
92-
} addrs[] __counted_by(max_addrs);
95+
struct afs_address addrs[] __counted_by(max_addrs);
9396
#define AFS_MAX_ADDRESSES ((unsigned int)(sizeof(unsigned long) * 8))
9497
};
9598

@@ -420,7 +423,7 @@ struct afs_vlserver {
420423
atomic_t probe_outstanding;
421424
spinlock_t probe_lock;
422425
struct {
423-
unsigned int rtt; /* RTT in uS */
426+
unsigned int rtt; /* Best RTT in uS (or UINT_MAX) */
424427
u32 abort_code;
425428
short error;
426429
unsigned short flags;
@@ -537,7 +540,7 @@ struct afs_server {
537540
atomic_t probe_outstanding;
538541
spinlock_t probe_lock;
539542
struct {
540-
unsigned int rtt; /* RTT in uS */
543+
unsigned int rtt; /* Best RTT in uS (or UINT_MAX) */
541544
u32 abort_code;
542545
short error;
543546
bool responded:1;
@@ -964,9 +967,7 @@ static inline struct afs_addr_list *afs_get_addrlist(struct afs_addr_list *alist
964967
refcount_inc(&alist->usage);
965968
return alist;
966969
}
967-
extern struct afs_addr_list *afs_alloc_addrlist(unsigned int,
968-
unsigned short,
969-
unsigned short);
970+
extern struct afs_addr_list *afs_alloc_addrlist(unsigned int nr, u16 service_id);
970971
extern void afs_put_addrlist(struct afs_addr_list *);
971972
extern struct afs_vlserver_list *afs_parse_text_addrs(struct afs_net *,
972973
const char *, size_t, char,
@@ -977,8 +978,10 @@ extern struct afs_vlserver_list *afs_dns_query(struct afs_cell *, time64_t *);
977978
extern bool afs_iterate_addresses(struct afs_addr_cursor *);
978979
extern int afs_end_cursor(struct afs_addr_cursor *);
979980

980-
extern void afs_merge_fs_addr4(struct afs_addr_list *, __be32, u16);
981-
extern void afs_merge_fs_addr6(struct afs_addr_list *, __be32 *, u16);
981+
extern int afs_merge_fs_addr4(struct afs_net *net, struct afs_addr_list *addr,
982+
__be32 xdr, u16 port);
983+
extern int afs_merge_fs_addr6(struct afs_net *net, struct afs_addr_list *addr,
984+
__be32 *xdr, u16 port);
982985

983986
/*
984987
* callback.c
@@ -1405,8 +1408,7 @@ extern void __exit afs_clean_up_permit_cache(void);
14051408
*/
14061409
extern spinlock_t afs_server_peer_lock;
14071410

1408-
extern struct afs_server *afs_find_server(struct afs_net *,
1409-
const struct sockaddr_rxrpc *);
1411+
extern struct afs_server *afs_find_server(struct afs_net *, const struct rxrpc_peer *);
14101412
extern struct afs_server *afs_find_server_by_uuid(struct afs_net *, const uuid_t *);
14111413
extern struct afs_server *afs_lookup_server(struct afs_cell *, struct key *, const uuid_t *, u32);
14121414
extern struct afs_server *afs_get_server(struct afs_server *, enum afs_server_trace);

fs/afs/proc.c

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v)
307307
for (i = 0; i < alist->nr_addrs; i++)
308308
seq_printf(m, " %c %pISpc\n",
309309
alist->preferred == i ? '>' : '-',
310-
&alist->addrs[i].srx.transport);
310+
rxrpc_kernel_remote_addr(alist->addrs[i].peer));
311311
}
312312
seq_printf(m, " info: fl=%lx rtt=%d\n", vlserver->flags, vlserver->rtt);
313313
seq_printf(m, " probe: fl=%x e=%d ac=%d out=%d\n",
@@ -398,9 +398,10 @@ static int afs_proc_servers_show(struct seq_file *m, void *v)
398398
seq_printf(m, " - ALIST v=%u rsp=%lx f=%lx\n",
399399
alist->version, alist->responded, alist->failed);
400400
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));
404405
return 0;
405406
}
406407

fs/afs/rotate.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ bool afs_select_fileserver(struct afs_operation *op)
113113
struct afs_server *server;
114114
struct afs_vnode *vnode = op->file[0].vnode;
115115
struct afs_error e;
116-
u32 rtt;
116+
unsigned int rtt;
117117
int error = op->ac.error, i;
118118

119119
_enter("%lx[%d],%lx[%d],%d,%d",
@@ -420,7 +420,7 @@ bool afs_select_fileserver(struct afs_operation *op)
420420
}
421421

422422
op->index = -1;
423-
rtt = U32_MAX;
423+
rtt = UINT_MAX;
424424
for (i = 0; i < op->server_list->nr_servers; i++) {
425425
struct afs_server *s = op->server_list->servers[i].server;
426426

@@ -488,7 +488,7 @@ bool afs_select_fileserver(struct afs_operation *op)
488488

489489
_debug("address [%u] %u/%u %pISp",
490490
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));
492492

493493
_leave(" = t");
494494
return true;

0 commit comments

Comments
 (0)