xref: /openbmc/linux/fs/afs/rxrpc.c (revision 060f35a317ef09101b128f399dce7ed13d019461)
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:
399*a5e15707SDavid 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);
403*a5e15707SDavid Howells 	if (call->async) {
404*a5e15707SDavid Howells 		afs_see_call(call, afs_call_trace_async_abort);
405*a5e15707SDavid Howells 		return;
406*a5e15707SDavid Howells 	}
407*a5e15707SDavid Howells 
408*a5e15707SDavid Howells 	if (ret == -ECONNABORTED) {
409f105da1aSDavid Howells 		len = 0;
410de4eda9dSAl Viro 		iov_iter_kvec(&msg.msg_iter, ITER_DEST, NULL, 0, 0);
411eb9950ebSDavid Howells 		rxrpc_kernel_recv_data(call->net->socket, rxcall,
412f105da1aSDavid Howells 				       &msg.msg_iter, &len, false,
413eb9950ebSDavid Howells 				       &call->abort_code, &call->service_id);
414d2ddc776SDavid Howells 		ac->abort_code = call->abort_code;
415d2ddc776SDavid Howells 		ac->responded = true;
41670af0e3bSDavid Howells 	}
417025db80cSDavid Howells 	call->error = ret;
418025db80cSDavid Howells 	trace_afs_call_done(call);
41908e0e7c8SDavid Howells error_kill_call:
420*a5e15707SDavid Howells 	if (call->async)
421*a5e15707SDavid Howells 		afs_see_call(call, afs_call_trace_async_kill);
4223bf0fb6fSDavid Howells 	if (call->type->done)
4233bf0fb6fSDavid Howells 		call->type->done(call);
42434fa4761SDavid Howells 
42534fa4761SDavid Howells 	/* We need to dispose of the extra ref we grabbed for an async call.
42634fa4761SDavid Howells 	 * The call, however, might be queued on afs_async_calls and we need to
42734fa4761SDavid Howells 	 * make sure we don't get any more notifications that might requeue it.
42834fa4761SDavid Howells 	 */
429e0416e7dSDavid Howells 	if (call->rxcall)
430e0416e7dSDavid Howells 		rxrpc_kernel_shutdown_call(call->net->socket, call->rxcall);
43134fa4761SDavid Howells 	if (call->async) {
43234fa4761SDavid Howells 		if (cancel_work_sync(&call->async_work))
433341f741fSDavid Howells 			afs_put_call(call);
4348715fe2fSDavid Howells 		afs_set_call_complete(call, ret, 0);
43534fa4761SDavid Howells 	}
43634fa4761SDavid Howells 
437d2ddc776SDavid Howells 	ac->error = ret;
43834fa4761SDavid Howells 	call->state = AFS_CALL_COMPLETE;
43908e0e7c8SDavid Howells 	_leave(" = %d", ret);
44008e0e7c8SDavid Howells }
44108e0e7c8SDavid Howells 
44208e0e7c8SDavid Howells /*
44305092755SDavid Howells  * Log remote abort codes that indicate that we have a protocol disagreement
44405092755SDavid Howells  * with the server.
44505092755SDavid Howells  */
afs_log_error(struct afs_call * call,s32 remote_abort)44605092755SDavid Howells static void afs_log_error(struct afs_call *call, s32 remote_abort)
44705092755SDavid Howells {
44805092755SDavid Howells 	static int max = 0;
44905092755SDavid Howells 	const char *msg;
45005092755SDavid Howells 	int m;
45105092755SDavid Howells 
45205092755SDavid Howells 	switch (remote_abort) {
45305092755SDavid Howells 	case RX_EOF:		 msg = "unexpected EOF";	break;
45405092755SDavid Howells 	case RXGEN_CC_MARSHAL:	 msg = "client marshalling";	break;
45505092755SDavid Howells 	case RXGEN_CC_UNMARSHAL: msg = "client unmarshalling";	break;
45605092755SDavid Howells 	case RXGEN_SS_MARSHAL:	 msg = "server marshalling";	break;
45705092755SDavid Howells 	case RXGEN_SS_UNMARSHAL: msg = "server unmarshalling";	break;
45805092755SDavid Howells 	case RXGEN_DECODE:	 msg = "opcode decode";		break;
45905092755SDavid Howells 	case RXGEN_SS_XDRFREE:	 msg = "server XDR cleanup";	break;
46005092755SDavid Howells 	case RXGEN_CC_XDRFREE:	 msg = "client XDR cleanup";	break;
46105092755SDavid Howells 	case -32:		 msg = "insufficient data";	break;
46205092755SDavid Howells 	default:
46305092755SDavid Howells 		return;
46405092755SDavid Howells 	}
46505092755SDavid Howells 
46605092755SDavid Howells 	m = max;
46705092755SDavid Howells 	if (m < 3) {
46805092755SDavid Howells 		max = m + 1;
46905092755SDavid Howells 		pr_notice("kAFS: Peer reported %s failure on %s [%pISp]\n",
47005092755SDavid Howells 			  msg, call->type->name,
47105092755SDavid Howells 			  &call->alist->addrs[call->addr_ix].transport);
47205092755SDavid Howells 	}
47305092755SDavid Howells }
47405092755SDavid Howells 
47505092755SDavid Howells /*
47608e0e7c8SDavid Howells  * deliver messages to a call
47708e0e7c8SDavid Howells  */
afs_deliver_to_call(struct afs_call * call)47808e0e7c8SDavid Howells static void afs_deliver_to_call(struct afs_call *call)
47908e0e7c8SDavid Howells {
48098bf40cdSDavid Howells 	enum afs_call_state state;
481f105da1aSDavid Howells 	size_t len;
48298bf40cdSDavid Howells 	u32 abort_code, remote_abort = 0;
48308e0e7c8SDavid Howells 	int ret;
48408e0e7c8SDavid Howells 
485d001648eSDavid Howells 	_enter("%s", call->type->name);
48608e0e7c8SDavid Howells 
48798bf40cdSDavid Howells 	while (state = READ_ONCE(call->state),
48898bf40cdSDavid Howells 	       state == AFS_CALL_CL_AWAIT_REPLY ||
48998bf40cdSDavid Howells 	       state == AFS_CALL_SV_AWAIT_OP_ID ||
49098bf40cdSDavid Howells 	       state == AFS_CALL_SV_AWAIT_REQUEST ||
49198bf40cdSDavid Howells 	       state == AFS_CALL_SV_AWAIT_ACK
492d001648eSDavid Howells 	       ) {
49398bf40cdSDavid Howells 		if (state == AFS_CALL_SV_AWAIT_ACK) {
494f105da1aSDavid Howells 			len = 0;
495de4eda9dSAl Viro 			iov_iter_kvec(&call->def_iter, ITER_DEST, NULL, 0, 0);
496f044c884SDavid Howells 			ret = rxrpc_kernel_recv_data(call->net->socket,
497fc276122SDavid Howells 						     call->rxcall, &call->def_iter,
498f105da1aSDavid Howells 						     &len, false, &remote_abort,
499a68f4a27SDavid Howells 						     &call->service_id);
500fc276122SDavid Howells 			trace_afs_receive_data(call, &call->def_iter, false, ret);
5018e8d7f13SDavid Howells 
502d001648eSDavid Howells 			if (ret == -EINPROGRESS || ret == -EAGAIN)
503d001648eSDavid Howells 				return;
50498bf40cdSDavid Howells 			if (ret < 0 || ret == 1) {
50598bf40cdSDavid Howells 				if (ret == 1)
50698bf40cdSDavid Howells 					ret = 0;
507025db80cSDavid Howells 				goto call_complete;
50898bf40cdSDavid Howells 			}
509d001648eSDavid Howells 			return;
510d001648eSDavid Howells 		}
511d001648eSDavid Howells 
512d001648eSDavid Howells 		ret = call->type->deliver(call);
51398bf40cdSDavid Howells 		state = READ_ONCE(call->state);
51438355eecSDavid Howells 		if (ret == 0 && call->unmarshalling_error)
51538355eecSDavid Howells 			ret = -EBADMSG;
516d001648eSDavid Howells 		switch (ret) {
51708e0e7c8SDavid Howells 		case 0:
5183bf0fb6fSDavid Howells 			afs_queue_call_work(call);
519f2686b09SDavid Howells 			if (state == AFS_CALL_CL_PROC_REPLY) {
52020325960SDavid Howells 				if (call->op)
521f2686b09SDavid Howells 					set_bit(AFS_SERVER_FL_MAY_HAVE_CB,
52220325960SDavid Howells 						&call->op->server->flags);
523025db80cSDavid Howells 				goto call_complete;
524f2686b09SDavid Howells 			}
52598bf40cdSDavid Howells 			ASSERTCMP(state, >, AFS_CALL_CL_PROC_REPLY);
526d001648eSDavid Howells 			goto done;
527d001648eSDavid Howells 		case -EINPROGRESS:
528d001648eSDavid Howells 		case -EAGAIN:
529d001648eSDavid Howells 			goto out;
53070af0e3bSDavid Howells 		case -ECONNABORTED:
53198bf40cdSDavid Howells 			ASSERTCMP(state, ==, AFS_CALL_COMPLETE);
53205092755SDavid Howells 			afs_log_error(call, call->abort_code);
53398bf40cdSDavid Howells 			goto done;
53408e0e7c8SDavid Howells 		case -ENOTSUPP:
5351157f153SDavid Howells 			abort_code = RXGEN_OPCODE;
536f044c884SDavid Howells 			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
53757af281eSDavid Howells 						abort_code, ret,
53857af281eSDavid Howells 						afs_abort_op_not_supported);
53998bf40cdSDavid Howells 			goto local_abort;
5404ac15ea5SDavid Howells 		case -EIO:
5414ac15ea5SDavid Howells 			pr_err("kAFS: Call %u in bad state %u\n",
5424ac15ea5SDavid Howells 			       call->debug_id, state);
543df561f66SGustavo A. R. Silva 			fallthrough;
544d001648eSDavid Howells 		case -ENODATA:
545d001648eSDavid Howells 		case -EBADMSG:
546d001648eSDavid Howells 		case -EMSGSIZE:
547de696c47SDavid Howells 		case -ENOMEM:
548de696c47SDavid Howells 		case -EFAULT:
54908e0e7c8SDavid Howells 			abort_code = RXGEN_CC_UNMARSHAL;
55098bf40cdSDavid Howells 			if (state != AFS_CALL_CL_AWAIT_REPLY)
55108e0e7c8SDavid Howells 				abort_code = RXGEN_SS_UNMARSHAL;
552f044c884SDavid Howells 			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
55357af281eSDavid Howells 						abort_code, ret,
55457af281eSDavid Howells 						afs_abort_unmarshal_error);
55598bf40cdSDavid Howells 			goto local_abort;
5568022c4b9SDavid Howells 		default:
557de696c47SDavid Howells 			abort_code = RX_CALL_DEAD;
5588022c4b9SDavid Howells 			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
55957af281eSDavid Howells 						abort_code, ret,
56057af281eSDavid Howells 						afs_abort_general_error);
5618022c4b9SDavid Howells 			goto local_abort;
56208e0e7c8SDavid Howells 		}
56308e0e7c8SDavid Howells 	}
56408e0e7c8SDavid Howells 
565d001648eSDavid Howells done:
5663bf0fb6fSDavid Howells 	if (call->type->done)
5673bf0fb6fSDavid Howells 		call->type->done(call);
568d001648eSDavid Howells out:
56908e0e7c8SDavid Howells 	_leave("");
570d001648eSDavid Howells 	return;
571d001648eSDavid Howells 
57298bf40cdSDavid Howells local_abort:
57398bf40cdSDavid Howells 	abort_code = 0;
574025db80cSDavid Howells call_complete:
57598bf40cdSDavid Howells 	afs_set_call_complete(call, ret, remote_abort);
576d001648eSDavid Howells 	goto done;
57708e0e7c8SDavid Howells }
57808e0e7c8SDavid Howells 
57908e0e7c8SDavid Howells /*
5800b9bf381SDavid Howells  * Wait synchronously for a call to complete and clean up the call struct.
58108e0e7c8SDavid Howells  */
afs_wait_for_call_to_complete(struct afs_call * call,struct afs_addr_cursor * ac)5820b9bf381SDavid Howells long afs_wait_for_call_to_complete(struct afs_call *call,
583d2ddc776SDavid Howells 				   struct afs_addr_cursor *ac)
58408e0e7c8SDavid Howells {
58533cd7f2bSDavid Howells 	long ret;
586f7f1dd31SMarc Dionne 	bool rxrpc_complete = false;
58708e0e7c8SDavid Howells 
58808e0e7c8SDavid Howells 	DECLARE_WAITQUEUE(myself, current);
58908e0e7c8SDavid Howells 
59008e0e7c8SDavid Howells 	_enter("");
59108e0e7c8SDavid Howells 
5920b9bf381SDavid Howells 	ret = call->error;
5930b9bf381SDavid Howells 	if (ret < 0)
5940b9bf381SDavid Howells 		goto out;
5950b9bf381SDavid Howells 
59608e0e7c8SDavid Howells 	add_wait_queue(&call->waitq, &myself);
59708e0e7c8SDavid Howells 	for (;;) {
598bc5e3a54SDavid Howells 		set_current_state(TASK_UNINTERRUPTIBLE);
59908e0e7c8SDavid Howells 
60008e0e7c8SDavid Howells 		/* deliver any messages that are in the queue */
60198bf40cdSDavid Howells 		if (!afs_check_call_state(call, AFS_CALL_COMPLETE) &&
60298bf40cdSDavid Howells 		    call->need_attention) {
603d001648eSDavid Howells 			call->need_attention = false;
60408e0e7c8SDavid Howells 			__set_current_state(TASK_RUNNING);
60508e0e7c8SDavid Howells 			afs_deliver_to_call(call);
60608e0e7c8SDavid Howells 			continue;
60708e0e7c8SDavid Howells 		}
60808e0e7c8SDavid Howells 
60998bf40cdSDavid Howells 		if (afs_check_call_state(call, AFS_CALL_COMPLETE))
61008e0e7c8SDavid Howells 			break;
611bc5e3a54SDavid Howells 
6127d7587dbSDavid Howells 		if (!rxrpc_kernel_check_life(call->net->socket, call->rxcall)) {
613f7f1dd31SMarc Dionne 			/* rxrpc terminated the call. */
614f7f1dd31SMarc Dionne 			rxrpc_complete = true;
615f7f1dd31SMarc Dionne 			break;
616f7f1dd31SMarc Dionne 		}
617f7f1dd31SMarc Dionne 
6187d7587dbSDavid Howells 		schedule();
61908e0e7c8SDavid Howells 	}
62008e0e7c8SDavid Howells 
62108e0e7c8SDavid Howells 	remove_wait_queue(&call->waitq, &myself);
62208e0e7c8SDavid Howells 	__set_current_state(TASK_RUNNING);
62308e0e7c8SDavid Howells 
62498bf40cdSDavid Howells 	if (!afs_check_call_state(call, AFS_CALL_COMPLETE)) {
625f7f1dd31SMarc Dionne 		if (rxrpc_complete) {
626f7f1dd31SMarc Dionne 			afs_set_call_complete(call, call->error, call->abort_code);
627f7f1dd31SMarc Dionne 		} else {
628f7f1dd31SMarc Dionne 			/* Kill off the call if it's still live. */
629954cd6dcSDavid Howells 			_debug("call interrupted");
630d2ddc776SDavid Howells 			if (rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
63157af281eSDavid Howells 						    RX_USER_ABORT, -EINTR,
63257af281eSDavid Howells 						    afs_abort_interrupted))
63398bf40cdSDavid Howells 				afs_set_call_complete(call, -EINTR, 0);
63408e0e7c8SDavid Howells 		}
635f7f1dd31SMarc Dionne 	}
63608e0e7c8SDavid Howells 
63798bf40cdSDavid Howells 	spin_lock_bh(&call->state_lock);
638d2ddc776SDavid Howells 	ac->abort_code = call->abort_code;
639d2ddc776SDavid Howells 	ac->error = call->error;
64098bf40cdSDavid Howells 	spin_unlock_bh(&call->state_lock);
641d2ddc776SDavid Howells 
642d2ddc776SDavid Howells 	ret = ac->error;
643d2ddc776SDavid Howells 	switch (ret) {
644d2ddc776SDavid Howells 	case 0:
645ffba718eSDavid Howells 		ret = call->ret0;
646ffba718eSDavid Howells 		call->ret0 = 0;
647ffba718eSDavid Howells 
648df561f66SGustavo A. R. Silva 		fallthrough;
649d2ddc776SDavid Howells 	case -ECONNABORTED:
650d2ddc776SDavid Howells 		ac->responded = true;
651d2ddc776SDavid Howells 		break;
652d2ddc776SDavid Howells 	}
65333cd7f2bSDavid Howells 
6540b9bf381SDavid Howells out:
65508e0e7c8SDavid Howells 	_debug("call complete");
656341f741fSDavid Howells 	afs_put_call(call);
65733cd7f2bSDavid Howells 	_leave(" = %p", (void *)ret);
65808e0e7c8SDavid Howells 	return ret;
65908e0e7c8SDavid Howells }
66008e0e7c8SDavid Howells 
66108e0e7c8SDavid Howells /*
66208e0e7c8SDavid Howells  * wake up a waiting call
66308e0e7c8SDavid Howells  */
afs_wake_up_call_waiter(struct sock * sk,struct rxrpc_call * rxcall,unsigned long call_user_ID)664d001648eSDavid Howells static void afs_wake_up_call_waiter(struct sock *sk, struct rxrpc_call *rxcall,
665d001648eSDavid Howells 				    unsigned long call_user_ID)
66608e0e7c8SDavid Howells {
667d001648eSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
668d001648eSDavid Howells 
669d001648eSDavid Howells 	call->need_attention = true;
67008e0e7c8SDavid Howells 	wake_up(&call->waitq);
67108e0e7c8SDavid Howells }
67208e0e7c8SDavid Howells 
67308e0e7c8SDavid Howells /*
67408e0e7c8SDavid Howells  * wake up an asynchronous call
67508e0e7c8SDavid Howells  */
afs_wake_up_async_call(struct sock * sk,struct rxrpc_call * rxcall,unsigned long call_user_ID)676d001648eSDavid Howells static void afs_wake_up_async_call(struct sock *sk, struct rxrpc_call *rxcall,
677d001648eSDavid Howells 				   unsigned long call_user_ID)
67808e0e7c8SDavid Howells {
679d001648eSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
680c56f9ec8SDavid Howells 	int r;
681d001648eSDavid Howells 
6828e8d7f13SDavid Howells 	trace_afs_notify_call(rxcall, call);
683d001648eSDavid Howells 	call->need_attention = true;
684341f741fSDavid Howells 
685c56f9ec8SDavid Howells 	if (__refcount_inc_not_zero(&call->ref, &r)) {
6862757a4dcSDavid Howells 		trace_afs_call(call->debug_id, afs_call_trace_wake, r + 1,
687f044c884SDavid Howells 			       atomic_read(&call->net->nr_outstanding_calls),
688341f741fSDavid Howells 			       __builtin_return_address(0));
689341f741fSDavid Howells 
690341f741fSDavid Howells 		if (!queue_work(afs_async_calls, &call->async_work))
691341f741fSDavid Howells 			afs_put_call(call);
692341f741fSDavid Howells 	}
69308e0e7c8SDavid Howells }
69408e0e7c8SDavid Howells 
69508e0e7c8SDavid Howells /*
696341f741fSDavid Howells  * Perform I/O processing on an asynchronous call.  The work item carries a ref
697341f741fSDavid Howells  * to the call struct that we either need to release or to pass on.
69808e0e7c8SDavid Howells  */
afs_process_async_call(struct work_struct * work)699d001648eSDavid Howells static void afs_process_async_call(struct work_struct *work)
70008e0e7c8SDavid Howells {
701d001648eSDavid Howells 	struct afs_call *call = container_of(work, struct afs_call, async_work);
702d001648eSDavid Howells 
70308e0e7c8SDavid Howells 	_enter("");
70408e0e7c8SDavid Howells 
705d001648eSDavid Howells 	if (call->state < AFS_CALL_COMPLETE && call->need_attention) {
706d001648eSDavid Howells 		call->need_attention = false;
70708e0e7c8SDavid Howells 		afs_deliver_to_call(call);
708d001648eSDavid Howells 	}
70908e0e7c8SDavid Howells 
710341f741fSDavid Howells 	afs_put_call(call);
71108e0e7c8SDavid Howells 	_leave("");
71208e0e7c8SDavid Howells }
71308e0e7c8SDavid Howells 
afs_rx_attach(struct rxrpc_call * rxcall,unsigned long user_call_ID)71400e90712SDavid Howells static void afs_rx_attach(struct rxrpc_call *rxcall, unsigned long user_call_ID)
71500e90712SDavid Howells {
71600e90712SDavid Howells 	struct afs_call *call = (struct afs_call *)user_call_ID;
71700e90712SDavid Howells 
71800e90712SDavid Howells 	call->rxcall = rxcall;
71900e90712SDavid Howells }
72000e90712SDavid Howells 
72100e90712SDavid Howells /*
72200e90712SDavid Howells  * Charge the incoming call preallocation.
72300e90712SDavid Howells  */
afs_charge_preallocation(struct work_struct * work)724f044c884SDavid Howells void afs_charge_preallocation(struct work_struct *work)
72500e90712SDavid Howells {
726f044c884SDavid Howells 	struct afs_net *net =
727f044c884SDavid Howells 		container_of(work, struct afs_net, charge_preallocation_work);
728f044c884SDavid Howells 	struct afs_call *call = net->spare_incoming_call;
72900e90712SDavid Howells 
73000e90712SDavid Howells 	for (;;) {
73100e90712SDavid Howells 		if (!call) {
732f044c884SDavid Howells 			call = afs_alloc_call(net, &afs_RXCMxxxx, GFP_KERNEL);
73300e90712SDavid Howells 			if (!call)
73400e90712SDavid Howells 				break;
73500e90712SDavid Howells 
736dde9f095SDavid Howells 			call->drop_ref = true;
73756ff9c83SDavid Howells 			call->async = true;
73898bf40cdSDavid Howells 			call->state = AFS_CALL_SV_AWAIT_OP_ID;
73956ff9c83SDavid Howells 			init_waitqueue_head(&call->waitq);
74012bdcf33SDavid Howells 			afs_extract_to_tmp(call);
74100e90712SDavid Howells 		}
74200e90712SDavid Howells 
743f044c884SDavid Howells 		if (rxrpc_kernel_charge_accept(net->socket,
74400e90712SDavid Howells 					       afs_wake_up_async_call,
74500e90712SDavid Howells 					       afs_rx_attach,
74600e90712SDavid Howells 					       (unsigned long)call,
747a25e21f0SDavid Howells 					       GFP_KERNEL,
748a25e21f0SDavid Howells 					       call->debug_id) < 0)
74900e90712SDavid Howells 			break;
75000e90712SDavid Howells 		call = NULL;
75100e90712SDavid Howells 	}
752f044c884SDavid Howells 	net->spare_incoming_call = call;
75300e90712SDavid Howells }
75400e90712SDavid Howells 
75500e90712SDavid Howells /*
75600e90712SDavid Howells  * Discard a preallocated call when a socket is shut down.
75700e90712SDavid Howells  */
afs_rx_discard_new_call(struct rxrpc_call * rxcall,unsigned long user_call_ID)75800e90712SDavid Howells static void afs_rx_discard_new_call(struct rxrpc_call *rxcall,
75900e90712SDavid Howells 				    unsigned long user_call_ID)
76000e90712SDavid Howells {
76100e90712SDavid Howells 	struct afs_call *call = (struct afs_call *)user_call_ID;
76200e90712SDavid Howells 
76300e90712SDavid Howells 	call->rxcall = NULL;
764341f741fSDavid Howells 	afs_put_call(call);
76500e90712SDavid Howells }
76600e90712SDavid Howells 
76708e0e7c8SDavid Howells /*
768d001648eSDavid Howells  * Notification of an incoming call.
769d001648eSDavid Howells  */
afs_rx_new_call(struct sock * sk,struct rxrpc_call * rxcall,unsigned long user_call_ID)77000e90712SDavid Howells static void afs_rx_new_call(struct sock *sk, struct rxrpc_call *rxcall,
77100e90712SDavid Howells 			    unsigned long user_call_ID)
772d001648eSDavid Howells {
773f044c884SDavid Howells 	struct afs_net *net = afs_sock2net(sk);
774f044c884SDavid Howells 
775f044c884SDavid Howells 	queue_work(afs_wq, &net->charge_preallocation_work);
776d001648eSDavid Howells }
777d001648eSDavid Howells 
778d001648eSDavid Howells /*
779372ee163SDavid Howells  * Grab the operation ID from an incoming cache manager call.  The socket
780372ee163SDavid Howells  * buffer is discarded on error or if we don't yet have sufficient data.
78108e0e7c8SDavid Howells  */
afs_deliver_cm_op_id(struct afs_call * call)782d001648eSDavid Howells static int afs_deliver_cm_op_id(struct afs_call *call)
78308e0e7c8SDavid Howells {
784d001648eSDavid Howells 	int ret;
78508e0e7c8SDavid Howells 
786fc276122SDavid Howells 	_enter("{%zu}", iov_iter_count(call->iter));
78708e0e7c8SDavid Howells 
78808e0e7c8SDavid Howells 	/* the operation ID forms the first four bytes of the request data */
78912bdcf33SDavid Howells 	ret = afs_extract_data(call, true);
790d001648eSDavid Howells 	if (ret < 0)
791d001648eSDavid Howells 		return ret;
79208e0e7c8SDavid Howells 
79350a2c953SDavid Howells 	call->operation_ID = ntohl(call->tmp);
79498bf40cdSDavid Howells 	afs_set_call_state(call, AFS_CALL_SV_AWAIT_OP_ID, AFS_CALL_SV_AWAIT_REQUEST);
79508e0e7c8SDavid Howells 
79608e0e7c8SDavid Howells 	/* ask the cache manager to route the call (it'll change the call type
79708e0e7c8SDavid Howells 	 * if successful) */
79808e0e7c8SDavid Howells 	if (!afs_cm_incoming_call(call))
79908e0e7c8SDavid Howells 		return -ENOTSUPP;
80008e0e7c8SDavid Howells 
8018e8d7f13SDavid Howells 	trace_afs_cb_call(call);
8028e8d7f13SDavid Howells 
80308e0e7c8SDavid Howells 	/* pass responsibility for the remainer of this message off to the
80408e0e7c8SDavid Howells 	 * cache manager op */
805d001648eSDavid Howells 	return call->type->deliver(call);
80608e0e7c8SDavid Howells }
80708e0e7c8SDavid Howells 
80808e0e7c8SDavid Howells /*
809e833251aSDavid Howells  * Advance the AFS call state when an RxRPC service call ends the transmit
810e833251aSDavid Howells  * phase.
811e833251aSDavid Howells  */
afs_notify_end_reply_tx(struct sock * sock,struct rxrpc_call * rxcall,unsigned long call_user_ID)812e833251aSDavid Howells static void afs_notify_end_reply_tx(struct sock *sock,
813e833251aSDavid Howells 				    struct rxrpc_call *rxcall,
814e833251aSDavid Howells 				    unsigned long call_user_ID)
815e833251aSDavid Howells {
816e833251aSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
817e833251aSDavid Howells 
81898bf40cdSDavid Howells 	afs_set_call_state(call, AFS_CALL_SV_REPLYING, AFS_CALL_SV_AWAIT_ACK);
819e833251aSDavid Howells }
820e833251aSDavid Howells 
821e833251aSDavid Howells /*
82208e0e7c8SDavid Howells  * send an empty reply
82308e0e7c8SDavid Howells  */
afs_send_empty_reply(struct afs_call * call)82408e0e7c8SDavid Howells void afs_send_empty_reply(struct afs_call *call)
82508e0e7c8SDavid Howells {
826f044c884SDavid Howells 	struct afs_net *net = call->net;
82708e0e7c8SDavid Howells 	struct msghdr msg;
82808e0e7c8SDavid Howells 
82908e0e7c8SDavid Howells 	_enter("");
83008e0e7c8SDavid Howells 
831f044c884SDavid Howells 	rxrpc_kernel_set_tx_length(net->socket, call->rxcall, 0);
832e754eba6SDavid Howells 
83308e0e7c8SDavid Howells 	msg.msg_name		= NULL;
83408e0e7c8SDavid Howells 	msg.msg_namelen		= 0;
835de4eda9dSAl Viro 	iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, NULL, 0, 0);
83608e0e7c8SDavid Howells 	msg.msg_control		= NULL;
83708e0e7c8SDavid Howells 	msg.msg_controllen	= 0;
83808e0e7c8SDavid Howells 	msg.msg_flags		= 0;
83908e0e7c8SDavid Howells 
840f044c884SDavid Howells 	switch (rxrpc_kernel_send_data(net->socket, call->rxcall, &msg, 0,
841e833251aSDavid Howells 				       afs_notify_end_reply_tx)) {
84208e0e7c8SDavid Howells 	case 0:
84308e0e7c8SDavid Howells 		_leave(" [replied]");
84408e0e7c8SDavid Howells 		return;
84508e0e7c8SDavid Howells 
84608e0e7c8SDavid Howells 	case -ENOMEM:
84708e0e7c8SDavid Howells 		_debug("oom");
848f044c884SDavid Howells 		rxrpc_kernel_abort_call(net->socket, call->rxcall,
84957af281eSDavid Howells 					RXGEN_SS_MARSHAL, -ENOMEM,
85057af281eSDavid Howells 					afs_abort_oom);
851df561f66SGustavo A. R. Silva 		fallthrough;
85208e0e7c8SDavid Howells 	default:
85308e0e7c8SDavid Howells 		_leave(" [error]");
85408e0e7c8SDavid Howells 		return;
85508e0e7c8SDavid Howells 	}
85608e0e7c8SDavid Howells }
85708e0e7c8SDavid Howells 
85808e0e7c8SDavid Howells /*
859b908fe6bSDavid Howells  * send a simple reply
860b908fe6bSDavid Howells  */
afs_send_simple_reply(struct afs_call * call,const void * buf,size_t len)861b908fe6bSDavid Howells void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
862b908fe6bSDavid Howells {
863f044c884SDavid Howells 	struct afs_net *net = call->net;
864b908fe6bSDavid Howells 	struct msghdr msg;
8652e90b1c4SAl Viro 	struct kvec iov[1];
866bd6dc742SDavid Howells 	int n;
867b908fe6bSDavid Howells 
868b908fe6bSDavid Howells 	_enter("");
869b908fe6bSDavid Howells 
870f044c884SDavid Howells 	rxrpc_kernel_set_tx_length(net->socket, call->rxcall, len);
871e754eba6SDavid Howells 
872b908fe6bSDavid Howells 	iov[0].iov_base		= (void *) buf;
873b908fe6bSDavid Howells 	iov[0].iov_len		= len;
874b908fe6bSDavid Howells 	msg.msg_name		= NULL;
875b908fe6bSDavid Howells 	msg.msg_namelen		= 0;
876de4eda9dSAl Viro 	iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, iov, 1, len);
877b908fe6bSDavid Howells 	msg.msg_control		= NULL;
878b908fe6bSDavid Howells 	msg.msg_controllen	= 0;
879b908fe6bSDavid Howells 	msg.msg_flags		= 0;
880b908fe6bSDavid Howells 
881f044c884SDavid Howells 	n = rxrpc_kernel_send_data(net->socket, call->rxcall, &msg, len,
882e833251aSDavid Howells 				   afs_notify_end_reply_tx);
883bd6dc742SDavid Howells 	if (n >= 0) {
8846c67c7c3SDavid Howells 		/* Success */
885b908fe6bSDavid Howells 		_leave(" [replied]");
886b908fe6bSDavid Howells 		return;
887bd6dc742SDavid Howells 	}
8886c67c7c3SDavid Howells 
889bd6dc742SDavid Howells 	if (n == -ENOMEM) {
890b908fe6bSDavid Howells 		_debug("oom");
891f044c884SDavid Howells 		rxrpc_kernel_abort_call(net->socket, call->rxcall,
89257af281eSDavid Howells 					RXGEN_SS_MARSHAL, -ENOMEM,
89357af281eSDavid Howells 					afs_abort_oom);
894bd6dc742SDavid Howells 	}
895b908fe6bSDavid Howells 	_leave(" [error]");
896b908fe6bSDavid Howells }
897b908fe6bSDavid Howells 
898b908fe6bSDavid Howells /*
899372ee163SDavid Howells  * Extract a piece of data from the received data socket buffers.
90008e0e7c8SDavid Howells  */
afs_extract_data(struct afs_call * call,bool want_more)90112bdcf33SDavid Howells int afs_extract_data(struct afs_call *call, bool want_more)
90208e0e7c8SDavid Howells {
903f044c884SDavid Howells 	struct afs_net *net = call->net;
904fc276122SDavid Howells 	struct iov_iter *iter = call->iter;
90598bf40cdSDavid Howells 	enum afs_call_state state;
9067888da95SDan Carpenter 	u32 remote_abort = 0;
907d001648eSDavid Howells 	int ret;
90808e0e7c8SDavid Howells 
909f105da1aSDavid Howells 	_enter("{%s,%zu,%zu},%d",
910f105da1aSDavid Howells 	       call->type->name, call->iov_len, iov_iter_count(iter), want_more);
91108e0e7c8SDavid Howells 
91212bdcf33SDavid Howells 	ret = rxrpc_kernel_recv_data(net->socket, call->rxcall, iter,
913f105da1aSDavid Howells 				     &call->iov_len, want_more, &remote_abort,
914a68f4a27SDavid Howells 				     &call->service_id);
91593368b6bSDavid Howells 	trace_afs_receive_data(call, call->iter, want_more, ret);
916d001648eSDavid Howells 	if (ret == 0 || ret == -EAGAIN)
917d001648eSDavid Howells 		return ret;
91808e0e7c8SDavid Howells 
91998bf40cdSDavid Howells 	state = READ_ONCE(call->state);
920d001648eSDavid Howells 	if (ret == 1) {
92198bf40cdSDavid Howells 		switch (state) {
92298bf40cdSDavid Howells 		case AFS_CALL_CL_AWAIT_REPLY:
92398bf40cdSDavid Howells 			afs_set_call_state(call, state, AFS_CALL_CL_PROC_REPLY);
924d001648eSDavid Howells 			break;
92598bf40cdSDavid Howells 		case AFS_CALL_SV_AWAIT_REQUEST:
92698bf40cdSDavid Howells 			afs_set_call_state(call, state, AFS_CALL_SV_REPLYING);
927d001648eSDavid Howells 			break;
92898bf40cdSDavid Howells 		case AFS_CALL_COMPLETE:
92998bf40cdSDavid Howells 			kdebug("prem complete %d", call->error);
930f51375cdSDavid Howells 			return afs_io_error(call, afs_io_error_extract);
931d001648eSDavid Howells 		default:
932d001648eSDavid Howells 			break;
93308e0e7c8SDavid Howells 		}
93408e0e7c8SDavid Howells 		return 0;
93508e0e7c8SDavid Howells 	}
936d001648eSDavid Howells 
93798bf40cdSDavid Howells 	afs_set_call_complete(call, ret, remote_abort);
938d001648eSDavid Howells 	return ret;
939d001648eSDavid Howells }
9405f702c8eSDavid Howells 
9415f702c8eSDavid Howells /*
9425f702c8eSDavid Howells  * Log protocol error production.
9435f702c8eSDavid Howells  */
afs_protocol_error(struct afs_call * call,enum afs_eproto_cause cause)9447126ead9SDavid Howells noinline int afs_protocol_error(struct afs_call *call,
945160cb957SDavid Howells 				enum afs_eproto_cause cause)
9465f702c8eSDavid Howells {
9477126ead9SDavid Howells 	trace_afs_protocol_error(call, cause);
94838355eecSDavid Howells 	if (call)
94938355eecSDavid Howells 		call->unmarshalling_error = true;
9507126ead9SDavid Howells 	return -EBADMSG;
9515f702c8eSDavid Howells }
952