Skip to content

Commit d0fcece

Browse files
committed
Merge tag 'rxrpc-next-20170829' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
David Howells says: ==================== rxrpc: Miscellany Here are a number of patches that make some changes/fixes and add a couple of extensions to AF_RXRPC for kernel services to use. The changes and fixes are: (1) Use time64_t rather than u32 outside of protocol or UAPI-representative structures. (2) Use the correct time stamp when loading a key from an XDR-encoded Kerberos 5 key. (3) Fix IPv6 support. (4) Fix some places where the error code is being incorrectly made positive before returning. (5) Remove some white space. And the extensions: (6) Add an end-of-Tx phase notification, thereby allowing kAFS to transition the state on its own call record at the correct point, rather than having to do it in advance and risk non-completion of the call in the wrong state. (7) Allow a kernel client call to be retried if it fails on a network error, thereby making it possible for kAFS to iterate over a number of IP addresses without having to reload the Tx queue and re-encrypt data each time. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 3d86e35 + c038a58 commit d0fcece

File tree

17 files changed

+419
-90
lines changed

17 files changed

+419
-90
lines changed

Documentation/networking/rxrpc.txt

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -818,10 +818,15 @@ The kernel interface functions are as follows:
818818

819819
(*) Send data through a call.
820820

821+
typedef void (*rxrpc_notify_end_tx_t)(struct sock *sk,
822+
unsigned long user_call_ID,
823+
struct sk_buff *skb);
824+
821825
int rxrpc_kernel_send_data(struct socket *sock,
822826
struct rxrpc_call *call,
823827
struct msghdr *msg,
824-
size_t len);
828+
size_t len,
829+
rxrpc_notify_end_tx_t notify_end_rx);
825830

826831
This is used to supply either the request part of a client call or the
827832
reply part of a server call. msg.msg_iovlen and msg.msg_iov specify the
@@ -832,6 +837,11 @@ The kernel interface functions are as follows:
832837
The msg must not specify a destination address, control data or any flags
833838
other than MSG_MORE. len is the total amount of data to transmit.
834839

840+
notify_end_rx can be NULL or it can be used to specify a function to be
841+
called when the call changes state to end the Tx phase. This function is
842+
called with the call-state spinlock held to prevent any reply or final ACK
843+
from being delivered first.
844+
835845
(*) Receive data from a call.
836846

837847
int rxrpc_kernel_recv_data(struct socket *sock,
@@ -965,6 +975,51 @@ The kernel interface functions are as follows:
965975
size should be set when the call is begun. tx_total_len may not be less
966976
than zero.
967977

978+
(*) Check to see the completion state of a call so that the caller can assess
979+
whether it needs to be retried.
980+
981+
enum rxrpc_call_completion {
982+
RXRPC_CALL_SUCCEEDED,
983+
RXRPC_CALL_REMOTELY_ABORTED,
984+
RXRPC_CALL_LOCALLY_ABORTED,
985+
RXRPC_CALL_LOCAL_ERROR,
986+
RXRPC_CALL_NETWORK_ERROR,
987+
};
988+
989+
int rxrpc_kernel_check_call(struct socket *sock, struct rxrpc_call *call,
990+
enum rxrpc_call_completion *_compl,
991+
u32 *_abort_code);
992+
993+
On return, -EINPROGRESS will be returned if the call is still ongoing; if
994+
it is finished, *_compl will be set to indicate the manner of completion,
995+
*_abort_code will be set to any abort code that occurred. 0 will be
996+
returned on a successful completion, -ECONNABORTED will be returned if the
997+
client failed due to a remote abort and anything else will return an
998+
appropriate error code.
999+
1000+
The caller should look at this information to decide if it's worth
1001+
retrying the call.
1002+
1003+
(*) Retry a client call.
1004+
1005+
int rxrpc_kernel_retry_call(struct socket *sock,
1006+
struct rxrpc_call *call,
1007+
struct sockaddr_rxrpc *srx,
1008+
struct key *key);
1009+
1010+
This attempts to partially reinitialise a call and submit it again whilst
1011+
reusing the original call's Tx queue to avoid the need to repackage and
1012+
re-encrypt the data to be sent. call indicates the call to retry, srx the
1013+
new address to send it to and key the encryption key to use for signing or
1014+
encrypting the packets.
1015+
1016+
For this to work, the first Tx data packet must still be in the transmit
1017+
queue, and currently this is only permitted for local and network errors
1018+
and the call must not have been aborted. Any partially constructed Tx
1019+
packet is left as is and can continue being filled afterwards.
1020+
1021+
It returns 0 if the call was requeued and an error otherwise.
1022+
9681023

9691024
=======================
9701025
CONFIGURABLE PARAMETERS

fs/afs/rxrpc.c

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,19 @@ static void afs_load_bvec(struct afs_call *call, struct msghdr *msg,
291291
iov_iter_bvec(&msg->msg_iter, WRITE | ITER_BVEC, bv, nr, bytes);
292292
}
293293

294+
/*
295+
* Advance the AFS call state when the RxRPC call ends the transmit phase.
296+
*/
297+
static void afs_notify_end_request_tx(struct sock *sock,
298+
struct rxrpc_call *rxcall,
299+
unsigned long call_user_ID)
300+
{
301+
struct afs_call *call = (struct afs_call *)call_user_ID;
302+
303+
if (call->state == AFS_CALL_REQUESTING)
304+
call->state = AFS_CALL_AWAIT_REPLY;
305+
}
306+
294307
/*
295308
* attach the data from a bunch of pages on an inode to a call
296309
*/
@@ -310,14 +323,8 @@ static int afs_send_pages(struct afs_call *call, struct msghdr *msg)
310323
bytes = msg->msg_iter.count;
311324
nr = msg->msg_iter.nr_segs;
312325

313-
/* Have to change the state *before* sending the last
314-
* packet as RxRPC might give us the reply before it
315-
* returns from sending the request.
316-
*/
317-
if (first + nr - 1 >= last)
318-
call->state = AFS_CALL_AWAIT_REPLY;
319-
ret = rxrpc_kernel_send_data(afs_socket, call->rxcall,
320-
msg, bytes);
326+
ret = rxrpc_kernel_send_data(afs_socket, call->rxcall, msg,
327+
bytes, afs_notify_end_request_tx);
321328
for (loop = 0; loop < nr; loop++)
322329
put_page(bv[loop].bv_page);
323330
if (ret < 0)
@@ -409,7 +416,8 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
409416
if (!call->send_pages)
410417
call->state = AFS_CALL_AWAIT_REPLY;
411418
ret = rxrpc_kernel_send_data(afs_socket, rxcall,
412-
&msg, call->request_size);
419+
&msg, call->request_size,
420+
afs_notify_end_request_tx);
413421
if (ret < 0)
414422
goto error_do_abort;
415423

@@ -740,6 +748,20 @@ static int afs_deliver_cm_op_id(struct afs_call *call)
740748
return call->type->deliver(call);
741749
}
742750

751+
/*
752+
* Advance the AFS call state when an RxRPC service call ends the transmit
753+
* phase.
754+
*/
755+
static void afs_notify_end_reply_tx(struct sock *sock,
756+
struct rxrpc_call *rxcall,
757+
unsigned long call_user_ID)
758+
{
759+
struct afs_call *call = (struct afs_call *)call_user_ID;
760+
761+
if (call->state == AFS_CALL_REPLYING)
762+
call->state = AFS_CALL_AWAIT_ACK;
763+
}
764+
743765
/*
744766
* send an empty reply
745767
*/
@@ -759,7 +781,8 @@ void afs_send_empty_reply(struct afs_call *call)
759781
msg.msg_flags = 0;
760782

761783
call->state = AFS_CALL_AWAIT_ACK;
762-
switch (rxrpc_kernel_send_data(afs_socket, call->rxcall, &msg, 0)) {
784+
switch (rxrpc_kernel_send_data(afs_socket, call->rxcall, &msg, 0,
785+
afs_notify_end_reply_tx)) {
763786
case 0:
764787
_leave(" [replied]");
765788
return;
@@ -797,7 +820,8 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
797820
msg.msg_flags = 0;
798821

799822
call->state = AFS_CALL_AWAIT_ACK;
800-
n = rxrpc_kernel_send_data(afs_socket, call->rxcall, &msg, len);
823+
n = rxrpc_kernel_send_data(afs_socket, call->rxcall, &msg, len,
824+
afs_notify_end_reply_tx);
801825
if (n >= 0) {
802826
/* Success */
803827
_leave(" [replied]");

include/keys/rxrpc-type.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,4 +127,27 @@ struct rxrpc_key_data_v1 {
127127
#define AFSTOKEN_K5_ADDRESSES_MAX 16 /* max K5 addresses */
128128
#define AFSTOKEN_K5_AUTHDATA_MAX 16 /* max K5 pieces of auth data */
129129

130+
/*
131+
* Truncate a time64_t to the range from 1970 to 2106 as in the network
132+
* protocol.
133+
*/
134+
static inline u32 rxrpc_time64_to_u32(time64_t time)
135+
{
136+
if (time < 0)
137+
return 0;
138+
139+
if (time > UINT_MAX)
140+
return UINT_MAX;
141+
142+
return (u32)time;
143+
}
144+
145+
/*
146+
* Extend u32 back to time64_t using the same 1970-2106 range.
147+
*/
148+
static inline time64_t rxrpc_u32_to_time64(u32 time)
149+
{
150+
return (time64_t)time;
151+
}
152+
130153
#endif /* _KEYS_RXRPC_TYPE_H */

include/net/af_rxrpc.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,22 @@ struct sock;
1919
struct socket;
2020
struct rxrpc_call;
2121

22+
/*
23+
* Call completion condition (state == RXRPC_CALL_COMPLETE).
24+
*/
25+
enum rxrpc_call_completion {
26+
RXRPC_CALL_SUCCEEDED, /* - Normal termination */
27+
RXRPC_CALL_REMOTELY_ABORTED, /* - call aborted by peer */
28+
RXRPC_CALL_LOCALLY_ABORTED, /* - call aborted locally on error or close */
29+
RXRPC_CALL_LOCAL_ERROR, /* - call failed due to local error */
30+
RXRPC_CALL_NETWORK_ERROR, /* - call terminated by network error */
31+
NR__RXRPC_CALL_COMPLETIONS
32+
};
33+
2234
typedef void (*rxrpc_notify_rx_t)(struct sock *, struct rxrpc_call *,
2335
unsigned long);
36+
typedef void (*rxrpc_notify_end_tx_t)(struct sock *, struct rxrpc_call *,
37+
unsigned long);
2438
typedef void (*rxrpc_notify_new_call_t)(struct sock *, struct rxrpc_call *,
2539
unsigned long);
2640
typedef void (*rxrpc_discard_new_call_t)(struct rxrpc_call *, unsigned long);
@@ -37,7 +51,8 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *,
3751
gfp_t,
3852
rxrpc_notify_rx_t);
3953
int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *,
40-
struct msghdr *, size_t);
54+
struct msghdr *, size_t,
55+
rxrpc_notify_end_tx_t);
4156
int rxrpc_kernel_recv_data(struct socket *, struct rxrpc_call *,
4257
void *, size_t, size_t *, bool, u32 *);
4358
bool rxrpc_kernel_abort_call(struct socket *, struct rxrpc_call *,
@@ -48,5 +63,9 @@ void rxrpc_kernel_get_peer(struct socket *, struct rxrpc_call *,
4863
int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
4964
rxrpc_user_attach_call_t, unsigned long, gfp_t);
5065
void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64);
66+
int rxrpc_kernel_retry_call(struct socket *, struct rxrpc_call *,
67+
struct sockaddr_rxrpc *, struct key *);
68+
int rxrpc_kernel_check_call(struct socket *, struct rxrpc_call *,
69+
enum rxrpc_call_completion *, u32 *);
5170

5271
#endif /* _NET_RXRPC_H */

net/rxrpc/af_rxrpc.c

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,75 @@ void rxrpc_kernel_end_call(struct socket *sock, struct rxrpc_call *call)
336336
}
337337
EXPORT_SYMBOL(rxrpc_kernel_end_call);
338338

339+
/**
340+
* rxrpc_kernel_check_call - Check a call's state
341+
* @sock: The socket the call is on
342+
* @call: The call to check
343+
* @_compl: Where to store the completion state
344+
* @_abort_code: Where to store any abort code
345+
*
346+
* Allow a kernel service to query the state of a call and find out the manner
347+
* of its termination if it has completed. Returns -EINPROGRESS if the call is
348+
* still going, 0 if the call finished successfully, -ECONNABORTED if the call
349+
* was aborted and an appropriate error if the call failed in some other way.
350+
*/
351+
int rxrpc_kernel_check_call(struct socket *sock, struct rxrpc_call *call,
352+
enum rxrpc_call_completion *_compl, u32 *_abort_code)
353+
{
354+
if (call->state != RXRPC_CALL_COMPLETE)
355+
return -EINPROGRESS;
356+
smp_rmb();
357+
*_compl = call->completion;
358+
*_abort_code = call->abort_code;
359+
return call->error;
360+
}
361+
EXPORT_SYMBOL(rxrpc_kernel_check_call);
362+
363+
/**
364+
* rxrpc_kernel_retry_call - Allow a kernel service to retry a call
365+
* @sock: The socket the call is on
366+
* @call: The call to retry
367+
* @srx: The address of the peer to contact
368+
* @key: The security context to use (defaults to socket setting)
369+
*
370+
* Allow a kernel service to try resending a client call that failed due to a
371+
* network error to a new address. The Tx queue is maintained intact, thereby
372+
* relieving the need to re-encrypt any request data that has already been
373+
* buffered.
374+
*/
375+
int rxrpc_kernel_retry_call(struct socket *sock, struct rxrpc_call *call,
376+
struct sockaddr_rxrpc *srx, struct key *key)
377+
{
378+
struct rxrpc_conn_parameters cp;
379+
struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
380+
int ret;
381+
382+
_enter("%d{%d}", call->debug_id, atomic_read(&call->usage));
383+
384+
if (!key)
385+
key = rx->key;
386+
if (key && !key->payload.data[0])
387+
key = NULL; /* a no-security key */
388+
389+
memset(&cp, 0, sizeof(cp));
390+
cp.local = rx->local;
391+
cp.key = key;
392+
cp.security_level = 0;
393+
cp.exclusive = false;
394+
cp.service_id = srx->srx_service;
395+
396+
mutex_lock(&call->user_mutex);
397+
398+
ret = rxrpc_prepare_call_for_retry(rx, call);
399+
if (ret == 0)
400+
ret = rxrpc_retry_client_call(rx, call, &cp, srx, GFP_KERNEL);
401+
402+
mutex_unlock(&call->user_mutex);
403+
_leave(" = %d", ret);
404+
return ret;
405+
}
406+
EXPORT_SYMBOL(rxrpc_kernel_retry_call);
407+
339408
/**
340409
* rxrpc_kernel_new_call_notification - Get notifications of new calls
341410
* @sock: The socket to intercept received messages on
@@ -591,13 +660,13 @@ static int rxrpc_getsockopt(struct socket *sock, int level, int optname,
591660
char __user *optval, int __user *_optlen)
592661
{
593662
int optlen;
594-
663+
595664
if (level != SOL_RXRPC)
596665
return -EOPNOTSUPP;
597666

598667
if (get_user(optlen, _optlen))
599668
return -EFAULT;
600-
669+
601670
switch (optname) {
602671
case RXRPC_SUPPORTED_CMSG:
603672
if (optlen < sizeof(int))
@@ -606,7 +675,7 @@ static int rxrpc_getsockopt(struct socket *sock, int level, int optname,
606675
put_user(sizeof(int), _optlen))
607676
return -EFAULT;
608677
return 0;
609-
678+
610679
default:
611680
return -EOPNOTSUPP;
612681
}

0 commit comments

Comments
 (0)