xref: /openbmc/linux/fs/afs/rxrpc.c (revision fc276122)
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"
1608e0e7c8SDavid Howells 
17f044c884SDavid Howells struct workqueue_struct *afs_async_calls;
1808e0e7c8SDavid Howells 
19d001648eSDavid Howells static void afs_wake_up_call_waiter(struct sock *, struct rxrpc_call *, unsigned long);
20d001648eSDavid Howells static void afs_wake_up_async_call(struct sock *, struct rxrpc_call *, unsigned long);
2134fa4761SDavid Howells static void afs_delete_async_call(struct work_struct *);
22d001648eSDavid Howells static void afs_process_async_call(struct work_struct *);
2300e90712SDavid Howells static void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned long);
2400e90712SDavid Howells static void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long);
25d001648eSDavid Howells static int afs_deliver_cm_op_id(struct afs_call *);
2608e0e7c8SDavid Howells 
2708e0e7c8SDavid Howells /* asynchronous incoming call initial processing */
2808e0e7c8SDavid Howells static const struct afs_call_type afs_RXCMxxxx = {
2900d3b7a4SDavid Howells 	.name		= "CB.xxxx",
3008e0e7c8SDavid Howells 	.deliver	= afs_deliver_cm_op_id,
3108e0e7c8SDavid Howells };
3208e0e7c8SDavid Howells 
3308e0e7c8SDavid Howells /*
3408e0e7c8SDavid Howells  * open an RxRPC socket and bind it to be a server for callback notifications
3508e0e7c8SDavid Howells  * - the socket is left in blocking mode and non-blocking ops use MSG_DONTWAIT
3608e0e7c8SDavid Howells  */
37f044c884SDavid Howells int afs_open_socket(struct afs_net *net)
3808e0e7c8SDavid Howells {
3908e0e7c8SDavid Howells 	struct sockaddr_rxrpc srx;
4008e0e7c8SDavid Howells 	struct socket *socket;
414776cab4SDavid Howells 	unsigned int min_level;
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 
614776cab4SDavid Howells 	min_level = RXRPC_SECURITY_ENCRYPT;
624776cab4SDavid Howells 	ret = kernel_setsockopt(socket, SOL_RXRPC, RXRPC_MIN_SECURITY_LEVEL,
634776cab4SDavid Howells 				(void *)&min_level, sizeof(min_level));
644776cab4SDavid Howells 	if (ret < 0)
654776cab4SDavid Howells 		goto error_2;
664776cab4SDavid Howells 
6708e0e7c8SDavid Howells 	ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
6883732ec5SMarc Dionne 	if (ret == -EADDRINUSE) {
6983732ec5SMarc Dionne 		srx.transport.sin6.sin6_port = 0;
7083732ec5SMarc Dionne 		ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
7183732ec5SMarc Dionne 	}
720e119b41SDavid Howells 	if (ret < 0)
730e119b41SDavid Howells 		goto error_2;
740e119b41SDavid Howells 
7535dbfba3SDavid Howells 	srx.srx_service = YFS_CM_SERVICE;
7635dbfba3SDavid Howells 	ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
7735dbfba3SDavid Howells 	if (ret < 0)
7835dbfba3SDavid Howells 		goto error_2;
7935dbfba3SDavid Howells 
803bf0fb6fSDavid Howells 	/* Ideally, we'd turn on service upgrade here, but we can't because
813bf0fb6fSDavid Howells 	 * OpenAFS is buggy and leaks the userStatus field from packet to
823bf0fb6fSDavid Howells 	 * packet and between FS packets and CB packets - so if we try to do an
833bf0fb6fSDavid Howells 	 * upgrade on an FS packet, OpenAFS will leak that into the CB packet
843bf0fb6fSDavid Howells 	 * it sends back to us.
853bf0fb6fSDavid Howells 	 */
8635dbfba3SDavid Howells 
8700e90712SDavid Howells 	rxrpc_kernel_new_call_notification(socket, afs_rx_new_call,
8800e90712SDavid Howells 					   afs_rx_discard_new_call);
89d001648eSDavid Howells 
900e119b41SDavid Howells 	ret = kernel_listen(socket, INT_MAX);
910e119b41SDavid Howells 	if (ret < 0)
920e119b41SDavid Howells 		goto error_2;
9308e0e7c8SDavid Howells 
94f044c884SDavid Howells 	net->socket = socket;
95f044c884SDavid Howells 	afs_charge_preallocation(&net->charge_preallocation_work);
9608e0e7c8SDavid Howells 	_leave(" = 0");
9708e0e7c8SDavid Howells 	return 0;
980e119b41SDavid Howells 
990e119b41SDavid Howells error_2:
1000e119b41SDavid Howells 	sock_release(socket);
1010e119b41SDavid Howells error_1:
1020e119b41SDavid Howells 	_leave(" = %d", ret);
1030e119b41SDavid Howells 	return ret;
10408e0e7c8SDavid Howells }
10508e0e7c8SDavid Howells 
10608e0e7c8SDavid Howells /*
10708e0e7c8SDavid Howells  * close the RxRPC socket AFS was using
10808e0e7c8SDavid Howells  */
109f044c884SDavid Howells void afs_close_socket(struct afs_net *net)
11008e0e7c8SDavid Howells {
11108e0e7c8SDavid Howells 	_enter("");
11208e0e7c8SDavid Howells 
113f044c884SDavid Howells 	kernel_listen(net->socket, 0);
114341f741fSDavid Howells 	flush_workqueue(afs_async_calls);
115341f741fSDavid Howells 
116f044c884SDavid Howells 	if (net->spare_incoming_call) {
117f044c884SDavid Howells 		afs_put_call(net->spare_incoming_call);
118f044c884SDavid Howells 		net->spare_incoming_call = NULL;
11900e90712SDavid Howells 	}
12000e90712SDavid Howells 
121f044c884SDavid Howells 	_debug("outstanding %u", atomic_read(&net->nr_outstanding_calls));
122ab1fbe32SPeter Zijlstra 	wait_var_event(&net->nr_outstanding_calls,
123ab1fbe32SPeter Zijlstra 		       !atomic_read(&net->nr_outstanding_calls));
1242f02f7aeSDavid Howells 	_debug("no outstanding calls");
1252f02f7aeSDavid Howells 
126f044c884SDavid Howells 	kernel_sock_shutdown(net->socket, SHUT_RDWR);
127248f219cSDavid Howells 	flush_workqueue(afs_async_calls);
128f044c884SDavid Howells 	sock_release(net->socket);
12908e0e7c8SDavid Howells 
13008e0e7c8SDavid Howells 	_debug("dework");
13108e0e7c8SDavid Howells 	_leave("");
13208e0e7c8SDavid Howells }
13308e0e7c8SDavid Howells 
13408e0e7c8SDavid Howells /*
135341f741fSDavid Howells  * Allocate a call.
13600d3b7a4SDavid Howells  */
137f044c884SDavid Howells static struct afs_call *afs_alloc_call(struct afs_net *net,
138f044c884SDavid Howells 				       const struct afs_call_type *type,
139341f741fSDavid Howells 				       gfp_t gfp)
14000d3b7a4SDavid Howells {
141341f741fSDavid Howells 	struct afs_call *call;
142341f741fSDavid Howells 	int o;
14300d3b7a4SDavid Howells 
144341f741fSDavid Howells 	call = kzalloc(sizeof(*call), gfp);
145341f741fSDavid Howells 	if (!call)
146341f741fSDavid Howells 		return NULL;
14700d3b7a4SDavid Howells 
148341f741fSDavid Howells 	call->type = type;
149f044c884SDavid Howells 	call->net = net;
150a25e21f0SDavid Howells 	call->debug_id = atomic_inc_return(&rxrpc_debug_id);
151341f741fSDavid Howells 	atomic_set(&call->usage, 1);
152341f741fSDavid Howells 	INIT_WORK(&call->async_work, afs_process_async_call);
153341f741fSDavid Howells 	init_waitqueue_head(&call->waitq);
15498bf40cdSDavid Howells 	spin_lock_init(&call->state_lock);
155fc276122SDavid Howells 	call->iter = &call->def_iter;
1562f02f7aeSDavid Howells 
157f044c884SDavid Howells 	o = atomic_inc_return(&net->nr_outstanding_calls);
158341f741fSDavid Howells 	trace_afs_call(call, afs_call_trace_alloc, 1, o,
159341f741fSDavid Howells 		       __builtin_return_address(0));
160341f741fSDavid Howells 	return call;
16100d3b7a4SDavid Howells }
16200d3b7a4SDavid Howells 
16300d3b7a4SDavid Howells /*
164341f741fSDavid Howells  * Dispose of a reference on a call.
1656c67c7c3SDavid Howells  */
166341f741fSDavid Howells void afs_put_call(struct afs_call *call)
1676c67c7c3SDavid Howells {
168f044c884SDavid Howells 	struct afs_net *net = call->net;
169341f741fSDavid Howells 	int n = atomic_dec_return(&call->usage);
170f044c884SDavid Howells 	int o = atomic_read(&net->nr_outstanding_calls);
171341f741fSDavid Howells 
172341f741fSDavid Howells 	trace_afs_call(call, afs_call_trace_put, n + 1, o,
173341f741fSDavid Howells 		       __builtin_return_address(0));
174341f741fSDavid Howells 
175341f741fSDavid Howells 	ASSERTCMP(n, >=, 0);
176341f741fSDavid Howells 	if (n == 0) {
177341f741fSDavid Howells 		ASSERT(!work_pending(&call->async_work));
178341f741fSDavid Howells 		ASSERT(call->type->name != NULL);
179341f741fSDavid Howells 
1806c67c7c3SDavid Howells 		if (call->rxcall) {
181f044c884SDavid Howells 			rxrpc_kernel_end_call(net->socket, call->rxcall);
1826c67c7c3SDavid Howells 			call->rxcall = NULL;
1836c67c7c3SDavid Howells 		}
1846cf12869SNathaniel Wesley Filardo 		if (call->type->destructor)
1856c67c7c3SDavid Howells 			call->type->destructor(call);
186341f741fSDavid Howells 
18745218193SDavid Howells 		afs_put_server(call->net, call->server, afs_server_trace_put_call);
188d2ddc776SDavid Howells 		afs_put_cb_interest(call->net, call->cbi);
1893bf0fb6fSDavid Howells 		afs_put_addrlist(call->alist);
190341f741fSDavid Howells 		kfree(call->request);
191a25e21f0SDavid Howells 
192a25e21f0SDavid Howells 		trace_afs_call(call, afs_call_trace_free, 0, o,
193a25e21f0SDavid Howells 			       __builtin_return_address(0));
194341f741fSDavid Howells 		kfree(call);
195341f741fSDavid Howells 
196f044c884SDavid Howells 		o = atomic_dec_return(&net->nr_outstanding_calls);
197341f741fSDavid Howells 		if (o == 0)
198ab1fbe32SPeter Zijlstra 			wake_up_var(&net->nr_outstanding_calls);
199341f741fSDavid Howells 	}
2006cf12869SNathaniel Wesley Filardo }
2016cf12869SNathaniel Wesley Filardo 
2027a75b007SDavid Howells static struct afs_call *afs_get_call(struct afs_call *call,
2037a75b007SDavid Howells 				     enum afs_call_trace why)
2047a75b007SDavid Howells {
2057a75b007SDavid Howells 	int u = atomic_inc_return(&call->usage);
2067a75b007SDavid Howells 
2077a75b007SDavid Howells 	trace_afs_call(call, why, u,
2087a75b007SDavid Howells 		       atomic_read(&call->net->nr_outstanding_calls),
2097a75b007SDavid Howells 		       __builtin_return_address(0));
2107a75b007SDavid Howells 	return call;
2117a75b007SDavid Howells }
2127a75b007SDavid Howells 
2136cf12869SNathaniel Wesley Filardo /*
2143bf0fb6fSDavid Howells  * Queue the call for actual work.
2156cf12869SNathaniel Wesley Filardo  */
2163bf0fb6fSDavid Howells static void afs_queue_call_work(struct afs_call *call)
2176cf12869SNathaniel Wesley Filardo {
2183bf0fb6fSDavid Howells 	if (call->type->work) {
219341f741fSDavid Howells 		INIT_WORK(&call->work, call->type->work);
220341f741fSDavid Howells 
2217a75b007SDavid Howells 		afs_get_call(call, afs_call_trace_work);
222341f741fSDavid Howells 		if (!queue_work(afs_wq, &call->work))
223341f741fSDavid Howells 			afs_put_call(call);
2243bf0fb6fSDavid Howells 	}
2256c67c7c3SDavid Howells }
2266c67c7c3SDavid Howells 
2276c67c7c3SDavid Howells /*
22808e0e7c8SDavid Howells  * allocate a call with flat request and reply buffers
22908e0e7c8SDavid Howells  */
230f044c884SDavid Howells struct afs_call *afs_alloc_flat_call(struct afs_net *net,
231f044c884SDavid Howells 				     const struct afs_call_type *type,
232d001648eSDavid Howells 				     size_t request_size, size_t reply_max)
23308e0e7c8SDavid Howells {
23408e0e7c8SDavid Howells 	struct afs_call *call;
23508e0e7c8SDavid Howells 
236f044c884SDavid Howells 	call = afs_alloc_call(net, type, GFP_NOFS);
23708e0e7c8SDavid Howells 	if (!call)
23808e0e7c8SDavid Howells 		goto nomem_call;
23908e0e7c8SDavid Howells 
24000d3b7a4SDavid Howells 	if (request_size) {
241341f741fSDavid Howells 		call->request_size = request_size;
24200d3b7a4SDavid Howells 		call->request = kmalloc(request_size, GFP_NOFS);
24300d3b7a4SDavid Howells 		if (!call->request)
24400d3b7a4SDavid Howells 			goto nomem_free;
24500d3b7a4SDavid Howells 	}
24600d3b7a4SDavid Howells 
247d001648eSDavid Howells 	if (reply_max) {
248341f741fSDavid Howells 		call->reply_max = reply_max;
249d001648eSDavid Howells 		call->buffer = kmalloc(reply_max, GFP_NOFS);
25000d3b7a4SDavid Howells 		if (!call->buffer)
25100d3b7a4SDavid Howells 			goto nomem_free;
25200d3b7a4SDavid Howells 	}
25300d3b7a4SDavid Howells 
25412bdcf33SDavid Howells 	afs_extract_to_buf(call, call->reply_max);
255025db80cSDavid Howells 	call->operation_ID = type->op;
25608e0e7c8SDavid Howells 	init_waitqueue_head(&call->waitq);
25708e0e7c8SDavid Howells 	return call;
25808e0e7c8SDavid Howells 
25900d3b7a4SDavid Howells nomem_free:
260341f741fSDavid Howells 	afs_put_call(call);
26108e0e7c8SDavid Howells nomem_call:
26208e0e7c8SDavid Howells 	return NULL;
26308e0e7c8SDavid Howells }
26408e0e7c8SDavid Howells 
26508e0e7c8SDavid Howells /*
26608e0e7c8SDavid Howells  * clean up a call with flat buffer
26708e0e7c8SDavid Howells  */
26808e0e7c8SDavid Howells void afs_flat_call_destructor(struct afs_call *call)
26908e0e7c8SDavid Howells {
27008e0e7c8SDavid Howells 	_enter("");
27108e0e7c8SDavid Howells 
27208e0e7c8SDavid Howells 	kfree(call->request);
27308e0e7c8SDavid Howells 	call->request = NULL;
27408e0e7c8SDavid Howells 	kfree(call->buffer);
27508e0e7c8SDavid Howells 	call->buffer = NULL;
27608e0e7c8SDavid Howells }
27708e0e7c8SDavid Howells 
2782f5705a5SDavid Howells #define AFS_BVEC_MAX 8
2792f5705a5SDavid Howells 
2802f5705a5SDavid Howells /*
2812f5705a5SDavid Howells  * Load the given bvec with the next few pages.
2822f5705a5SDavid Howells  */
2832f5705a5SDavid Howells static void afs_load_bvec(struct afs_call *call, struct msghdr *msg,
2842f5705a5SDavid Howells 			  struct bio_vec *bv, pgoff_t first, pgoff_t last,
2852f5705a5SDavid Howells 			  unsigned offset)
2862f5705a5SDavid Howells {
2872f5705a5SDavid Howells 	struct page *pages[AFS_BVEC_MAX];
2882f5705a5SDavid Howells 	unsigned int nr, n, i, to, bytes = 0;
2892f5705a5SDavid Howells 
2902f5705a5SDavid Howells 	nr = min_t(pgoff_t, last - first + 1, AFS_BVEC_MAX);
2912f5705a5SDavid Howells 	n = find_get_pages_contig(call->mapping, first, nr, pages);
2922f5705a5SDavid Howells 	ASSERTCMP(n, ==, nr);
2932f5705a5SDavid Howells 
2942f5705a5SDavid Howells 	msg->msg_flags |= MSG_MORE;
2952f5705a5SDavid Howells 	for (i = 0; i < nr; i++) {
2962f5705a5SDavid Howells 		to = PAGE_SIZE;
2972f5705a5SDavid Howells 		if (first + i >= last) {
2982f5705a5SDavid Howells 			to = call->last_to;
2992f5705a5SDavid Howells 			msg->msg_flags &= ~MSG_MORE;
3002f5705a5SDavid Howells 		}
3012f5705a5SDavid Howells 		bv[i].bv_page = pages[i];
3022f5705a5SDavid Howells 		bv[i].bv_len = to - offset;
3032f5705a5SDavid Howells 		bv[i].bv_offset = offset;
3042f5705a5SDavid Howells 		bytes += to - offset;
3052f5705a5SDavid Howells 		offset = 0;
3062f5705a5SDavid Howells 	}
3072f5705a5SDavid Howells 
308aa563d7bSDavid Howells 	iov_iter_bvec(&msg->msg_iter, WRITE, bv, nr, bytes);
3092f5705a5SDavid Howells }
3102f5705a5SDavid Howells 
31108e0e7c8SDavid Howells /*
312e833251aSDavid Howells  * Advance the AFS call state when the RxRPC call ends the transmit phase.
313e833251aSDavid Howells  */
314e833251aSDavid Howells static void afs_notify_end_request_tx(struct sock *sock,
315e833251aSDavid Howells 				      struct rxrpc_call *rxcall,
316e833251aSDavid Howells 				      unsigned long call_user_ID)
317e833251aSDavid Howells {
318e833251aSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
319e833251aSDavid Howells 
32098bf40cdSDavid Howells 	afs_set_call_state(call, AFS_CALL_CL_REQUESTING, AFS_CALL_CL_AWAIT_REPLY);
321e833251aSDavid Howells }
322e833251aSDavid Howells 
323e833251aSDavid Howells /*
32431143d5dSDavid Howells  * attach the data from a bunch of pages on an inode to a call
32531143d5dSDavid Howells  */
32639c6aceaSAl Viro static int afs_send_pages(struct afs_call *call, struct msghdr *msg)
32731143d5dSDavid Howells {
3282f5705a5SDavid Howells 	struct bio_vec bv[AFS_BVEC_MAX];
3292f5705a5SDavid Howells 	unsigned int bytes, nr, loop, offset;
33031143d5dSDavid Howells 	pgoff_t first = call->first, last = call->last;
33131143d5dSDavid Howells 	int ret;
33231143d5dSDavid Howells 
33331143d5dSDavid Howells 	offset = call->first_offset;
33431143d5dSDavid Howells 	call->first_offset = 0;
33531143d5dSDavid Howells 
33631143d5dSDavid Howells 	do {
3372f5705a5SDavid Howells 		afs_load_bvec(call, msg, bv, first, last, offset);
3382c099014SDavid Howells 		trace_afs_send_pages(call, msg, first, last, offset);
3392c099014SDavid Howells 
34031143d5dSDavid Howells 		offset = 0;
3412f5705a5SDavid Howells 		bytes = msg->msg_iter.count;
3422f5705a5SDavid Howells 		nr = msg->msg_iter.nr_segs;
34331143d5dSDavid Howells 
344f044c884SDavid Howells 		ret = rxrpc_kernel_send_data(call->net->socket, call->rxcall, msg,
345e833251aSDavid Howells 					     bytes, afs_notify_end_request_tx);
3462f5705a5SDavid Howells 		for (loop = 0; loop < nr; loop++)
3472f5705a5SDavid Howells 			put_page(bv[loop].bv_page);
34831143d5dSDavid Howells 		if (ret < 0)
34931143d5dSDavid Howells 			break;
35031143d5dSDavid Howells 
3512f5705a5SDavid Howells 		first += nr;
3525bbf5d39SDavid Howells 	} while (first <= last);
35331143d5dSDavid Howells 
3542c099014SDavid Howells 	trace_afs_sent_pages(call, call->first, last, first, ret);
35531143d5dSDavid Howells 	return ret;
35631143d5dSDavid Howells }
35731143d5dSDavid Howells 
35831143d5dSDavid Howells /*
3590b9bf381SDavid Howells  * Initiate a call and synchronously queue up the parameters for dispatch.  Any
3600b9bf381SDavid Howells  * error is stored into the call struct, which the caller must check for.
36108e0e7c8SDavid Howells  */
3620b9bf381SDavid Howells void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp)
36308e0e7c8SDavid Howells {
3642feeaf84SDavid Howells 	struct sockaddr_rxrpc *srx = &ac->alist->addrs[ac->index];
36508e0e7c8SDavid Howells 	struct rxrpc_call *rxcall;
36608e0e7c8SDavid Howells 	struct msghdr msg;
36708e0e7c8SDavid Howells 	struct kvec iov[1];
368e754eba6SDavid Howells 	s64 tx_total_len;
36908e0e7c8SDavid Howells 	int ret;
37008e0e7c8SDavid Howells 
3714d9df986SDavid Howells 	_enter(",{%pISp},", &srx->transport);
37208e0e7c8SDavid Howells 
37300d3b7a4SDavid Howells 	ASSERT(call->type != NULL);
37400d3b7a4SDavid Howells 	ASSERT(call->type->name != NULL);
37500d3b7a4SDavid Howells 
37631143d5dSDavid Howells 	_debug("____MAKE %p{%s,%x} [%d]____",
37731143d5dSDavid Howells 	       call, call->type->name, key_serial(call->key),
378f044c884SDavid Howells 	       atomic_read(&call->net->nr_outstanding_calls));
37900d3b7a4SDavid Howells 
3803bf0fb6fSDavid Howells 	call->addr_ix = ac->index;
3813bf0fb6fSDavid Howells 	call->alist = afs_get_addrlist(ac->alist);
38208e0e7c8SDavid Howells 
383e754eba6SDavid Howells 	/* Work out the length we're going to transmit.  This is awkward for
384e754eba6SDavid Howells 	 * calls such as FS.StoreData where there's an extra injection of data
385e754eba6SDavid Howells 	 * after the initial fixed part.
386e754eba6SDavid Howells 	 */
387e754eba6SDavid Howells 	tx_total_len = call->request_size;
388e754eba6SDavid Howells 	if (call->send_pages) {
3891199db60SDavid Howells 		if (call->last == call->first) {
390e754eba6SDavid Howells 			tx_total_len += call->last_to - call->first_offset;
3911199db60SDavid Howells 		} else {
3921199db60SDavid Howells 			/* It looks mathematically like you should be able to
3931199db60SDavid Howells 			 * combine the following lines with the ones above, but
3941199db60SDavid Howells 			 * unsigned arithmetic is fun when it wraps...
3951199db60SDavid Howells 			 */
3961199db60SDavid Howells 			tx_total_len += PAGE_SIZE - call->first_offset;
3971199db60SDavid Howells 			tx_total_len += call->last_to;
3981199db60SDavid Howells 			tx_total_len += (call->last - call->first - 1) * PAGE_SIZE;
3991199db60SDavid Howells 		}
400e754eba6SDavid Howells 	}
401e754eba6SDavid Howells 
40234fa4761SDavid Howells 	/* If the call is going to be asynchronous, we need an extra ref for
40334fa4761SDavid Howells 	 * the call to hold itself so the caller need not hang on to its ref.
40434fa4761SDavid Howells 	 */
40534fa4761SDavid Howells 	if (call->async)
40634fa4761SDavid Howells 		afs_get_call(call, afs_call_trace_get);
40734fa4761SDavid Howells 
40808e0e7c8SDavid Howells 	/* create a call */
4094d9df986SDavid Howells 	rxcall = rxrpc_kernel_begin_call(call->net->socket, srx, call->key,
410e754eba6SDavid Howells 					 (unsigned long)call,
411e754eba6SDavid Howells 					 tx_total_len, gfp,
4120b9bf381SDavid Howells 					 (call->async ?
41356ff9c83SDavid Howells 					  afs_wake_up_async_call :
414a68f4a27SDavid Howells 					  afs_wake_up_call_waiter),
415a25e21f0SDavid Howells 					 call->upgrade,
41620b8391fSDavid Howells 					 call->intr,
417a25e21f0SDavid Howells 					 call->debug_id);
41808e0e7c8SDavid Howells 	if (IS_ERR(rxcall)) {
41908e0e7c8SDavid Howells 		ret = PTR_ERR(rxcall);
4203bf0fb6fSDavid Howells 		call->error = ret;
42108e0e7c8SDavid Howells 		goto error_kill_call;
42208e0e7c8SDavid Howells 	}
42308e0e7c8SDavid Howells 
42408e0e7c8SDavid Howells 	call->rxcall = rxcall;
42508e0e7c8SDavid Howells 
42694f699c9SDavid Howells 	if (call->max_lifespan)
42794f699c9SDavid Howells 		rxrpc_kernel_set_max_life(call->net->socket, rxcall,
42894f699c9SDavid Howells 					  call->max_lifespan);
42994f699c9SDavid Howells 
43008e0e7c8SDavid Howells 	/* send the request */
43108e0e7c8SDavid Howells 	iov[0].iov_base	= call->request;
43208e0e7c8SDavid Howells 	iov[0].iov_len	= call->request_size;
43308e0e7c8SDavid Howells 
43408e0e7c8SDavid Howells 	msg.msg_name		= NULL;
43508e0e7c8SDavid Howells 	msg.msg_namelen		= 0;
436aa563d7bSDavid Howells 	iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, call->request_size);
43708e0e7c8SDavid Howells 	msg.msg_control		= NULL;
43808e0e7c8SDavid Howells 	msg.msg_controllen	= 0;
439bc5e3a54SDavid Howells 	msg.msg_flags		= MSG_WAITALL | (call->send_pages ? MSG_MORE : 0);
44008e0e7c8SDavid Howells 
441f044c884SDavid Howells 	ret = rxrpc_kernel_send_data(call->net->socket, rxcall,
442e833251aSDavid Howells 				     &msg, call->request_size,
443e833251aSDavid Howells 				     afs_notify_end_request_tx);
44408e0e7c8SDavid Howells 	if (ret < 0)
44508e0e7c8SDavid Howells 		goto error_do_abort;
44608e0e7c8SDavid Howells 
44731143d5dSDavid Howells 	if (call->send_pages) {
44839c6aceaSAl Viro 		ret = afs_send_pages(call, &msg);
44931143d5dSDavid Howells 		if (ret < 0)
45031143d5dSDavid Howells 			goto error_do_abort;
45131143d5dSDavid Howells 	}
45231143d5dSDavid Howells 
45334fa4761SDavid Howells 	/* Note that at this point, we may have received the reply or an abort
45434fa4761SDavid Howells 	 * - and an asynchronous call may already have completed.
4550b9bf381SDavid Howells 	 *
4560b9bf381SDavid Howells 	 * afs_wait_for_call_to_complete(call, ac)
4570b9bf381SDavid Howells 	 * must be called to synchronously clean up.
45834fa4761SDavid Howells 	 */
4590b9bf381SDavid Howells 	return;
46008e0e7c8SDavid Howells 
46108e0e7c8SDavid Howells error_do_abort:
46270af0e3bSDavid Howells 	if (ret != -ECONNABORTED) {
463f044c884SDavid Howells 		rxrpc_kernel_abort_call(call->net->socket, rxcall,
464f044c884SDavid Howells 					RX_USER_ABORT, ret, "KSD");
46570af0e3bSDavid Howells 	} else {
466aa563d7bSDavid Howells 		iov_iter_kvec(&msg.msg_iter, READ, NULL, 0, 0);
467eb9950ebSDavid Howells 		rxrpc_kernel_recv_data(call->net->socket, rxcall,
468eb9950ebSDavid Howells 				       &msg.msg_iter, false,
469eb9950ebSDavid Howells 				       &call->abort_code, &call->service_id);
470d2ddc776SDavid Howells 		ac->abort_code = call->abort_code;
471d2ddc776SDavid Howells 		ac->responded = true;
47270af0e3bSDavid Howells 	}
473025db80cSDavid Howells 	call->error = ret;
474025db80cSDavid Howells 	trace_afs_call_done(call);
47508e0e7c8SDavid Howells error_kill_call:
4763bf0fb6fSDavid Howells 	if (call->type->done)
4773bf0fb6fSDavid Howells 		call->type->done(call);
47834fa4761SDavid Howells 
47934fa4761SDavid Howells 	/* We need to dispose of the extra ref we grabbed for an async call.
48034fa4761SDavid Howells 	 * The call, however, might be queued on afs_async_calls and we need to
48134fa4761SDavid Howells 	 * make sure we don't get any more notifications that might requeue it.
48234fa4761SDavid Howells 	 */
48334fa4761SDavid Howells 	if (call->rxcall) {
48434fa4761SDavid Howells 		rxrpc_kernel_end_call(call->net->socket, call->rxcall);
48534fa4761SDavid Howells 		call->rxcall = NULL;
48634fa4761SDavid Howells 	}
48734fa4761SDavid Howells 	if (call->async) {
48834fa4761SDavid Howells 		if (cancel_work_sync(&call->async_work))
489341f741fSDavid Howells 			afs_put_call(call);
49034fa4761SDavid Howells 		afs_put_call(call);
49134fa4761SDavid Howells 	}
49234fa4761SDavid Howells 
493d2ddc776SDavid Howells 	ac->error = ret;
49434fa4761SDavid Howells 	call->state = AFS_CALL_COMPLETE;
49508e0e7c8SDavid Howells 	_leave(" = %d", ret);
49608e0e7c8SDavid Howells }
49708e0e7c8SDavid Howells 
49808e0e7c8SDavid Howells /*
49908e0e7c8SDavid Howells  * deliver messages to a call
50008e0e7c8SDavid Howells  */
50108e0e7c8SDavid Howells static void afs_deliver_to_call(struct afs_call *call)
50208e0e7c8SDavid Howells {
50398bf40cdSDavid Howells 	enum afs_call_state state;
50498bf40cdSDavid Howells 	u32 abort_code, remote_abort = 0;
50508e0e7c8SDavid Howells 	int ret;
50608e0e7c8SDavid Howells 
507d001648eSDavid Howells 	_enter("%s", call->type->name);
50808e0e7c8SDavid Howells 
50998bf40cdSDavid Howells 	while (state = READ_ONCE(call->state),
51098bf40cdSDavid Howells 	       state == AFS_CALL_CL_AWAIT_REPLY ||
51198bf40cdSDavid Howells 	       state == AFS_CALL_SV_AWAIT_OP_ID ||
51298bf40cdSDavid Howells 	       state == AFS_CALL_SV_AWAIT_REQUEST ||
51398bf40cdSDavid Howells 	       state == AFS_CALL_SV_AWAIT_ACK
514d001648eSDavid Howells 	       ) {
51598bf40cdSDavid Howells 		if (state == AFS_CALL_SV_AWAIT_ACK) {
516fc276122SDavid Howells 			iov_iter_kvec(&call->def_iter, READ, NULL, 0, 0);
517f044c884SDavid Howells 			ret = rxrpc_kernel_recv_data(call->net->socket,
518fc276122SDavid Howells 						     call->rxcall, &call->def_iter,
51912bdcf33SDavid Howells 						     false, &remote_abort,
520a68f4a27SDavid Howells 						     &call->service_id);
521fc276122SDavid Howells 			trace_afs_receive_data(call, &call->def_iter, false, ret);
5228e8d7f13SDavid Howells 
523d001648eSDavid Howells 			if (ret == -EINPROGRESS || ret == -EAGAIN)
524d001648eSDavid Howells 				return;
52598bf40cdSDavid Howells 			if (ret < 0 || ret == 1) {
52698bf40cdSDavid Howells 				if (ret == 1)
52798bf40cdSDavid Howells 					ret = 0;
528025db80cSDavid Howells 				goto call_complete;
52998bf40cdSDavid Howells 			}
530d001648eSDavid Howells 			return;
531d001648eSDavid Howells 		}
532d001648eSDavid Howells 
5334571577fSDavid Howells 		if (!call->have_reply_time &&
53412d8e95aSDavid Howells 		    rxrpc_kernel_get_reply_time(call->net->socket,
53512d8e95aSDavid Howells 						call->rxcall,
53612d8e95aSDavid Howells 						&call->reply_time))
5374571577fSDavid Howells 			call->have_reply_time = true;
53812d8e95aSDavid Howells 
539d001648eSDavid Howells 		ret = call->type->deliver(call);
54098bf40cdSDavid Howells 		state = READ_ONCE(call->state);
541d001648eSDavid Howells 		switch (ret) {
54208e0e7c8SDavid Howells 		case 0:
5433bf0fb6fSDavid Howells 			afs_queue_call_work(call);
544f2686b09SDavid Howells 			if (state == AFS_CALL_CL_PROC_REPLY) {
545f2686b09SDavid Howells 				if (call->cbi)
546f2686b09SDavid Howells 					set_bit(AFS_SERVER_FL_MAY_HAVE_CB,
547f2686b09SDavid Howells 						&call->cbi->server->flags);
548025db80cSDavid Howells 				goto call_complete;
549f2686b09SDavid Howells 			}
55098bf40cdSDavid Howells 			ASSERTCMP(state, >, AFS_CALL_CL_PROC_REPLY);
551d001648eSDavid Howells 			goto done;
552d001648eSDavid Howells 		case -EINPROGRESS:
553d001648eSDavid Howells 		case -EAGAIN:
554d001648eSDavid Howells 			goto out;
55570af0e3bSDavid Howells 		case -ECONNABORTED:
55698bf40cdSDavid Howells 			ASSERTCMP(state, ==, AFS_CALL_COMPLETE);
55798bf40cdSDavid Howells 			goto done;
55808e0e7c8SDavid Howells 		case -ENOTSUPP:
5591157f153SDavid Howells 			abort_code = RXGEN_OPCODE;
560f044c884SDavid Howells 			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
5613a92789aSDavid Howells 						abort_code, ret, "KIV");
56298bf40cdSDavid Howells 			goto local_abort;
5634ac15ea5SDavid Howells 		case -EIO:
5644ac15ea5SDavid Howells 			pr_err("kAFS: Call %u in bad state %u\n",
5654ac15ea5SDavid Howells 			       call->debug_id, state);
5664ac15ea5SDavid Howells 			/* Fall through */
567d001648eSDavid Howells 		case -ENODATA:
568d001648eSDavid Howells 		case -EBADMSG:
569d001648eSDavid Howells 		case -EMSGSIZE:
57008e0e7c8SDavid Howells 			abort_code = RXGEN_CC_UNMARSHAL;
57198bf40cdSDavid Howells 			if (state != AFS_CALL_CL_AWAIT_REPLY)
57208e0e7c8SDavid Howells 				abort_code = RXGEN_SS_UNMARSHAL;
573f044c884SDavid Howells 			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
57412bdcf33SDavid Howells 						abort_code, ret, "KUM");
57598bf40cdSDavid Howells 			goto local_abort;
5768022c4b9SDavid Howells 		default:
5778022c4b9SDavid Howells 			abort_code = RX_USER_ABORT;
5788022c4b9SDavid Howells 			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
5798022c4b9SDavid Howells 						abort_code, ret, "KER");
5808022c4b9SDavid Howells 			goto local_abort;
58108e0e7c8SDavid Howells 		}
58208e0e7c8SDavid Howells 	}
58308e0e7c8SDavid Howells 
584d001648eSDavid Howells done:
5853bf0fb6fSDavid Howells 	if (call->type->done)
5863bf0fb6fSDavid Howells 		call->type->done(call);
58798bf40cdSDavid Howells 	if (state == AFS_CALL_COMPLETE && call->incoming)
588341f741fSDavid Howells 		afs_put_call(call);
589d001648eSDavid Howells out:
59008e0e7c8SDavid Howells 	_leave("");
591d001648eSDavid Howells 	return;
592d001648eSDavid Howells 
59398bf40cdSDavid Howells local_abort:
59498bf40cdSDavid Howells 	abort_code = 0;
595025db80cSDavid Howells call_complete:
59698bf40cdSDavid Howells 	afs_set_call_complete(call, ret, remote_abort);
59798bf40cdSDavid Howells 	state = AFS_CALL_COMPLETE;
598d001648eSDavid Howells 	goto done;
59908e0e7c8SDavid Howells }
60008e0e7c8SDavid Howells 
60108e0e7c8SDavid Howells /*
6020b9bf381SDavid Howells  * Wait synchronously for a call to complete and clean up the call struct.
60308e0e7c8SDavid Howells  */
6040b9bf381SDavid Howells long afs_wait_for_call_to_complete(struct afs_call *call,
605d2ddc776SDavid Howells 				   struct afs_addr_cursor *ac)
60608e0e7c8SDavid Howells {
607bc5e3a54SDavid Howells 	signed long rtt2, timeout;
60833cd7f2bSDavid Howells 	long ret;
6097150ceaaSDavid Howells 	bool stalled = false;
610bc5e3a54SDavid Howells 	u64 rtt;
611bc5e3a54SDavid Howells 	u32 life, last_life;
612f7f1dd31SMarc Dionne 	bool rxrpc_complete = false;
61308e0e7c8SDavid Howells 
61408e0e7c8SDavid Howells 	DECLARE_WAITQUEUE(myself, current);
61508e0e7c8SDavid Howells 
61608e0e7c8SDavid Howells 	_enter("");
61708e0e7c8SDavid Howells 
6180b9bf381SDavid Howells 	ret = call->error;
6190b9bf381SDavid Howells 	if (ret < 0)
6200b9bf381SDavid Howells 		goto out;
6210b9bf381SDavid Howells 
622f044c884SDavid Howells 	rtt = rxrpc_kernel_get_rtt(call->net->socket, call->rxcall);
623bc5e3a54SDavid Howells 	rtt2 = nsecs_to_jiffies64(rtt) * 2;
624bc5e3a54SDavid Howells 	if (rtt2 < 2)
625bc5e3a54SDavid Howells 		rtt2 = 2;
626bc5e3a54SDavid Howells 
627bc5e3a54SDavid Howells 	timeout = rtt2;
6284611da30SMarc Dionne 	rxrpc_kernel_check_life(call->net->socket, call->rxcall, &last_life);
629bc5e3a54SDavid Howells 
63008e0e7c8SDavid Howells 	add_wait_queue(&call->waitq, &myself);
63108e0e7c8SDavid Howells 	for (;;) {
632bc5e3a54SDavid Howells 		set_current_state(TASK_UNINTERRUPTIBLE);
63308e0e7c8SDavid Howells 
63408e0e7c8SDavid Howells 		/* deliver any messages that are in the queue */
63598bf40cdSDavid Howells 		if (!afs_check_call_state(call, AFS_CALL_COMPLETE) &&
63698bf40cdSDavid Howells 		    call->need_attention) {
637d001648eSDavid Howells 			call->need_attention = false;
63808e0e7c8SDavid Howells 			__set_current_state(TASK_RUNNING);
63908e0e7c8SDavid Howells 			afs_deliver_to_call(call);
64008e0e7c8SDavid Howells 			continue;
64108e0e7c8SDavid Howells 		}
64208e0e7c8SDavid Howells 
64398bf40cdSDavid Howells 		if (afs_check_call_state(call, AFS_CALL_COMPLETE))
64408e0e7c8SDavid Howells 			break;
645bc5e3a54SDavid Howells 
646f7f1dd31SMarc Dionne 		if (!rxrpc_kernel_check_life(call->net->socket, call->rxcall, &life)) {
647f7f1dd31SMarc Dionne 			/* rxrpc terminated the call. */
648f7f1dd31SMarc Dionne 			rxrpc_complete = true;
649f7f1dd31SMarc Dionne 			break;
650f7f1dd31SMarc Dionne 		}
651f7f1dd31SMarc Dionne 
65220b8391fSDavid Howells 		if (call->intr && timeout == 0 &&
6537150ceaaSDavid Howells 		    life == last_life && signal_pending(current)) {
6547150ceaaSDavid Howells 			if (stalled)
655bc5e3a54SDavid Howells 				break;
6567150ceaaSDavid Howells 			__set_current_state(TASK_RUNNING);
6577150ceaaSDavid Howells 			rxrpc_kernel_probe_life(call->net->socket, call->rxcall);
6587150ceaaSDavid Howells 			timeout = rtt2;
6597150ceaaSDavid Howells 			stalled = true;
6607150ceaaSDavid Howells 			continue;
6617150ceaaSDavid Howells 		}
662bc5e3a54SDavid Howells 
663bc5e3a54SDavid Howells 		if (life != last_life) {
664bc5e3a54SDavid Howells 			timeout = rtt2;
665bc5e3a54SDavid Howells 			last_life = life;
6667150ceaaSDavid Howells 			stalled = false;
667bc5e3a54SDavid Howells 		}
668bc5e3a54SDavid Howells 
669bc5e3a54SDavid Howells 		timeout = schedule_timeout(timeout);
67008e0e7c8SDavid Howells 	}
67108e0e7c8SDavid Howells 
67208e0e7c8SDavid Howells 	remove_wait_queue(&call->waitq, &myself);
67308e0e7c8SDavid Howells 	__set_current_state(TASK_RUNNING);
67408e0e7c8SDavid Howells 
67598bf40cdSDavid Howells 	if (!afs_check_call_state(call, AFS_CALL_COMPLETE)) {
676f7f1dd31SMarc Dionne 		if (rxrpc_complete) {
677f7f1dd31SMarc Dionne 			afs_set_call_complete(call, call->error, call->abort_code);
678f7f1dd31SMarc Dionne 		} else {
679f7f1dd31SMarc Dionne 			/* Kill off the call if it's still live. */
680954cd6dcSDavid Howells 			_debug("call interrupted");
681d2ddc776SDavid Howells 			if (rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
68298bf40cdSDavid Howells 						    RX_USER_ABORT, -EINTR, "KWI"))
68398bf40cdSDavid Howells 				afs_set_call_complete(call, -EINTR, 0);
68408e0e7c8SDavid Howells 		}
685f7f1dd31SMarc Dionne 	}
68608e0e7c8SDavid Howells 
68798bf40cdSDavid Howells 	spin_lock_bh(&call->state_lock);
688d2ddc776SDavid Howells 	ac->abort_code = call->abort_code;
689d2ddc776SDavid Howells 	ac->error = call->error;
69098bf40cdSDavid Howells 	spin_unlock_bh(&call->state_lock);
691d2ddc776SDavid Howells 
692d2ddc776SDavid Howells 	ret = ac->error;
693d2ddc776SDavid Howells 	switch (ret) {
694d2ddc776SDavid Howells 	case 0:
695ffba718eSDavid Howells 		ret = call->ret0;
696ffba718eSDavid Howells 		call->ret0 = 0;
697ffba718eSDavid Howells 
698d2ddc776SDavid Howells 		/* Fall through */
699d2ddc776SDavid Howells 	case -ECONNABORTED:
700d2ddc776SDavid Howells 		ac->responded = true;
701d2ddc776SDavid Howells 		break;
702d2ddc776SDavid Howells 	}
70333cd7f2bSDavid Howells 
7040b9bf381SDavid Howells out:
70508e0e7c8SDavid Howells 	_debug("call complete");
706341f741fSDavid Howells 	afs_put_call(call);
70733cd7f2bSDavid Howells 	_leave(" = %p", (void *)ret);
70808e0e7c8SDavid Howells 	return ret;
70908e0e7c8SDavid Howells }
71008e0e7c8SDavid Howells 
71108e0e7c8SDavid Howells /*
71208e0e7c8SDavid Howells  * wake up a waiting call
71308e0e7c8SDavid Howells  */
714d001648eSDavid Howells static void afs_wake_up_call_waiter(struct sock *sk, struct rxrpc_call *rxcall,
715d001648eSDavid Howells 				    unsigned long call_user_ID)
71608e0e7c8SDavid Howells {
717d001648eSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
718d001648eSDavid Howells 
719d001648eSDavid Howells 	call->need_attention = true;
72008e0e7c8SDavid Howells 	wake_up(&call->waitq);
72108e0e7c8SDavid Howells }
72208e0e7c8SDavid Howells 
72308e0e7c8SDavid Howells /*
72408e0e7c8SDavid Howells  * wake up an asynchronous call
72508e0e7c8SDavid Howells  */
726d001648eSDavid Howells static void afs_wake_up_async_call(struct sock *sk, struct rxrpc_call *rxcall,
727d001648eSDavid Howells 				   unsigned long call_user_ID)
72808e0e7c8SDavid Howells {
729d001648eSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
730341f741fSDavid Howells 	int u;
731d001648eSDavid Howells 
7328e8d7f13SDavid Howells 	trace_afs_notify_call(rxcall, call);
733d001648eSDavid Howells 	call->need_attention = true;
734341f741fSDavid Howells 
735bfc18e38SMark Rutland 	u = atomic_fetch_add_unless(&call->usage, 1, 0);
736341f741fSDavid Howells 	if (u != 0) {
737341f741fSDavid Howells 		trace_afs_call(call, afs_call_trace_wake, u,
738f044c884SDavid Howells 			       atomic_read(&call->net->nr_outstanding_calls),
739341f741fSDavid Howells 			       __builtin_return_address(0));
740341f741fSDavid Howells 
741341f741fSDavid Howells 		if (!queue_work(afs_async_calls, &call->async_work))
742341f741fSDavid Howells 			afs_put_call(call);
743341f741fSDavid Howells 	}
74408e0e7c8SDavid Howells }
74508e0e7c8SDavid Howells 
74608e0e7c8SDavid Howells /*
747341f741fSDavid Howells  * Delete an asynchronous call.  The work item carries a ref to the call struct
748341f741fSDavid Howells  * that we need to release.
74908e0e7c8SDavid Howells  */
750d001648eSDavid Howells static void afs_delete_async_call(struct work_struct *work)
75108e0e7c8SDavid Howells {
752d001648eSDavid Howells 	struct afs_call *call = container_of(work, struct afs_call, async_work);
753d001648eSDavid Howells 
75408e0e7c8SDavid Howells 	_enter("");
75508e0e7c8SDavid Howells 
756341f741fSDavid Howells 	afs_put_call(call);
75708e0e7c8SDavid Howells 
75808e0e7c8SDavid Howells 	_leave("");
75908e0e7c8SDavid Howells }
76008e0e7c8SDavid Howells 
76108e0e7c8SDavid Howells /*
762341f741fSDavid Howells  * Perform I/O processing on an asynchronous call.  The work item carries a ref
763341f741fSDavid Howells  * to the call struct that we either need to release or to pass on.
76408e0e7c8SDavid Howells  */
765d001648eSDavid Howells static void afs_process_async_call(struct work_struct *work)
76608e0e7c8SDavid Howells {
767d001648eSDavid Howells 	struct afs_call *call = container_of(work, struct afs_call, async_work);
768d001648eSDavid Howells 
76908e0e7c8SDavid Howells 	_enter("");
77008e0e7c8SDavid Howells 
771d001648eSDavid Howells 	if (call->state < AFS_CALL_COMPLETE && call->need_attention) {
772d001648eSDavid Howells 		call->need_attention = false;
77308e0e7c8SDavid Howells 		afs_deliver_to_call(call);
774d001648eSDavid Howells 	}
77508e0e7c8SDavid Howells 
77656ff9c83SDavid Howells 	if (call->state == AFS_CALL_COMPLETE) {
777341f741fSDavid Howells 		/* We have two refs to release - one from the alloc and one
778341f741fSDavid Howells 		 * queued with the work item - and we can't just deallocate the
779341f741fSDavid Howells 		 * call because the work item may be queued again.
780341f741fSDavid Howells 		 */
781d001648eSDavid Howells 		call->async_work.func = afs_delete_async_call;
782341f741fSDavid Howells 		if (!queue_work(afs_async_calls, &call->async_work))
783341f741fSDavid Howells 			afs_put_call(call);
78408e0e7c8SDavid Howells 	}
78508e0e7c8SDavid Howells 
786341f741fSDavid Howells 	afs_put_call(call);
78708e0e7c8SDavid Howells 	_leave("");
78808e0e7c8SDavid Howells }
78908e0e7c8SDavid Howells 
79000e90712SDavid Howells static void afs_rx_attach(struct rxrpc_call *rxcall, unsigned long user_call_ID)
79100e90712SDavid Howells {
79200e90712SDavid Howells 	struct afs_call *call = (struct afs_call *)user_call_ID;
79300e90712SDavid Howells 
79400e90712SDavid Howells 	call->rxcall = rxcall;
79500e90712SDavid Howells }
79600e90712SDavid Howells 
79700e90712SDavid Howells /*
79800e90712SDavid Howells  * Charge the incoming call preallocation.
79900e90712SDavid Howells  */
800f044c884SDavid Howells void afs_charge_preallocation(struct work_struct *work)
80100e90712SDavid Howells {
802f044c884SDavid Howells 	struct afs_net *net =
803f044c884SDavid Howells 		container_of(work, struct afs_net, charge_preallocation_work);
804f044c884SDavid Howells 	struct afs_call *call = net->spare_incoming_call;
80500e90712SDavid Howells 
80600e90712SDavid Howells 	for (;;) {
80700e90712SDavid Howells 		if (!call) {
808f044c884SDavid Howells 			call = afs_alloc_call(net, &afs_RXCMxxxx, GFP_KERNEL);
80900e90712SDavid Howells 			if (!call)
81000e90712SDavid Howells 				break;
81100e90712SDavid Howells 
81256ff9c83SDavid Howells 			call->async = true;
81398bf40cdSDavid Howells 			call->state = AFS_CALL_SV_AWAIT_OP_ID;
81456ff9c83SDavid Howells 			init_waitqueue_head(&call->waitq);
81512bdcf33SDavid Howells 			afs_extract_to_tmp(call);
81600e90712SDavid Howells 		}
81700e90712SDavid Howells 
818f044c884SDavid Howells 		if (rxrpc_kernel_charge_accept(net->socket,
81900e90712SDavid Howells 					       afs_wake_up_async_call,
82000e90712SDavid Howells 					       afs_rx_attach,
82100e90712SDavid Howells 					       (unsigned long)call,
822a25e21f0SDavid Howells 					       GFP_KERNEL,
823a25e21f0SDavid Howells 					       call->debug_id) < 0)
82400e90712SDavid Howells 			break;
82500e90712SDavid Howells 		call = NULL;
82600e90712SDavid Howells 	}
827f044c884SDavid Howells 	net->spare_incoming_call = call;
82800e90712SDavid Howells }
82900e90712SDavid Howells 
83000e90712SDavid Howells /*
83100e90712SDavid Howells  * Discard a preallocated call when a socket is shut down.
83200e90712SDavid Howells  */
83300e90712SDavid Howells static void afs_rx_discard_new_call(struct rxrpc_call *rxcall,
83400e90712SDavid Howells 				    unsigned long user_call_ID)
83500e90712SDavid Howells {
83600e90712SDavid Howells 	struct afs_call *call = (struct afs_call *)user_call_ID;
83700e90712SDavid Howells 
83800e90712SDavid Howells 	call->rxcall = NULL;
839341f741fSDavid Howells 	afs_put_call(call);
84000e90712SDavid Howells }
84100e90712SDavid Howells 
84208e0e7c8SDavid Howells /*
843d001648eSDavid Howells  * Notification of an incoming call.
844d001648eSDavid Howells  */
84500e90712SDavid Howells static void afs_rx_new_call(struct sock *sk, struct rxrpc_call *rxcall,
84600e90712SDavid Howells 			    unsigned long user_call_ID)
847d001648eSDavid Howells {
848f044c884SDavid Howells 	struct afs_net *net = afs_sock2net(sk);
849f044c884SDavid Howells 
850f044c884SDavid Howells 	queue_work(afs_wq, &net->charge_preallocation_work);
851d001648eSDavid Howells }
852d001648eSDavid Howells 
853d001648eSDavid Howells /*
854372ee163SDavid Howells  * Grab the operation ID from an incoming cache manager call.  The socket
855372ee163SDavid Howells  * buffer is discarded on error or if we don't yet have sufficient data.
85608e0e7c8SDavid Howells  */
857d001648eSDavid Howells static int afs_deliver_cm_op_id(struct afs_call *call)
85808e0e7c8SDavid Howells {
859d001648eSDavid Howells 	int ret;
86008e0e7c8SDavid Howells 
861fc276122SDavid Howells 	_enter("{%zu}", iov_iter_count(call->iter));
86208e0e7c8SDavid Howells 
86308e0e7c8SDavid Howells 	/* the operation ID forms the first four bytes of the request data */
86412bdcf33SDavid Howells 	ret = afs_extract_data(call, true);
865d001648eSDavid Howells 	if (ret < 0)
866d001648eSDavid Howells 		return ret;
86708e0e7c8SDavid Howells 
86850a2c953SDavid Howells 	call->operation_ID = ntohl(call->tmp);
86998bf40cdSDavid Howells 	afs_set_call_state(call, AFS_CALL_SV_AWAIT_OP_ID, AFS_CALL_SV_AWAIT_REQUEST);
87008e0e7c8SDavid Howells 
87108e0e7c8SDavid Howells 	/* ask the cache manager to route the call (it'll change the call type
87208e0e7c8SDavid Howells 	 * if successful) */
87308e0e7c8SDavid Howells 	if (!afs_cm_incoming_call(call))
87408e0e7c8SDavid Howells 		return -ENOTSUPP;
87508e0e7c8SDavid Howells 
8768e8d7f13SDavid Howells 	trace_afs_cb_call(call);
8778e8d7f13SDavid Howells 
87808e0e7c8SDavid Howells 	/* pass responsibility for the remainer of this message off to the
87908e0e7c8SDavid Howells 	 * cache manager op */
880d001648eSDavid Howells 	return call->type->deliver(call);
88108e0e7c8SDavid Howells }
88208e0e7c8SDavid Howells 
88308e0e7c8SDavid Howells /*
884e833251aSDavid Howells  * Advance the AFS call state when an RxRPC service call ends the transmit
885e833251aSDavid Howells  * phase.
886e833251aSDavid Howells  */
887e833251aSDavid Howells static void afs_notify_end_reply_tx(struct sock *sock,
888e833251aSDavid Howells 				    struct rxrpc_call *rxcall,
889e833251aSDavid Howells 				    unsigned long call_user_ID)
890e833251aSDavid Howells {
891e833251aSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
892e833251aSDavid Howells 
89398bf40cdSDavid Howells 	afs_set_call_state(call, AFS_CALL_SV_REPLYING, AFS_CALL_SV_AWAIT_ACK);
894e833251aSDavid Howells }
895e833251aSDavid Howells 
896e833251aSDavid Howells /*
89708e0e7c8SDavid Howells  * send an empty reply
89808e0e7c8SDavid Howells  */
89908e0e7c8SDavid Howells void afs_send_empty_reply(struct afs_call *call)
90008e0e7c8SDavid Howells {
901f044c884SDavid Howells 	struct afs_net *net = call->net;
90208e0e7c8SDavid Howells 	struct msghdr msg;
90308e0e7c8SDavid Howells 
90408e0e7c8SDavid Howells 	_enter("");
90508e0e7c8SDavid Howells 
906f044c884SDavid Howells 	rxrpc_kernel_set_tx_length(net->socket, call->rxcall, 0);
907e754eba6SDavid Howells 
90808e0e7c8SDavid Howells 	msg.msg_name		= NULL;
90908e0e7c8SDavid Howells 	msg.msg_namelen		= 0;
910aa563d7bSDavid Howells 	iov_iter_kvec(&msg.msg_iter, WRITE, NULL, 0, 0);
91108e0e7c8SDavid Howells 	msg.msg_control		= NULL;
91208e0e7c8SDavid Howells 	msg.msg_controllen	= 0;
91308e0e7c8SDavid Howells 	msg.msg_flags		= 0;
91408e0e7c8SDavid Howells 
915f044c884SDavid Howells 	switch (rxrpc_kernel_send_data(net->socket, call->rxcall, &msg, 0,
916e833251aSDavid Howells 				       afs_notify_end_reply_tx)) {
91708e0e7c8SDavid Howells 	case 0:
91808e0e7c8SDavid Howells 		_leave(" [replied]");
91908e0e7c8SDavid Howells 		return;
92008e0e7c8SDavid Howells 
92108e0e7c8SDavid Howells 	case -ENOMEM:
92208e0e7c8SDavid Howells 		_debug("oom");
923f044c884SDavid Howells 		rxrpc_kernel_abort_call(net->socket, call->rxcall,
9243a92789aSDavid Howells 					RX_USER_ABORT, -ENOMEM, "KOO");
925e690c9e3SGustavo A. R. Silva 		/* Fall through */
92608e0e7c8SDavid Howells 	default:
92708e0e7c8SDavid Howells 		_leave(" [error]");
92808e0e7c8SDavid Howells 		return;
92908e0e7c8SDavid Howells 	}
93008e0e7c8SDavid Howells }
93108e0e7c8SDavid Howells 
93208e0e7c8SDavid Howells /*
933b908fe6bSDavid Howells  * send a simple reply
934b908fe6bSDavid Howells  */
935b908fe6bSDavid Howells void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
936b908fe6bSDavid Howells {
937f044c884SDavid Howells 	struct afs_net *net = call->net;
938b908fe6bSDavid Howells 	struct msghdr msg;
9392e90b1c4SAl Viro 	struct kvec iov[1];
940bd6dc742SDavid Howells 	int n;
941b908fe6bSDavid Howells 
942b908fe6bSDavid Howells 	_enter("");
943b908fe6bSDavid Howells 
944f044c884SDavid Howells 	rxrpc_kernel_set_tx_length(net->socket, call->rxcall, len);
945e754eba6SDavid Howells 
946b908fe6bSDavid Howells 	iov[0].iov_base		= (void *) buf;
947b908fe6bSDavid Howells 	iov[0].iov_len		= len;
948b908fe6bSDavid Howells 	msg.msg_name		= NULL;
949b908fe6bSDavid Howells 	msg.msg_namelen		= 0;
950aa563d7bSDavid Howells 	iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, len);
951b908fe6bSDavid Howells 	msg.msg_control		= NULL;
952b908fe6bSDavid Howells 	msg.msg_controllen	= 0;
953b908fe6bSDavid Howells 	msg.msg_flags		= 0;
954b908fe6bSDavid Howells 
955f044c884SDavid Howells 	n = rxrpc_kernel_send_data(net->socket, call->rxcall, &msg, len,
956e833251aSDavid Howells 				   afs_notify_end_reply_tx);
957bd6dc742SDavid Howells 	if (n >= 0) {
9586c67c7c3SDavid Howells 		/* Success */
959b908fe6bSDavid Howells 		_leave(" [replied]");
960b908fe6bSDavid Howells 		return;
961bd6dc742SDavid Howells 	}
9626c67c7c3SDavid Howells 
963bd6dc742SDavid Howells 	if (n == -ENOMEM) {
964b908fe6bSDavid Howells 		_debug("oom");
965f044c884SDavid Howells 		rxrpc_kernel_abort_call(net->socket, call->rxcall,
9663a92789aSDavid Howells 					RX_USER_ABORT, -ENOMEM, "KOO");
967bd6dc742SDavid Howells 	}
968b908fe6bSDavid Howells 	_leave(" [error]");
969b908fe6bSDavid Howells }
970b908fe6bSDavid Howells 
971b908fe6bSDavid Howells /*
972372ee163SDavid Howells  * Extract a piece of data from the received data socket buffers.
97308e0e7c8SDavid Howells  */
97412bdcf33SDavid Howells int afs_extract_data(struct afs_call *call, bool want_more)
97508e0e7c8SDavid Howells {
976f044c884SDavid Howells 	struct afs_net *net = call->net;
977fc276122SDavid Howells 	struct iov_iter *iter = call->iter;
97898bf40cdSDavid Howells 	enum afs_call_state state;
9797888da95SDan Carpenter 	u32 remote_abort = 0;
980d001648eSDavid Howells 	int ret;
98108e0e7c8SDavid Howells 
98212bdcf33SDavid Howells 	_enter("{%s,%zu},%d", call->type->name, iov_iter_count(iter), want_more);
98308e0e7c8SDavid Howells 
98412bdcf33SDavid Howells 	ret = rxrpc_kernel_recv_data(net->socket, call->rxcall, iter,
98598bf40cdSDavid Howells 				     want_more, &remote_abort,
986a68f4a27SDavid Howells 				     &call->service_id);
987d001648eSDavid Howells 	if (ret == 0 || ret == -EAGAIN)
988d001648eSDavid Howells 		return ret;
98908e0e7c8SDavid Howells 
99098bf40cdSDavid Howells 	state = READ_ONCE(call->state);
991d001648eSDavid Howells 	if (ret == 1) {
99298bf40cdSDavid Howells 		switch (state) {
99398bf40cdSDavid Howells 		case AFS_CALL_CL_AWAIT_REPLY:
99498bf40cdSDavid Howells 			afs_set_call_state(call, state, AFS_CALL_CL_PROC_REPLY);
995d001648eSDavid Howells 			break;
99698bf40cdSDavid Howells 		case AFS_CALL_SV_AWAIT_REQUEST:
99798bf40cdSDavid Howells 			afs_set_call_state(call, state, AFS_CALL_SV_REPLYING);
998d001648eSDavid Howells 			break;
99998bf40cdSDavid Howells 		case AFS_CALL_COMPLETE:
100098bf40cdSDavid Howells 			kdebug("prem complete %d", call->error);
1001f51375cdSDavid Howells 			return afs_io_error(call, afs_io_error_extract);
1002d001648eSDavid Howells 		default:
1003d001648eSDavid Howells 			break;
100408e0e7c8SDavid Howells 		}
100508e0e7c8SDavid Howells 		return 0;
100608e0e7c8SDavid Howells 	}
1007d001648eSDavid Howells 
100898bf40cdSDavid Howells 	afs_set_call_complete(call, ret, remote_abort);
1009d001648eSDavid Howells 	return ret;
1010d001648eSDavid Howells }
10115f702c8eSDavid Howells 
10125f702c8eSDavid Howells /*
10135f702c8eSDavid Howells  * Log protocol error production.
10145f702c8eSDavid Howells  */
1015160cb957SDavid Howells noinline int afs_protocol_error(struct afs_call *call, int error,
1016160cb957SDavid Howells 				enum afs_eproto_cause cause)
10175f702c8eSDavid Howells {
1018160cb957SDavid Howells 	trace_afs_protocol_error(call, error, cause);
10195f702c8eSDavid Howells 	return error;
10205f702c8eSDavid Howells }
1021