Skip to content

Commit 7eca9cc

Browse files
committed
Merge tag 'rxrpc-rewrite-20170607-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs
David Howells says: ==================== rxrpc: Tx length parameter Here's a set of patches that allows someone initiating a client call with AF_RXRPC to indicate upfront the total amount of data that will be transmitted. This will allow AF_RXRPC to encrypt directly from source buffer to packet rather than having to copy into the buffer and only encrypt when it's full (the encrypted portion of the packet starts with a length and so we can't encrypt until we know what the length will be). The three patches are: (1) Provide a means of finding out what control message types are actually supported. EINVAL is reported if an unsupported cmsg type is seen, so we don't want to set the new cmsg unless we know it will be accepted. (2) Consolidate some stuff into a struct to reduce the parameter count on the function that parses the cmsg buffer. (3) Introduce the RXRPC_TX_LENGTH cmsg. This can be provided on the first sendmsg() that contributes data to a client call request or a service call reply. If provided, the user must provide exactly that amount of data or an error will be incurred. Changes in version 2: (*) struct rxrpc_send_params::tx_total_len should be s64 not u64. Thanks to Julia Lawall for reporting this. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
2 parents 546692e + e754eba commit 7eca9cc

File tree

8 files changed

+207
-57
lines changed

8 files changed

+207
-57
lines changed

Documentation/networking/rxrpc.txt

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ calls, to invoke certain actions and to report certain conditions. These are:
327327
RXRPC_ACCEPT s-- n/a Accept new call
328328
RXRPC_EXCLUSIVE_CALL s-- n/a Make an exclusive client call
329329
RXRPC_UPGRADE_SERVICE s-- n/a Client call can be upgraded
330+
RXRPC_TX_LENGTH s-- data len Total length of Tx data
330331

331332
(SRT = usable in Sendmsg / delivered by Recvmsg / Terminal message)
332333

@@ -406,6 +407,23 @@ calls, to invoke certain actions and to report certain conditions. These are:
406407
future communication to that server and RXRPC_UPGRADE_SERVICE should no
407408
longer be set.
408409

410+
(*) RXRPC_TX_LENGTH
411+
412+
This is used to inform the kernel of the total amount of data that is
413+
going to be transmitted by a call (whether in a client request or a
414+
service response). If given, it allows the kernel to encrypt from the
415+
userspace buffer directly to the packet buffers, rather than copying into
416+
the buffer and then encrypting in place. This may only be given with the
417+
first sendmsg() providing data for a call. EMSGSIZE will be generated if
418+
the amount of data actually given is different.
419+
420+
This takes a parameter of __s64 type that indicates how much will be
421+
transmitted. This may not be less than zero.
422+
423+
The symbol RXRPC__SUPPORTED is defined as one more than the highest control
424+
message type supported. At run time this can be queried by means of the
425+
RXRPC_SUPPORTED_CMSG socket option (see below).
426+
409427

410428
==============
411429
SOCKET OPTIONS
@@ -459,6 +477,11 @@ AF_RXRPC sockets support a few socket options at the SOL_RXRPC level:
459477
must point to an array of two unsigned short ints. The first is the
460478
service ID to upgrade from and the second the service ID to upgrade to.
461479

480+
(*) RXRPC_SUPPORTED_CMSG
481+
482+
This is a read-only option that writes an int into the buffer indicating
483+
the highest control message type supported.
484+
462485

463486
========
464487
SECURITY
@@ -568,6 +591,9 @@ A client would issue an operation by:
568591
MSG_MORE should be set in msghdr::msg_flags on all but the last part of
569592
the request. Multiple requests may be made simultaneously.
570593

594+
An RXRPC_TX_LENGTH control message can also be specified on the first
595+
sendmsg() call.
596+
571597
If a call is intended to go to a destination other than the default
572598
specified through connect(), then msghdr::msg_name should be set on the
573599
first request message of that call.
@@ -755,6 +781,7 @@ The kernel interface functions are as follows:
755781
struct sockaddr_rxrpc *srx,
756782
struct key *key,
757783
unsigned long user_call_ID,
784+
s64 tx_total_len,
758785
gfp_t gfp);
759786

760787
This allocates the infrastructure to make a new RxRPC call and assigns
@@ -771,6 +798,11 @@ The kernel interface functions are as follows:
771798
control data buffer. It is entirely feasible to use this to point to a
772799
kernel data structure.
773800

801+
tx_total_len is the amount of data the caller is intending to transmit
802+
with this call (or -1 if unknown at this point). Setting the data size
803+
allows the kernel to encrypt directly to the packet buffers, thereby
804+
saving a copy. The value may not be less than -1.
805+
774806
If this function is successful, an opaque reference to the RxRPC call is
775807
returned. The caller now holds a reference on this and it must be
776808
properly ended.
@@ -922,6 +954,17 @@ The kernel interface functions are as follows:
922954

923955
This is used to find the remote peer address of a call.
924956

957+
(*) Set the total transmit data size on a call.
958+
959+
void rxrpc_kernel_set_tx_length(struct socket *sock,
960+
struct rxrpc_call *call,
961+
s64 tx_total_len);
962+
963+
This sets the amount of data that the caller is intending to transmit on a
964+
call. It's intended to be used for setting the reply size as the request
965+
size should be set when the call is begun. tx_total_len may not be less
966+
than zero.
967+
925968

926969
=======================
927970
CONFIGURABLE PARAMETERS

fs/afs/rxrpc.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
341341
struct msghdr msg;
342342
struct kvec iov[1];
343343
size_t offset;
344+
s64 tx_total_len;
344345
u32 abort_code;
345346
int ret;
346347

@@ -364,9 +365,20 @@ int afs_make_call(struct in_addr *addr, struct afs_call *call, gfp_t gfp,
364365
srx.transport.sin.sin_port = call->port;
365366
memcpy(&srx.transport.sin.sin_addr, addr, 4);
366367

368+
/* Work out the length we're going to transmit. This is awkward for
369+
* calls such as FS.StoreData where there's an extra injection of data
370+
* after the initial fixed part.
371+
*/
372+
tx_total_len = call->request_size;
373+
if (call->send_pages) {
374+
tx_total_len += call->last_to - call->first_offset;
375+
tx_total_len += (call->last - call->first) * PAGE_SIZE;
376+
}
377+
367378
/* create a call */
368379
rxcall = rxrpc_kernel_begin_call(afs_socket, &srx, call->key,
369-
(unsigned long) call, gfp,
380+
(unsigned long)call,
381+
tx_total_len, gfp,
370382
(async ?
371383
afs_wake_up_async_call :
372384
afs_wake_up_call_waiter));
@@ -738,6 +750,8 @@ void afs_send_empty_reply(struct afs_call *call)
738750

739751
_enter("");
740752

753+
rxrpc_kernel_set_tx_length(afs_socket, call->rxcall, 0);
754+
741755
msg.msg_name = NULL;
742756
msg.msg_namelen = 0;
743757
iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, NULL, 0, 0);
@@ -772,6 +786,8 @@ void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
772786

773787
_enter("");
774788

789+
rxrpc_kernel_set_tx_length(afs_socket, call->rxcall, len);
790+
775791
iov[0].iov_base = (void *) buf;
776792
iov[0].iov_len = len;
777793
msg.msg_name = NULL;

include/linux/rxrpc.h

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,28 @@ struct sockaddr_rxrpc {
3838
#define RXRPC_EXCLUSIVE_CONNECTION 3 /* Deprecated; use RXRPC_EXCLUSIVE_CALL instead */
3939
#define RXRPC_MIN_SECURITY_LEVEL 4 /* minimum security level */
4040
#define RXRPC_UPGRADEABLE_SERVICE 5 /* Upgrade service[0] -> service[1] */
41+
#define RXRPC_SUPPORTED_CMSG 6 /* Get highest supported control message type */
4142

4243
/*
4344
* RxRPC control messages
4445
* - If neither abort or accept are specified, the message is a data message.
4546
* - terminal messages mean that a user call ID tag can be recycled
4647
* - s/r/- indicate whether these are applicable to sendmsg() and/or recvmsg()
4748
*/
48-
#define RXRPC_USER_CALL_ID 1 /* sr: user call ID specifier */
49-
#define RXRPC_ABORT 2 /* sr: abort request / notification [terminal] */
50-
#define RXRPC_ACK 3 /* -r: [Service] RPC op final ACK received [terminal] */
51-
#define RXRPC_NET_ERROR 5 /* -r: network error received [terminal] */
52-
#define RXRPC_BUSY 6 /* -r: server busy received [terminal] */
53-
#define RXRPC_LOCAL_ERROR 7 /* -r: local error generated [terminal] */
54-
#define RXRPC_NEW_CALL 8 /* -r: [Service] new incoming call notification */
55-
#define RXRPC_ACCEPT 9 /* s-: [Service] accept request */
56-
#define RXRPC_EXCLUSIVE_CALL 10 /* s-: Call should be on exclusive connection */
57-
#define RXRPC_UPGRADE_SERVICE 11 /* s-: Request service upgrade for client call */
49+
enum rxrpc_cmsg_type {
50+
RXRPC_USER_CALL_ID = 1, /* sr: user call ID specifier */
51+
RXRPC_ABORT = 2, /* sr: abort request / notification [terminal] */
52+
RXRPC_ACK = 3, /* -r: [Service] RPC op final ACK received [terminal] */
53+
RXRPC_NET_ERROR = 5, /* -r: network error received [terminal] */
54+
RXRPC_BUSY = 6, /* -r: server busy received [terminal] */
55+
RXRPC_LOCAL_ERROR = 7, /* -r: local error generated [terminal] */
56+
RXRPC_NEW_CALL = 8, /* -r: [Service] new incoming call notification */
57+
RXRPC_ACCEPT = 9, /* s-: [Service] accept request */
58+
RXRPC_EXCLUSIVE_CALL = 10, /* s-: Call should be on exclusive connection */
59+
RXRPC_UPGRADE_SERVICE = 11, /* s-: Request service upgrade for client call */
60+
RXRPC_TX_LENGTH = 12, /* s-: Total length of Tx data */
61+
RXRPC__SUPPORTED
62+
};
5863

5964
/*
6065
* RxRPC security levels

include/net/af_rxrpc.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *,
3333
struct sockaddr_rxrpc *,
3434
struct key *,
3535
unsigned long,
36+
s64,
3637
gfp_t,
3738
rxrpc_notify_rx_t);
3839
int rxrpc_kernel_send_data(struct socket *, struct rxrpc_call *,
@@ -46,5 +47,6 @@ void rxrpc_kernel_get_peer(struct socket *, struct rxrpc_call *,
4647
struct sockaddr_rxrpc *);
4748
int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
4849
rxrpc_user_attach_call_t, unsigned long, gfp_t);
50+
void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64);
4951

5052
#endif /* _NET_RXRPC_H */

net/rxrpc/af_rxrpc.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ static int rxrpc_listen(struct socket *sock, int backlog)
262262
* @srx: The address of the peer to contact
263263
* @key: The security context to use (defaults to socket setting)
264264
* @user_call_ID: The ID to use
265+
* @tx_total_len: Total length of data to transmit during the call (or -1)
265266
* @gfp: The allocation constraints
266267
* @notify_rx: Where to send notifications instead of socket queue
267268
*
@@ -276,6 +277,7 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
276277
struct sockaddr_rxrpc *srx,
277278
struct key *key,
278279
unsigned long user_call_ID,
280+
s64 tx_total_len,
279281
gfp_t gfp,
280282
rxrpc_notify_rx_t notify_rx)
281283
{
@@ -303,7 +305,8 @@ struct rxrpc_call *rxrpc_kernel_begin_call(struct socket *sock,
303305
cp.security_level = 0;
304306
cp.exclusive = false;
305307
cp.service_id = srx->srx_service;
306-
call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, gfp);
308+
call = rxrpc_new_client_call(rx, &cp, srx, user_call_ID, tx_total_len,
309+
gfp);
307310
/* The socket has been unlocked. */
308311
if (!IS_ERR(call))
309312
call->notify_rx = notify_rx;
@@ -581,6 +584,34 @@ static int rxrpc_setsockopt(struct socket *sock, int level, int optname,
581584
return ret;
582585
}
583586

587+
/*
588+
* Get socket options.
589+
*/
590+
static int rxrpc_getsockopt(struct socket *sock, int level, int optname,
591+
char __user *optval, int __user *_optlen)
592+
{
593+
int optlen;
594+
595+
if (level != SOL_RXRPC)
596+
return -EOPNOTSUPP;
597+
598+
if (get_user(optlen, _optlen))
599+
return -EFAULT;
600+
601+
switch (optname) {
602+
case RXRPC_SUPPORTED_CMSG:
603+
if (optlen < sizeof(int))
604+
return -ETOOSMALL;
605+
if (put_user(RXRPC__SUPPORTED - 1, (int __user *)optval) ||
606+
put_user(sizeof(int), _optlen))
607+
return -EFAULT;
608+
return 0;
609+
610+
default:
611+
return -EOPNOTSUPP;
612+
}
613+
}
614+
584615
/*
585616
* permit an RxRPC socket to be polled
586617
*/
@@ -784,7 +815,7 @@ static const struct proto_ops rxrpc_rpc_ops = {
784815
.listen = rxrpc_listen,
785816
.shutdown = rxrpc_shutdown,
786817
.setsockopt = rxrpc_setsockopt,
787-
.getsockopt = sock_no_getsockopt,
818+
.getsockopt = rxrpc_getsockopt,
788819
.sendmsg = rxrpc_sendmsg,
789820
.recvmsg = rxrpc_recvmsg,
790821
.mmap = sock_no_mmap,

net/rxrpc/ar-internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ struct rxrpc_call {
528528
struct rb_node sock_node; /* Node in rx->calls */
529529
struct sk_buff *tx_pending; /* Tx socket buffer being filled */
530530
wait_queue_head_t waitq; /* Wait queue for channel or Tx */
531+
s64 tx_total_len; /* Total length left to be transmitted (or -1) */
531532
__be32 crypto_buf[2]; /* Temporary packet crypto buffer */
532533
unsigned long user_call_ID; /* user-defined call ID */
533534
unsigned long flags;
@@ -683,7 +684,7 @@ struct rxrpc_call *rxrpc_alloc_call(gfp_t);
683684
struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *,
684685
struct rxrpc_conn_parameters *,
685686
struct sockaddr_rxrpc *,
686-
unsigned long, gfp_t);
687+
unsigned long, s64, gfp_t);
687688
void rxrpc_incoming_call(struct rxrpc_sock *, struct rxrpc_call *,
688689
struct sk_buff *);
689690
void rxrpc_release_call(struct rxrpc_sock *, struct rxrpc_call *);

net/rxrpc/call_object.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ struct rxrpc_call *rxrpc_alloc_call(gfp_t gfp)
127127
rwlock_init(&call->state_lock);
128128
atomic_set(&call->usage, 1);
129129
call->debug_id = atomic_inc_return(&rxrpc_debug_id);
130+
call->tx_total_len = -1;
130131

131132
memset(&call->sock_node, 0xed, sizeof(call->sock_node));
132133

@@ -201,6 +202,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
201202
struct rxrpc_conn_parameters *cp,
202203
struct sockaddr_rxrpc *srx,
203204
unsigned long user_call_ID,
205+
s64 tx_total_len,
204206
gfp_t gfp)
205207
__releases(&rx->sk.sk_lock.slock)
206208
{
@@ -219,6 +221,7 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *rx,
219221
return call;
220222
}
221223

224+
call->tx_total_len = tx_total_len;
222225
trace_rxrpc_call(call, rxrpc_call_new_client, atomic_read(&call->usage),
223226
here, (const void *)user_call_ID);
224227

0 commit comments

Comments
 (0)