xref: /openbmc/linux/net/rxrpc/sendmsg.c (revision 360823a09426347ea8f232b0b0b5156d0aed0302)
1b4d0d230SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
20b58b8a1SDavid Howells /* AF_RXRPC sendmsg() implementation.
30b58b8a1SDavid Howells  *
40b58b8a1SDavid Howells  * Copyright (C) 2007, 2016 Red Hat, Inc. All Rights Reserved.
50b58b8a1SDavid Howells  * Written by David Howells (dhowells@redhat.com)
60b58b8a1SDavid Howells  */
70b58b8a1SDavid Howells 
80b58b8a1SDavid Howells #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
90b58b8a1SDavid Howells 
100b58b8a1SDavid Howells #include <linux/net.h>
110b58b8a1SDavid Howells #include <linux/gfp.h>
120b58b8a1SDavid Howells #include <linux/skbuff.h>
130b58b8a1SDavid Howells #include <linux/export.h>
14174cd4b1SIngo Molnar #include <linux/sched/signal.h>
15174cd4b1SIngo Molnar 
160b58b8a1SDavid Howells #include <net/sock.h>
170b58b8a1SDavid Howells #include <net/af_rxrpc.h>
180b58b8a1SDavid Howells #include "ar-internal.h"
190b58b8a1SDavid Howells 
200b58b8a1SDavid Howells /*
21a343b174SDavid Howells  * Propose an abort to be made in the I/O thread.
22a343b174SDavid Howells  */
rxrpc_propose_abort(struct rxrpc_call * call,s32 abort_code,int error,enum rxrpc_abort_reason why)2357af281eSDavid Howells bool rxrpc_propose_abort(struct rxrpc_call *call, s32 abort_code, int error,
2457af281eSDavid Howells 			 enum rxrpc_abort_reason why)
25a343b174SDavid Howells {
2657af281eSDavid Howells 	_enter("{%d},%d,%d,%u", call->debug_id, abort_code, error, why);
27a343b174SDavid Howells 
28d41b3f5bSDavid Howells 	if (!call->send_abort && !rxrpc_call_is_complete(call)) {
29a343b174SDavid Howells 		call->send_abort_why = why;
30a343b174SDavid Howells 		call->send_abort_err = error;
3157af281eSDavid Howells 		call->send_abort_seq = 0;
32a343b174SDavid Howells 		/* Request abort locklessly vs rxrpc_input_call_event(). */
33a343b174SDavid Howells 		smp_store_release(&call->send_abort, abort_code);
34a343b174SDavid Howells 		rxrpc_poke_call(call, rxrpc_call_poke_abort);
35a343b174SDavid Howells 		return true;
36a343b174SDavid Howells 	}
37a343b174SDavid Howells 
38a343b174SDavid Howells 	return false;
39a343b174SDavid Howells }
40a343b174SDavid Howells 
41a343b174SDavid Howells /*
429d35d880SDavid Howells  * Wait for a call to become connected.  Interruption here doesn't cause the
439d35d880SDavid Howells  * call to be aborted.
449d35d880SDavid Howells  */
rxrpc_wait_to_be_connected(struct rxrpc_call * call,long * timeo)459d35d880SDavid Howells static int rxrpc_wait_to_be_connected(struct rxrpc_call *call, long *timeo)
469d35d880SDavid Howells {
479d35d880SDavid Howells 	DECLARE_WAITQUEUE(myself, current);
489d35d880SDavid Howells 	int ret = 0;
499d35d880SDavid Howells 
509d35d880SDavid Howells 	_enter("%d", call->debug_id);
519d35d880SDavid Howells 
529d35d880SDavid Howells 	if (rxrpc_call_state(call) != RXRPC_CALL_CLIENT_AWAIT_CONN)
532b5fdc0fSDavid Howells 		goto no_wait;
549d35d880SDavid Howells 
559d35d880SDavid Howells 	add_wait_queue_exclusive(&call->waitq, &myself);
569d35d880SDavid Howells 
579d35d880SDavid Howells 	for (;;) {
589d35d880SDavid Howells 		switch (call->interruptibility) {
599d35d880SDavid Howells 		case RXRPC_INTERRUPTIBLE:
609d35d880SDavid Howells 		case RXRPC_PREINTERRUPTIBLE:
619d35d880SDavid Howells 			set_current_state(TASK_INTERRUPTIBLE);
629d35d880SDavid Howells 			break;
639d35d880SDavid Howells 		case RXRPC_UNINTERRUPTIBLE:
649d35d880SDavid Howells 		default:
659d35d880SDavid Howells 			set_current_state(TASK_UNINTERRUPTIBLE);
669d35d880SDavid Howells 			break;
679d35d880SDavid Howells 		}
682b5fdc0fSDavid Howells 
692b5fdc0fSDavid Howells 		if (rxrpc_call_state(call) != RXRPC_CALL_CLIENT_AWAIT_CONN)
709d35d880SDavid Howells 			break;
719d35d880SDavid Howells 		if ((call->interruptibility == RXRPC_INTERRUPTIBLE ||
729d35d880SDavid Howells 		     call->interruptibility == RXRPC_PREINTERRUPTIBLE) &&
739d35d880SDavid Howells 		    signal_pending(current)) {
749d35d880SDavid Howells 			ret = sock_intr_errno(*timeo);
759d35d880SDavid Howells 			break;
769d35d880SDavid Howells 		}
779d35d880SDavid Howells 		*timeo = schedule_timeout(*timeo);
789d35d880SDavid Howells 	}
799d35d880SDavid Howells 
809d35d880SDavid Howells 	remove_wait_queue(&call->waitq, &myself);
819d35d880SDavid Howells 	__set_current_state(TASK_RUNNING);
829d35d880SDavid Howells 
832b5fdc0fSDavid Howells no_wait:
849d35d880SDavid Howells 	if (ret == 0 && rxrpc_call_is_complete(call))
859d35d880SDavid Howells 		ret = call->error;
869d35d880SDavid Howells 
879d35d880SDavid Howells 	_leave(" = %d", ret);
889d35d880SDavid Howells 	return ret;
899d35d880SDavid Howells }
909d35d880SDavid Howells 
919d35d880SDavid Howells /*
92158fe666SDavid Howells  * Return true if there's sufficient Tx queue space.
93158fe666SDavid Howells  */
rxrpc_check_tx_space(struct rxrpc_call * call,rxrpc_seq_t * _tx_win)94158fe666SDavid Howells static bool rxrpc_check_tx_space(struct rxrpc_call *call, rxrpc_seq_t *_tx_win)
95158fe666SDavid Howells {
96158fe666SDavid Howells 	if (_tx_win)
97cf37b598SDavid Howells 		*_tx_win = call->tx_bottom;
98cf37b598SDavid Howells 	return call->tx_prepared - call->tx_bottom < 256;
99158fe666SDavid Howells }
100158fe666SDavid Howells 
101158fe666SDavid Howells /*
102bc5e3a54SDavid Howells  * Wait for space to appear in the Tx queue or a signal to occur.
103bc5e3a54SDavid Howells  */
rxrpc_wait_for_tx_window_intr(struct rxrpc_sock * rx,struct rxrpc_call * call,long * timeo)104bc5e3a54SDavid Howells static int rxrpc_wait_for_tx_window_intr(struct rxrpc_sock *rx,
105bc5e3a54SDavid Howells 					 struct rxrpc_call *call,
106bc5e3a54SDavid Howells 					 long *timeo)
107bc5e3a54SDavid Howells {
108bc5e3a54SDavid Howells 	for (;;) {
109bc5e3a54SDavid Howells 		set_current_state(TASK_INTERRUPTIBLE);
110158fe666SDavid Howells 		if (rxrpc_check_tx_space(call, NULL))
111bc5e3a54SDavid Howells 			return 0;
112bc5e3a54SDavid Howells 
113d41b3f5bSDavid Howells 		if (rxrpc_call_is_complete(call))
114bc5e3a54SDavid Howells 			return call->error;
115bc5e3a54SDavid Howells 
116bc5e3a54SDavid Howells 		if (signal_pending(current))
117bc5e3a54SDavid Howells 			return sock_intr_errno(*timeo);
118bc5e3a54SDavid Howells 
119a4ea4c47SDavid Howells 		trace_rxrpc_txqueue(call, rxrpc_txqueue_wait);
120bc5e3a54SDavid Howells 		*timeo = schedule_timeout(*timeo);
121bc5e3a54SDavid Howells 	}
122bc5e3a54SDavid Howells }
123bc5e3a54SDavid Howells 
124bc5e3a54SDavid Howells /*
125bc5e3a54SDavid Howells  * Wait for space to appear in the Tx queue uninterruptibly, but with
126bc5e3a54SDavid Howells  * a timeout of 2*RTT if no progress was made and a signal occurred.
127bc5e3a54SDavid Howells  */
rxrpc_wait_for_tx_window_waitall(struct rxrpc_sock * rx,struct rxrpc_call * call)128e138aa7dSDavid Howells static int rxrpc_wait_for_tx_window_waitall(struct rxrpc_sock *rx,
129bc5e3a54SDavid Howells 					    struct rxrpc_call *call)
130bc5e3a54SDavid Howells {
131bc5e3a54SDavid Howells 	rxrpc_seq_t tx_start, tx_win;
132c410bf01SDavid Howells 	signed long rtt, timeout;
133bc5e3a54SDavid Howells 
134c410bf01SDavid Howells 	rtt = READ_ONCE(call->peer->srtt_us) >> 3;
135c410bf01SDavid Howells 	rtt = usecs_to_jiffies(rtt) * 2;
136c410bf01SDavid Howells 	if (rtt < 2)
137c410bf01SDavid Howells 		rtt = 2;
138bc5e3a54SDavid Howells 
139c410bf01SDavid Howells 	timeout = rtt;
140a4ea4c47SDavid Howells 	tx_start = smp_load_acquire(&call->acks_hard_ack);
141bc5e3a54SDavid Howells 
142bc5e3a54SDavid Howells 	for (;;) {
143bc5e3a54SDavid Howells 		set_current_state(TASK_UNINTERRUPTIBLE);
144bc5e3a54SDavid Howells 
145158fe666SDavid Howells 		if (rxrpc_check_tx_space(call, &tx_win))
146bc5e3a54SDavid Howells 			return 0;
147bc5e3a54SDavid Howells 
148d41b3f5bSDavid Howells 		if (rxrpc_call_is_complete(call))
149bc5e3a54SDavid Howells 			return call->error;
150bc5e3a54SDavid Howells 
151e138aa7dSDavid Howells 		if (timeout == 0 &&
152bc5e3a54SDavid Howells 		    tx_win == tx_start && signal_pending(current))
153bc5e3a54SDavid Howells 			return -EINTR;
154bc5e3a54SDavid Howells 
155bc5e3a54SDavid Howells 		if (tx_win != tx_start) {
156c410bf01SDavid Howells 			timeout = rtt;
157bc5e3a54SDavid Howells 			tx_start = tx_win;
158bc5e3a54SDavid Howells 		}
159bc5e3a54SDavid Howells 
160a4ea4c47SDavid Howells 		trace_rxrpc_txqueue(call, rxrpc_txqueue_wait);
161bc5e3a54SDavid Howells 		timeout = schedule_timeout(timeout);
162bc5e3a54SDavid Howells 	}
163bc5e3a54SDavid Howells }
164bc5e3a54SDavid Howells 
165bc5e3a54SDavid Howells /*
166e138aa7dSDavid Howells  * Wait for space to appear in the Tx queue uninterruptibly.
167e138aa7dSDavid Howells  */
rxrpc_wait_for_tx_window_nonintr(struct rxrpc_sock * rx,struct rxrpc_call * call,long * timeo)168e138aa7dSDavid Howells static int rxrpc_wait_for_tx_window_nonintr(struct rxrpc_sock *rx,
169e138aa7dSDavid Howells 					    struct rxrpc_call *call,
170e138aa7dSDavid Howells 					    long *timeo)
171e138aa7dSDavid Howells {
172e138aa7dSDavid Howells 	for (;;) {
173e138aa7dSDavid Howells 		set_current_state(TASK_UNINTERRUPTIBLE);
174e138aa7dSDavid Howells 		if (rxrpc_check_tx_space(call, NULL))
175e138aa7dSDavid Howells 			return 0;
176e138aa7dSDavid Howells 
177d41b3f5bSDavid Howells 		if (rxrpc_call_is_complete(call))
178e138aa7dSDavid Howells 			return call->error;
179e138aa7dSDavid Howells 
180a4ea4c47SDavid Howells 		trace_rxrpc_txqueue(call, rxrpc_txqueue_wait);
181e138aa7dSDavid Howells 		*timeo = schedule_timeout(*timeo);
182e138aa7dSDavid Howells 	}
183e138aa7dSDavid Howells }
184e138aa7dSDavid Howells 
185e138aa7dSDavid Howells /*
1860b58b8a1SDavid Howells  * wait for space to appear in the transmit/ACK window
1870b58b8a1SDavid Howells  * - caller holds the socket locked
1880b58b8a1SDavid Howells  */
rxrpc_wait_for_tx_window(struct rxrpc_sock * rx,struct rxrpc_call * call,long * timeo,bool waitall)1890b58b8a1SDavid Howells static int rxrpc_wait_for_tx_window(struct rxrpc_sock *rx,
1900b58b8a1SDavid Howells 				    struct rxrpc_call *call,
191bc5e3a54SDavid Howells 				    long *timeo,
192bc5e3a54SDavid Howells 				    bool waitall)
1930b58b8a1SDavid Howells {
1940b58b8a1SDavid Howells 	DECLARE_WAITQUEUE(myself, current);
1950b58b8a1SDavid Howells 	int ret;
1960b58b8a1SDavid Howells 
197a4ea4c47SDavid Howells 	_enter(",{%u,%u,%u,%u}",
198a4ea4c47SDavid Howells 	       call->tx_bottom, call->acks_hard_ack, call->tx_top, call->tx_winsize);
1990b58b8a1SDavid Howells 
2000b58b8a1SDavid Howells 	add_wait_queue(&call->waitq, &myself);
2010b58b8a1SDavid Howells 
202e138aa7dSDavid Howells 	switch (call->interruptibility) {
203e138aa7dSDavid Howells 	case RXRPC_INTERRUPTIBLE:
204bc5e3a54SDavid Howells 		if (waitall)
205e138aa7dSDavid Howells 			ret = rxrpc_wait_for_tx_window_waitall(rx, call);
206bc5e3a54SDavid Howells 		else
207bc5e3a54SDavid Howells 			ret = rxrpc_wait_for_tx_window_intr(rx, call, timeo);
208e138aa7dSDavid Howells 		break;
209e138aa7dSDavid Howells 	case RXRPC_PREINTERRUPTIBLE:
210e138aa7dSDavid Howells 	case RXRPC_UNINTERRUPTIBLE:
211e138aa7dSDavid Howells 	default:
212e138aa7dSDavid Howells 		ret = rxrpc_wait_for_tx_window_nonintr(rx, call, timeo);
213e138aa7dSDavid Howells 		break;
214e138aa7dSDavid Howells 	}
2150b58b8a1SDavid Howells 
2160b58b8a1SDavid Howells 	remove_wait_queue(&call->waitq, &myself);
2170b58b8a1SDavid Howells 	set_current_state(TASK_RUNNING);
2180b58b8a1SDavid Howells 	_leave(" = %d", ret);
2190b58b8a1SDavid Howells 	return ret;
2200b58b8a1SDavid Howells }
2210b58b8a1SDavid Howells 
2220b58b8a1SDavid Howells /*
223e833251aSDavid Howells  * Notify the owner of the call that the transmit phase is ended and the last
224e833251aSDavid Howells  * packet has been queued.
225e833251aSDavid Howells  */
rxrpc_notify_end_tx(struct rxrpc_sock * rx,struct rxrpc_call * call,rxrpc_notify_end_tx_t notify_end_tx)226e833251aSDavid Howells static void rxrpc_notify_end_tx(struct rxrpc_sock *rx, struct rxrpc_call *call,
227e833251aSDavid Howells 				rxrpc_notify_end_tx_t notify_end_tx)
228e833251aSDavid Howells {
229e833251aSDavid Howells 	if (notify_end_tx)
230e833251aSDavid Howells 		notify_end_tx(&rx->sk, call, call->user_call_ID);
231e833251aSDavid Howells }
232e833251aSDavid Howells 
233e833251aSDavid Howells /*
2348e8715aaSMarc Dionne  * Queue a DATA packet for transmission, set the resend timeout and send
2358e8715aaSMarc Dionne  * the packet immediately.  Returns the error from rxrpc_send_data_packet()
2368e8715aaSMarc Dionne  * in case the caller wants to do something with it.
2370b58b8a1SDavid Howells  */
rxrpc_queue_packet(struct rxrpc_sock * rx,struct rxrpc_call * call,struct rxrpc_txbuf * txb,rxrpc_notify_end_tx_t notify_end_tx)238a4ea4c47SDavid Howells static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
239a4ea4c47SDavid Howells 			       struct rxrpc_txbuf *txb,
240e833251aSDavid Howells 			       rxrpc_notify_end_tx_t notify_end_tx)
2410b58b8a1SDavid Howells {
242a4ea4c47SDavid Howells 	rxrpc_seq_t seq = txb->seq;
2435e6ef4f1SDavid Howells 	bool last = test_bit(RXRPC_TXBUF_LAST, &txb->flags), poke;
2440b58b8a1SDavid Howells 
245b0154246SDavid Howells 	rxrpc_inc_stat(call->rxnet, stat_tx_data);
246b0154246SDavid Howells 
247cf37b598SDavid Howells 	ASSERTCMP(txb->seq, ==, call->tx_prepared + 1);
248248f219cSDavid Howells 
249b24d2891SDavid Howells 	/* We have to set the timestamp before queueing as the retransmit
250b24d2891SDavid Howells 	 * algorithm can see the packet as soon as we queue it.
251b24d2891SDavid Howells 	 */
252a4ea4c47SDavid Howells 	txb->last_sent = ktime_get_real();
253b24d2891SDavid Howells 
25470790dbeSDavid Howells 	if (last)
255a4ea4c47SDavid Howells 		trace_rxrpc_txqueue(call, rxrpc_txqueue_queue_last);
25670790dbeSDavid Howells 	else
257a4ea4c47SDavid Howells 		trace_rxrpc_txqueue(call, rxrpc_txqueue_queue);
2580b58b8a1SDavid Howells 
259cf37b598SDavid Howells 	/* Add the packet to the call's output buffer */
260cf37b598SDavid Howells 	spin_lock(&call->tx_lock);
2615e6ef4f1SDavid Howells 	poke = list_empty(&call->tx_sendmsg);
262cf37b598SDavid Howells 	list_add_tail(&txb->call_link, &call->tx_sendmsg);
263cf37b598SDavid Howells 	call->tx_prepared = seq;
2642d689424SDavid Howells 	if (last)
2652d689424SDavid Howells 		rxrpc_notify_end_tx(rx, call, notify_end_tx);
266cf37b598SDavid Howells 	spin_unlock(&call->tx_lock);
267cf37b598SDavid Howells 
2685e6ef4f1SDavid Howells 	if (poke)
2695e6ef4f1SDavid Howells 		rxrpc_poke_call(call, rxrpc_call_poke_start);
2700b58b8a1SDavid Howells }
2710b58b8a1SDavid Howells 
2720b58b8a1SDavid Howells /*
2730b58b8a1SDavid Howells  * send data through a socket
2740b58b8a1SDavid Howells  * - must be called in process context
275540b1c48SDavid Howells  * - The caller holds the call user access mutex, but not the socket lock.
2760b58b8a1SDavid Howells  */
rxrpc_send_data(struct rxrpc_sock * rx,struct rxrpc_call * call,struct msghdr * msg,size_t len,rxrpc_notify_end_tx_t notify_end_tx,bool * _dropped_lock)2770b58b8a1SDavid Howells static int rxrpc_send_data(struct rxrpc_sock *rx,
2780b58b8a1SDavid Howells 			   struct rxrpc_call *call,
279e833251aSDavid Howells 			   struct msghdr *msg, size_t len,
280b0f571ecSDavid Howells 			   rxrpc_notify_end_tx_t notify_end_tx,
281b0f571ecSDavid Howells 			   bool *_dropped_lock)
2820b58b8a1SDavid Howells {
283a4ea4c47SDavid Howells 	struct rxrpc_txbuf *txb;
2840b58b8a1SDavid Howells 	struct sock *sk = &rx->sk;
285b0f571ecSDavid Howells 	enum rxrpc_call_state state;
2860b58b8a1SDavid Howells 	long timeo;
287b0f571ecSDavid Howells 	bool more = msg->msg_flags & MSG_MORE;
288b0f571ecSDavid Howells 	int ret, copied = 0;
2890b58b8a1SDavid Howells 
2900b58b8a1SDavid Howells 	timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
2910b58b8a1SDavid Howells 
2929d35d880SDavid Howells 	ret = rxrpc_wait_to_be_connected(call, &timeo);
2939d35d880SDavid Howells 	if (ret < 0)
2949d35d880SDavid Howells 		return ret;
2959d35d880SDavid Howells 
2969d35d880SDavid Howells 	if (call->conn->state == RXRPC_CONN_CLIENT_UNSECURED) {
2979d35d880SDavid Howells 		ret = rxrpc_init_client_conn_security(call->conn);
2989d35d880SDavid Howells 		if (ret < 0)
2999d35d880SDavid Howells 			return ret;
3009d35d880SDavid Howells 	}
3019d35d880SDavid Howells 
3020b58b8a1SDavid Howells 	/* this should be in poll */
3030b58b8a1SDavid Howells 	sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk);
3040b58b8a1SDavid Howells 
305b0f571ecSDavid Howells reload:
306446be550SDavid Howells 	txb = call->tx_pending;
307446be550SDavid Howells 	call->tx_pending = NULL;
308446be550SDavid Howells 	if (txb)
309446be550SDavid Howells 		rxrpc_see_txbuf(txb, rxrpc_txbuf_see_send_more);
310446be550SDavid Howells 
311b0f571ecSDavid Howells 	ret = -EPIPE;
312639f181fSDavid Howells 	if (sk->sk_shutdown & SEND_SHUTDOWN)
313b0f571ecSDavid Howells 		goto maybe_error;
314d41b3f5bSDavid Howells 	state = rxrpc_call_state(call);
315b0f571ecSDavid Howells 	ret = -ESHUTDOWN;
316b0f571ecSDavid Howells 	if (state >= RXRPC_CALL_COMPLETE)
317b0f571ecSDavid Howells 		goto maybe_error;
318b0f571ecSDavid Howells 	ret = -EPROTO;
319b0f571ecSDavid Howells 	if (state != RXRPC_CALL_CLIENT_SEND_REQUEST &&
320b0f571ecSDavid Howells 	    state != RXRPC_CALL_SERVER_ACK_REQUEST &&
3212d689424SDavid Howells 	    state != RXRPC_CALL_SERVER_SEND_REPLY) {
3222d689424SDavid Howells 		/* Request phase complete for this client call */
3232d689424SDavid Howells 		trace_rxrpc_abort(call->debug_id, rxrpc_sendmsg_late_send,
3242d689424SDavid Howells 				  call->cid, call->call_id, call->rx_consumed,
3252d689424SDavid Howells 				  0, -EPROTO);
326b0f571ecSDavid Howells 		goto maybe_error;
3272d689424SDavid Howells 	}
3280b58b8a1SDavid Howells 
329b0f571ecSDavid Howells 	ret = -EMSGSIZE;
330e754eba6SDavid Howells 	if (call->tx_total_len != -1) {
331b0f571ecSDavid Howells 		if (len - copied > call->tx_total_len)
332b0f571ecSDavid Howells 			goto maybe_error;
333b0f571ecSDavid Howells 		if (!more && len - copied != call->tx_total_len)
334b0f571ecSDavid Howells 			goto maybe_error;
335e754eba6SDavid Howells 	}
336e754eba6SDavid Howells 
3370b58b8a1SDavid Howells 	do {
338a4ea4c47SDavid Howells 		if (!txb) {
339d7d775b1SDavid Howells 			size_t remain, bufsize, chunk, offset;
3400b58b8a1SDavid Howells 
3410b58b8a1SDavid Howells 			_debug("alloc");
3420b58b8a1SDavid Howells 
343b0f571ecSDavid Howells 			if (!rxrpc_check_tx_space(call, NULL))
344b0f571ecSDavid Howells 				goto wait_for_space;
3450b58b8a1SDavid Howells 
346d7d775b1SDavid Howells 			/* Work out the maximum size of a packet.  Assume that
347d7d775b1SDavid Howells 			 * the security header is going to be in the padded
348d7d775b1SDavid Howells 			 * region (enc blocksize), but the trailer is not.
349d7d775b1SDavid Howells 			 */
350d7d775b1SDavid Howells 			remain = more ? INT_MAX : msg_data_left(msg);
351d7d775b1SDavid Howells 			ret = call->conn->security->how_much_data(call, remain,
352d7d775b1SDavid Howells 								  &bufsize, &chunk, &offset);
353d7d775b1SDavid Howells 			if (ret < 0)
354d7d775b1SDavid Howells 				goto maybe_error;
3550b58b8a1SDavid Howells 
356d7d775b1SDavid Howells 			_debug("SIZE: %zu/%zu @%zu", chunk, bufsize, offset);
3570b58b8a1SDavid Howells 
3580b58b8a1SDavid Howells 			/* create a buffer that we can retain until it's ACK'd */
359a4ea4c47SDavid Howells 			ret = -ENOMEM;
360a4ea4c47SDavid Howells 			txb = rxrpc_alloc_txbuf(call, RXRPC_PACKET_TYPE_DATA,
361a4ea4c47SDavid Howells 						GFP_KERNEL);
362a4ea4c47SDavid Howells 			if (!txb)
3630b58b8a1SDavid Howells 				goto maybe_error;
3640b58b8a1SDavid Howells 
365a4ea4c47SDavid Howells 			txb->offset = offset;
366a4ea4c47SDavid Howells 			txb->space -= offset;
367a4ea4c47SDavid Howells 			txb->space = min_t(size_t, chunk, txb->space);
3680b58b8a1SDavid Howells 		}
3690b58b8a1SDavid Howells 
3700b58b8a1SDavid Howells 		_debug("append");
3710b58b8a1SDavid Howells 
3720b58b8a1SDavid Howells 		/* append next segment of data to the current buffer */
3730b58b8a1SDavid Howells 		if (msg_data_left(msg) > 0) {
374a4ea4c47SDavid Howells 			size_t copy = min_t(size_t, txb->space, msg_data_left(msg));
3750b58b8a1SDavid Howells 
376a4ea4c47SDavid Howells 			_debug("add %zu", copy);
377a4ea4c47SDavid Howells 			if (!copy_from_iter_full(txb->data + txb->offset, copy,
378a4ea4c47SDavid Howells 						 &msg->msg_iter))
3790b58b8a1SDavid Howells 				goto efault;
380a4ea4c47SDavid Howells 			_debug("added");
381a4ea4c47SDavid Howells 			txb->space -= copy;
382a4ea4c47SDavid Howells 			txb->len += copy;
383a4ea4c47SDavid Howells 			txb->offset += copy;
3840b58b8a1SDavid Howells 			copied += copy;
385e754eba6SDavid Howells 			if (call->tx_total_len != -1)
386e754eba6SDavid Howells 				call->tx_total_len -= copy;
3870b58b8a1SDavid Howells 		}
3880b58b8a1SDavid Howells 
389e122d845SDavid Howells 		/* check for the far side aborting the call or a network error
390e122d845SDavid Howells 		 * occurring */
391d41b3f5bSDavid Howells 		if (rxrpc_call_is_complete(call))
392e122d845SDavid Howells 			goto call_terminated;
393e122d845SDavid Howells 
3940b58b8a1SDavid Howells 		/* add the packet to the send queue if it's now full */
395a4ea4c47SDavid Howells 		if (!txb->space ||
3960b58b8a1SDavid Howells 		    (msg_data_left(msg) == 0 && !more)) {
397a4ea4c47SDavid Howells 			if (msg_data_left(msg) == 0 && !more) {
398a4ea4c47SDavid Howells 				txb->wire.flags |= RXRPC_LAST_PACKET;
399a4ea4c47SDavid Howells 				__set_bit(RXRPC_TXBUF_LAST, &txb->flags);
400a4ea4c47SDavid Howells 			}
401a4ea4c47SDavid Howells 			else if (call->tx_top - call->acks_hard_ack <
402248f219cSDavid Howells 				 call->tx_winsize)
403a4ea4c47SDavid Howells 				txb->wire.flags |= RXRPC_MORE_PACKETS;
4040b58b8a1SDavid Howells 
405a4ea4c47SDavid Howells 			ret = call->security->secure_packet(call, txb);
4060b58b8a1SDavid Howells 			if (ret < 0)
4070b58b8a1SDavid Howells 				goto out;
4080b58b8a1SDavid Howells 
409a4ea4c47SDavid Howells 			rxrpc_queue_packet(rx, call, txb, notify_end_tx);
410a4ea4c47SDavid Howells 			txb = NULL;
4110b58b8a1SDavid Howells 		}
4120b58b8a1SDavid Howells 	} while (msg_data_left(msg) > 0);
4130b58b8a1SDavid Howells 
4140b58b8a1SDavid Howells success:
4150b58b8a1SDavid Howells 	ret = copied;
416d41b3f5bSDavid Howells 	if (rxrpc_call_is_complete(call) &&
417d41b3f5bSDavid Howells 	    call->error < 0)
4184ba68c51SDavid Howells 		ret = call->error;
4190b58b8a1SDavid Howells out:
420a4ea4c47SDavid Howells 	call->tx_pending = txb;
4210b58b8a1SDavid Howells 	_leave(" = %d", ret);
4220b58b8a1SDavid Howells 	return ret;
4230b58b8a1SDavid Howells 
424e122d845SDavid Howells call_terminated:
425a4ea4c47SDavid Howells 	rxrpc_put_txbuf(txb, rxrpc_txbuf_put_send_aborted);
426e122d845SDavid Howells 	_leave(" = %d", call->error);
427e122d845SDavid Howells 	return call->error;
428e122d845SDavid Howells 
4290b58b8a1SDavid Howells maybe_error:
4300b58b8a1SDavid Howells 	if (copied)
4310b58b8a1SDavid Howells 		goto success;
4320b58b8a1SDavid Howells 	goto out;
4330b58b8a1SDavid Howells 
4340b58b8a1SDavid Howells efault:
4350b58b8a1SDavid Howells 	ret = -EFAULT;
4360b58b8a1SDavid Howells 	goto out;
437b0f571ecSDavid Howells 
438b0f571ecSDavid Howells wait_for_space:
439b0f571ecSDavid Howells 	ret = -EAGAIN;
440b0f571ecSDavid Howells 	if (msg->msg_flags & MSG_DONTWAIT)
441b0f571ecSDavid Howells 		goto maybe_error;
442b0f571ecSDavid Howells 	mutex_unlock(&call->user_mutex);
443b0f571ecSDavid Howells 	*_dropped_lock = true;
444b0f571ecSDavid Howells 	ret = rxrpc_wait_for_tx_window(rx, call, &timeo,
445b0f571ecSDavid Howells 				       msg->msg_flags & MSG_WAITALL);
446b0f571ecSDavid Howells 	if (ret < 0)
447b0f571ecSDavid Howells 		goto maybe_error;
448b0f571ecSDavid Howells 	if (call->interruptibility == RXRPC_INTERRUPTIBLE) {
449b0f571ecSDavid Howells 		if (mutex_lock_interruptible(&call->user_mutex) < 0) {
450b0f571ecSDavid Howells 			ret = sock_intr_errno(timeo);
451b0f571ecSDavid Howells 			goto maybe_error;
452b0f571ecSDavid Howells 		}
453b0f571ecSDavid Howells 	} else {
454b0f571ecSDavid Howells 		mutex_lock(&call->user_mutex);
455b0f571ecSDavid Howells 	}
456b0f571ecSDavid Howells 	*_dropped_lock = false;
457b0f571ecSDavid Howells 	goto reload;
4580b58b8a1SDavid Howells }
459df423a4aSDavid Howells 
460df423a4aSDavid Howells /*
461df423a4aSDavid Howells  * extract control messages from the sendmsg() control buffer
462df423a4aSDavid Howells  */
rxrpc_sendmsg_cmsg(struct msghdr * msg,struct rxrpc_send_params * p)4633ab26a6fSDavid Howells static int rxrpc_sendmsg_cmsg(struct msghdr *msg, struct rxrpc_send_params *p)
464df423a4aSDavid Howells {
465df423a4aSDavid Howells 	struct cmsghdr *cmsg;
466df423a4aSDavid Howells 	bool got_user_ID = false;
467df423a4aSDavid Howells 	int len;
468df423a4aSDavid Howells 
469df423a4aSDavid Howells 	if (msg->msg_controllen == 0)
470df423a4aSDavid Howells 		return -EINVAL;
471df423a4aSDavid Howells 
472df423a4aSDavid Howells 	for_each_cmsghdr(cmsg, msg) {
473df423a4aSDavid Howells 		if (!CMSG_OK(msg, cmsg))
474df423a4aSDavid Howells 			return -EINVAL;
475df423a4aSDavid Howells 
4761ff8cebfSyuan linyu 		len = cmsg->cmsg_len - sizeof(struct cmsghdr);
477df423a4aSDavid Howells 		_debug("CMSG %d, %d, %d",
478df423a4aSDavid Howells 		       cmsg->cmsg_level, cmsg->cmsg_type, len);
479df423a4aSDavid Howells 
480df423a4aSDavid Howells 		if (cmsg->cmsg_level != SOL_RXRPC)
481df423a4aSDavid Howells 			continue;
482df423a4aSDavid Howells 
483df423a4aSDavid Howells 		switch (cmsg->cmsg_type) {
484df423a4aSDavid Howells 		case RXRPC_USER_CALL_ID:
485df423a4aSDavid Howells 			if (msg->msg_flags & MSG_CMSG_COMPAT) {
486df423a4aSDavid Howells 				if (len != sizeof(u32))
487df423a4aSDavid Howells 					return -EINVAL;
48848124178SDavid Howells 				p->call.user_call_ID = *(u32 *)CMSG_DATA(cmsg);
489df423a4aSDavid Howells 			} else {
490df423a4aSDavid Howells 				if (len != sizeof(unsigned long))
491df423a4aSDavid Howells 					return -EINVAL;
49248124178SDavid Howells 				p->call.user_call_ID = *(unsigned long *)
493df423a4aSDavid Howells 					CMSG_DATA(cmsg);
494df423a4aSDavid Howells 			}
495df423a4aSDavid Howells 			got_user_ID = true;
496df423a4aSDavid Howells 			break;
497df423a4aSDavid Howells 
498df423a4aSDavid Howells 		case RXRPC_ABORT:
4993ab26a6fSDavid Howells 			if (p->command != RXRPC_CMD_SEND_DATA)
500df423a4aSDavid Howells 				return -EINVAL;
5013ab26a6fSDavid Howells 			p->command = RXRPC_CMD_SEND_ABORT;
5023ab26a6fSDavid Howells 			if (len != sizeof(p->abort_code))
503df423a4aSDavid Howells 				return -EINVAL;
5043ab26a6fSDavid Howells 			p->abort_code = *(unsigned int *)CMSG_DATA(cmsg);
5053ab26a6fSDavid Howells 			if (p->abort_code == 0)
506df423a4aSDavid Howells 				return -EINVAL;
507df423a4aSDavid Howells 			break;
508df423a4aSDavid Howells 
5092d914c1bSDavid Howells 		case RXRPC_CHARGE_ACCEPT:
5103ab26a6fSDavid Howells 			if (p->command != RXRPC_CMD_SEND_DATA)
511df423a4aSDavid Howells 				return -EINVAL;
5122d914c1bSDavid Howells 			p->command = RXRPC_CMD_CHARGE_ACCEPT;
513df423a4aSDavid Howells 			if (len != 0)
514df423a4aSDavid Howells 				return -EINVAL;
515df423a4aSDavid Howells 			break;
516df423a4aSDavid Howells 
517df423a4aSDavid Howells 		case RXRPC_EXCLUSIVE_CALL:
5183ab26a6fSDavid Howells 			p->exclusive = true;
519df423a4aSDavid Howells 			if (len != 0)
520df423a4aSDavid Howells 				return -EINVAL;
521df423a4aSDavid Howells 			break;
5224e255721SDavid Howells 
5234e255721SDavid Howells 		case RXRPC_UPGRADE_SERVICE:
5243ab26a6fSDavid Howells 			p->upgrade = true;
5254e255721SDavid Howells 			if (len != 0)
5264e255721SDavid Howells 				return -EINVAL;
5274e255721SDavid Howells 			break;
5284e255721SDavid Howells 
529e754eba6SDavid Howells 		case RXRPC_TX_LENGTH:
53048124178SDavid Howells 			if (p->call.tx_total_len != -1 || len != sizeof(__s64))
531e754eba6SDavid Howells 				return -EINVAL;
53248124178SDavid Howells 			p->call.tx_total_len = *(__s64 *)CMSG_DATA(cmsg);
53348124178SDavid Howells 			if (p->call.tx_total_len < 0)
534e754eba6SDavid Howells 				return -EINVAL;
535e754eba6SDavid Howells 			break;
536e754eba6SDavid Howells 
537a158bdd3SDavid Howells 		case RXRPC_SET_CALL_TIMEOUT:
538a158bdd3SDavid Howells 			if (len & 3 || len < 4 || len > 12)
539a158bdd3SDavid Howells 				return -EINVAL;
540a158bdd3SDavid Howells 			memcpy(&p->call.timeouts, CMSG_DATA(cmsg), len);
541a158bdd3SDavid Howells 			p->call.nr_timeouts = len / 4;
542a158bdd3SDavid Howells 			if (p->call.timeouts.hard > INT_MAX / HZ)
543a158bdd3SDavid Howells 				return -ERANGE;
544a158bdd3SDavid Howells 			if (p->call.nr_timeouts >= 2 && p->call.timeouts.idle > 60 * 60 * 1000)
545a158bdd3SDavid Howells 				return -ERANGE;
546a158bdd3SDavid Howells 			if (p->call.nr_timeouts >= 3 && p->call.timeouts.normal > 60 * 60 * 1000)
547a158bdd3SDavid Howells 				return -ERANGE;
548a158bdd3SDavid Howells 			break;
549a158bdd3SDavid Howells 
550df423a4aSDavid Howells 		default:
551df423a4aSDavid Howells 			return -EINVAL;
552df423a4aSDavid Howells 		}
553df423a4aSDavid Howells 	}
554df423a4aSDavid Howells 
555df423a4aSDavid Howells 	if (!got_user_ID)
556df423a4aSDavid Howells 		return -EINVAL;
55748124178SDavid Howells 	if (p->call.tx_total_len != -1 && p->command != RXRPC_CMD_SEND_DATA)
558e754eba6SDavid Howells 		return -EINVAL;
559df423a4aSDavid Howells 	_leave(" = 0");
560df423a4aSDavid Howells 	return 0;
561df423a4aSDavid Howells }
562df423a4aSDavid Howells 
563df423a4aSDavid Howells /*
564df423a4aSDavid Howells  * Create a new client call for sendmsg().
565540b1c48SDavid Howells  * - Called with the socket lock held, which it must release.
566540b1c48SDavid Howells  * - If it returns a call, the call's lock will need releasing by the caller.
567df423a4aSDavid Howells  */
568df423a4aSDavid Howells static struct rxrpc_call *
rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock * rx,struct msghdr * msg,struct rxrpc_send_params * p)569df423a4aSDavid Howells rxrpc_new_client_call_for_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg,
5703ab26a6fSDavid Howells 				  struct rxrpc_send_params *p)
571540b1c48SDavid Howells 	__releases(&rx->sk.sk_lock.slock)
57288f2a825SDavid Howells 	__acquires(&call->user_mutex)
573df423a4aSDavid Howells {
574df423a4aSDavid Howells 	struct rxrpc_conn_parameters cp;
575df423a4aSDavid Howells 	struct rxrpc_call *call;
576df423a4aSDavid Howells 	struct key *key;
577df423a4aSDavid Howells 
578df423a4aSDavid Howells 	DECLARE_SOCKADDR(struct sockaddr_rxrpc *, srx, msg->msg_name);
579df423a4aSDavid Howells 
580df423a4aSDavid Howells 	_enter("");
581df423a4aSDavid Howells 
582540b1c48SDavid Howells 	if (!msg->msg_name) {
583540b1c48SDavid Howells 		release_sock(&rx->sk);
584df423a4aSDavid Howells 		return ERR_PTR(-EDESTADDRREQ);
585540b1c48SDavid Howells 	}
586df423a4aSDavid Howells 
587df423a4aSDavid Howells 	key = rx->key;
588df423a4aSDavid Howells 	if (key && !rx->key->payload.data[0])
589df423a4aSDavid Howells 		key = NULL;
590df423a4aSDavid Howells 
591df423a4aSDavid Howells 	memset(&cp, 0, sizeof(cp));
592df423a4aSDavid Howells 	cp.local		= rx->local;
593df423a4aSDavid Howells 	cp.key			= rx->key;
594df423a4aSDavid Howells 	cp.security_level	= rx->min_sec_level;
5953ab26a6fSDavid Howells 	cp.exclusive		= rx->exclusive | p->exclusive;
5963ab26a6fSDavid Howells 	cp.upgrade		= p->upgrade;
597df423a4aSDavid Howells 	cp.service_id		= srx->srx_service;
598a25e21f0SDavid Howells 	call = rxrpc_new_client_call(rx, &cp, srx, &p->call, GFP_KERNEL,
599a25e21f0SDavid Howells 				     atomic_inc_return(&rxrpc_debug_id));
600540b1c48SDavid Howells 	/* The socket is now unlocked */
601df423a4aSDavid Howells 
602df423a4aSDavid Howells 	_leave(" = %p\n", call);
603df423a4aSDavid Howells 	return call;
604df423a4aSDavid Howells }
605df423a4aSDavid Howells 
606df423a4aSDavid Howells /*
607df423a4aSDavid Howells  * send a message forming part of a client call through an RxRPC socket
608df423a4aSDavid Howells  * - caller holds the socket locked
609df423a4aSDavid Howells  * - the socket may be either a client socket or a server socket
610df423a4aSDavid Howells  */
rxrpc_do_sendmsg(struct rxrpc_sock * rx,struct msghdr * msg,size_t len)611df423a4aSDavid Howells int rxrpc_do_sendmsg(struct rxrpc_sock *rx, struct msghdr *msg, size_t len)
612540b1c48SDavid Howells 	__releases(&rx->sk.sk_lock.slock)
613df423a4aSDavid Howells {
614df423a4aSDavid Howells 	struct rxrpc_call *call;
615a158bdd3SDavid Howells 	unsigned long now, j;
616b0f571ecSDavid Howells 	bool dropped_lock = false;
617df423a4aSDavid Howells 	int ret;
618df423a4aSDavid Howells 
6193ab26a6fSDavid Howells 	struct rxrpc_send_params p = {
62048124178SDavid Howells 		.call.tx_total_len	= -1,
62148124178SDavid Howells 		.call.user_call_ID	= 0,
622a158bdd3SDavid Howells 		.call.nr_timeouts	= 0,
623e138aa7dSDavid Howells 		.call.interruptibility	= RXRPC_INTERRUPTIBLE,
6243ab26a6fSDavid Howells 		.abort_code		= 0,
6253ab26a6fSDavid Howells 		.command		= RXRPC_CMD_SEND_DATA,
6263ab26a6fSDavid Howells 		.exclusive		= false,
62748ca2463SDavid Howells 		.upgrade		= false,
6283ab26a6fSDavid Howells 	};
6293ab26a6fSDavid Howells 
630df423a4aSDavid Howells 	_enter("");
631df423a4aSDavid Howells 
6323ab26a6fSDavid Howells 	ret = rxrpc_sendmsg_cmsg(msg, &p);
633df423a4aSDavid Howells 	if (ret < 0)
634540b1c48SDavid Howells 		goto error_release_sock;
635df423a4aSDavid Howells 
6362d914c1bSDavid Howells 	if (p.command == RXRPC_CMD_CHARGE_ACCEPT) {
637540b1c48SDavid Howells 		ret = -EINVAL;
638df423a4aSDavid Howells 		if (rx->sk.sk_state != RXRPC_SERVER_LISTENING)
639540b1c48SDavid Howells 			goto error_release_sock;
6402d914c1bSDavid Howells 		ret = rxrpc_user_charge_accept(rx, p.call.user_call_ID);
6412d914c1bSDavid Howells 		goto error_release_sock;
642df423a4aSDavid Howells 	}
643df423a4aSDavid Howells 
64448124178SDavid Howells 	call = rxrpc_find_call_by_user_ID(rx, p.call.user_call_ID);
645df423a4aSDavid Howells 	if (!call) {
646540b1c48SDavid Howells 		ret = -EBADSLT;
6473ab26a6fSDavid Howells 		if (p.command != RXRPC_CMD_SEND_DATA)
648540b1c48SDavid Howells 			goto error_release_sock;
6493ab26a6fSDavid Howells 		call = rxrpc_new_client_call_for_sendmsg(rx, msg, &p);
650540b1c48SDavid Howells 		/* The socket is now unlocked... */
651df423a4aSDavid Howells 		if (IS_ERR(call))
652df423a4aSDavid Howells 			return PTR_ERR(call);
653540b1c48SDavid Howells 		/* ... and we have the call lock. */
654db099c62SDavid Howells 		p.call.nr_timeouts = 0;
65565550098SDavid Howells 		ret = 0;
656d41b3f5bSDavid Howells 		if (rxrpc_call_is_complete(call))
65765550098SDavid Howells 			goto out_put_unlock;
658540b1c48SDavid Howells 	} else {
659d41b3f5bSDavid Howells 		switch (rxrpc_call_state(call)) {
660146d8fefSDavid Howells 		case RXRPC_CALL_CLIENT_AWAIT_CONN:
661*7770b221SDavid Howells 		case RXRPC_CALL_SERVER_RECV_REQUEST:
6620eb362d2SDavid Howells 			if (p.command == RXRPC_CMD_SEND_ABORT)
6630eb362d2SDavid Howells 				break;
6640eb362d2SDavid Howells 			fallthrough;
6650eb362d2SDavid Howells 		case RXRPC_CALL_UNINITIALISED:
6660eb362d2SDavid Howells 		case RXRPC_CALL_SERVER_PREALLOC:
667cb0fc0c9SDavid Howells 			rxrpc_put_call(call, rxrpc_call_put_sendmsg);
66837411cadSDavid Howells 			ret = -EBUSY;
66937411cadSDavid Howells 			goto error_release_sock;
670146d8fefSDavid Howells 		default:
671146d8fefSDavid Howells 			break;
672146d8fefSDavid Howells 		}
67337411cadSDavid Howells 
674540b1c48SDavid Howells 		ret = mutex_lock_interruptible(&call->user_mutex);
675540b1c48SDavid Howells 		release_sock(&rx->sk);
676540b1c48SDavid Howells 		if (ret < 0) {
677540b1c48SDavid Howells 			ret = -ERESTARTSYS;
678540b1c48SDavid Howells 			goto error_put;
679540b1c48SDavid Howells 		}
680e754eba6SDavid Howells 
68148124178SDavid Howells 		if (p.call.tx_total_len != -1) {
682e754eba6SDavid Howells 			ret = -EINVAL;
683e754eba6SDavid Howells 			if (call->tx_total_len != -1 ||
684e754eba6SDavid Howells 			    call->tx_pending ||
685e754eba6SDavid Howells 			    call->tx_top != 0)
6864feb2c44SDavid Howells 				goto out_put_unlock;
68748124178SDavid Howells 			call->tx_total_len = p.call.tx_total_len;
688e754eba6SDavid Howells 		}
689df423a4aSDavid Howells 	}
690df423a4aSDavid Howells 
691a158bdd3SDavid Howells 	switch (p.call.nr_timeouts) {
692a158bdd3SDavid Howells 	case 3:
693a158bdd3SDavid Howells 		j = msecs_to_jiffies(p.call.timeouts.normal);
694a158bdd3SDavid Howells 		if (p.call.timeouts.normal > 0 && j == 0)
695a158bdd3SDavid Howells 			j = 1;
696a158bdd3SDavid Howells 		WRITE_ONCE(call->next_rx_timo, j);
697df561f66SGustavo A. R. Silva 		fallthrough;
698a158bdd3SDavid Howells 	case 2:
699a158bdd3SDavid Howells 		j = msecs_to_jiffies(p.call.timeouts.idle);
700a158bdd3SDavid Howells 		if (p.call.timeouts.idle > 0 && j == 0)
701a158bdd3SDavid Howells 			j = 1;
702a158bdd3SDavid Howells 		WRITE_ONCE(call->next_req_timo, j);
703df561f66SGustavo A. R. Silva 		fallthrough;
704a158bdd3SDavid Howells 	case 1:
705a158bdd3SDavid Howells 		if (p.call.timeouts.hard > 0) {
7060d098d83SDavid Howells 			j = p.call.timeouts.hard * HZ;
707a158bdd3SDavid Howells 			now = jiffies;
708a158bdd3SDavid Howells 			j += now;
709a158bdd3SDavid Howells 			WRITE_ONCE(call->expect_term_by, j);
710a158bdd3SDavid Howells 			rxrpc_reduce_call_timer(call, j, now,
711a158bdd3SDavid Howells 						rxrpc_timer_set_for_hard);
712a158bdd3SDavid Howells 		}
713a158bdd3SDavid Howells 		break;
714a158bdd3SDavid Howells 	}
715a158bdd3SDavid Howells 
7162d689424SDavid Howells 	if (rxrpc_call_is_complete(call)) {
717df423a4aSDavid Howells 		/* it's too late for this call */
718df423a4aSDavid Howells 		ret = -ESHUTDOWN;
7193ab26a6fSDavid Howells 	} else if (p.command == RXRPC_CMD_SEND_ABORT) {
72057af281eSDavid Howells 		rxrpc_propose_abort(call, p.abort_code, -ECONNABORTED,
72157af281eSDavid Howells 				    rxrpc_abort_call_sendmsg);
722df423a4aSDavid Howells 		ret = 0;
7233ab26a6fSDavid Howells 	} else if (p.command != RXRPC_CMD_SEND_DATA) {
724df423a4aSDavid Howells 		ret = -EINVAL;
725df423a4aSDavid Howells 	} else {
726b0f571ecSDavid Howells 		ret = rxrpc_send_data(rx, call, msg, len, NULL, &dropped_lock);
727df423a4aSDavid Howells 	}
728df423a4aSDavid Howells 
72903a6c822SDavid Howells out_put_unlock:
730b0f571ecSDavid Howells 	if (!dropped_lock)
731540b1c48SDavid Howells 		mutex_unlock(&call->user_mutex);
732540b1c48SDavid Howells error_put:
733cb0fc0c9SDavid Howells 	rxrpc_put_call(call, rxrpc_call_put_sendmsg);
734df423a4aSDavid Howells 	_leave(" = %d", ret);
735df423a4aSDavid Howells 	return ret;
736540b1c48SDavid Howells 
737540b1c48SDavid Howells error_release_sock:
738540b1c48SDavid Howells 	release_sock(&rx->sk);
739540b1c48SDavid Howells 	return ret;
740df423a4aSDavid Howells }
741df423a4aSDavid Howells 
742df423a4aSDavid Howells /**
743df423a4aSDavid Howells  * rxrpc_kernel_send_data - Allow a kernel service to send data on a call
744df423a4aSDavid Howells  * @sock: The socket the call is on
745df423a4aSDavid Howells  * @call: The call to send data through
746df423a4aSDavid Howells  * @msg: The data to send
747df423a4aSDavid Howells  * @len: The amount of data to send
748e833251aSDavid Howells  * @notify_end_tx: Notification that the last packet is queued.
749df423a4aSDavid Howells  *
750df423a4aSDavid Howells  * Allow a kernel service to send data on a call.  The call must be in an state
751df423a4aSDavid Howells  * appropriate to sending data.  No control data should be supplied in @msg,
752df423a4aSDavid Howells  * nor should an address be supplied.  MSG_MORE should be flagged if there's
753df423a4aSDavid Howells  * more data to come, otherwise this data will end the transmission phase.
754df423a4aSDavid Howells  */
rxrpc_kernel_send_data(struct socket * sock,struct rxrpc_call * call,struct msghdr * msg,size_t len,rxrpc_notify_end_tx_t notify_end_tx)755df423a4aSDavid Howells int rxrpc_kernel_send_data(struct socket *sock, struct rxrpc_call *call,
756e833251aSDavid Howells 			   struct msghdr *msg, size_t len,
757e833251aSDavid Howells 			   rxrpc_notify_end_tx_t notify_end_tx)
758df423a4aSDavid Howells {
759b0f571ecSDavid Howells 	bool dropped_lock = false;
760df423a4aSDavid Howells 	int ret;
761df423a4aSDavid Howells 
7622d689424SDavid Howells 	_enter("{%d},", call->debug_id);
763df423a4aSDavid Howells 
764df423a4aSDavid Howells 	ASSERTCMP(msg->msg_name, ==, NULL);
765df423a4aSDavid Howells 	ASSERTCMP(msg->msg_control, ==, NULL);
766df423a4aSDavid Howells 
767540b1c48SDavid Howells 	mutex_lock(&call->user_mutex);
768df423a4aSDavid Howells 
769e833251aSDavid Howells 	ret = rxrpc_send_data(rxrpc_sk(sock->sk), call, msg, len,
770b0f571ecSDavid Howells 			      notify_end_tx, &dropped_lock);
7712d689424SDavid Howells 	if (ret == -ESHUTDOWN)
772bd2db2d2SDavid Howells 		ret = call->error;
773df423a4aSDavid Howells 
774b0f571ecSDavid Howells 	if (!dropped_lock)
775540b1c48SDavid Howells 		mutex_unlock(&call->user_mutex);
776df423a4aSDavid Howells 	_leave(" = %d", ret);
777df423a4aSDavid Howells 	return ret;
778df423a4aSDavid Howells }
779df423a4aSDavid Howells EXPORT_SYMBOL(rxrpc_kernel_send_data);
780df423a4aSDavid Howells 
781df423a4aSDavid Howells /**
782df423a4aSDavid Howells  * rxrpc_kernel_abort_call - Allow a kernel service to abort a call
783df423a4aSDavid Howells  * @sock: The socket the call is on
784df423a4aSDavid Howells  * @call: The call to be aborted
785df423a4aSDavid Howells  * @abort_code: The abort code to stick into the ABORT packet
7865a42976dSDavid Howells  * @error: Local error value
78757af281eSDavid Howells  * @why: Indication as to why.
788df423a4aSDavid Howells  *
78984a4c09cSDavid Howells  * Allow a kernel service to abort a call, if it's still in an abortable state
79084a4c09cSDavid Howells  * and return true if the call was aborted, false if it was already complete.
791df423a4aSDavid Howells  */
rxrpc_kernel_abort_call(struct socket * sock,struct rxrpc_call * call,u32 abort_code,int error,enum rxrpc_abort_reason why)79284a4c09cSDavid Howells bool rxrpc_kernel_abort_call(struct socket *sock, struct rxrpc_call *call,
79357af281eSDavid Howells 			     u32 abort_code, int error, enum rxrpc_abort_reason why)
794df423a4aSDavid Howells {
79584a4c09cSDavid Howells 	bool aborted;
79684a4c09cSDavid Howells 
79757af281eSDavid Howells 	_enter("{%d},%d,%d,%u", call->debug_id, abort_code, error, why);
798df423a4aSDavid Howells 
799540b1c48SDavid Howells 	mutex_lock(&call->user_mutex);
800a343b174SDavid Howells 	aborted = rxrpc_propose_abort(call, abort_code, error, why);
801540b1c48SDavid Howells 	mutex_unlock(&call->user_mutex);
80284a4c09cSDavid Howells 	return aborted;
803df423a4aSDavid Howells }
804df423a4aSDavid Howells EXPORT_SYMBOL(rxrpc_kernel_abort_call);
805e754eba6SDavid Howells 
806e754eba6SDavid Howells /**
807e754eba6SDavid Howells  * rxrpc_kernel_set_tx_length - Set the total Tx length on a call
808e754eba6SDavid Howells  * @sock: The socket the call is on
809e754eba6SDavid Howells  * @call: The call to be informed
810e754eba6SDavid Howells  * @tx_total_len: The amount of data to be transmitted for this call
811e754eba6SDavid Howells  *
812e754eba6SDavid Howells  * Allow a kernel service to set the total transmit length on a call.  This
813e754eba6SDavid Howells  * allows buffer-to-packet encrypt-and-copy to be performed.
814e754eba6SDavid Howells  *
815e754eba6SDavid Howells  * This function is primarily for use for setting the reply length since the
816e754eba6SDavid Howells  * request length can be set when beginning the call.
817e754eba6SDavid Howells  */
rxrpc_kernel_set_tx_length(struct socket * sock,struct rxrpc_call * call,s64 tx_total_len)818e754eba6SDavid Howells void rxrpc_kernel_set_tx_length(struct socket *sock, struct rxrpc_call *call,
819e754eba6SDavid Howells 				s64 tx_total_len)
820e754eba6SDavid Howells {
821e754eba6SDavid Howells 	WARN_ON(call->tx_total_len != -1);
822e754eba6SDavid Howells 	call->tx_total_len = tx_total_len;
823e754eba6SDavid Howells }
824e754eba6SDavid Howells EXPORT_SYMBOL(rxrpc_kernel_set_tx_length);
825