xref: /openbmc/linux/fs/afs/rxrpc.c (revision 8715fe2f)
12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
208e0e7c8SDavid Howells /* Maintain an RxRPC server socket to do AFS communications through
308e0e7c8SDavid Howells  *
408e0e7c8SDavid Howells  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
508e0e7c8SDavid Howells  * Written by David Howells (dhowells@redhat.com)
608e0e7c8SDavid Howells  */
708e0e7c8SDavid Howells 
85a0e3ad6STejun Heo #include <linux/slab.h>
9174cd4b1SIngo Molnar #include <linux/sched/signal.h>
10174cd4b1SIngo Molnar 
1108e0e7c8SDavid Howells #include <net/sock.h>
1208e0e7c8SDavid Howells #include <net/af_rxrpc.h>
1308e0e7c8SDavid Howells #include "internal.h"
1408e0e7c8SDavid Howells #include "afs_cm.h"
1535dbfba3SDavid Howells #include "protocol_yfs.h"
1657af281eSDavid Howells #define RXRPC_TRACE_ONLY_DEFINE_ENUMS
1757af281eSDavid Howells #include <trace/events/rxrpc.h>
1808e0e7c8SDavid Howells 
19f044c884SDavid Howells struct workqueue_struct *afs_async_calls;
2008e0e7c8SDavid Howells 
21d001648eSDavid Howells static void afs_wake_up_call_waiter(struct sock *, struct rxrpc_call *, unsigned long);
22d001648eSDavid Howells static void afs_wake_up_async_call(struct sock *, struct rxrpc_call *, unsigned long);
23d001648eSDavid Howells static void afs_process_async_call(struct work_struct *);
2400e90712SDavid Howells static void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned long);
2500e90712SDavid Howells static void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long);
26d001648eSDavid Howells static int afs_deliver_cm_op_id(struct afs_call *);
2708e0e7c8SDavid Howells 
2808e0e7c8SDavid Howells /* asynchronous incoming call initial processing */
2908e0e7c8SDavid Howells static const struct afs_call_type afs_RXCMxxxx = {
3000d3b7a4SDavid Howells 	.name		= "CB.xxxx",
3108e0e7c8SDavid Howells 	.deliver	= afs_deliver_cm_op_id,
3208e0e7c8SDavid Howells };
3308e0e7c8SDavid Howells 
3408e0e7c8SDavid Howells /*
3508e0e7c8SDavid Howells  * open an RxRPC socket and bind it to be a server for callback notifications
3608e0e7c8SDavid Howells  * - the socket is left in blocking mode and non-blocking ops use MSG_DONTWAIT
3708e0e7c8SDavid Howells  */
afs_open_socket(struct afs_net * net)38f044c884SDavid Howells int afs_open_socket(struct afs_net *net)
3908e0e7c8SDavid Howells {
4008e0e7c8SDavid Howells 	struct sockaddr_rxrpc srx;
4108e0e7c8SDavid Howells 	struct socket *socket;
4208e0e7c8SDavid Howells 	int ret;
4308e0e7c8SDavid Howells 
4408e0e7c8SDavid Howells 	_enter("");
4508e0e7c8SDavid Howells 
465b86d4ffSDavid Howells 	ret = sock_create_kern(net->net, AF_RXRPC, SOCK_DGRAM, PF_INET6, &socket);
470e119b41SDavid Howells 	if (ret < 0)
480e119b41SDavid Howells 		goto error_1;
4908e0e7c8SDavid Howells 
5008e0e7c8SDavid Howells 	socket->sk->sk_allocation = GFP_NOFS;
5108e0e7c8SDavid Howells 
5208e0e7c8SDavid Howells 	/* bind the callback manager's address to make this a server socket */
533838d3ecSDavid Howells 	memset(&srx, 0, sizeof(srx));
5408e0e7c8SDavid Howells 	srx.srx_family			= AF_RXRPC;
5508e0e7c8SDavid Howells 	srx.srx_service			= CM_SERVICE;
5608e0e7c8SDavid Howells 	srx.transport_type		= SOCK_DGRAM;
573838d3ecSDavid Howells 	srx.transport_len		= sizeof(srx.transport.sin6);
583838d3ecSDavid Howells 	srx.transport.sin6.sin6_family	= AF_INET6;
593838d3ecSDavid Howells 	srx.transport.sin6.sin6_port	= htons(AFS_CM_PORT);
6008e0e7c8SDavid Howells 
61298cd88aSChristoph Hellwig 	ret = rxrpc_sock_set_min_security_level(socket->sk,
62298cd88aSChristoph Hellwig 						RXRPC_SECURITY_ENCRYPT);
634776cab4SDavid Howells 	if (ret < 0)
644776cab4SDavid Howells 		goto error_2;
654776cab4SDavid Howells 
6608e0e7c8SDavid Howells 	ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
6783732ec5SMarc Dionne 	if (ret == -EADDRINUSE) {
6883732ec5SMarc Dionne 		srx.transport.sin6.sin6_port = 0;
6983732ec5SMarc Dionne 		ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
7083732ec5SMarc Dionne 	}
710e119b41SDavid Howells 	if (ret < 0)
720e119b41SDavid Howells 		goto error_2;
730e119b41SDavid Howells 
7435dbfba3SDavid Howells 	srx.srx_service = YFS_CM_SERVICE;
7535dbfba3SDavid Howells 	ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
7635dbfba3SDavid Howells 	if (ret < 0)
7735dbfba3SDavid Howells 		goto error_2;
7835dbfba3SDavid Howells 
793bf0fb6fSDavid Howells 	/* Ideally, we'd turn on service upgrade here, but we can't because
803bf0fb6fSDavid Howells 	 * OpenAFS is buggy and leaks the userStatus field from packet to
813bf0fb6fSDavid Howells 	 * packet and between FS packets and CB packets - so if we try to do an
823bf0fb6fSDavid Howells 	 * upgrade on an FS packet, OpenAFS will leak that into the CB packet
833bf0fb6fSDavid Howells 	 * it sends back to us.
843bf0fb6fSDavid Howells 	 */
8535dbfba3SDavid Howells 
8600e90712SDavid Howells 	rxrpc_kernel_new_call_notification(socket, afs_rx_new_call,
8700e90712SDavid Howells 					   afs_rx_discard_new_call);
88d001648eSDavid Howells 
890e119b41SDavid Howells 	ret = kernel_listen(socket, INT_MAX);
900e119b41SDavid Howells 	if (ret < 0)
910e119b41SDavid Howells 		goto error_2;
9208e0e7c8SDavid Howells 
93f044c884SDavid Howells 	net->socket = socket;
94f044c884SDavid Howells 	afs_charge_preallocation(&net->charge_preallocation_work);
9508e0e7c8SDavid Howells 	_leave(" = 0");
9608e0e7c8SDavid Howells 	return 0;
970e119b41SDavid Howells 
980e119b41SDavid Howells error_2:
990e119b41SDavid Howells 	sock_release(socket);
1000e119b41SDavid Howells error_1:
1010e119b41SDavid Howells 	_leave(" = %d", ret);
1020e119b41SDavid Howells 	return ret;
10308e0e7c8SDavid Howells }
10408e0e7c8SDavid Howells 
10508e0e7c8SDavid Howells /*
10608e0e7c8SDavid Howells  * close the RxRPC socket AFS was using
10708e0e7c8SDavid Howells  */
afs_close_socket(struct afs_net * net)108f044c884SDavid Howells void afs_close_socket(struct afs_net *net)
10908e0e7c8SDavid Howells {
11008e0e7c8SDavid Howells 	_enter("");
11108e0e7c8SDavid Howells 
112f044c884SDavid Howells 	kernel_listen(net->socket, 0);
113341f741fSDavid Howells 	flush_workqueue(afs_async_calls);
114341f741fSDavid Howells 
115f044c884SDavid Howells 	if (net->spare_incoming_call) {
116f044c884SDavid Howells 		afs_put_call(net->spare_incoming_call);
117f044c884SDavid Howells 		net->spare_incoming_call = NULL;
11800e90712SDavid Howells 	}
11900e90712SDavid Howells 
120f044c884SDavid Howells 	_debug("outstanding %u", atomic_read(&net->nr_outstanding_calls));
121ab1fbe32SPeter Zijlstra 	wait_var_event(&net->nr_outstanding_calls,
122ab1fbe32SPeter Zijlstra 		       !atomic_read(&net->nr_outstanding_calls));
1232f02f7aeSDavid Howells 	_debug("no outstanding calls");
1242f02f7aeSDavid Howells 
125f044c884SDavid Howells 	kernel_sock_shutdown(net->socket, SHUT_RDWR);
126248f219cSDavid Howells 	flush_workqueue(afs_async_calls);
127f044c884SDavid Howells 	sock_release(net->socket);
12808e0e7c8SDavid Howells 
12908e0e7c8SDavid Howells 	_debug("dework");
13008e0e7c8SDavid Howells 	_leave("");
13108e0e7c8SDavid Howells }
13208e0e7c8SDavid Howells 
13308e0e7c8SDavid Howells /*
134341f741fSDavid Howells  * Allocate a call.
13500d3b7a4SDavid Howells  */
afs_alloc_call(struct afs_net * net,const struct afs_call_type * type,gfp_t gfp)136f044c884SDavid Howells static struct afs_call *afs_alloc_call(struct afs_net *net,
137f044c884SDavid Howells 				       const struct afs_call_type *type,
138341f741fSDavid Howells 				       gfp_t gfp)
13900d3b7a4SDavid Howells {
140341f741fSDavid Howells 	struct afs_call *call;
141341f741fSDavid Howells 	int o;
14200d3b7a4SDavid Howells 
143341f741fSDavid Howells 	call = kzalloc(sizeof(*call), gfp);
144341f741fSDavid Howells 	if (!call)
145341f741fSDavid Howells 		return NULL;
14600d3b7a4SDavid Howells 
147341f741fSDavid Howells 	call->type = type;
148f044c884SDavid Howells 	call->net = net;
149a25e21f0SDavid Howells 	call->debug_id = atomic_inc_return(&rxrpc_debug_id);
150c56f9ec8SDavid Howells 	refcount_set(&call->ref, 1);
151341f741fSDavid Howells 	INIT_WORK(&call->async_work, afs_process_async_call);
152341f741fSDavid Howells 	init_waitqueue_head(&call->waitq);
15398bf40cdSDavid Howells 	spin_lock_init(&call->state_lock);
154fc276122SDavid Howells 	call->iter = &call->def_iter;
1552f02f7aeSDavid Howells 
156f044c884SDavid Howells 	o = atomic_inc_return(&net->nr_outstanding_calls);
1572757a4dcSDavid Howells 	trace_afs_call(call->debug_id, afs_call_trace_alloc, 1, o,
158341f741fSDavid Howells 		       __builtin_return_address(0));
159341f741fSDavid Howells 	return call;
16000d3b7a4SDavid Howells }
16100d3b7a4SDavid Howells 
16200d3b7a4SDavid Howells /*
163341f741fSDavid Howells  * Dispose of a reference on a call.
1646c67c7c3SDavid Howells  */
afs_put_call(struct afs_call * call)165341f741fSDavid Howells void afs_put_call(struct afs_call *call)
1666c67c7c3SDavid Howells {
167f044c884SDavid Howells 	struct afs_net *net = call->net;
1682757a4dcSDavid Howells 	unsigned int debug_id = call->debug_id;
169c56f9ec8SDavid Howells 	bool zero;
170c56f9ec8SDavid Howells 	int r, o;
171341f741fSDavid Howells 
172c56f9ec8SDavid Howells 	zero = __refcount_dec_and_test(&call->ref, &r);
173c56f9ec8SDavid Howells 	o = atomic_read(&net->nr_outstanding_calls);
1742757a4dcSDavid Howells 	trace_afs_call(debug_id, afs_call_trace_put, r - 1, o,
175341f741fSDavid Howells 		       __builtin_return_address(0));
176341f741fSDavid Howells 
177c56f9ec8SDavid Howells 	if (zero) {
178341f741fSDavid Howells 		ASSERT(!work_pending(&call->async_work));
179341f741fSDavid Howells 		ASSERT(call->type->name != NULL);
180341f741fSDavid Howells 
1816c67c7c3SDavid Howells 		if (call->rxcall) {
182e0416e7dSDavid Howells 			rxrpc_kernel_shutdown_call(net->socket, call->rxcall);
183e0416e7dSDavid Howells 			rxrpc_kernel_put_call(net->socket, call->rxcall);
1846c67c7c3SDavid Howells 			call->rxcall = NULL;
1856c67c7c3SDavid Howells 		}
1866cf12869SNathaniel Wesley Filardo 		if (call->type->destructor)
1876c67c7c3SDavid Howells 			call->type->destructor(call);
188341f741fSDavid Howells 
189977e5f8eSDavid Howells 		afs_unuse_server_notime(call->net, call->server, afs_server_trace_put_call);
1903bf0fb6fSDavid Howells 		afs_put_addrlist(call->alist);
191341f741fSDavid Howells 		kfree(call->request);
192a25e21f0SDavid Howells 
1932757a4dcSDavid Howells 		trace_afs_call(call->debug_id, afs_call_trace_free, 0, o,
194a25e21f0SDavid Howells 			       __builtin_return_address(0));
195341f741fSDavid Howells 		kfree(call);
196341f741fSDavid Howells 
197f044c884SDavid Howells 		o = atomic_dec_return(&net->nr_outstanding_calls);
198341f741fSDavid Howells 		if (o == 0)
199ab1fbe32SPeter Zijlstra 			wake_up_var(&net->nr_outstanding_calls);
200341f741fSDavid Howells 	}
2016cf12869SNathaniel Wesley Filardo }
2026cf12869SNathaniel Wesley Filardo 
afs_get_call(struct afs_call * call,enum afs_call_trace why)2037a75b007SDavid Howells static struct afs_call *afs_get_call(struct afs_call *call,
2047a75b007SDavid Howells 				     enum afs_call_trace why)
2057a75b007SDavid Howells {
206c56f9ec8SDavid Howells 	int r;
2077a75b007SDavid Howells 
208c56f9ec8SDavid Howells 	__refcount_inc(&call->ref, &r);
209c56f9ec8SDavid Howells 
2102757a4dcSDavid Howells 	trace_afs_call(call->debug_id, why, r + 1,
2117a75b007SDavid Howells 		       atomic_read(&call->net->nr_outstanding_calls),
2127a75b007SDavid Howells 		       __builtin_return_address(0));
2137a75b007SDavid Howells 	return call;
2147a75b007SDavid Howells }
2157a75b007SDavid Howells 
2166cf12869SNathaniel Wesley Filardo /*
2173bf0fb6fSDavid Howells  * Queue the call for actual work.
2186cf12869SNathaniel Wesley Filardo  */
afs_queue_call_work(struct afs_call * call)2193bf0fb6fSDavid Howells static void afs_queue_call_work(struct afs_call *call)
2206cf12869SNathaniel Wesley Filardo {
2213bf0fb6fSDavid Howells 	if (call->type->work) {
222341f741fSDavid Howells 		INIT_WORK(&call->work, call->type->work);
223341f741fSDavid Howells 
2247a75b007SDavid Howells 		afs_get_call(call, afs_call_trace_work);
225341f741fSDavid Howells 		if (!queue_work(afs_wq, &call->work))
226341f741fSDavid Howells 			afs_put_call(call);
2273bf0fb6fSDavid Howells 	}
2286c67c7c3SDavid Howells }
2296c67c7c3SDavid Howells 
2306c67c7c3SDavid Howells /*
23108e0e7c8SDavid Howells  * allocate a call with flat request and reply buffers
23208e0e7c8SDavid Howells  */
afs_alloc_flat_call(struct afs_net * net,const struct afs_call_type * type,size_t request_size,size_t reply_max)233f044c884SDavid Howells struct afs_call *afs_alloc_flat_call(struct afs_net *net,
234f044c884SDavid Howells 				     const struct afs_call_type *type,
235d001648eSDavid Howells 				     size_t request_size, size_t reply_max)
23608e0e7c8SDavid Howells {
23708e0e7c8SDavid Howells 	struct afs_call *call;
23808e0e7c8SDavid Howells 
239f044c884SDavid Howells 	call = afs_alloc_call(net, type, GFP_NOFS);
24008e0e7c8SDavid Howells 	if (!call)
24108e0e7c8SDavid Howells 		goto nomem_call;
24208e0e7c8SDavid Howells 
24300d3b7a4SDavid Howells 	if (request_size) {
244341f741fSDavid Howells 		call->request_size = request_size;
24500d3b7a4SDavid Howells 		call->request = kmalloc(request_size, GFP_NOFS);
24600d3b7a4SDavid Howells 		if (!call->request)
24700d3b7a4SDavid Howells 			goto nomem_free;
24800d3b7a4SDavid Howells 	}
24900d3b7a4SDavid Howells 
250d001648eSDavid Howells 	if (reply_max) {
251341f741fSDavid Howells 		call->reply_max = reply_max;
252d001648eSDavid Howells 		call->buffer = kmalloc(reply_max, GFP_NOFS);
25300d3b7a4SDavid Howells 		if (!call->buffer)
25400d3b7a4SDavid Howells 			goto nomem_free;
25500d3b7a4SDavid Howells 	}
25600d3b7a4SDavid Howells 
25712bdcf33SDavid Howells 	afs_extract_to_buf(call, call->reply_max);
258025db80cSDavid Howells 	call->operation_ID = type->op;
25908e0e7c8SDavid Howells 	init_waitqueue_head(&call->waitq);
26008e0e7c8SDavid Howells 	return call;
26108e0e7c8SDavid Howells 
26200d3b7a4SDavid Howells nomem_free:
263341f741fSDavid Howells 	afs_put_call(call);
26408e0e7c8SDavid Howells nomem_call:
26508e0e7c8SDavid Howells 	return NULL;
26608e0e7c8SDavid Howells }
26708e0e7c8SDavid Howells 
26808e0e7c8SDavid Howells /*
26908e0e7c8SDavid Howells  * clean up a call with flat buffer
27008e0e7c8SDavid Howells  */
afs_flat_call_destructor(struct afs_call * call)27108e0e7c8SDavid Howells void afs_flat_call_destructor(struct afs_call *call)
27208e0e7c8SDavid Howells {
27308e0e7c8SDavid Howells 	_enter("");
27408e0e7c8SDavid Howells 
27508e0e7c8SDavid Howells 	kfree(call->request);
27608e0e7c8SDavid Howells 	call->request = NULL;
27708e0e7c8SDavid Howells 	kfree(call->buffer);
27808e0e7c8SDavid Howells 	call->buffer = NULL;
27908e0e7c8SDavid Howells }
28008e0e7c8SDavid Howells 
28108e0e7c8SDavid Howells /*
282e833251aSDavid Howells  * Advance the AFS call state when the RxRPC call ends the transmit phase.
283e833251aSDavid Howells  */
afs_notify_end_request_tx(struct sock * sock,struct rxrpc_call * rxcall,unsigned long call_user_ID)284e833251aSDavid Howells static void afs_notify_end_request_tx(struct sock *sock,
285e833251aSDavid Howells 				      struct rxrpc_call *rxcall,
286e833251aSDavid Howells 				      unsigned long call_user_ID)
287e833251aSDavid Howells {
288e833251aSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
289e833251aSDavid Howells 
29098bf40cdSDavid Howells 	afs_set_call_state(call, AFS_CALL_CL_REQUESTING, AFS_CALL_CL_AWAIT_REPLY);
291e833251aSDavid Howells }
292e833251aSDavid Howells 
293e833251aSDavid Howells /*
2940b9bf381SDavid Howells  * Initiate a call and synchronously queue up the parameters for dispatch.  Any
2950b9bf381SDavid Howells  * error is stored into the call struct, which the caller must check for.
29608e0e7c8SDavid Howells  */
afs_make_call(struct afs_addr_cursor * ac,struct afs_call * call,gfp_t gfp)2970b9bf381SDavid Howells void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp)
29808e0e7c8SDavid Howells {
2992feeaf84SDavid Howells 	struct sockaddr_rxrpc *srx = &ac->alist->addrs[ac->index];
30008e0e7c8SDavid Howells 	struct rxrpc_call *rxcall;
30108e0e7c8SDavid Howells 	struct msghdr msg;
30208e0e7c8SDavid Howells 	struct kvec iov[1];
303f105da1aSDavid Howells 	size_t len;
304e754eba6SDavid Howells 	s64 tx_total_len;
30508e0e7c8SDavid Howells 	int ret;
30608e0e7c8SDavid Howells 
3074d9df986SDavid Howells 	_enter(",{%pISp},", &srx->transport);
30808e0e7c8SDavid Howells 
30900d3b7a4SDavid Howells 	ASSERT(call->type != NULL);
31000d3b7a4SDavid Howells 	ASSERT(call->type->name != NULL);
31100d3b7a4SDavid Howells 
31231143d5dSDavid Howells 	_debug("____MAKE %p{%s,%x} [%d]____",
31331143d5dSDavid Howells 	       call, call->type->name, key_serial(call->key),
314f044c884SDavid Howells 	       atomic_read(&call->net->nr_outstanding_calls));
31500d3b7a4SDavid Howells 
3163bf0fb6fSDavid Howells 	call->addr_ix = ac->index;
3173bf0fb6fSDavid Howells 	call->alist = afs_get_addrlist(ac->alist);
31808e0e7c8SDavid Howells 
319e754eba6SDavid Howells 	/* Work out the length we're going to transmit.  This is awkward for
320e754eba6SDavid Howells 	 * calls such as FS.StoreData where there's an extra injection of data
321e754eba6SDavid Howells 	 * after the initial fixed part.
322e754eba6SDavid Howells 	 */
323e754eba6SDavid Howells 	tx_total_len = call->request_size;
324bd80d8a8SDavid Howells 	if (call->write_iter)
325bd80d8a8SDavid Howells 		tx_total_len += iov_iter_count(call->write_iter);
326e754eba6SDavid Howells 
32734fa4761SDavid Howells 	/* If the call is going to be asynchronous, we need an extra ref for
32834fa4761SDavid Howells 	 * the call to hold itself so the caller need not hang on to its ref.
32934fa4761SDavid Howells 	 */
330dde9f095SDavid Howells 	if (call->async) {
33134fa4761SDavid Howells 		afs_get_call(call, afs_call_trace_get);
332dde9f095SDavid Howells 		call->drop_ref = true;
333dde9f095SDavid Howells 	}
33434fa4761SDavid Howells 
33508e0e7c8SDavid Howells 	/* create a call */
3364d9df986SDavid Howells 	rxcall = rxrpc_kernel_begin_call(call->net->socket, srx, call->key,
337e754eba6SDavid Howells 					 (unsigned long)call,
338db099c62SDavid Howells 					 tx_total_len,
339db099c62SDavid Howells 					 call->max_lifespan,
340db099c62SDavid Howells 					 gfp,
3410b9bf381SDavid Howells 					 (call->async ?
34256ff9c83SDavid Howells 					  afs_wake_up_async_call :
343a68f4a27SDavid Howells 					  afs_wake_up_call_waiter),
344a25e21f0SDavid Howells 					 call->upgrade,
345e138aa7dSDavid Howells 					 (call->intr ? RXRPC_PREINTERRUPTIBLE :
346e138aa7dSDavid Howells 					  RXRPC_UNINTERRUPTIBLE),
347a25e21f0SDavid Howells 					 call->debug_id);
34808e0e7c8SDavid Howells 	if (IS_ERR(rxcall)) {
34908e0e7c8SDavid Howells 		ret = PTR_ERR(rxcall);
3503bf0fb6fSDavid Howells 		call->error = ret;
35108e0e7c8SDavid Howells 		goto error_kill_call;
35208e0e7c8SDavid Howells 	}
35308e0e7c8SDavid Howells 
35408e0e7c8SDavid Howells 	call->rxcall = rxcall;
3557903192cSDavid Howells 	call->issue_time = ktime_get_real();
35694f699c9SDavid Howells 
35708e0e7c8SDavid Howells 	/* send the request */
35808e0e7c8SDavid Howells 	iov[0].iov_base	= call->request;
35908e0e7c8SDavid Howells 	iov[0].iov_len	= call->request_size;
36008e0e7c8SDavid Howells 
36108e0e7c8SDavid Howells 	msg.msg_name		= NULL;
36208e0e7c8SDavid Howells 	msg.msg_namelen		= 0;
363de4eda9dSAl Viro 	iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, iov, 1, call->request_size);
36408e0e7c8SDavid Howells 	msg.msg_control		= NULL;
36508e0e7c8SDavid Howells 	msg.msg_controllen	= 0;
366bd80d8a8SDavid Howells 	msg.msg_flags		= MSG_WAITALL | (call->write_iter ? MSG_MORE : 0);
36708e0e7c8SDavid Howells 
368f044c884SDavid Howells 	ret = rxrpc_kernel_send_data(call->net->socket, rxcall,
369e833251aSDavid Howells 				     &msg, call->request_size,
370e833251aSDavid Howells 				     afs_notify_end_request_tx);
37108e0e7c8SDavid Howells 	if (ret < 0)
37208e0e7c8SDavid Howells 		goto error_do_abort;
37308e0e7c8SDavid Howells 
374bd80d8a8SDavid Howells 	if (call->write_iter) {
375bd80d8a8SDavid Howells 		msg.msg_iter = *call->write_iter;
376bd80d8a8SDavid Howells 		msg.msg_flags &= ~MSG_MORE;
377bd80d8a8SDavid Howells 		trace_afs_send_data(call, &msg);
378bd80d8a8SDavid Howells 
379bd80d8a8SDavid Howells 		ret = rxrpc_kernel_send_data(call->net->socket,
380bd80d8a8SDavid Howells 					     call->rxcall, &msg,
381bd80d8a8SDavid Howells 					     iov_iter_count(&msg.msg_iter),
382bd80d8a8SDavid Howells 					     afs_notify_end_request_tx);
383bd80d8a8SDavid Howells 		*call->write_iter = msg.msg_iter;
384bd80d8a8SDavid Howells 
385bd80d8a8SDavid Howells 		trace_afs_sent_data(call, &msg, ret);
38631143d5dSDavid Howells 		if (ret < 0)
38731143d5dSDavid Howells 			goto error_do_abort;
38831143d5dSDavid Howells 	}
38931143d5dSDavid Howells 
39034fa4761SDavid Howells 	/* Note that at this point, we may have received the reply or an abort
39134fa4761SDavid Howells 	 * - and an asynchronous call may already have completed.
3920b9bf381SDavid Howells 	 *
3930b9bf381SDavid Howells 	 * afs_wait_for_call_to_complete(call, ac)
3940b9bf381SDavid Howells 	 * must be called to synchronously clean up.
39534fa4761SDavid Howells 	 */
3960b9bf381SDavid Howells 	return;
39708e0e7c8SDavid Howells 
39808e0e7c8SDavid Howells error_do_abort:
39970af0e3bSDavid Howells 	if (ret != -ECONNABORTED) {
400f044c884SDavid Howells 		rxrpc_kernel_abort_call(call->net->socket, rxcall,
40157af281eSDavid Howells 					RX_USER_ABORT, ret,
40257af281eSDavid Howells 					afs_abort_send_data_error);
40370af0e3bSDavid Howells 	} else {
404f105da1aSDavid Howells 		len = 0;
405de4eda9dSAl Viro 		iov_iter_kvec(&msg.msg_iter, ITER_DEST, NULL, 0, 0);
406eb9950ebSDavid Howells 		rxrpc_kernel_recv_data(call->net->socket, rxcall,
407f105da1aSDavid Howells 				       &msg.msg_iter, &len, false,
408eb9950ebSDavid Howells 				       &call->abort_code, &call->service_id);
409d2ddc776SDavid Howells 		ac->abort_code = call->abort_code;
410d2ddc776SDavid Howells 		ac->responded = true;
41170af0e3bSDavid Howells 	}
412025db80cSDavid Howells 	call->error = ret;
413025db80cSDavid Howells 	trace_afs_call_done(call);
41408e0e7c8SDavid Howells error_kill_call:
4153bf0fb6fSDavid Howells 	if (call->type->done)
4163bf0fb6fSDavid Howells 		call->type->done(call);
41734fa4761SDavid Howells 
41834fa4761SDavid Howells 	/* We need to dispose of the extra ref we grabbed for an async call.
41934fa4761SDavid Howells 	 * The call, however, might be queued on afs_async_calls and we need to
42034fa4761SDavid Howells 	 * make sure we don't get any more notifications that might requeue it.
42134fa4761SDavid Howells 	 */
422e0416e7dSDavid Howells 	if (call->rxcall)
423e0416e7dSDavid Howells 		rxrpc_kernel_shutdown_call(call->net->socket, call->rxcall);
42434fa4761SDavid Howells 	if (call->async) {
42534fa4761SDavid Howells 		if (cancel_work_sync(&call->async_work))
426341f741fSDavid Howells 			afs_put_call(call);
427*8715fe2fSDavid Howells 		afs_set_call_complete(call, ret, 0);
42834fa4761SDavid Howells 	}
42934fa4761SDavid Howells 
430d2ddc776SDavid Howells 	ac->error = ret;
43134fa4761SDavid Howells 	call->state = AFS_CALL_COMPLETE;
43208e0e7c8SDavid Howells 	_leave(" = %d", ret);
43308e0e7c8SDavid Howells }
43408e0e7c8SDavid Howells 
43508e0e7c8SDavid Howells /*
43605092755SDavid Howells  * Log remote abort codes that indicate that we have a protocol disagreement
43705092755SDavid Howells  * with the server.
43805092755SDavid Howells  */
afs_log_error(struct afs_call * call,s32 remote_abort)43905092755SDavid Howells static void afs_log_error(struct afs_call *call, s32 remote_abort)
44005092755SDavid Howells {
44105092755SDavid Howells 	static int max = 0;
44205092755SDavid Howells 	const char *msg;
44305092755SDavid Howells 	int m;
44405092755SDavid Howells 
44505092755SDavid Howells 	switch (remote_abort) {
44605092755SDavid Howells 	case RX_EOF:		 msg = "unexpected EOF";	break;
44705092755SDavid Howells 	case RXGEN_CC_MARSHAL:	 msg = "client marshalling";	break;
44805092755SDavid Howells 	case RXGEN_CC_UNMARSHAL: msg = "client unmarshalling";	break;
44905092755SDavid Howells 	case RXGEN_SS_MARSHAL:	 msg = "server marshalling";	break;
45005092755SDavid Howells 	case RXGEN_SS_UNMARSHAL: msg = "server unmarshalling";	break;
45105092755SDavid Howells 	case RXGEN_DECODE:	 msg = "opcode decode";		break;
45205092755SDavid Howells 	case RXGEN_SS_XDRFREE:	 msg = "server XDR cleanup";	break;
45305092755SDavid Howells 	case RXGEN_CC_XDRFREE:	 msg = "client XDR cleanup";	break;
45405092755SDavid Howells 	case -32:		 msg = "insufficient data";	break;
45505092755SDavid Howells 	default:
45605092755SDavid Howells 		return;
45705092755SDavid Howells 	}
45805092755SDavid Howells 
45905092755SDavid Howells 	m = max;
46005092755SDavid Howells 	if (m < 3) {
46105092755SDavid Howells 		max = m + 1;
46205092755SDavid Howells 		pr_notice("kAFS: Peer reported %s failure on %s [%pISp]\n",
46305092755SDavid Howells 			  msg, call->type->name,
46405092755SDavid Howells 			  &call->alist->addrs[call->addr_ix].transport);
46505092755SDavid Howells 	}
46605092755SDavid Howells }
46705092755SDavid Howells 
46805092755SDavid Howells /*
46908e0e7c8SDavid Howells  * deliver messages to a call
47008e0e7c8SDavid Howells  */
afs_deliver_to_call(struct afs_call * call)47108e0e7c8SDavid Howells static void afs_deliver_to_call(struct afs_call *call)
47208e0e7c8SDavid Howells {
47398bf40cdSDavid Howells 	enum afs_call_state state;
474f105da1aSDavid Howells 	size_t len;
47598bf40cdSDavid Howells 	u32 abort_code, remote_abort = 0;
47608e0e7c8SDavid Howells 	int ret;
47708e0e7c8SDavid Howells 
478d001648eSDavid Howells 	_enter("%s", call->type->name);
47908e0e7c8SDavid Howells 
48098bf40cdSDavid Howells 	while (state = READ_ONCE(call->state),
48198bf40cdSDavid Howells 	       state == AFS_CALL_CL_AWAIT_REPLY ||
48298bf40cdSDavid Howells 	       state == AFS_CALL_SV_AWAIT_OP_ID ||
48398bf40cdSDavid Howells 	       state == AFS_CALL_SV_AWAIT_REQUEST ||
48498bf40cdSDavid Howells 	       state == AFS_CALL_SV_AWAIT_ACK
485d001648eSDavid Howells 	       ) {
48698bf40cdSDavid Howells 		if (state == AFS_CALL_SV_AWAIT_ACK) {
487f105da1aSDavid Howells 			len = 0;
488de4eda9dSAl Viro 			iov_iter_kvec(&call->def_iter, ITER_DEST, NULL, 0, 0);
489f044c884SDavid Howells 			ret = rxrpc_kernel_recv_data(call->net->socket,
490fc276122SDavid Howells 						     call->rxcall, &call->def_iter,
491f105da1aSDavid Howells 						     &len, false, &remote_abort,
492a68f4a27SDavid Howells 						     &call->service_id);
493fc276122SDavid Howells 			trace_afs_receive_data(call, &call->def_iter, false, ret);
4948e8d7f13SDavid Howells 
495d001648eSDavid Howells 			if (ret == -EINPROGRESS || ret == -EAGAIN)
496d001648eSDavid Howells 				return;
49798bf40cdSDavid Howells 			if (ret < 0 || ret == 1) {
49898bf40cdSDavid Howells 				if (ret == 1)
49998bf40cdSDavid Howells 					ret = 0;
500025db80cSDavid Howells 				goto call_complete;
50198bf40cdSDavid Howells 			}
502d001648eSDavid Howells 			return;
503d001648eSDavid Howells 		}
504d001648eSDavid Howells 
505d001648eSDavid Howells 		ret = call->type->deliver(call);
50698bf40cdSDavid Howells 		state = READ_ONCE(call->state);
50738355eecSDavid Howells 		if (ret == 0 && call->unmarshalling_error)
50838355eecSDavid Howells 			ret = -EBADMSG;
509d001648eSDavid Howells 		switch (ret) {
51008e0e7c8SDavid Howells 		case 0:
5113bf0fb6fSDavid Howells 			afs_queue_call_work(call);
512f2686b09SDavid Howells 			if (state == AFS_CALL_CL_PROC_REPLY) {
51320325960SDavid Howells 				if (call->op)
514f2686b09SDavid Howells 					set_bit(AFS_SERVER_FL_MAY_HAVE_CB,
51520325960SDavid Howells 						&call->op->server->flags);
516025db80cSDavid Howells 				goto call_complete;
517f2686b09SDavid Howells 			}
51898bf40cdSDavid Howells 			ASSERTCMP(state, >, AFS_CALL_CL_PROC_REPLY);
519d001648eSDavid Howells 			goto done;
520d001648eSDavid Howells 		case -EINPROGRESS:
521d001648eSDavid Howells 		case -EAGAIN:
522d001648eSDavid Howells 			goto out;
52370af0e3bSDavid Howells 		case -ECONNABORTED:
52498bf40cdSDavid Howells 			ASSERTCMP(state, ==, AFS_CALL_COMPLETE);
52505092755SDavid Howells 			afs_log_error(call, call->abort_code);
52698bf40cdSDavid Howells 			goto done;
52708e0e7c8SDavid Howells 		case -ENOTSUPP:
5281157f153SDavid Howells 			abort_code = RXGEN_OPCODE;
529f044c884SDavid Howells 			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
53057af281eSDavid Howells 						abort_code, ret,
53157af281eSDavid Howells 						afs_abort_op_not_supported);
53298bf40cdSDavid Howells 			goto local_abort;
5334ac15ea5SDavid Howells 		case -EIO:
5344ac15ea5SDavid Howells 			pr_err("kAFS: Call %u in bad state %u\n",
5354ac15ea5SDavid Howells 			       call->debug_id, state);
536df561f66SGustavo A. R. Silva 			fallthrough;
537d001648eSDavid Howells 		case -ENODATA:
538d001648eSDavid Howells 		case -EBADMSG:
539d001648eSDavid Howells 		case -EMSGSIZE:
540de696c47SDavid Howells 		case -ENOMEM:
541de696c47SDavid Howells 		case -EFAULT:
54208e0e7c8SDavid Howells 			abort_code = RXGEN_CC_UNMARSHAL;
54398bf40cdSDavid Howells 			if (state != AFS_CALL_CL_AWAIT_REPLY)
54408e0e7c8SDavid Howells 				abort_code = RXGEN_SS_UNMARSHAL;
545f044c884SDavid Howells 			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
54657af281eSDavid Howells 						abort_code, ret,
54757af281eSDavid Howells 						afs_abort_unmarshal_error);
54898bf40cdSDavid Howells 			goto local_abort;
5498022c4b9SDavid Howells 		default:
550de696c47SDavid Howells 			abort_code = RX_CALL_DEAD;
5518022c4b9SDavid Howells 			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
55257af281eSDavid Howells 						abort_code, ret,
55357af281eSDavid Howells 						afs_abort_general_error);
5548022c4b9SDavid Howells 			goto local_abort;
55508e0e7c8SDavid Howells 		}
55608e0e7c8SDavid Howells 	}
55708e0e7c8SDavid Howells 
558d001648eSDavid Howells done:
5593bf0fb6fSDavid Howells 	if (call->type->done)
5603bf0fb6fSDavid Howells 		call->type->done(call);
561d001648eSDavid Howells out:
56208e0e7c8SDavid Howells 	_leave("");
563d001648eSDavid Howells 	return;
564d001648eSDavid Howells 
56598bf40cdSDavid Howells local_abort:
56698bf40cdSDavid Howells 	abort_code = 0;
567025db80cSDavid Howells call_complete:
56898bf40cdSDavid Howells 	afs_set_call_complete(call, ret, remote_abort);
56998bf40cdSDavid Howells 	state = AFS_CALL_COMPLETE;
570d001648eSDavid Howells 	goto done;
57108e0e7c8SDavid Howells }
57208e0e7c8SDavid Howells 
57308e0e7c8SDavid Howells /*
5740b9bf381SDavid Howells  * Wait synchronously for a call to complete and clean up the call struct.
57508e0e7c8SDavid Howells  */
afs_wait_for_call_to_complete(struct afs_call * call,struct afs_addr_cursor * ac)5760b9bf381SDavid Howells long afs_wait_for_call_to_complete(struct afs_call *call,
577d2ddc776SDavid Howells 				   struct afs_addr_cursor *ac)
57808e0e7c8SDavid Howells {
57933cd7f2bSDavid Howells 	long ret;
580f7f1dd31SMarc Dionne 	bool rxrpc_complete = false;
58108e0e7c8SDavid Howells 
58208e0e7c8SDavid Howells 	DECLARE_WAITQUEUE(myself, current);
58308e0e7c8SDavid Howells 
58408e0e7c8SDavid Howells 	_enter("");
58508e0e7c8SDavid Howells 
5860b9bf381SDavid Howells 	ret = call->error;
5870b9bf381SDavid Howells 	if (ret < 0)
5880b9bf381SDavid Howells 		goto out;
5890b9bf381SDavid Howells 
59008e0e7c8SDavid Howells 	add_wait_queue(&call->waitq, &myself);
59108e0e7c8SDavid Howells 	for (;;) {
592bc5e3a54SDavid Howells 		set_current_state(TASK_UNINTERRUPTIBLE);
59308e0e7c8SDavid Howells 
59408e0e7c8SDavid Howells 		/* deliver any messages that are in the queue */
59598bf40cdSDavid Howells 		if (!afs_check_call_state(call, AFS_CALL_COMPLETE) &&
59698bf40cdSDavid Howells 		    call->need_attention) {
597d001648eSDavid Howells 			call->need_attention = false;
59808e0e7c8SDavid Howells 			__set_current_state(TASK_RUNNING);
59908e0e7c8SDavid Howells 			afs_deliver_to_call(call);
60008e0e7c8SDavid Howells 			continue;
60108e0e7c8SDavid Howells 		}
60208e0e7c8SDavid Howells 
60398bf40cdSDavid Howells 		if (afs_check_call_state(call, AFS_CALL_COMPLETE))
60408e0e7c8SDavid Howells 			break;
605bc5e3a54SDavid Howells 
6067d7587dbSDavid Howells 		if (!rxrpc_kernel_check_life(call->net->socket, call->rxcall)) {
607f7f1dd31SMarc Dionne 			/* rxrpc terminated the call. */
608f7f1dd31SMarc Dionne 			rxrpc_complete = true;
609f7f1dd31SMarc Dionne 			break;
610f7f1dd31SMarc Dionne 		}
611f7f1dd31SMarc Dionne 
6127d7587dbSDavid Howells 		schedule();
61308e0e7c8SDavid Howells 	}
61408e0e7c8SDavid Howells 
61508e0e7c8SDavid Howells 	remove_wait_queue(&call->waitq, &myself);
61608e0e7c8SDavid Howells 	__set_current_state(TASK_RUNNING);
61708e0e7c8SDavid Howells 
61898bf40cdSDavid Howells 	if (!afs_check_call_state(call, AFS_CALL_COMPLETE)) {
619f7f1dd31SMarc Dionne 		if (rxrpc_complete) {
620f7f1dd31SMarc Dionne 			afs_set_call_complete(call, call->error, call->abort_code);
621f7f1dd31SMarc Dionne 		} else {
622f7f1dd31SMarc Dionne 			/* Kill off the call if it's still live. */
623954cd6dcSDavid Howells 			_debug("call interrupted");
624d2ddc776SDavid Howells 			if (rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
62557af281eSDavid Howells 						    RX_USER_ABORT, -EINTR,
62657af281eSDavid Howells 						    afs_abort_interrupted))
62798bf40cdSDavid Howells 				afs_set_call_complete(call, -EINTR, 0);
62808e0e7c8SDavid Howells 		}
629f7f1dd31SMarc Dionne 	}
63008e0e7c8SDavid Howells 
63198bf40cdSDavid Howells 	spin_lock_bh(&call->state_lock);
632d2ddc776SDavid Howells 	ac->abort_code = call->abort_code;
633d2ddc776SDavid Howells 	ac->error = call->error;
63498bf40cdSDavid Howells 	spin_unlock_bh(&call->state_lock);
635d2ddc776SDavid Howells 
636d2ddc776SDavid Howells 	ret = ac->error;
637d2ddc776SDavid Howells 	switch (ret) {
638d2ddc776SDavid Howells 	case 0:
639ffba718eSDavid Howells 		ret = call->ret0;
640ffba718eSDavid Howells 		call->ret0 = 0;
641ffba718eSDavid Howells 
642df561f66SGustavo A. R. Silva 		fallthrough;
643d2ddc776SDavid Howells 	case -ECONNABORTED:
644d2ddc776SDavid Howells 		ac->responded = true;
645d2ddc776SDavid Howells 		break;
646d2ddc776SDavid Howells 	}
64733cd7f2bSDavid Howells 
6480b9bf381SDavid Howells out:
64908e0e7c8SDavid Howells 	_debug("call complete");
650341f741fSDavid Howells 	afs_put_call(call);
65133cd7f2bSDavid Howells 	_leave(" = %p", (void *)ret);
65208e0e7c8SDavid Howells 	return ret;
65308e0e7c8SDavid Howells }
65408e0e7c8SDavid Howells 
65508e0e7c8SDavid Howells /*
65608e0e7c8SDavid Howells  * wake up a waiting call
65708e0e7c8SDavid Howells  */
afs_wake_up_call_waiter(struct sock * sk,struct rxrpc_call * rxcall,unsigned long call_user_ID)658d001648eSDavid Howells static void afs_wake_up_call_waiter(struct sock *sk, struct rxrpc_call *rxcall,
659d001648eSDavid Howells 				    unsigned long call_user_ID)
66008e0e7c8SDavid Howells {
661d001648eSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
662d001648eSDavid Howells 
663d001648eSDavid Howells 	call->need_attention = true;
66408e0e7c8SDavid Howells 	wake_up(&call->waitq);
66508e0e7c8SDavid Howells }
66608e0e7c8SDavid Howells 
66708e0e7c8SDavid Howells /*
66808e0e7c8SDavid Howells  * wake up an asynchronous call
66908e0e7c8SDavid Howells  */
afs_wake_up_async_call(struct sock * sk,struct rxrpc_call * rxcall,unsigned long call_user_ID)670d001648eSDavid Howells static void afs_wake_up_async_call(struct sock *sk, struct rxrpc_call *rxcall,
671d001648eSDavid Howells 				   unsigned long call_user_ID)
67208e0e7c8SDavid Howells {
673d001648eSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
674c56f9ec8SDavid Howells 	int r;
675d001648eSDavid Howells 
6768e8d7f13SDavid Howells 	trace_afs_notify_call(rxcall, call);
677d001648eSDavid Howells 	call->need_attention = true;
678341f741fSDavid Howells 
679c56f9ec8SDavid Howells 	if (__refcount_inc_not_zero(&call->ref, &r)) {
6802757a4dcSDavid Howells 		trace_afs_call(call->debug_id, afs_call_trace_wake, r + 1,
681f044c884SDavid Howells 			       atomic_read(&call->net->nr_outstanding_calls),
682341f741fSDavid Howells 			       __builtin_return_address(0));
683341f741fSDavid Howells 
684341f741fSDavid Howells 		if (!queue_work(afs_async_calls, &call->async_work))
685341f741fSDavid Howells 			afs_put_call(call);
686341f741fSDavid Howells 	}
68708e0e7c8SDavid Howells }
68808e0e7c8SDavid Howells 
68908e0e7c8SDavid Howells /*
690341f741fSDavid Howells  * Perform I/O processing on an asynchronous call.  The work item carries a ref
691341f741fSDavid Howells  * to the call struct that we either need to release or to pass on.
69208e0e7c8SDavid Howells  */
afs_process_async_call(struct work_struct * work)693d001648eSDavid Howells static void afs_process_async_call(struct work_struct *work)
69408e0e7c8SDavid Howells {
695d001648eSDavid Howells 	struct afs_call *call = container_of(work, struct afs_call, async_work);
696d001648eSDavid Howells 
69708e0e7c8SDavid Howells 	_enter("");
69808e0e7c8SDavid Howells 
699d001648eSDavid Howells 	if (call->state < AFS_CALL_COMPLETE && call->need_attention) {
700d001648eSDavid Howells 		call->need_attention = false;
70108e0e7c8SDavid Howells 		afs_deliver_to_call(call);
702d001648eSDavid Howells 	}
70308e0e7c8SDavid Howells 
704341f741fSDavid Howells 	afs_put_call(call);
70508e0e7c8SDavid Howells 	_leave("");
70608e0e7c8SDavid Howells }
70708e0e7c8SDavid Howells 
afs_rx_attach(struct rxrpc_call * rxcall,unsigned long user_call_ID)70800e90712SDavid Howells static void afs_rx_attach(struct rxrpc_call *rxcall, unsigned long user_call_ID)
70900e90712SDavid Howells {
71000e90712SDavid Howells 	struct afs_call *call = (struct afs_call *)user_call_ID;
71100e90712SDavid Howells 
71200e90712SDavid Howells 	call->rxcall = rxcall;
71300e90712SDavid Howells }
71400e90712SDavid Howells 
71500e90712SDavid Howells /*
71600e90712SDavid Howells  * Charge the incoming call preallocation.
71700e90712SDavid Howells  */
afs_charge_preallocation(struct work_struct * work)718f044c884SDavid Howells void afs_charge_preallocation(struct work_struct *work)
71900e90712SDavid Howells {
720f044c884SDavid Howells 	struct afs_net *net =
721f044c884SDavid Howells 		container_of(work, struct afs_net, charge_preallocation_work);
722f044c884SDavid Howells 	struct afs_call *call = net->spare_incoming_call;
72300e90712SDavid Howells 
72400e90712SDavid Howells 	for (;;) {
72500e90712SDavid Howells 		if (!call) {
726f044c884SDavid Howells 			call = afs_alloc_call(net, &afs_RXCMxxxx, GFP_KERNEL);
72700e90712SDavid Howells 			if (!call)
72800e90712SDavid Howells 				break;
72900e90712SDavid Howells 
730dde9f095SDavid Howells 			call->drop_ref = true;
73156ff9c83SDavid Howells 			call->async = true;
73298bf40cdSDavid Howells 			call->state = AFS_CALL_SV_AWAIT_OP_ID;
73356ff9c83SDavid Howells 			init_waitqueue_head(&call->waitq);
73412bdcf33SDavid Howells 			afs_extract_to_tmp(call);
73500e90712SDavid Howells 		}
73600e90712SDavid Howells 
737f044c884SDavid Howells 		if (rxrpc_kernel_charge_accept(net->socket,
73800e90712SDavid Howells 					       afs_wake_up_async_call,
73900e90712SDavid Howells 					       afs_rx_attach,
74000e90712SDavid Howells 					       (unsigned long)call,
741a25e21f0SDavid Howells 					       GFP_KERNEL,
742a25e21f0SDavid Howells 					       call->debug_id) < 0)
74300e90712SDavid Howells 			break;
74400e90712SDavid Howells 		call = NULL;
74500e90712SDavid Howells 	}
746f044c884SDavid Howells 	net->spare_incoming_call = call;
74700e90712SDavid Howells }
74800e90712SDavid Howells 
74900e90712SDavid Howells /*
75000e90712SDavid Howells  * Discard a preallocated call when a socket is shut down.
75100e90712SDavid Howells  */
afs_rx_discard_new_call(struct rxrpc_call * rxcall,unsigned long user_call_ID)75200e90712SDavid Howells static void afs_rx_discard_new_call(struct rxrpc_call *rxcall,
75300e90712SDavid Howells 				    unsigned long user_call_ID)
75400e90712SDavid Howells {
75500e90712SDavid Howells 	struct afs_call *call = (struct afs_call *)user_call_ID;
75600e90712SDavid Howells 
75700e90712SDavid Howells 	call->rxcall = NULL;
758341f741fSDavid Howells 	afs_put_call(call);
75900e90712SDavid Howells }
76000e90712SDavid Howells 
76108e0e7c8SDavid Howells /*
762d001648eSDavid Howells  * Notification of an incoming call.
763d001648eSDavid Howells  */
afs_rx_new_call(struct sock * sk,struct rxrpc_call * rxcall,unsigned long user_call_ID)76400e90712SDavid Howells static void afs_rx_new_call(struct sock *sk, struct rxrpc_call *rxcall,
76500e90712SDavid Howells 			    unsigned long user_call_ID)
766d001648eSDavid Howells {
767f044c884SDavid Howells 	struct afs_net *net = afs_sock2net(sk);
768f044c884SDavid Howells 
769f044c884SDavid Howells 	queue_work(afs_wq, &net->charge_preallocation_work);
770d001648eSDavid Howells }
771d001648eSDavid Howells 
772d001648eSDavid Howells /*
773372ee163SDavid Howells  * Grab the operation ID from an incoming cache manager call.  The socket
774372ee163SDavid Howells  * buffer is discarded on error or if we don't yet have sufficient data.
77508e0e7c8SDavid Howells  */
afs_deliver_cm_op_id(struct afs_call * call)776d001648eSDavid Howells static int afs_deliver_cm_op_id(struct afs_call *call)
77708e0e7c8SDavid Howells {
778d001648eSDavid Howells 	int ret;
77908e0e7c8SDavid Howells 
780fc276122SDavid Howells 	_enter("{%zu}", iov_iter_count(call->iter));
78108e0e7c8SDavid Howells 
78208e0e7c8SDavid Howells 	/* the operation ID forms the first four bytes of the request data */
78312bdcf33SDavid Howells 	ret = afs_extract_data(call, true);
784d001648eSDavid Howells 	if (ret < 0)
785d001648eSDavid Howells 		return ret;
78608e0e7c8SDavid Howells 
78750a2c953SDavid Howells 	call->operation_ID = ntohl(call->tmp);
78898bf40cdSDavid Howells 	afs_set_call_state(call, AFS_CALL_SV_AWAIT_OP_ID, AFS_CALL_SV_AWAIT_REQUEST);
78908e0e7c8SDavid Howells 
79008e0e7c8SDavid Howells 	/* ask the cache manager to route the call (it'll change the call type
79108e0e7c8SDavid Howells 	 * if successful) */
79208e0e7c8SDavid Howells 	if (!afs_cm_incoming_call(call))
79308e0e7c8SDavid Howells 		return -ENOTSUPP;
79408e0e7c8SDavid Howells 
7958e8d7f13SDavid Howells 	trace_afs_cb_call(call);
7968e8d7f13SDavid Howells 
79708e0e7c8SDavid Howells 	/* pass responsibility for the remainer of this message off to the
79808e0e7c8SDavid Howells 	 * cache manager op */
799d001648eSDavid Howells 	return call->type->deliver(call);
80008e0e7c8SDavid Howells }
80108e0e7c8SDavid Howells 
80208e0e7c8SDavid Howells /*
803e833251aSDavid Howells  * Advance the AFS call state when an RxRPC service call ends the transmit
804e833251aSDavid Howells  * phase.
805e833251aSDavid Howells  */
afs_notify_end_reply_tx(struct sock * sock,struct rxrpc_call * rxcall,unsigned long call_user_ID)806e833251aSDavid Howells static void afs_notify_end_reply_tx(struct sock *sock,
807e833251aSDavid Howells 				    struct rxrpc_call *rxcall,
808e833251aSDavid Howells 				    unsigned long call_user_ID)
809e833251aSDavid Howells {
810e833251aSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
811e833251aSDavid Howells 
81298bf40cdSDavid Howells 	afs_set_call_state(call, AFS_CALL_SV_REPLYING, AFS_CALL_SV_AWAIT_ACK);
813e833251aSDavid Howells }
814e833251aSDavid Howells 
815e833251aSDavid Howells /*
81608e0e7c8SDavid Howells  * send an empty reply
81708e0e7c8SDavid Howells  */
afs_send_empty_reply(struct afs_call * call)81808e0e7c8SDavid Howells void afs_send_empty_reply(struct afs_call *call)
81908e0e7c8SDavid Howells {
820f044c884SDavid Howells 	struct afs_net *net = call->net;
82108e0e7c8SDavid Howells 	struct msghdr msg;
82208e0e7c8SDavid Howells 
82308e0e7c8SDavid Howells 	_enter("");
82408e0e7c8SDavid Howells 
825f044c884SDavid Howells 	rxrpc_kernel_set_tx_length(net->socket, call->rxcall, 0);
826e754eba6SDavid Howells 
82708e0e7c8SDavid Howells 	msg.msg_name		= NULL;
82808e0e7c8SDavid Howells 	msg.msg_namelen		= 0;
829de4eda9dSAl Viro 	iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, NULL, 0, 0);
83008e0e7c8SDavid Howells 	msg.msg_control		= NULL;
83108e0e7c8SDavid Howells 	msg.msg_controllen	= 0;
83208e0e7c8SDavid Howells 	msg.msg_flags		= 0;
83308e0e7c8SDavid Howells 
834f044c884SDavid Howells 	switch (rxrpc_kernel_send_data(net->socket, call->rxcall, &msg, 0,
835e833251aSDavid Howells 				       afs_notify_end_reply_tx)) {
83608e0e7c8SDavid Howells 	case 0:
83708e0e7c8SDavid Howells 		_leave(" [replied]");
83808e0e7c8SDavid Howells 		return;
83908e0e7c8SDavid Howells 
84008e0e7c8SDavid Howells 	case -ENOMEM:
84108e0e7c8SDavid Howells 		_debug("oom");
842f044c884SDavid Howells 		rxrpc_kernel_abort_call(net->socket, call->rxcall,
84357af281eSDavid Howells 					RXGEN_SS_MARSHAL, -ENOMEM,
84457af281eSDavid Howells 					afs_abort_oom);
845df561f66SGustavo A. R. Silva 		fallthrough;
84608e0e7c8SDavid Howells 	default:
84708e0e7c8SDavid Howells 		_leave(" [error]");
84808e0e7c8SDavid Howells 		return;
84908e0e7c8SDavid Howells 	}
85008e0e7c8SDavid Howells }
85108e0e7c8SDavid Howells 
85208e0e7c8SDavid Howells /*
853b908fe6bSDavid Howells  * send a simple reply
854b908fe6bSDavid Howells  */
afs_send_simple_reply(struct afs_call * call,const void * buf,size_t len)855b908fe6bSDavid Howells void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
856b908fe6bSDavid Howells {
857f044c884SDavid Howells 	struct afs_net *net = call->net;
858b908fe6bSDavid Howells 	struct msghdr msg;
8592e90b1c4SAl Viro 	struct kvec iov[1];
860bd6dc742SDavid Howells 	int n;
861b908fe6bSDavid Howells 
862b908fe6bSDavid Howells 	_enter("");
863b908fe6bSDavid Howells 
864f044c884SDavid Howells 	rxrpc_kernel_set_tx_length(net->socket, call->rxcall, len);
865e754eba6SDavid Howells 
866b908fe6bSDavid Howells 	iov[0].iov_base		= (void *) buf;
867b908fe6bSDavid Howells 	iov[0].iov_len		= len;
868b908fe6bSDavid Howells 	msg.msg_name		= NULL;
869b908fe6bSDavid Howells 	msg.msg_namelen		= 0;
870de4eda9dSAl Viro 	iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, iov, 1, len);
871b908fe6bSDavid Howells 	msg.msg_control		= NULL;
872b908fe6bSDavid Howells 	msg.msg_controllen	= 0;
873b908fe6bSDavid Howells 	msg.msg_flags		= 0;
874b908fe6bSDavid Howells 
875f044c884SDavid Howells 	n = rxrpc_kernel_send_data(net->socket, call->rxcall, &msg, len,
876e833251aSDavid Howells 				   afs_notify_end_reply_tx);
877bd6dc742SDavid Howells 	if (n >= 0) {
8786c67c7c3SDavid Howells 		/* Success */
879b908fe6bSDavid Howells 		_leave(" [replied]");
880b908fe6bSDavid Howells 		return;
881bd6dc742SDavid Howells 	}
8826c67c7c3SDavid Howells 
883bd6dc742SDavid Howells 	if (n == -ENOMEM) {
884b908fe6bSDavid Howells 		_debug("oom");
885f044c884SDavid Howells 		rxrpc_kernel_abort_call(net->socket, call->rxcall,
88657af281eSDavid Howells 					RXGEN_SS_MARSHAL, -ENOMEM,
88757af281eSDavid Howells 					afs_abort_oom);
888bd6dc742SDavid Howells 	}
889b908fe6bSDavid Howells 	_leave(" [error]");
890b908fe6bSDavid Howells }
891b908fe6bSDavid Howells 
892b908fe6bSDavid Howells /*
893372ee163SDavid Howells  * Extract a piece of data from the received data socket buffers.
89408e0e7c8SDavid Howells  */
afs_extract_data(struct afs_call * call,bool want_more)89512bdcf33SDavid Howells int afs_extract_data(struct afs_call *call, bool want_more)
89608e0e7c8SDavid Howells {
897f044c884SDavid Howells 	struct afs_net *net = call->net;
898fc276122SDavid Howells 	struct iov_iter *iter = call->iter;
89998bf40cdSDavid Howells 	enum afs_call_state state;
9007888da95SDan Carpenter 	u32 remote_abort = 0;
901d001648eSDavid Howells 	int ret;
90208e0e7c8SDavid Howells 
903f105da1aSDavid Howells 	_enter("{%s,%zu,%zu},%d",
904f105da1aSDavid Howells 	       call->type->name, call->iov_len, iov_iter_count(iter), want_more);
90508e0e7c8SDavid Howells 
90612bdcf33SDavid Howells 	ret = rxrpc_kernel_recv_data(net->socket, call->rxcall, iter,
907f105da1aSDavid Howells 				     &call->iov_len, want_more, &remote_abort,
908a68f4a27SDavid Howells 				     &call->service_id);
90993368b6bSDavid Howells 	trace_afs_receive_data(call, call->iter, want_more, ret);
910d001648eSDavid Howells 	if (ret == 0 || ret == -EAGAIN)
911d001648eSDavid Howells 		return ret;
91208e0e7c8SDavid Howells 
91398bf40cdSDavid Howells 	state = READ_ONCE(call->state);
914d001648eSDavid Howells 	if (ret == 1) {
91598bf40cdSDavid Howells 		switch (state) {
91698bf40cdSDavid Howells 		case AFS_CALL_CL_AWAIT_REPLY:
91798bf40cdSDavid Howells 			afs_set_call_state(call, state, AFS_CALL_CL_PROC_REPLY);
918d001648eSDavid Howells 			break;
91998bf40cdSDavid Howells 		case AFS_CALL_SV_AWAIT_REQUEST:
92098bf40cdSDavid Howells 			afs_set_call_state(call, state, AFS_CALL_SV_REPLYING);
921d001648eSDavid Howells 			break;
92298bf40cdSDavid Howells 		case AFS_CALL_COMPLETE:
92398bf40cdSDavid Howells 			kdebug("prem complete %d", call->error);
924f51375cdSDavid Howells 			return afs_io_error(call, afs_io_error_extract);
925d001648eSDavid Howells 		default:
926d001648eSDavid Howells 			break;
92708e0e7c8SDavid Howells 		}
92808e0e7c8SDavid Howells 		return 0;
92908e0e7c8SDavid Howells 	}
930d001648eSDavid Howells 
93198bf40cdSDavid Howells 	afs_set_call_complete(call, ret, remote_abort);
932d001648eSDavid Howells 	return ret;
933d001648eSDavid Howells }
9345f702c8eSDavid Howells 
9355f702c8eSDavid Howells /*
9365f702c8eSDavid Howells  * Log protocol error production.
9375f702c8eSDavid Howells  */
afs_protocol_error(struct afs_call * call,enum afs_eproto_cause cause)9387126ead9SDavid Howells noinline int afs_protocol_error(struct afs_call *call,
939160cb957SDavid Howells 				enum afs_eproto_cause cause)
9405f702c8eSDavid Howells {
9417126ead9SDavid Howells 	trace_afs_protocol_error(call, cause);
94238355eecSDavid Howells 	if (call)
94338355eecSDavid Howells 		call->unmarshalling_error = true;
9447126ead9SDavid Howells 	return -EBADMSG;
9455f702c8eSDavid Howells }
946