xref: /openbmc/linux/fs/afs/rxrpc.c (revision 7150ceaa)
108e0e7c8SDavid Howells /* Maintain an RxRPC server socket to do AFS communications through
208e0e7c8SDavid Howells  *
308e0e7c8SDavid Howells  * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
408e0e7c8SDavid Howells  * Written by David Howells (dhowells@redhat.com)
508e0e7c8SDavid Howells  *
608e0e7c8SDavid Howells  * This program is free software; you can redistribute it and/or
708e0e7c8SDavid Howells  * modify it under the terms of the GNU General Public License
808e0e7c8SDavid Howells  * as published by the Free Software Foundation; either version
908e0e7c8SDavid Howells  * 2 of the License, or (at your option) any later version.
1008e0e7c8SDavid Howells  */
1108e0e7c8SDavid Howells 
125a0e3ad6STejun Heo #include <linux/slab.h>
13174cd4b1SIngo Molnar #include <linux/sched/signal.h>
14174cd4b1SIngo Molnar 
1508e0e7c8SDavid Howells #include <net/sock.h>
1608e0e7c8SDavid Howells #include <net/af_rxrpc.h>
1708e0e7c8SDavid Howells #include "internal.h"
1808e0e7c8SDavid Howells #include "afs_cm.h"
1935dbfba3SDavid Howells #include "protocol_yfs.h"
2008e0e7c8SDavid Howells 
21f044c884SDavid Howells struct workqueue_struct *afs_async_calls;
2208e0e7c8SDavid Howells 
23d001648eSDavid Howells static void afs_wake_up_call_waiter(struct sock *, struct rxrpc_call *, unsigned long);
24d2ddc776SDavid Howells static long afs_wait_for_call_to_complete(struct afs_call *, struct afs_addr_cursor *);
25d001648eSDavid Howells static void afs_wake_up_async_call(struct sock *, struct rxrpc_call *, unsigned long);
26d001648eSDavid Howells static void afs_process_async_call(struct work_struct *);
2700e90712SDavid Howells static void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned long);
2800e90712SDavid Howells static void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long);
29d001648eSDavid Howells static int afs_deliver_cm_op_id(struct afs_call *);
3008e0e7c8SDavid Howells 
3108e0e7c8SDavid Howells /* asynchronous incoming call initial processing */
3208e0e7c8SDavid Howells static const struct afs_call_type afs_RXCMxxxx = {
3300d3b7a4SDavid Howells 	.name		= "CB.xxxx",
3408e0e7c8SDavid Howells 	.deliver	= afs_deliver_cm_op_id,
3508e0e7c8SDavid Howells };
3608e0e7c8SDavid Howells 
3708e0e7c8SDavid Howells /*
3808e0e7c8SDavid Howells  * open an RxRPC socket and bind it to be a server for callback notifications
3908e0e7c8SDavid Howells  * - the socket is left in blocking mode and non-blocking ops use MSG_DONTWAIT
4008e0e7c8SDavid Howells  */
41f044c884SDavid Howells int afs_open_socket(struct afs_net *net)
4208e0e7c8SDavid Howells {
4308e0e7c8SDavid Howells 	struct sockaddr_rxrpc srx;
4408e0e7c8SDavid Howells 	struct socket *socket;
454776cab4SDavid Howells 	unsigned int min_level;
4608e0e7c8SDavid Howells 	int ret;
4708e0e7c8SDavid Howells 
4808e0e7c8SDavid Howells 	_enter("");
4908e0e7c8SDavid Howells 
505b86d4ffSDavid Howells 	ret = sock_create_kern(net->net, AF_RXRPC, SOCK_DGRAM, PF_INET6, &socket);
510e119b41SDavid Howells 	if (ret < 0)
520e119b41SDavid Howells 		goto error_1;
5308e0e7c8SDavid Howells 
5408e0e7c8SDavid Howells 	socket->sk->sk_allocation = GFP_NOFS;
5508e0e7c8SDavid Howells 
5608e0e7c8SDavid Howells 	/* bind the callback manager's address to make this a server socket */
573838d3ecSDavid Howells 	memset(&srx, 0, sizeof(srx));
5808e0e7c8SDavid Howells 	srx.srx_family			= AF_RXRPC;
5908e0e7c8SDavid Howells 	srx.srx_service			= CM_SERVICE;
6008e0e7c8SDavid Howells 	srx.transport_type		= SOCK_DGRAM;
613838d3ecSDavid Howells 	srx.transport_len		= sizeof(srx.transport.sin6);
623838d3ecSDavid Howells 	srx.transport.sin6.sin6_family	= AF_INET6;
633838d3ecSDavid Howells 	srx.transport.sin6.sin6_port	= htons(AFS_CM_PORT);
6408e0e7c8SDavid Howells 
654776cab4SDavid Howells 	min_level = RXRPC_SECURITY_ENCRYPT;
664776cab4SDavid Howells 	ret = kernel_setsockopt(socket, SOL_RXRPC, RXRPC_MIN_SECURITY_LEVEL,
674776cab4SDavid Howells 				(void *)&min_level, sizeof(min_level));
684776cab4SDavid Howells 	if (ret < 0)
694776cab4SDavid Howells 		goto error_2;
704776cab4SDavid Howells 
7108e0e7c8SDavid Howells 	ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
7283732ec5SMarc Dionne 	if (ret == -EADDRINUSE) {
7383732ec5SMarc Dionne 		srx.transport.sin6.sin6_port = 0;
7483732ec5SMarc Dionne 		ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
7583732ec5SMarc Dionne 	}
760e119b41SDavid Howells 	if (ret < 0)
770e119b41SDavid Howells 		goto error_2;
780e119b41SDavid Howells 
7935dbfba3SDavid Howells 	srx.srx_service = YFS_CM_SERVICE;
8035dbfba3SDavid Howells 	ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
8135dbfba3SDavid Howells 	if (ret < 0)
8235dbfba3SDavid Howells 		goto error_2;
8335dbfba3SDavid Howells 
843bf0fb6fSDavid Howells 	/* Ideally, we'd turn on service upgrade here, but we can't because
853bf0fb6fSDavid Howells 	 * OpenAFS is buggy and leaks the userStatus field from packet to
863bf0fb6fSDavid Howells 	 * packet and between FS packets and CB packets - so if we try to do an
873bf0fb6fSDavid Howells 	 * upgrade on an FS packet, OpenAFS will leak that into the CB packet
883bf0fb6fSDavid Howells 	 * it sends back to us.
893bf0fb6fSDavid Howells 	 */
9035dbfba3SDavid Howells 
9100e90712SDavid Howells 	rxrpc_kernel_new_call_notification(socket, afs_rx_new_call,
9200e90712SDavid Howells 					   afs_rx_discard_new_call);
93d001648eSDavid Howells 
940e119b41SDavid Howells 	ret = kernel_listen(socket, INT_MAX);
950e119b41SDavid Howells 	if (ret < 0)
960e119b41SDavid Howells 		goto error_2;
9708e0e7c8SDavid Howells 
98f044c884SDavid Howells 	net->socket = socket;
99f044c884SDavid Howells 	afs_charge_preallocation(&net->charge_preallocation_work);
10008e0e7c8SDavid Howells 	_leave(" = 0");
10108e0e7c8SDavid Howells 	return 0;
1020e119b41SDavid Howells 
1030e119b41SDavid Howells error_2:
1040e119b41SDavid Howells 	sock_release(socket);
1050e119b41SDavid Howells error_1:
1060e119b41SDavid Howells 	_leave(" = %d", ret);
1070e119b41SDavid Howells 	return ret;
10808e0e7c8SDavid Howells }
10908e0e7c8SDavid Howells 
11008e0e7c8SDavid Howells /*
11108e0e7c8SDavid Howells  * close the RxRPC socket AFS was using
11208e0e7c8SDavid Howells  */
113f044c884SDavid Howells void afs_close_socket(struct afs_net *net)
11408e0e7c8SDavid Howells {
11508e0e7c8SDavid Howells 	_enter("");
11608e0e7c8SDavid Howells 
117f044c884SDavid Howells 	kernel_listen(net->socket, 0);
118341f741fSDavid Howells 	flush_workqueue(afs_async_calls);
119341f741fSDavid Howells 
120f044c884SDavid Howells 	if (net->spare_incoming_call) {
121f044c884SDavid Howells 		afs_put_call(net->spare_incoming_call);
122f044c884SDavid Howells 		net->spare_incoming_call = NULL;
12300e90712SDavid Howells 	}
12400e90712SDavid Howells 
125f044c884SDavid Howells 	_debug("outstanding %u", atomic_read(&net->nr_outstanding_calls));
126ab1fbe32SPeter Zijlstra 	wait_var_event(&net->nr_outstanding_calls,
127ab1fbe32SPeter Zijlstra 		       !atomic_read(&net->nr_outstanding_calls));
1282f02f7aeSDavid Howells 	_debug("no outstanding calls");
1292f02f7aeSDavid Howells 
130f044c884SDavid Howells 	kernel_sock_shutdown(net->socket, SHUT_RDWR);
131248f219cSDavid Howells 	flush_workqueue(afs_async_calls);
132f044c884SDavid Howells 	sock_release(net->socket);
13308e0e7c8SDavid Howells 
13408e0e7c8SDavid Howells 	_debug("dework");
13508e0e7c8SDavid Howells 	_leave("");
13608e0e7c8SDavid Howells }
13708e0e7c8SDavid Howells 
13808e0e7c8SDavid Howells /*
139341f741fSDavid Howells  * Allocate a call.
14000d3b7a4SDavid Howells  */
141f044c884SDavid Howells static struct afs_call *afs_alloc_call(struct afs_net *net,
142f044c884SDavid Howells 				       const struct afs_call_type *type,
143341f741fSDavid Howells 				       gfp_t gfp)
14400d3b7a4SDavid Howells {
145341f741fSDavid Howells 	struct afs_call *call;
146341f741fSDavid Howells 	int o;
14700d3b7a4SDavid Howells 
148341f741fSDavid Howells 	call = kzalloc(sizeof(*call), gfp);
149341f741fSDavid Howells 	if (!call)
150341f741fSDavid Howells 		return NULL;
15100d3b7a4SDavid Howells 
152341f741fSDavid Howells 	call->type = type;
153f044c884SDavid Howells 	call->net = net;
154a25e21f0SDavid Howells 	call->debug_id = atomic_inc_return(&rxrpc_debug_id);
155341f741fSDavid Howells 	atomic_set(&call->usage, 1);
156341f741fSDavid Howells 	INIT_WORK(&call->async_work, afs_process_async_call);
157341f741fSDavid Howells 	init_waitqueue_head(&call->waitq);
15898bf40cdSDavid Howells 	spin_lock_init(&call->state_lock);
15912bdcf33SDavid Howells 	call->_iter = &call->iter;
1602f02f7aeSDavid Howells 
161f044c884SDavid Howells 	o = atomic_inc_return(&net->nr_outstanding_calls);
162341f741fSDavid Howells 	trace_afs_call(call, afs_call_trace_alloc, 1, o,
163341f741fSDavid Howells 		       __builtin_return_address(0));
164341f741fSDavid Howells 	return call;
16500d3b7a4SDavid Howells }
16600d3b7a4SDavid Howells 
16700d3b7a4SDavid Howells /*
168341f741fSDavid Howells  * Dispose of a reference on a call.
1696c67c7c3SDavid Howells  */
170341f741fSDavid Howells void afs_put_call(struct afs_call *call)
1716c67c7c3SDavid Howells {
172f044c884SDavid Howells 	struct afs_net *net = call->net;
173341f741fSDavid Howells 	int n = atomic_dec_return(&call->usage);
174f044c884SDavid Howells 	int o = atomic_read(&net->nr_outstanding_calls);
175341f741fSDavid Howells 
176341f741fSDavid Howells 	trace_afs_call(call, afs_call_trace_put, n + 1, o,
177341f741fSDavid Howells 		       __builtin_return_address(0));
178341f741fSDavid Howells 
179341f741fSDavid Howells 	ASSERTCMP(n, >=, 0);
180341f741fSDavid Howells 	if (n == 0) {
181341f741fSDavid Howells 		ASSERT(!work_pending(&call->async_work));
182341f741fSDavid Howells 		ASSERT(call->type->name != NULL);
183341f741fSDavid Howells 
1846c67c7c3SDavid Howells 		if (call->rxcall) {
185f044c884SDavid Howells 			rxrpc_kernel_end_call(net->socket, call->rxcall);
1866c67c7c3SDavid Howells 			call->rxcall = NULL;
1876c67c7c3SDavid Howells 		}
1886cf12869SNathaniel Wesley Filardo 		if (call->type->destructor)
1896c67c7c3SDavid Howells 			call->type->destructor(call);
190341f741fSDavid Howells 
191d0676a16SDavid Howells 		afs_put_server(call->net, call->cm_server);
192d2ddc776SDavid Howells 		afs_put_cb_interest(call->net, call->cbi);
1933bf0fb6fSDavid Howells 		afs_put_addrlist(call->alist);
194341f741fSDavid Howells 		kfree(call->request);
195a25e21f0SDavid Howells 
196a25e21f0SDavid Howells 		trace_afs_call(call, afs_call_trace_free, 0, o,
197a25e21f0SDavid Howells 			       __builtin_return_address(0));
198341f741fSDavid Howells 		kfree(call);
199341f741fSDavid Howells 
200f044c884SDavid Howells 		o = atomic_dec_return(&net->nr_outstanding_calls);
201341f741fSDavid Howells 		if (o == 0)
202ab1fbe32SPeter Zijlstra 			wake_up_var(&net->nr_outstanding_calls);
203341f741fSDavid Howells 	}
2046cf12869SNathaniel Wesley Filardo }
2056cf12869SNathaniel Wesley Filardo 
2066cf12869SNathaniel Wesley Filardo /*
2073bf0fb6fSDavid Howells  * Queue the call for actual work.
2086cf12869SNathaniel Wesley Filardo  */
2093bf0fb6fSDavid Howells static void afs_queue_call_work(struct afs_call *call)
2106cf12869SNathaniel Wesley Filardo {
2113bf0fb6fSDavid Howells 	if (call->type->work) {
212341f741fSDavid Howells 		int u = atomic_inc_return(&call->usage);
213341f741fSDavid Howells 
214341f741fSDavid Howells 		trace_afs_call(call, afs_call_trace_work, u,
215f044c884SDavid Howells 			       atomic_read(&call->net->nr_outstanding_calls),
216341f741fSDavid Howells 			       __builtin_return_address(0));
217341f741fSDavid Howells 
218341f741fSDavid Howells 		INIT_WORK(&call->work, call->type->work);
219341f741fSDavid Howells 
220341f741fSDavid Howells 		if (!queue_work(afs_wq, &call->work))
221341f741fSDavid Howells 			afs_put_call(call);
2223bf0fb6fSDavid Howells 	}
2236c67c7c3SDavid Howells }
2246c67c7c3SDavid Howells 
2256c67c7c3SDavid Howells /*
22608e0e7c8SDavid Howells  * allocate a call with flat request and reply buffers
22708e0e7c8SDavid Howells  */
228f044c884SDavid Howells struct afs_call *afs_alloc_flat_call(struct afs_net *net,
229f044c884SDavid Howells 				     const struct afs_call_type *type,
230d001648eSDavid Howells 				     size_t request_size, size_t reply_max)
23108e0e7c8SDavid Howells {
23208e0e7c8SDavid Howells 	struct afs_call *call;
23308e0e7c8SDavid Howells 
234f044c884SDavid Howells 	call = afs_alloc_call(net, type, GFP_NOFS);
23508e0e7c8SDavid Howells 	if (!call)
23608e0e7c8SDavid Howells 		goto nomem_call;
23708e0e7c8SDavid Howells 
23800d3b7a4SDavid Howells 	if (request_size) {
239341f741fSDavid Howells 		call->request_size = request_size;
24000d3b7a4SDavid Howells 		call->request = kmalloc(request_size, GFP_NOFS);
24100d3b7a4SDavid Howells 		if (!call->request)
24200d3b7a4SDavid Howells 			goto nomem_free;
24300d3b7a4SDavid Howells 	}
24400d3b7a4SDavid Howells 
245d001648eSDavid Howells 	if (reply_max) {
246341f741fSDavid Howells 		call->reply_max = reply_max;
247d001648eSDavid Howells 		call->buffer = kmalloc(reply_max, GFP_NOFS);
24800d3b7a4SDavid Howells 		if (!call->buffer)
24900d3b7a4SDavid Howells 			goto nomem_free;
25000d3b7a4SDavid Howells 	}
25100d3b7a4SDavid Howells 
25212bdcf33SDavid Howells 	afs_extract_to_buf(call, call->reply_max);
253025db80cSDavid Howells 	call->operation_ID = type->op;
25408e0e7c8SDavid Howells 	init_waitqueue_head(&call->waitq);
25508e0e7c8SDavid Howells 	return call;
25608e0e7c8SDavid Howells 
25700d3b7a4SDavid Howells nomem_free:
258341f741fSDavid Howells 	afs_put_call(call);
25908e0e7c8SDavid Howells nomem_call:
26008e0e7c8SDavid Howells 	return NULL;
26108e0e7c8SDavid Howells }
26208e0e7c8SDavid Howells 
26308e0e7c8SDavid Howells /*
26408e0e7c8SDavid Howells  * clean up a call with flat buffer
26508e0e7c8SDavid Howells  */
26608e0e7c8SDavid Howells void afs_flat_call_destructor(struct afs_call *call)
26708e0e7c8SDavid Howells {
26808e0e7c8SDavid Howells 	_enter("");
26908e0e7c8SDavid Howells 
27008e0e7c8SDavid Howells 	kfree(call->request);
27108e0e7c8SDavid Howells 	call->request = NULL;
27208e0e7c8SDavid Howells 	kfree(call->buffer);
27308e0e7c8SDavid Howells 	call->buffer = NULL;
27408e0e7c8SDavid Howells }
27508e0e7c8SDavid Howells 
2762f5705a5SDavid Howells #define AFS_BVEC_MAX 8
2772f5705a5SDavid Howells 
2782f5705a5SDavid Howells /*
2792f5705a5SDavid Howells  * Load the given bvec with the next few pages.
2802f5705a5SDavid Howells  */
2812f5705a5SDavid Howells static void afs_load_bvec(struct afs_call *call, struct msghdr *msg,
2822f5705a5SDavid Howells 			  struct bio_vec *bv, pgoff_t first, pgoff_t last,
2832f5705a5SDavid Howells 			  unsigned offset)
2842f5705a5SDavid Howells {
2852f5705a5SDavid Howells 	struct page *pages[AFS_BVEC_MAX];
2862f5705a5SDavid Howells 	unsigned int nr, n, i, to, bytes = 0;
2872f5705a5SDavid Howells 
2882f5705a5SDavid Howells 	nr = min_t(pgoff_t, last - first + 1, AFS_BVEC_MAX);
2892f5705a5SDavid Howells 	n = find_get_pages_contig(call->mapping, first, nr, pages);
2902f5705a5SDavid Howells 	ASSERTCMP(n, ==, nr);
2912f5705a5SDavid Howells 
2922f5705a5SDavid Howells 	msg->msg_flags |= MSG_MORE;
2932f5705a5SDavid Howells 	for (i = 0; i < nr; i++) {
2942f5705a5SDavid Howells 		to = PAGE_SIZE;
2952f5705a5SDavid Howells 		if (first + i >= last) {
2962f5705a5SDavid Howells 			to = call->last_to;
2972f5705a5SDavid Howells 			msg->msg_flags &= ~MSG_MORE;
2982f5705a5SDavid Howells 		}
2992f5705a5SDavid Howells 		bv[i].bv_page = pages[i];
3002f5705a5SDavid Howells 		bv[i].bv_len = to - offset;
3012f5705a5SDavid Howells 		bv[i].bv_offset = offset;
3022f5705a5SDavid Howells 		bytes += to - offset;
3032f5705a5SDavid Howells 		offset = 0;
3042f5705a5SDavid Howells 	}
3052f5705a5SDavid Howells 
306aa563d7bSDavid Howells 	iov_iter_bvec(&msg->msg_iter, WRITE, bv, nr, bytes);
3072f5705a5SDavid Howells }
3082f5705a5SDavid Howells 
30908e0e7c8SDavid Howells /*
310e833251aSDavid Howells  * Advance the AFS call state when the RxRPC call ends the transmit phase.
311e833251aSDavid Howells  */
312e833251aSDavid Howells static void afs_notify_end_request_tx(struct sock *sock,
313e833251aSDavid Howells 				      struct rxrpc_call *rxcall,
314e833251aSDavid Howells 				      unsigned long call_user_ID)
315e833251aSDavid Howells {
316e833251aSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
317e833251aSDavid Howells 
31898bf40cdSDavid Howells 	afs_set_call_state(call, AFS_CALL_CL_REQUESTING, AFS_CALL_CL_AWAIT_REPLY);
319e833251aSDavid Howells }
320e833251aSDavid Howells 
321e833251aSDavid Howells /*
32231143d5dSDavid Howells  * attach the data from a bunch of pages on an inode to a call
32331143d5dSDavid Howells  */
32439c6aceaSAl Viro static int afs_send_pages(struct afs_call *call, struct msghdr *msg)
32531143d5dSDavid Howells {
3262f5705a5SDavid Howells 	struct bio_vec bv[AFS_BVEC_MAX];
3272f5705a5SDavid Howells 	unsigned int bytes, nr, loop, offset;
32831143d5dSDavid Howells 	pgoff_t first = call->first, last = call->last;
32931143d5dSDavid Howells 	int ret;
33031143d5dSDavid Howells 
33131143d5dSDavid Howells 	offset = call->first_offset;
33231143d5dSDavid Howells 	call->first_offset = 0;
33331143d5dSDavid Howells 
33431143d5dSDavid Howells 	do {
3352f5705a5SDavid Howells 		afs_load_bvec(call, msg, bv, first, last, offset);
3362c099014SDavid Howells 		trace_afs_send_pages(call, msg, first, last, offset);
3372c099014SDavid Howells 
33831143d5dSDavid Howells 		offset = 0;
3392f5705a5SDavid Howells 		bytes = msg->msg_iter.count;
3402f5705a5SDavid Howells 		nr = msg->msg_iter.nr_segs;
34131143d5dSDavid Howells 
342f044c884SDavid Howells 		ret = rxrpc_kernel_send_data(call->net->socket, call->rxcall, msg,
343e833251aSDavid Howells 					     bytes, afs_notify_end_request_tx);
3442f5705a5SDavid Howells 		for (loop = 0; loop < nr; loop++)
3452f5705a5SDavid Howells 			put_page(bv[loop].bv_page);
34631143d5dSDavid Howells 		if (ret < 0)
34731143d5dSDavid Howells 			break;
34831143d5dSDavid Howells 
3492f5705a5SDavid Howells 		first += nr;
3505bbf5d39SDavid Howells 	} while (first <= last);
35131143d5dSDavid Howells 
3522c099014SDavid Howells 	trace_afs_sent_pages(call, call->first, last, first, ret);
35331143d5dSDavid Howells 	return ret;
35431143d5dSDavid Howells }
35531143d5dSDavid Howells 
35631143d5dSDavid Howells /*
35708e0e7c8SDavid Howells  * initiate a call
35808e0e7c8SDavid Howells  */
3598b2a464cSDavid Howells long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
3604d9df986SDavid Howells 		   gfp_t gfp, bool async)
36108e0e7c8SDavid Howells {
3622feeaf84SDavid Howells 	struct sockaddr_rxrpc *srx = &ac->alist->addrs[ac->index];
36308e0e7c8SDavid Howells 	struct rxrpc_call *rxcall;
36408e0e7c8SDavid Howells 	struct msghdr msg;
36508e0e7c8SDavid Howells 	struct kvec iov[1];
366e754eba6SDavid Howells 	s64 tx_total_len;
36708e0e7c8SDavid Howells 	int ret;
36808e0e7c8SDavid Howells 
3694d9df986SDavid Howells 	_enter(",{%pISp},", &srx->transport);
37008e0e7c8SDavid Howells 
37100d3b7a4SDavid Howells 	ASSERT(call->type != NULL);
37200d3b7a4SDavid Howells 	ASSERT(call->type->name != NULL);
37300d3b7a4SDavid Howells 
37431143d5dSDavid Howells 	_debug("____MAKE %p{%s,%x} [%d]____",
37531143d5dSDavid Howells 	       call, call->type->name, key_serial(call->key),
376f044c884SDavid Howells 	       atomic_read(&call->net->nr_outstanding_calls));
37700d3b7a4SDavid Howells 
37856ff9c83SDavid Howells 	call->async = async;
3793bf0fb6fSDavid Howells 	call->addr_ix = ac->index;
3803bf0fb6fSDavid Howells 	call->alist = afs_get_addrlist(ac->alist);
38108e0e7c8SDavid Howells 
382e754eba6SDavid Howells 	/* Work out the length we're going to transmit.  This is awkward for
383e754eba6SDavid Howells 	 * calls such as FS.StoreData where there's an extra injection of data
384e754eba6SDavid Howells 	 * after the initial fixed part.
385e754eba6SDavid Howells 	 */
386e754eba6SDavid Howells 	tx_total_len = call->request_size;
387e754eba6SDavid Howells 	if (call->send_pages) {
3881199db60SDavid Howells 		if (call->last == call->first) {
389e754eba6SDavid Howells 			tx_total_len += call->last_to - call->first_offset;
3901199db60SDavid Howells 		} else {
3911199db60SDavid Howells 			/* It looks mathematically like you should be able to
3921199db60SDavid Howells 			 * combine the following lines with the ones above, but
3931199db60SDavid Howells 			 * unsigned arithmetic is fun when it wraps...
3941199db60SDavid Howells 			 */
3951199db60SDavid Howells 			tx_total_len += PAGE_SIZE - call->first_offset;
3961199db60SDavid Howells 			tx_total_len += call->last_to;
3971199db60SDavid Howells 			tx_total_len += (call->last - call->first - 1) * PAGE_SIZE;
3981199db60SDavid Howells 		}
399e754eba6SDavid Howells 	}
400e754eba6SDavid Howells 
40108e0e7c8SDavid Howells 	/* create a call */
4024d9df986SDavid Howells 	rxcall = rxrpc_kernel_begin_call(call->net->socket, srx, call->key,
403e754eba6SDavid Howells 					 (unsigned long)call,
404e754eba6SDavid Howells 					 tx_total_len, gfp,
40556ff9c83SDavid Howells 					 (async ?
40656ff9c83SDavid Howells 					  afs_wake_up_async_call :
407a68f4a27SDavid Howells 					  afs_wake_up_call_waiter),
408a25e21f0SDavid Howells 					 call->upgrade,
409a25e21f0SDavid Howells 					 call->debug_id);
41008e0e7c8SDavid Howells 	if (IS_ERR(rxcall)) {
41108e0e7c8SDavid Howells 		ret = PTR_ERR(rxcall);
4123bf0fb6fSDavid Howells 		call->error = ret;
41308e0e7c8SDavid Howells 		goto error_kill_call;
41408e0e7c8SDavid Howells 	}
41508e0e7c8SDavid Howells 
41608e0e7c8SDavid Howells 	call->rxcall = rxcall;
41708e0e7c8SDavid Howells 
41808e0e7c8SDavid Howells 	/* send the request */
41908e0e7c8SDavid Howells 	iov[0].iov_base	= call->request;
42008e0e7c8SDavid Howells 	iov[0].iov_len	= call->request_size;
42108e0e7c8SDavid Howells 
42208e0e7c8SDavid Howells 	msg.msg_name		= NULL;
42308e0e7c8SDavid Howells 	msg.msg_namelen		= 0;
424aa563d7bSDavid Howells 	iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, call->request_size);
42508e0e7c8SDavid Howells 	msg.msg_control		= NULL;
42608e0e7c8SDavid Howells 	msg.msg_controllen	= 0;
427bc5e3a54SDavid Howells 	msg.msg_flags		= MSG_WAITALL | (call->send_pages ? MSG_MORE : 0);
42808e0e7c8SDavid Howells 
429f044c884SDavid Howells 	ret = rxrpc_kernel_send_data(call->net->socket, rxcall,
430e833251aSDavid Howells 				     &msg, call->request_size,
431e833251aSDavid Howells 				     afs_notify_end_request_tx);
43208e0e7c8SDavid Howells 	if (ret < 0)
43308e0e7c8SDavid Howells 		goto error_do_abort;
43408e0e7c8SDavid Howells 
43531143d5dSDavid Howells 	if (call->send_pages) {
43639c6aceaSAl Viro 		ret = afs_send_pages(call, &msg);
43731143d5dSDavid Howells 		if (ret < 0)
43831143d5dSDavid Howells 			goto error_do_abort;
43931143d5dSDavid Howells 	}
44031143d5dSDavid Howells 
44108e0e7c8SDavid Howells 	/* at this point, an async call may no longer exist as it may have
44208e0e7c8SDavid Howells 	 * already completed */
44356ff9c83SDavid Howells 	if (call->async)
44456ff9c83SDavid Howells 		return -EINPROGRESS;
44556ff9c83SDavid Howells 
446d2ddc776SDavid Howells 	return afs_wait_for_call_to_complete(call, ac);
44708e0e7c8SDavid Howells 
44808e0e7c8SDavid Howells error_do_abort:
44970af0e3bSDavid Howells 	call->state = AFS_CALL_COMPLETE;
45070af0e3bSDavid Howells 	if (ret != -ECONNABORTED) {
451f044c884SDavid Howells 		rxrpc_kernel_abort_call(call->net->socket, rxcall,
452f044c884SDavid Howells 					RX_USER_ABORT, ret, "KSD");
45370af0e3bSDavid Howells 	} else {
454aa563d7bSDavid Howells 		iov_iter_kvec(&msg.msg_iter, READ, NULL, 0, 0);
455eb9950ebSDavid Howells 		rxrpc_kernel_recv_data(call->net->socket, rxcall,
456eb9950ebSDavid Howells 				       &msg.msg_iter, false,
457eb9950ebSDavid Howells 				       &call->abort_code, &call->service_id);
458d2ddc776SDavid Howells 		ac->abort_code = call->abort_code;
459d2ddc776SDavid Howells 		ac->responded = true;
46070af0e3bSDavid Howells 	}
461025db80cSDavid Howells 	call->error = ret;
462025db80cSDavid Howells 	trace_afs_call_done(call);
46308e0e7c8SDavid Howells error_kill_call:
4643bf0fb6fSDavid Howells 	if (call->type->done)
4653bf0fb6fSDavid Howells 		call->type->done(call);
466341f741fSDavid Howells 	afs_put_call(call);
467d2ddc776SDavid Howells 	ac->error = ret;
46808e0e7c8SDavid Howells 	_leave(" = %d", ret);
46908e0e7c8SDavid Howells 	return ret;
47008e0e7c8SDavid Howells }
47108e0e7c8SDavid Howells 
47208e0e7c8SDavid Howells /*
47308e0e7c8SDavid Howells  * deliver messages to a call
47408e0e7c8SDavid Howells  */
47508e0e7c8SDavid Howells static void afs_deliver_to_call(struct afs_call *call)
47608e0e7c8SDavid Howells {
47798bf40cdSDavid Howells 	enum afs_call_state state;
47898bf40cdSDavid Howells 	u32 abort_code, remote_abort = 0;
47908e0e7c8SDavid Howells 	int ret;
48008e0e7c8SDavid Howells 
481d001648eSDavid Howells 	_enter("%s", call->type->name);
48208e0e7c8SDavid Howells 
48398bf40cdSDavid Howells 	while (state = READ_ONCE(call->state),
48498bf40cdSDavid Howells 	       state == AFS_CALL_CL_AWAIT_REPLY ||
48598bf40cdSDavid Howells 	       state == AFS_CALL_SV_AWAIT_OP_ID ||
48698bf40cdSDavid Howells 	       state == AFS_CALL_SV_AWAIT_REQUEST ||
48798bf40cdSDavid Howells 	       state == AFS_CALL_SV_AWAIT_ACK
488d001648eSDavid Howells 	       ) {
48998bf40cdSDavid Howells 		if (state == AFS_CALL_SV_AWAIT_ACK) {
49012bdcf33SDavid Howells 			iov_iter_kvec(&call->iter, READ, NULL, 0, 0);
491f044c884SDavid Howells 			ret = rxrpc_kernel_recv_data(call->net->socket,
49212bdcf33SDavid Howells 						     call->rxcall, &call->iter,
49312bdcf33SDavid Howells 						     false, &remote_abort,
494a68f4a27SDavid Howells 						     &call->service_id);
49512bdcf33SDavid Howells 			trace_afs_receive_data(call, &call->iter, false, ret);
4968e8d7f13SDavid Howells 
497d001648eSDavid Howells 			if (ret == -EINPROGRESS || ret == -EAGAIN)
498d001648eSDavid Howells 				return;
49998bf40cdSDavid Howells 			if (ret < 0 || ret == 1) {
50098bf40cdSDavid Howells 				if (ret == 1)
50198bf40cdSDavid Howells 					ret = 0;
502025db80cSDavid Howells 				goto call_complete;
50398bf40cdSDavid Howells 			}
504d001648eSDavid Howells 			return;
505d001648eSDavid Howells 		}
506d001648eSDavid Howells 
50712d8e95aSDavid Howells 		if (call->want_reply_time &&
50812d8e95aSDavid Howells 		    rxrpc_kernel_get_reply_time(call->net->socket,
50912d8e95aSDavid Howells 						call->rxcall,
51012d8e95aSDavid Howells 						&call->reply_time))
51112d8e95aSDavid Howells 			call->want_reply_time = false;
51212d8e95aSDavid Howells 
513d001648eSDavid Howells 		ret = call->type->deliver(call);
51498bf40cdSDavid Howells 		state = READ_ONCE(call->state);
515d001648eSDavid Howells 		switch (ret) {
51608e0e7c8SDavid Howells 		case 0:
5173bf0fb6fSDavid Howells 			afs_queue_call_work(call);
518f2686b09SDavid Howells 			if (state == AFS_CALL_CL_PROC_REPLY) {
519f2686b09SDavid Howells 				if (call->cbi)
520f2686b09SDavid Howells 					set_bit(AFS_SERVER_FL_MAY_HAVE_CB,
521f2686b09SDavid Howells 						&call->cbi->server->flags);
522025db80cSDavid Howells 				goto call_complete;
523f2686b09SDavid Howells 			}
52498bf40cdSDavid Howells 			ASSERTCMP(state, >, AFS_CALL_CL_PROC_REPLY);
525d001648eSDavid Howells 			goto done;
526d001648eSDavid Howells 		case -EINPROGRESS:
527d001648eSDavid Howells 		case -EAGAIN:
528d001648eSDavid Howells 			goto out;
52970af0e3bSDavid Howells 		case -ECONNABORTED:
53098bf40cdSDavid Howells 			ASSERTCMP(state, ==, AFS_CALL_COMPLETE);
53198bf40cdSDavid Howells 			goto done;
53208e0e7c8SDavid Howells 		case -ENOTSUPP:
5331157f153SDavid Howells 			abort_code = RXGEN_OPCODE;
534f044c884SDavid Howells 			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
5353a92789aSDavid Howells 						abort_code, ret, "KIV");
53698bf40cdSDavid Howells 			goto local_abort;
5374ac15ea5SDavid Howells 		case -EIO:
5384ac15ea5SDavid Howells 			pr_err("kAFS: Call %u in bad state %u\n",
5394ac15ea5SDavid Howells 			       call->debug_id, state);
5404ac15ea5SDavid Howells 			/* Fall through */
541d001648eSDavid Howells 		case -ENODATA:
542d001648eSDavid Howells 		case -EBADMSG:
543d001648eSDavid Howells 		case -EMSGSIZE:
54408e0e7c8SDavid Howells 		default:
54508e0e7c8SDavid Howells 			abort_code = RXGEN_CC_UNMARSHAL;
54698bf40cdSDavid Howells 			if (state != AFS_CALL_CL_AWAIT_REPLY)
54708e0e7c8SDavid Howells 				abort_code = RXGEN_SS_UNMARSHAL;
548f044c884SDavid Howells 			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
54912bdcf33SDavid Howells 						abort_code, ret, "KUM");
55098bf40cdSDavid Howells 			goto local_abort;
55108e0e7c8SDavid Howells 		}
55208e0e7c8SDavid Howells 	}
55308e0e7c8SDavid Howells 
554d001648eSDavid Howells done:
5553bf0fb6fSDavid Howells 	if (call->type->done)
5563bf0fb6fSDavid Howells 		call->type->done(call);
55798bf40cdSDavid Howells 	if (state == AFS_CALL_COMPLETE && call->incoming)
558341f741fSDavid Howells 		afs_put_call(call);
559d001648eSDavid Howells out:
56008e0e7c8SDavid Howells 	_leave("");
561d001648eSDavid Howells 	return;
562d001648eSDavid Howells 
56398bf40cdSDavid Howells local_abort:
56498bf40cdSDavid Howells 	abort_code = 0;
565025db80cSDavid Howells call_complete:
56698bf40cdSDavid Howells 	afs_set_call_complete(call, ret, remote_abort);
56798bf40cdSDavid Howells 	state = AFS_CALL_COMPLETE;
568d001648eSDavid Howells 	goto done;
56908e0e7c8SDavid Howells }
57008e0e7c8SDavid Howells 
57108e0e7c8SDavid Howells /*
57208e0e7c8SDavid Howells  * wait synchronously for a call to complete
57308e0e7c8SDavid Howells  */
574d2ddc776SDavid Howells static long afs_wait_for_call_to_complete(struct afs_call *call,
575d2ddc776SDavid Howells 					  struct afs_addr_cursor *ac)
57608e0e7c8SDavid Howells {
577bc5e3a54SDavid Howells 	signed long rtt2, timeout;
57833cd7f2bSDavid Howells 	long ret;
5797150ceaaSDavid Howells 	bool stalled = false;
580bc5e3a54SDavid Howells 	u64 rtt;
581bc5e3a54SDavid Howells 	u32 life, last_life;
58208e0e7c8SDavid Howells 
58308e0e7c8SDavid Howells 	DECLARE_WAITQUEUE(myself, current);
58408e0e7c8SDavid Howells 
58508e0e7c8SDavid Howells 	_enter("");
58608e0e7c8SDavid Howells 
587f044c884SDavid Howells 	rtt = rxrpc_kernel_get_rtt(call->net->socket, call->rxcall);
588bc5e3a54SDavid Howells 	rtt2 = nsecs_to_jiffies64(rtt) * 2;
589bc5e3a54SDavid Howells 	if (rtt2 < 2)
590bc5e3a54SDavid Howells 		rtt2 = 2;
591bc5e3a54SDavid Howells 
592bc5e3a54SDavid Howells 	timeout = rtt2;
593f044c884SDavid Howells 	last_life = rxrpc_kernel_check_life(call->net->socket, call->rxcall);
594bc5e3a54SDavid Howells 
59508e0e7c8SDavid Howells 	add_wait_queue(&call->waitq, &myself);
59608e0e7c8SDavid Howells 	for (;;) {
597bc5e3a54SDavid Howells 		set_current_state(TASK_UNINTERRUPTIBLE);
59808e0e7c8SDavid Howells 
59908e0e7c8SDavid Howells 		/* deliver any messages that are in the queue */
60098bf40cdSDavid Howells 		if (!afs_check_call_state(call, AFS_CALL_COMPLETE) &&
60198bf40cdSDavid Howells 		    call->need_attention) {
602d001648eSDavid Howells 			call->need_attention = false;
60308e0e7c8SDavid Howells 			__set_current_state(TASK_RUNNING);
60408e0e7c8SDavid Howells 			afs_deliver_to_call(call);
60508e0e7c8SDavid Howells 			continue;
60608e0e7c8SDavid Howells 		}
60708e0e7c8SDavid Howells 
60898bf40cdSDavid Howells 		if (afs_check_call_state(call, AFS_CALL_COMPLETE))
60908e0e7c8SDavid Howells 			break;
610bc5e3a54SDavid Howells 
611f044c884SDavid Howells 		life = rxrpc_kernel_check_life(call->net->socket, call->rxcall);
612bc5e3a54SDavid Howells 		if (timeout == 0 &&
6137150ceaaSDavid Howells 		    life == last_life && signal_pending(current)) {
6147150ceaaSDavid Howells 			if (stalled)
615bc5e3a54SDavid Howells 				break;
6167150ceaaSDavid Howells 			__set_current_state(TASK_RUNNING);
6177150ceaaSDavid Howells 			rxrpc_kernel_probe_life(call->net->socket, call->rxcall);
6187150ceaaSDavid Howells 			timeout = rtt2;
6197150ceaaSDavid Howells 			stalled = true;
6207150ceaaSDavid Howells 			continue;
6217150ceaaSDavid Howells 		}
622bc5e3a54SDavid Howells 
623bc5e3a54SDavid Howells 		if (life != last_life) {
624bc5e3a54SDavid Howells 			timeout = rtt2;
625bc5e3a54SDavid Howells 			last_life = life;
6267150ceaaSDavid Howells 			stalled = false;
627bc5e3a54SDavid Howells 		}
628bc5e3a54SDavid Howells 
629bc5e3a54SDavid Howells 		timeout = schedule_timeout(timeout);
63008e0e7c8SDavid Howells 	}
63108e0e7c8SDavid Howells 
63208e0e7c8SDavid Howells 	remove_wait_queue(&call->waitq, &myself);
63308e0e7c8SDavid Howells 	__set_current_state(TASK_RUNNING);
63408e0e7c8SDavid Howells 
635954cd6dcSDavid Howells 	/* Kill off the call if it's still live. */
63698bf40cdSDavid Howells 	if (!afs_check_call_state(call, AFS_CALL_COMPLETE)) {
637954cd6dcSDavid Howells 		_debug("call interrupted");
638d2ddc776SDavid Howells 		if (rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
63998bf40cdSDavid Howells 					    RX_USER_ABORT, -EINTR, "KWI"))
64098bf40cdSDavid Howells 			afs_set_call_complete(call, -EINTR, 0);
64108e0e7c8SDavid Howells 	}
64208e0e7c8SDavid Howells 
64398bf40cdSDavid Howells 	spin_lock_bh(&call->state_lock);
644d2ddc776SDavid Howells 	ac->abort_code = call->abort_code;
645d2ddc776SDavid Howells 	ac->error = call->error;
64698bf40cdSDavid Howells 	spin_unlock_bh(&call->state_lock);
647d2ddc776SDavid Howells 
648d2ddc776SDavid Howells 	ret = ac->error;
649d2ddc776SDavid Howells 	switch (ret) {
650d2ddc776SDavid Howells 	case 0:
651d2ddc776SDavid Howells 		if (call->ret_reply0) {
65233cd7f2bSDavid Howells 			ret = (long)call->reply[0];
65333cd7f2bSDavid Howells 			call->reply[0] = NULL;
65433cd7f2bSDavid Howells 		}
655d2ddc776SDavid Howells 		/* Fall through */
656d2ddc776SDavid Howells 	case -ECONNABORTED:
657d2ddc776SDavid Howells 		ac->responded = true;
658d2ddc776SDavid Howells 		break;
659d2ddc776SDavid Howells 	}
66033cd7f2bSDavid Howells 
66108e0e7c8SDavid Howells 	_debug("call complete");
662341f741fSDavid Howells 	afs_put_call(call);
66333cd7f2bSDavid Howells 	_leave(" = %p", (void *)ret);
66408e0e7c8SDavid Howells 	return ret;
66508e0e7c8SDavid Howells }
66608e0e7c8SDavid Howells 
66708e0e7c8SDavid Howells /*
66808e0e7c8SDavid Howells  * wake up a waiting call
66908e0e7c8SDavid Howells  */
670d001648eSDavid Howells static void afs_wake_up_call_waiter(struct sock *sk, struct rxrpc_call *rxcall,
671d001648eSDavid Howells 				    unsigned long call_user_ID)
67208e0e7c8SDavid Howells {
673d001648eSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
674d001648eSDavid Howells 
675d001648eSDavid Howells 	call->need_attention = true;
67608e0e7c8SDavid Howells 	wake_up(&call->waitq);
67708e0e7c8SDavid Howells }
67808e0e7c8SDavid Howells 
67908e0e7c8SDavid Howells /*
68008e0e7c8SDavid Howells  * wake up an asynchronous call
68108e0e7c8SDavid Howells  */
682d001648eSDavid Howells static void afs_wake_up_async_call(struct sock *sk, struct rxrpc_call *rxcall,
683d001648eSDavid Howells 				   unsigned long call_user_ID)
68408e0e7c8SDavid Howells {
685d001648eSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
686341f741fSDavid Howells 	int u;
687d001648eSDavid Howells 
6888e8d7f13SDavid Howells 	trace_afs_notify_call(rxcall, call);
689d001648eSDavid Howells 	call->need_attention = true;
690341f741fSDavid Howells 
691bfc18e38SMark Rutland 	u = atomic_fetch_add_unless(&call->usage, 1, 0);
692341f741fSDavid Howells 	if (u != 0) {
693341f741fSDavid Howells 		trace_afs_call(call, afs_call_trace_wake, u,
694f044c884SDavid Howells 			       atomic_read(&call->net->nr_outstanding_calls),
695341f741fSDavid Howells 			       __builtin_return_address(0));
696341f741fSDavid Howells 
697341f741fSDavid Howells 		if (!queue_work(afs_async_calls, &call->async_work))
698341f741fSDavid Howells 			afs_put_call(call);
699341f741fSDavid Howells 	}
70008e0e7c8SDavid Howells }
70108e0e7c8SDavid Howells 
70208e0e7c8SDavid Howells /*
703341f741fSDavid Howells  * Delete an asynchronous call.  The work item carries a ref to the call struct
704341f741fSDavid Howells  * that we need to release.
70508e0e7c8SDavid Howells  */
706d001648eSDavid Howells static void afs_delete_async_call(struct work_struct *work)
70708e0e7c8SDavid Howells {
708d001648eSDavid Howells 	struct afs_call *call = container_of(work, struct afs_call, async_work);
709d001648eSDavid Howells 
71008e0e7c8SDavid Howells 	_enter("");
71108e0e7c8SDavid Howells 
712341f741fSDavid Howells 	afs_put_call(call);
71308e0e7c8SDavid Howells 
71408e0e7c8SDavid Howells 	_leave("");
71508e0e7c8SDavid Howells }
71608e0e7c8SDavid Howells 
71708e0e7c8SDavid Howells /*
718341f741fSDavid Howells  * Perform I/O processing on an asynchronous call.  The work item carries a ref
719341f741fSDavid Howells  * to the call struct that we either need to release or to pass on.
72008e0e7c8SDavid Howells  */
721d001648eSDavid Howells static void afs_process_async_call(struct work_struct *work)
72208e0e7c8SDavid Howells {
723d001648eSDavid Howells 	struct afs_call *call = container_of(work, struct afs_call, async_work);
724d001648eSDavid Howells 
72508e0e7c8SDavid Howells 	_enter("");
72608e0e7c8SDavid Howells 
727d001648eSDavid Howells 	if (call->state < AFS_CALL_COMPLETE && call->need_attention) {
728d001648eSDavid Howells 		call->need_attention = false;
72908e0e7c8SDavid Howells 		afs_deliver_to_call(call);
730d001648eSDavid Howells 	}
73108e0e7c8SDavid Howells 
73256ff9c83SDavid Howells 	if (call->state == AFS_CALL_COMPLETE) {
733341f741fSDavid Howells 		/* We have two refs to release - one from the alloc and one
734341f741fSDavid Howells 		 * queued with the work item - and we can't just deallocate the
735341f741fSDavid Howells 		 * call because the work item may be queued again.
736341f741fSDavid Howells 		 */
737d001648eSDavid Howells 		call->async_work.func = afs_delete_async_call;
738341f741fSDavid Howells 		if (!queue_work(afs_async_calls, &call->async_work))
739341f741fSDavid Howells 			afs_put_call(call);
74008e0e7c8SDavid Howells 	}
74108e0e7c8SDavid Howells 
742341f741fSDavid Howells 	afs_put_call(call);
74308e0e7c8SDavid Howells 	_leave("");
74408e0e7c8SDavid Howells }
74508e0e7c8SDavid Howells 
74600e90712SDavid Howells static void afs_rx_attach(struct rxrpc_call *rxcall, unsigned long user_call_ID)
74700e90712SDavid Howells {
74800e90712SDavid Howells 	struct afs_call *call = (struct afs_call *)user_call_ID;
74900e90712SDavid Howells 
75000e90712SDavid Howells 	call->rxcall = rxcall;
75100e90712SDavid Howells }
75200e90712SDavid Howells 
75300e90712SDavid Howells /*
75400e90712SDavid Howells  * Charge the incoming call preallocation.
75500e90712SDavid Howells  */
756f044c884SDavid Howells void afs_charge_preallocation(struct work_struct *work)
75700e90712SDavid Howells {
758f044c884SDavid Howells 	struct afs_net *net =
759f044c884SDavid Howells 		container_of(work, struct afs_net, charge_preallocation_work);
760f044c884SDavid Howells 	struct afs_call *call = net->spare_incoming_call;
76100e90712SDavid Howells 
76200e90712SDavid Howells 	for (;;) {
76300e90712SDavid Howells 		if (!call) {
764f044c884SDavid Howells 			call = afs_alloc_call(net, &afs_RXCMxxxx, GFP_KERNEL);
76500e90712SDavid Howells 			if (!call)
76600e90712SDavid Howells 				break;
76700e90712SDavid Howells 
76856ff9c83SDavid Howells 			call->async = true;
76998bf40cdSDavid Howells 			call->state = AFS_CALL_SV_AWAIT_OP_ID;
77056ff9c83SDavid Howells 			init_waitqueue_head(&call->waitq);
77112bdcf33SDavid Howells 			afs_extract_to_tmp(call);
77200e90712SDavid Howells 		}
77300e90712SDavid Howells 
774f044c884SDavid Howells 		if (rxrpc_kernel_charge_accept(net->socket,
77500e90712SDavid Howells 					       afs_wake_up_async_call,
77600e90712SDavid Howells 					       afs_rx_attach,
77700e90712SDavid Howells 					       (unsigned long)call,
778a25e21f0SDavid Howells 					       GFP_KERNEL,
779a25e21f0SDavid Howells 					       call->debug_id) < 0)
78000e90712SDavid Howells 			break;
78100e90712SDavid Howells 		call = NULL;
78200e90712SDavid Howells 	}
783f044c884SDavid Howells 	net->spare_incoming_call = call;
78400e90712SDavid Howells }
78500e90712SDavid Howells 
78600e90712SDavid Howells /*
78700e90712SDavid Howells  * Discard a preallocated call when a socket is shut down.
78800e90712SDavid Howells  */
78900e90712SDavid Howells static void afs_rx_discard_new_call(struct rxrpc_call *rxcall,
79000e90712SDavid Howells 				    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 = NULL;
795341f741fSDavid Howells 	afs_put_call(call);
79600e90712SDavid Howells }
79700e90712SDavid Howells 
79808e0e7c8SDavid Howells /*
799d001648eSDavid Howells  * Notification of an incoming call.
800d001648eSDavid Howells  */
80100e90712SDavid Howells static void afs_rx_new_call(struct sock *sk, struct rxrpc_call *rxcall,
80200e90712SDavid Howells 			    unsigned long user_call_ID)
803d001648eSDavid Howells {
804f044c884SDavid Howells 	struct afs_net *net = afs_sock2net(sk);
805f044c884SDavid Howells 
806f044c884SDavid Howells 	queue_work(afs_wq, &net->charge_preallocation_work);
807d001648eSDavid Howells }
808d001648eSDavid Howells 
809d001648eSDavid Howells /*
810372ee163SDavid Howells  * Grab the operation ID from an incoming cache manager call.  The socket
811372ee163SDavid Howells  * buffer is discarded on error or if we don't yet have sufficient data.
81208e0e7c8SDavid Howells  */
813d001648eSDavid Howells static int afs_deliver_cm_op_id(struct afs_call *call)
81408e0e7c8SDavid Howells {
815d001648eSDavid Howells 	int ret;
81608e0e7c8SDavid Howells 
81712bdcf33SDavid Howells 	_enter("{%zu}", iov_iter_count(call->_iter));
81808e0e7c8SDavid Howells 
81908e0e7c8SDavid Howells 	/* the operation ID forms the first four bytes of the request data */
82012bdcf33SDavid Howells 	ret = afs_extract_data(call, true);
821d001648eSDavid Howells 	if (ret < 0)
822d001648eSDavid Howells 		return ret;
82308e0e7c8SDavid Howells 
82450a2c953SDavid Howells 	call->operation_ID = ntohl(call->tmp);
82598bf40cdSDavid Howells 	afs_set_call_state(call, AFS_CALL_SV_AWAIT_OP_ID, AFS_CALL_SV_AWAIT_REQUEST);
82608e0e7c8SDavid Howells 
82708e0e7c8SDavid Howells 	/* ask the cache manager to route the call (it'll change the call type
82808e0e7c8SDavid Howells 	 * if successful) */
82908e0e7c8SDavid Howells 	if (!afs_cm_incoming_call(call))
83008e0e7c8SDavid Howells 		return -ENOTSUPP;
83108e0e7c8SDavid Howells 
8328e8d7f13SDavid Howells 	trace_afs_cb_call(call);
8338e8d7f13SDavid Howells 
83408e0e7c8SDavid Howells 	/* pass responsibility for the remainer of this message off to the
83508e0e7c8SDavid Howells 	 * cache manager op */
836d001648eSDavid Howells 	return call->type->deliver(call);
83708e0e7c8SDavid Howells }
83808e0e7c8SDavid Howells 
83908e0e7c8SDavid Howells /*
840e833251aSDavid Howells  * Advance the AFS call state when an RxRPC service call ends the transmit
841e833251aSDavid Howells  * phase.
842e833251aSDavid Howells  */
843e833251aSDavid Howells static void afs_notify_end_reply_tx(struct sock *sock,
844e833251aSDavid Howells 				    struct rxrpc_call *rxcall,
845e833251aSDavid Howells 				    unsigned long call_user_ID)
846e833251aSDavid Howells {
847e833251aSDavid Howells 	struct afs_call *call = (struct afs_call *)call_user_ID;
848e833251aSDavid Howells 
84998bf40cdSDavid Howells 	afs_set_call_state(call, AFS_CALL_SV_REPLYING, AFS_CALL_SV_AWAIT_ACK);
850e833251aSDavid Howells }
851e833251aSDavid Howells 
852e833251aSDavid Howells /*
85308e0e7c8SDavid Howells  * send an empty reply
85408e0e7c8SDavid Howells  */
85508e0e7c8SDavid Howells void afs_send_empty_reply(struct afs_call *call)
85608e0e7c8SDavid Howells {
857f044c884SDavid Howells 	struct afs_net *net = call->net;
85808e0e7c8SDavid Howells 	struct msghdr msg;
85908e0e7c8SDavid Howells 
86008e0e7c8SDavid Howells 	_enter("");
86108e0e7c8SDavid Howells 
862f044c884SDavid Howells 	rxrpc_kernel_set_tx_length(net->socket, call->rxcall, 0);
863e754eba6SDavid Howells 
86408e0e7c8SDavid Howells 	msg.msg_name		= NULL;
86508e0e7c8SDavid Howells 	msg.msg_namelen		= 0;
866aa563d7bSDavid Howells 	iov_iter_kvec(&msg.msg_iter, WRITE, NULL, 0, 0);
86708e0e7c8SDavid Howells 	msg.msg_control		= NULL;
86808e0e7c8SDavid Howells 	msg.msg_controllen	= 0;
86908e0e7c8SDavid Howells 	msg.msg_flags		= 0;
87008e0e7c8SDavid Howells 
871f044c884SDavid Howells 	switch (rxrpc_kernel_send_data(net->socket, call->rxcall, &msg, 0,
872e833251aSDavid Howells 				       afs_notify_end_reply_tx)) {
87308e0e7c8SDavid Howells 	case 0:
87408e0e7c8SDavid Howells 		_leave(" [replied]");
87508e0e7c8SDavid Howells 		return;
87608e0e7c8SDavid Howells 
87708e0e7c8SDavid Howells 	case -ENOMEM:
87808e0e7c8SDavid Howells 		_debug("oom");
879f044c884SDavid Howells 		rxrpc_kernel_abort_call(net->socket, call->rxcall,
8803a92789aSDavid Howells 					RX_USER_ABORT, -ENOMEM, "KOO");
88108e0e7c8SDavid Howells 	default:
88208e0e7c8SDavid Howells 		_leave(" [error]");
88308e0e7c8SDavid Howells 		return;
88408e0e7c8SDavid Howells 	}
88508e0e7c8SDavid Howells }
88608e0e7c8SDavid Howells 
88708e0e7c8SDavid Howells /*
888b908fe6bSDavid Howells  * send a simple reply
889b908fe6bSDavid Howells  */
890b908fe6bSDavid Howells void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
891b908fe6bSDavid Howells {
892f044c884SDavid Howells 	struct afs_net *net = call->net;
893b908fe6bSDavid Howells 	struct msghdr msg;
8942e90b1c4SAl Viro 	struct kvec iov[1];
895bd6dc742SDavid Howells 	int n;
896b908fe6bSDavid Howells 
897b908fe6bSDavid Howells 	_enter("");
898b908fe6bSDavid Howells 
899f044c884SDavid Howells 	rxrpc_kernel_set_tx_length(net->socket, call->rxcall, len);
900e754eba6SDavid Howells 
901b908fe6bSDavid Howells 	iov[0].iov_base		= (void *) buf;
902b908fe6bSDavid Howells 	iov[0].iov_len		= len;
903b908fe6bSDavid Howells 	msg.msg_name		= NULL;
904b908fe6bSDavid Howells 	msg.msg_namelen		= 0;
905aa563d7bSDavid Howells 	iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, len);
906b908fe6bSDavid Howells 	msg.msg_control		= NULL;
907b908fe6bSDavid Howells 	msg.msg_controllen	= 0;
908b908fe6bSDavid Howells 	msg.msg_flags		= 0;
909b908fe6bSDavid Howells 
910f044c884SDavid Howells 	n = rxrpc_kernel_send_data(net->socket, call->rxcall, &msg, len,
911e833251aSDavid Howells 				   afs_notify_end_reply_tx);
912bd6dc742SDavid Howells 	if (n >= 0) {
9136c67c7c3SDavid Howells 		/* Success */
914b908fe6bSDavid Howells 		_leave(" [replied]");
915b908fe6bSDavid Howells 		return;
916bd6dc742SDavid Howells 	}
9176c67c7c3SDavid Howells 
918bd6dc742SDavid Howells 	if (n == -ENOMEM) {
919b908fe6bSDavid Howells 		_debug("oom");
920f044c884SDavid Howells 		rxrpc_kernel_abort_call(net->socket, call->rxcall,
9213a92789aSDavid Howells 					RX_USER_ABORT, -ENOMEM, "KOO");
922bd6dc742SDavid Howells 	}
923b908fe6bSDavid Howells 	_leave(" [error]");
924b908fe6bSDavid Howells }
925b908fe6bSDavid Howells 
926b908fe6bSDavid Howells /*
927372ee163SDavid Howells  * Extract a piece of data from the received data socket buffers.
92808e0e7c8SDavid Howells  */
92912bdcf33SDavid Howells int afs_extract_data(struct afs_call *call, bool want_more)
93008e0e7c8SDavid Howells {
931f044c884SDavid Howells 	struct afs_net *net = call->net;
93212bdcf33SDavid Howells 	struct iov_iter *iter = call->_iter;
93398bf40cdSDavid Howells 	enum afs_call_state state;
9347888da95SDan Carpenter 	u32 remote_abort = 0;
935d001648eSDavid Howells 	int ret;
93608e0e7c8SDavid Howells 
93712bdcf33SDavid Howells 	_enter("{%s,%zu},%d", call->type->name, iov_iter_count(iter), want_more);
93808e0e7c8SDavid Howells 
93912bdcf33SDavid Howells 	ret = rxrpc_kernel_recv_data(net->socket, call->rxcall, iter,
94098bf40cdSDavid Howells 				     want_more, &remote_abort,
941a68f4a27SDavid Howells 				     &call->service_id);
942d001648eSDavid Howells 	if (ret == 0 || ret == -EAGAIN)
943d001648eSDavid Howells 		return ret;
94408e0e7c8SDavid Howells 
94598bf40cdSDavid Howells 	state = READ_ONCE(call->state);
946d001648eSDavid Howells 	if (ret == 1) {
94798bf40cdSDavid Howells 		switch (state) {
94898bf40cdSDavid Howells 		case AFS_CALL_CL_AWAIT_REPLY:
94998bf40cdSDavid Howells 			afs_set_call_state(call, state, AFS_CALL_CL_PROC_REPLY);
950d001648eSDavid Howells 			break;
95198bf40cdSDavid Howells 		case AFS_CALL_SV_AWAIT_REQUEST:
95298bf40cdSDavid Howells 			afs_set_call_state(call, state, AFS_CALL_SV_REPLYING);
953d001648eSDavid Howells 			break;
95498bf40cdSDavid Howells 		case AFS_CALL_COMPLETE:
95598bf40cdSDavid Howells 			kdebug("prem complete %d", call->error);
956f51375cdSDavid Howells 			return afs_io_error(call, afs_io_error_extract);
957d001648eSDavid Howells 		default:
958d001648eSDavid Howells 			break;
95908e0e7c8SDavid Howells 		}
96008e0e7c8SDavid Howells 		return 0;
96108e0e7c8SDavid Howells 	}
962d001648eSDavid Howells 
96398bf40cdSDavid Howells 	afs_set_call_complete(call, ret, remote_abort);
964d001648eSDavid Howells 	return ret;
965d001648eSDavid Howells }
9665f702c8eSDavid Howells 
9675f702c8eSDavid Howells /*
9685f702c8eSDavid Howells  * Log protocol error production.
9695f702c8eSDavid Howells  */
970160cb957SDavid Howells noinline int afs_protocol_error(struct afs_call *call, int error,
971160cb957SDavid Howells 				enum afs_eproto_cause cause)
9725f702c8eSDavid Howells {
973160cb957SDavid Howells 	trace_afs_protocol_error(call, error, cause);
9745f702c8eSDavid Howells 	return error;
9755f702c8eSDavid Howells }
976