Skip to content

Commit f0e834e

Browse files
committed
Merge tag 'rxrpc-next-20181004' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
David Howells says: ==================== rxrpc: Development Here are some development patches for AF_RXRPC. The most significant points are: (1) Change the tracepoint that indicates a packet has been transmitted into one that indicates a packet is about to be transmitted. Without this, the response tracepoint may occur first if the round trip is fast enough. (2) Sort out AFS address list handling to better enforce maximum capacity to use helper functions to fill them and to do an insertion sort to order them. This is here to make (3) easier. (3) Keep AF_INET addresses as AF_INET addresses rather than converting them to AF_INET6 in both AF_RXRPC and kAFS. I hadn't realised that a UDP6 socket would just call down into UDP4 if given an AF_INET address. (4) Allow the timestamp on the first DATA packet of a reply to be retrieved by a kernel service. This will give the kAFS a more accurate base from which to calculate the callback promise expiration. (5) Allow the rxrpc protocol epoch value to be retrieved from an incoming call. This will allow kAFS to determine if the fileserver restarted and if two addresses apparently assigned to the same fileserver actually are different boxes. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents bbb4c43 + e908bcf commit f0e834e

File tree

15 files changed

+169
-106
lines changed

15 files changed

+169
-106
lines changed

Documentation/networking/rxrpc.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,6 +1069,31 @@ The kernel interface functions are as follows:
10691069

10701070
This function may transmit a PING ACK.
10711071

1072+
(*) Get reply timestamp.
1073+
1074+
bool rxrpc_kernel_get_reply_time(struct socket *sock,
1075+
struct rxrpc_call *call,
1076+
ktime_t *_ts)
1077+
1078+
This allows the timestamp on the first DATA packet of the reply of a
1079+
client call to be queried, provided that it is still in the Rx ring. If
1080+
successful, the timestamp will be stored into *_ts and true will be
1081+
returned; false will be returned otherwise.
1082+
1083+
(*) Get remote client epoch.
1084+
1085+
u32 rxrpc_kernel_get_epoch(struct socket *sock,
1086+
struct rxrpc_call *call)
1087+
1088+
This allows the epoch that's contained in packets of an incoming client
1089+
call to be queried. This value is returned. The function always
1090+
successful if the call is still in progress. It shouldn't be called once
1091+
the call has expired. Note that calling this on a local client call only
1092+
returns the local epoch.
1093+
1094+
This value can be used to determine if the remote client has been
1095+
restarted as it shouldn't change otherwise.
1096+
10721097

10731098
=======================
10741099
CONFIGURABLE PARAMETERS

fs/afs/addr_list.c

Lines changed: 50 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,6 @@
1717
#include "internal.h"
1818
#include "afs_fs.h"
1919

20-
//#define AFS_MAX_ADDRESSES
21-
// ((unsigned int)((PAGE_SIZE - sizeof(struct afs_addr_list)) /
22-
// sizeof(struct sockaddr_rxrpc)))
23-
#define AFS_MAX_ADDRESSES ((unsigned int)(sizeof(unsigned long) * 8))
24-
2520
/*
2621
* Release an address list.
2722
*/
@@ -43,11 +38,15 @@ struct afs_addr_list *afs_alloc_addrlist(unsigned int nr,
4338

4439
_enter("%u,%u,%u", nr, service, port);
4540

41+
if (nr > AFS_MAX_ADDRESSES)
42+
nr = AFS_MAX_ADDRESSES;
43+
4644
alist = kzalloc(struct_size(alist, addrs, nr), GFP_KERNEL);
4745
if (!alist)
4846
return NULL;
4947

5048
refcount_set(&alist->usage, 1);
49+
alist->max_addrs = nr;
5150

5251
for (i = 0; i < nr; i++) {
5352
struct sockaddr_rxrpc *srx = &alist->addrs[i];
@@ -109,8 +108,6 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
109108
} while (p < end);
110109

111110
_debug("%u/%u addresses", nr, AFS_MAX_ADDRESSES);
112-
if (nr > AFS_MAX_ADDRESSES)
113-
nr = AFS_MAX_ADDRESSES;
114111

115112
alist = afs_alloc_addrlist(nr, service, port);
116113
if (!alist)
@@ -119,8 +116,10 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
119116
/* Extract the addresses */
120117
p = text;
121118
do {
122-
struct sockaddr_rxrpc *srx = &alist->addrs[alist->nr_addrs];
123119
const char *q, *stop;
120+
unsigned int xport = port;
121+
__be32 x[4];
122+
int family;
124123

125124
if (*p == delim) {
126125
p++;
@@ -136,19 +135,12 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
136135
break;
137136
}
138137

139-
if (in4_pton(p, q - p,
140-
(u8 *)&srx->transport.sin6.sin6_addr.s6_addr32[3],
141-
-1, &stop)) {
142-
srx->transport.sin6.sin6_addr.s6_addr32[0] = 0;
143-
srx->transport.sin6.sin6_addr.s6_addr32[1] = 0;
144-
srx->transport.sin6.sin6_addr.s6_addr32[2] = htonl(0xffff);
145-
} else if (in6_pton(p, q - p,
146-
srx->transport.sin6.sin6_addr.s6_addr,
147-
-1, &stop)) {
148-
/* Nothing to do */
149-
} else {
138+
if (in4_pton(p, q - p, (u8 *)&x[0], -1, &stop))
139+
family = AF_INET;
140+
else if (in6_pton(p, q - p, (u8 *)x, -1, &stop))
141+
family = AF_INET6;
142+
else
150143
goto bad_address;
151-
}
152144

153145
if (stop != q)
154146
goto bad_address;
@@ -160,7 +152,7 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
160152
if (p < end) {
161153
if (*p == '+') {
162154
/* Port number specification "+1234" */
163-
unsigned int xport = 0;
155+
xport = 0;
164156
p++;
165157
if (p >= end || !isdigit(*p))
166158
goto bad_address;
@@ -171,16 +163,19 @@ struct afs_addr_list *afs_parse_text_addrs(const char *text, size_t len,
171163
goto bad_address;
172164
p++;
173165
} while (p < end && isdigit(*p));
174-
srx->transport.sin6.sin6_port = htons(xport);
175166
} else if (*p == delim) {
176167
p++;
177168
} else {
178169
goto bad_address;
179170
}
180171
}
181172

182-
alist->nr_addrs++;
183-
} while (p < end && alist->nr_addrs < AFS_MAX_ADDRESSES);
173+
if (family == AF_INET)
174+
afs_merge_fs_addr4(alist, x[0], xport);
175+
else
176+
afs_merge_fs_addr6(alist, x, xport);
177+
178+
} while (p < end);
184179

185180
_leave(" = [nr %u]", alist->nr_addrs);
186181
return alist;
@@ -237,19 +232,23 @@ struct afs_addr_list *afs_dns_query(struct afs_cell *cell, time64_t *_expiry)
237232
*/
238233
void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr, u16 port)
239234
{
240-
struct sockaddr_in6 *a;
241-
__be16 xport = htons(port);
235+
struct sockaddr_rxrpc *srx;
236+
u32 addr = ntohl(xdr);
242237
int i;
243238

239+
if (alist->nr_addrs >= alist->max_addrs)
240+
return;
241+
244242
for (i = 0; i < alist->nr_ipv4; i++) {
245-
a = &alist->addrs[i].transport.sin6;
246-
if (xdr == a->sin6_addr.s6_addr32[3] &&
247-
xport == a->sin6_port)
243+
struct sockaddr_in *a = &alist->addrs[i].transport.sin;
244+
u32 a_addr = ntohl(a->sin_addr.s_addr);
245+
u16 a_port = ntohs(a->sin_port);
246+
247+
if (addr == a_addr && port == a_port)
248248
return;
249-
if (xdr == a->sin6_addr.s6_addr32[3] &&
250-
(u16 __force)xport < (u16 __force)a->sin6_port)
249+
if (addr == a_addr && port < a_port)
251250
break;
252-
if ((u32 __force)xdr < (u32 __force)a->sin6_addr.s6_addr32[3])
251+
if (addr < a_addr)
253252
break;
254253
}
255254

@@ -258,12 +257,11 @@ void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr, u16 port)
258257
alist->addrs + i,
259258
sizeof(alist->addrs[0]) * (alist->nr_addrs - i));
260259

261-
a = &alist->addrs[i].transport.sin6;
262-
a->sin6_port = xport;
263-
a->sin6_addr.s6_addr32[0] = 0;
264-
a->sin6_addr.s6_addr32[1] = 0;
265-
a->sin6_addr.s6_addr32[2] = htonl(0xffff);
266-
a->sin6_addr.s6_addr32[3] = xdr;
260+
srx = &alist->addrs[i];
261+
srx->transport_len = sizeof(srx->transport.sin);
262+
srx->transport.sin.sin_family = AF_INET;
263+
srx->transport.sin.sin_port = htons(port);
264+
srx->transport.sin.sin_addr.s_addr = xdr;
267265
alist->nr_ipv4++;
268266
alist->nr_addrs++;
269267
}
@@ -273,18 +271,20 @@ void afs_merge_fs_addr4(struct afs_addr_list *alist, __be32 xdr, u16 port)
273271
*/
274272
void afs_merge_fs_addr6(struct afs_addr_list *alist, __be32 *xdr, u16 port)
275273
{
276-
struct sockaddr_in6 *a;
277-
__be16 xport = htons(port);
274+
struct sockaddr_rxrpc *srx;
278275
int i, diff;
279276

277+
if (alist->nr_addrs >= alist->max_addrs)
278+
return;
279+
280280
for (i = alist->nr_ipv4; i < alist->nr_addrs; i++) {
281-
a = &alist->addrs[i].transport.sin6;
281+
struct sockaddr_in6 *a = &alist->addrs[i].transport.sin6;
282+
u16 a_port = ntohs(a->sin6_port);
283+
282284
diff = memcmp(xdr, &a->sin6_addr, 16);
283-
if (diff == 0 &&
284-
xport == a->sin6_port)
285+
if (diff == 0 && port == a_port)
285286
return;
286-
if (diff == 0 &&
287-
(u16 __force)xport < (u16 __force)a->sin6_port)
287+
if (diff == 0 && port < a_port)
288288
break;
289289
if (diff < 0)
290290
break;
@@ -295,12 +295,11 @@ void afs_merge_fs_addr6(struct afs_addr_list *alist, __be32 *xdr, u16 port)
295295
alist->addrs + i,
296296
sizeof(alist->addrs[0]) * (alist->nr_addrs - i));
297297

298-
a = &alist->addrs[i].transport.sin6;
299-
a->sin6_port = xport;
300-
a->sin6_addr.s6_addr32[0] = xdr[0];
301-
a->sin6_addr.s6_addr32[1] = xdr[1];
302-
a->sin6_addr.s6_addr32[2] = xdr[2];
303-
a->sin6_addr.s6_addr32[3] = xdr[3];
298+
srx = &alist->addrs[i];
299+
srx->transport_len = sizeof(srx->transport.sin6);
300+
srx->transport.sin6.sin6_family = AF_INET6;
301+
srx->transport.sin6.sin6_port = htons(port);
302+
memcpy(&srx->transport.sin6.sin6_addr, xdr, 16);
304303
alist->nr_addrs++;
305304
}
306305

fs/afs/internal.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,12 +73,14 @@ struct afs_addr_list {
7373
struct rcu_head rcu; /* Must be first */
7474
refcount_t usage;
7575
u32 version; /* Version */
76-
unsigned short nr_addrs;
77-
unsigned short index; /* Address currently in use */
78-
unsigned short nr_ipv4; /* Number of IPv4 addresses */
76+
unsigned char max_addrs;
77+
unsigned char nr_addrs;
78+
unsigned char index; /* Address currently in use */
79+
unsigned char nr_ipv4; /* Number of IPv4 addresses */
7980
unsigned long probed; /* Mask of servers that have been probed */
8081
unsigned long yfs; /* Mask of servers that are YFS */
8182
struct sockaddr_rxrpc addrs[];
83+
#define AFS_MAX_ADDRESSES ((unsigned int)(sizeof(unsigned long) * 8))
8284
};
8385

8486
/*

include/net/af_rxrpc.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#define _NET_RXRPC_H
1414

1515
#include <linux/rxrpc.h>
16+
#include <linux/ktime.h>
1617

1718
struct key;
1819
struct sock;
@@ -77,5 +78,8 @@ int rxrpc_kernel_retry_call(struct socket *, struct rxrpc_call *,
7778
int rxrpc_kernel_check_call(struct socket *, struct rxrpc_call *,
7879
enum rxrpc_call_completion *, u32 *);
7980
u32 rxrpc_kernel_check_life(struct socket *, struct rxrpc_call *);
81+
u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *);
82+
bool rxrpc_kernel_get_reply_time(struct socket *, struct rxrpc_call *,
83+
ktime_t *);
8084

8185
#endif /* _NET_RXRPC_H */

net/rxrpc/af_rxrpc.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,8 @@ static int rxrpc_validate_address(struct rxrpc_sock *rx,
9797
srx->transport_len > len)
9898
return -EINVAL;
9999

100-
if (srx->transport.family != rx->family)
100+
if (srx->transport.family != rx->family &&
101+
srx->transport.family == AF_INET && rx->family != AF_INET6)
101102
return -EAFNOSUPPORT;
102103

103104
switch (srx->transport.family) {
@@ -384,6 +385,20 @@ u32 rxrpc_kernel_check_life(struct socket *sock, struct rxrpc_call *call)
384385
}
385386
EXPORT_SYMBOL(rxrpc_kernel_check_life);
386387

388+
/**
389+
* rxrpc_kernel_get_epoch - Retrieve the epoch value from a call.
390+
* @sock: The socket the call is on
391+
* @call: The call to query
392+
*
393+
* Allow a kernel service to retrieve the epoch value from a service call to
394+
* see if the client at the other end rebooted.
395+
*/
396+
u32 rxrpc_kernel_get_epoch(struct socket *sock, struct rxrpc_call *call)
397+
{
398+
return call->conn->proto.epoch;
399+
}
400+
EXPORT_SYMBOL(rxrpc_kernel_get_epoch);
401+
387402
/**
388403
* rxrpc_kernel_check_call - Check a call's state
389404
* @sock: The socket the call is on

net/rxrpc/ar-internal.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,7 +1095,6 @@ void rxrpc_new_skb(struct sk_buff *, enum rxrpc_skb_trace);
10951095
void rxrpc_see_skb(struct sk_buff *, enum rxrpc_skb_trace);
10961096
void rxrpc_get_skb(struct sk_buff *, enum rxrpc_skb_trace);
10971097
void rxrpc_free_skb(struct sk_buff *, enum rxrpc_skb_trace);
1098-
void rxrpc_lose_skb(struct sk_buff *, enum rxrpc_skb_trace);
10991098
void rxrpc_purge_queue(struct sk_buff_head *);
11001099

11011100
/*
@@ -1112,8 +1111,7 @@ static inline void rxrpc_sysctl_exit(void) {}
11121111
/*
11131112
* utils.c
11141113
*/
1115-
int rxrpc_extract_addr_from_skb(struct rxrpc_local *, struct sockaddr_rxrpc *,
1116-
struct sk_buff *);
1114+
int rxrpc_extract_addr_from_skb(struct sockaddr_rxrpc *, struct sk_buff *);
11171115

11181116
static inline bool before(u32 seq1, u32 seq2)
11191117
{

net/rxrpc/call_accept.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ static struct rxrpc_call *rxrpc_alloc_incoming_call(struct rxrpc_sock *rx,
280280
peer = NULL;
281281
if (!peer) {
282282
peer = b->peer_backlog[peer_tail];
283-
if (rxrpc_extract_addr_from_skb(local, &peer->srx, skb) < 0)
283+
if (rxrpc_extract_addr_from_skb(&peer->srx, skb) < 0)
284284
return NULL;
285285
b->peer_backlog[peer_tail] = NULL;
286286
smp_store_release(&b->peer_backlog_tail,

net/rxrpc/conn_object.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,12 @@ struct rxrpc_connection *rxrpc_find_connection_rcu(struct rxrpc_local *local,
8686

8787
_enter(",%x", sp->hdr.cid & RXRPC_CIDMASK);
8888

89-
if (rxrpc_extract_addr_from_skb(local, &srx, skb) < 0)
89+
if (rxrpc_extract_addr_from_skb(&srx, skb) < 0)
9090
goto not_found;
9191

92-
/* We may have to handle mixing IPv4 and IPv6 */
93-
if (srx.transport.family != local->srx.transport.family) {
92+
if (srx.transport.family != local->srx.transport.family &&
93+
(srx.transport.family == AF_INET &&
94+
local->srx.transport.family != AF_INET6)) {
9495
pr_warn_ratelimited("AF_RXRPC: Protocol mismatch %u not %u\n",
9596
srx.transport.family,
9697
local->srx.transport.family);

net/rxrpc/input.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,7 @@ void rxrpc_data_ready(struct sock *udp_sk)
11761176
static int lose;
11771177
if ((lose++ & 7) == 7) {
11781178
trace_rxrpc_rx_lose(sp);
1179-
rxrpc_lose_skb(skb, rxrpc_skb_rx_lost);
1179+
rxrpc_free_skb(skb, rxrpc_skb_rx_lost);
11801180
return;
11811181
}
11821182
}

net/rxrpc/local_event.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ static void rxrpc_send_version_request(struct rxrpc_local *local,
3939

4040
_enter("");
4141

42-
if (rxrpc_extract_addr_from_skb(local, &srx, skb) < 0)
42+
if (rxrpc_extract_addr_from_skb(&srx, skb) < 0)
4343
return;
4444

4545
msg.msg_name = &srx.transport;

net/rxrpc/output.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -378,11 +378,13 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
378378
if ((lose++ & 7) == 7) {
379379
ret = 0;
380380
lost = true;
381-
goto done;
382381
}
383382
}
384383

385-
_proto("Tx DATA %%%u { #%u }", serial, sp->hdr.seq);
384+
trace_rxrpc_tx_data(call, sp->hdr.seq, serial, whdr.flags,
385+
retrans, lost);
386+
if (lost)
387+
goto done;
386388

387389
/* send the packet with the don't fragment bit set if we currently
388390
* think it's small enough */
@@ -415,8 +417,6 @@ int rxrpc_send_data_packet(struct rxrpc_call *call, struct sk_buff *skb,
415417
goto send_fragmentable;
416418

417419
done:
418-
trace_rxrpc_tx_data(call, sp->hdr.seq, serial, whdr.flags,
419-
retrans, lost);
420420
if (ret >= 0) {
421421
if (whdr.flags & RXRPC_REQUEST_ACK) {
422422
call->peer->rtt_last_req = skb->tstamp;
@@ -561,7 +561,7 @@ void rxrpc_reject_packets(struct rxrpc_local *local)
561561
continue;
562562
}
563563

564-
if (rxrpc_extract_addr_from_skb(local, &srx, skb) == 0) {
564+
if (rxrpc_extract_addr_from_skb(&srx, skb) == 0) {
565565
msg.msg_namelen = srx.transport_len;
566566

567567
whdr.epoch = htonl(sp->hdr.epoch);

0 commit comments

Comments
 (0)