Skip to content

Commit 9854d75

Browse files
committed
Merge tag 'rxrpc-next-20171018' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
David Howells says: ==================== rxrpc: Add bits for kernel services Here are some patches that add a few things for kernel services to use: (1) Allow service upgrade to be requested and allow the resultant actual service ID to be obtained. (2) Allow the RTT time of a call to be obtained. (3) Allow a kernel service to find out if a call is still alive on a server between transmitting a request and getting the reply. (4) Allow data transmission to ignore signals if transmission progress is being made in reasonable time. This is also usable by userspace by passing MSG_WAITALL to sendmsg()[*]. [*] I'm not sure this is the right interface for this or whether a sockopt should be used instead. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 3732053 + bc5e3a5 commit 9854d75

File tree

8 files changed

+211
-41
lines changed

8 files changed

+211
-41
lines changed

Documentation/networking/rxrpc.txt

Lines changed: 51 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,18 @@ Interaction with the user of the RxRPC socket:
280280
nominated by a socket option.
281281

282282

283+
Notes on sendmsg:
284+
285+
(*) MSG_WAITALL can be set to tell sendmsg to ignore signals if the peer is
286+
making progress at accepting packets within a reasonable time such that we
287+
manage to queue up all the data for transmission. This requires the
288+
client to accept at least one packet per 2*RTT time period.
289+
290+
If this isn't set, sendmsg() will return immediately, either returning
291+
EINTR/ERESTARTSYS if nothing was consumed or returning the amount of data
292+
consumed.
293+
294+
283295
Notes on recvmsg:
284296

285297
(*) If there's a sequence of data messages belonging to a particular call on
@@ -782,7 +794,9 @@ The kernel interface functions are as follows:
782794
struct key *key,
783795
unsigned long user_call_ID,
784796
s64 tx_total_len,
785-
gfp_t gfp);
797+
gfp_t gfp,
798+
rxrpc_notify_rx_t notify_rx,
799+
bool upgrade);
786800

787801
This allocates the infrastructure to make a new RxRPC call and assigns
788802
call and connection numbers. The call will be made on the UDP port that
@@ -803,6 +817,13 @@ The kernel interface functions are as follows:
803817
allows the kernel to encrypt directly to the packet buffers, thereby
804818
saving a copy. The value may not be less than -1.
805819

820+
notify_rx is a pointer to a function to be called when events such as
821+
incoming data packets or remote aborts happen.
822+
823+
upgrade should be set to true if a client operation should request that
824+
the server upgrade the service to a better one. The resultant service ID
825+
is returned by rxrpc_kernel_recv_data().
826+
806827
If this function is successful, an opaque reference to the RxRPC call is
807828
returned. The caller now holds a reference on this and it must be
808829
properly ended.
@@ -850,7 +871,8 @@ The kernel interface functions are as follows:
850871
size_t size,
851872
size_t *_offset,
852873
bool want_more,
853-
u32 *_abort)
874+
u32 *_abort,
875+
u16 *_service)
854876

855877
This is used to receive data from either the reply part of a client call
856878
or the request part of a service call. buf and size specify how much
@@ -873,6 +895,9 @@ The kernel interface functions are as follows:
873895
If a remote ABORT is detected, the abort code received will be stored in
874896
*_abort and ECONNABORTED will be returned.
875897

898+
The service ID that the call ended up with is returned into *_service.
899+
This can be used to see if a call got a service upgrade.
900+
876901
(*) Abort a call.
877902

878903
void rxrpc_kernel_abort_call(struct socket *sock,
@@ -1020,6 +1045,30 @@ The kernel interface functions are as follows:
10201045

10211046
It returns 0 if the call was requeued and an error otherwise.
10221047

1048+
(*) Get call RTT.
1049+
1050+
u64 rxrpc_kernel_get_rtt(struct socket *sock, struct rxrpc_call *call);
1051+
1052+
Get the RTT time to the peer in use by a call. The value returned is in
1053+
nanoseconds.
1054+
1055+
(*) Check call still alive.
1056+
1057+
u32 rxrpc_kernel_check_life(struct socket *sock,
1058+
struct rxrpc_call *call);
1059+
1060+
This returns a number that is updated when ACKs are received from the peer
1061+
(notably including PING RESPONSE ACKs which we can elicit by sending PING
1062+
ACKs to see if the call still exists on the server). The caller should
1063+
compare the numbers of two calls to see if the call is still alive after
1064+
waiting for a suitable interval.
1065+
1066+
This allows the caller to work out if the server is still contactable and
1067+
if the call is still alive on the server whilst waiting for the server to
1068+
process a client operation.
1069+
1070+
This function may transmit a PING ACK.
1071+
10231072

10241073
=======================
10251074
CONFIGURABLE PARAMETERS

fs/afs/internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ struct afs_call {
100100
bool send_pages; /* T if data from mapping should be sent */
101101
bool need_attention; /* T if RxRPC poked us */
102102
bool async; /* T if asynchronous */
103+
bool upgrade; /* T to request service upgrade */
103104
u16 service_id; /* RxRPC service ID to call */
104105
__be16 port; /* target UDP port */
105106
u32 operation_ID; /* operation ID for an incoming call */

fs/afs/rxrpc.c

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,8 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
387387
tx_total_len, gfp,
388388
(async ?
389389
afs_wake_up_async_call :
390-
afs_wake_up_call_waiter));
390+
afs_wake_up_call_waiter),
391+
call->upgrade);
391392
call->key = NULL;
392393
if (IS_ERR(rxcall)) {
393394
ret = PTR_ERR(rxcall);
@@ -406,7 +407,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
406407
call->request_size);
407408
msg.msg_control = NULL;
408409
msg.msg_controllen = 0;
409-
msg.msg_flags = (call->send_pages ? MSG_MORE : 0);
410+
msg.msg_flags = MSG_WAITALL | (call->send_pages ? MSG_MORE : 0);
410411

411412
/* We have to change the state *before* sending the last packet as
412413
* rxrpc might give us the reply before it returns from sending the
@@ -443,7 +444,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
443444
abort_code = 0;
444445
offset = 0;
445446
rxrpc_kernel_recv_data(afs_socket, rxcall, NULL, 0, &offset,
446-
false, &abort_code);
447+
false, &abort_code, &call->service_id);
447448
ret = call->type->abort_to_error(abort_code);
448449
}
449450
error_kill_call:
@@ -471,7 +472,8 @@ static void afs_deliver_to_call(struct afs_call *call)
471472
size_t offset = 0;
472473
ret = rxrpc_kernel_recv_data(afs_socket, call->rxcall,
473474
NULL, 0, &offset, false,
474-
&call->abort_code);
475+
&call->abort_code,
476+
&call->service_id);
475477
trace_afs_recv_data(call, 0, offset, false, ret);
476478

477479
if (ret == -EINPROGRESS || ret == -EAGAIN)
@@ -536,15 +538,26 @@ static void afs_deliver_to_call(struct afs_call *call)
536538
*/
537539
static int afs_wait_for_call_to_complete(struct afs_call *call)
538540
{
541+
signed long rtt2, timeout;
539542
int ret;
543+
u64 rtt;
544+
u32 life, last_life;
540545

541546
DECLARE_WAITQUEUE(myself, current);
542547

543548
_enter("");
544549

550+
rtt = rxrpc_kernel_get_rtt(afs_socket, call->rxcall);
551+
rtt2 = nsecs_to_jiffies64(rtt) * 2;
552+
if (rtt2 < 2)
553+
rtt2 = 2;
554+
555+
timeout = rtt2;
556+
last_life = rxrpc_kernel_check_life(afs_socket, call->rxcall);
557+
545558
add_wait_queue(&call->waitq, &myself);
546559
for (;;) {
547-
set_current_state(TASK_INTERRUPTIBLE);
560+
set_current_state(TASK_UNINTERRUPTIBLE);
548561

549562
/* deliver any messages that are in the queue */
550563
if (call->state < AFS_CALL_COMPLETE && call->need_attention) {
@@ -554,10 +567,20 @@ static int afs_wait_for_call_to_complete(struct afs_call *call)
554567
continue;
555568
}
556569

557-
if (call->state == AFS_CALL_COMPLETE ||
558-
signal_pending(current))
570+
if (call->state == AFS_CALL_COMPLETE)
559571
break;
560-
schedule();
572+
573+
life = rxrpc_kernel_check_life(afs_socket, call->rxcall);
574+
if (timeout == 0 &&
575+
life == last_life && signal_pending(current))
576+
break;
577+
578+
if (life != last_life) {
579+
timeout = rtt2;
580+
last_life = life;
581+
}
582+
583+
timeout = schedule_timeout(timeout);
561584
}
562585

563586
remove_wait_queue(&call->waitq, &myself);
@@ -851,7 +874,8 @@ int afs_extract_data(struct afs_call *call, void *buf, size_t count,
851874

852875
ret = rxrpc_kernel_recv_data(afs_socket, call->rxcall,
853876
buf, count, &call->offset,
854-
want_more, &call->abort_code);
877+
want_more, &call->abort_code,
878+
&call->service_id);
855879
trace_afs_recv_data(call, count, call->offset, want_more, ret);
856880
if (ret == 0 || ret == -EAGAIN)
857881
return ret;

include/net/af_rxrpc.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,23 +49,26 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *,
4949
unsigned long,
5050
s64,
5151
gfp_t,
52-
rxrpc_notify_rx_t);
52+
rxrpc_notify_rx_t,
53+
bool);
5354
int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *,
5455
struct msghdr *, size_t,
5556
rxrpc_notify_end_tx_t);
5657
int rxrpc_kernel_recv_data(struct socket *, struct rxrpc_call *,
57-
void *, size_t, size_t *, bool, u32 *);
58+
void *, size_t, size_t *, bool, u32 *, u16 *);
5859
bool rxrpc_kernel_abort_call(struct socket *, struct rxrpc_call *,
5960
u32, int, const char *);
6061
void rxrpc_kernel_end_call(struct socket *, struct rxrpc_call *);
6162
void rxrpc_kernel_get_peer(struct socket *, struct rxrpc_call *,
6263
struct sockaddr_rxrpc *);
64+
u64 rxrpc_kernel_get_rtt(struct socket *, struct rxrpc_call *);
6365
int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
6466
rxrpc_user_attach_call_t, unsigned long, gfp_t);
6567
void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64);
6668
int rxrpc_kernel_retry_call(struct socket *, struct rxrpc_call *,
6769
struct sockaddr_rxrpc *, struct key *);
6870
int rxrpc_kernel_check_call(struct socket *, struct rxrpc_call *,
6971
enum rxrpc_call_completion *, u32 *);
72+
u32 rxrpc_kernel_check_life(struct socket *, struct rxrpc_call *);
7073

7174
#endif /* _NET_RXRPC_H */

net/rxrpc/af_rxrpc.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ static int rxrpc_listen(struct socket *sock, int backlog)
265265
* @tx_total_len: Total length of data to transmit during the call (or -1)
266266
* @gfp: The allocation constraints
267267
* @notify_rx: Where to send notifications instead of socket queue
268+
* @upgrade: Request service upgrade for call
268269
*
269270
* Allow a kernel service to begin a call on the nominated socket. This just
270271
* sets up all the internal tracking structures and allocates connection and
@@ -279,7 +280,8 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
279280
unsigned long user_call_ID,
280281
s64 tx_total_len,
281282
gfp_t gfp,
282-
rxrpc_notify_rx_t notify_rx)
283+
rxrpc_notify_rx_t notify_rx,
284+
bool upgrade)
283285
{
284286
struct rxrpc_conn_parameters cp;
285287
struct rxrpc_call *call;
@@ -304,6 +306,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
304306
cp.key = key;
305307
cp.security_level = 0;
306308
cp.exclusive = false;
309+
cp.upgrade = upgrade;
307310
cp.service_id = srx->srx_service;
308311
call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, tx_total_len,
309312
gfp);
@@ -336,6 +339,25 @@ void rxrpc_kernel_end_call(struct socket *sock, struct rxrpc_call *call)
336339
}
337340
EXPORT_SYMBOL(rxrpc_kernel_end_call);
338341

342+
/**
343+
* rxrpc_kernel_check_life - Check to see whether a call is still alive
344+
* @sock: The socket the call is on
345+
* @call: The call to check
346+
*
347+
* Allow a kernel service to find out whether a call is still alive - ie. we're
348+
* getting ACKs from the server. Returns a number representing the life state
349+
* which can be compared to that returned by a previous call.
350+
*
351+
* If this is a client call, ping ACKs will be sent to the server to find out
352+
* whether it's still responsive and whether the call is still alive on the
353+
* server.
354+
*/
355+
u32 rxrpc_kernel_check_life(struct socket *sock, struct rxrpc_call *call)
356+
{
357+
return call->acks_latest;
358+
}
359+
EXPORT_SYMBOL(rxrpc_kernel_check_life);
360+
339361
/**
340362
* rxrpc_kernel_check_call - Check a call's state
341363
* @sock: The socket the call is on

net/rxrpc/peer_object.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -411,3 +411,16 @@ void rxrpc_kernel_get_peer(struct socket *sock, struct rxrpc_call *call,
411411
*_srx = call->peer->srx;
412412
}
413413
EXPORT_SYMBOL(rxrpc_kernel_get_peer);
414+
415+
/**
416+
* rxrpc_kernel_get_rtt - Get a call's peer RTT
417+
* @sock: The socket on which the call is in progress.
418+
* @call: The call to query
419+
*
420+
* Get the call's peer RTT.
421+
*/
422+
u64 rxrpc_kernel_get_rtt(struct socket *sock, struct rxrpc_call *call)
423+
{
424+
return call->peer->rtt;
425+
}
426+
EXPORT_SYMBOL(rxrpc_kernel_get_rtt);

net/rxrpc/recvmsg.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
607607
* @_offset: The running offset into the buffer.
608608
* @want_more: True if more data is expected to be read
609609
* @_abort: Where the abort code is stored if -ECONNABORTED is returned
610+
* @_service: Where to store the actual service ID (may be upgraded)
610611
*
611612
* Allow a kernel service to receive data and pick up information about the
612613
* state of a call. Returns 0 if got what was asked for and there's more
@@ -624,7 +625,7 @@ int rxrpc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
624625
*/
625626
int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call,
626627
void *buf, size_t size, size_t *_offset,
627-
bool want_more, u32 *_abort)
628+
bool want_more, u32 *_abort, u16 *_service)
628629
{
629630
struct iov_iter iter;
630631
struct kvec iov;
@@ -680,6 +681,8 @@ int rxrpc_kernel_recv_data(struct socket *sock, struct rxrpc_call *call,
680681
read_phase_complete:
681682
ret = 1;
682683
out:
684+
if (_service)
685+
*_service = call->service_id;
683686
mutex_unlock(&call->user_mutex);
684687
_leave(" = %d [%zu,%d]", ret, *_offset, *_abort);
685688
return ret;

0 commit comments

Comments
 (0)