18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/* Maintain an RxRPC server socket to do AFS communications through
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
58c2ecf20Sopenharmony_ci * Written by David Howells (dhowells@redhat.com)
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <linux/slab.h>
98c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <net/sock.h>
128c2ecf20Sopenharmony_ci#include <net/af_rxrpc.h>
138c2ecf20Sopenharmony_ci#include "internal.h"
148c2ecf20Sopenharmony_ci#include "afs_cm.h"
158c2ecf20Sopenharmony_ci#include "protocol_yfs.h"
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_cistruct workqueue_struct *afs_async_calls;
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_cistatic void afs_wake_up_call_waiter(struct sock *, struct rxrpc_call *, unsigned long);
208c2ecf20Sopenharmony_cistatic void afs_wake_up_async_call(struct sock *, struct rxrpc_call *, unsigned long);
218c2ecf20Sopenharmony_cistatic void afs_process_async_call(struct work_struct *);
228c2ecf20Sopenharmony_cistatic void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned long);
238c2ecf20Sopenharmony_cistatic void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long);
248c2ecf20Sopenharmony_cistatic int afs_deliver_cm_op_id(struct afs_call *);
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci/* asynchronous incoming call initial processing */
278c2ecf20Sopenharmony_cistatic const struct afs_call_type afs_RXCMxxxx = {
288c2ecf20Sopenharmony_ci	.name		= "CB.xxxx",
298c2ecf20Sopenharmony_ci	.deliver	= afs_deliver_cm_op_id,
308c2ecf20Sopenharmony_ci};
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci/*
338c2ecf20Sopenharmony_ci * open an RxRPC socket and bind it to be a server for callback notifications
348c2ecf20Sopenharmony_ci * - the socket is left in blocking mode and non-blocking ops use MSG_DONTWAIT
358c2ecf20Sopenharmony_ci */
368c2ecf20Sopenharmony_ciint afs_open_socket(struct afs_net *net)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	struct sockaddr_rxrpc srx;
398c2ecf20Sopenharmony_ci	struct socket *socket;
408c2ecf20Sopenharmony_ci	int ret;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	_enter("");
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	ret = sock_create_kern(net->net, AF_RXRPC, SOCK_DGRAM, PF_INET6, &socket);
458c2ecf20Sopenharmony_ci	if (ret < 0)
468c2ecf20Sopenharmony_ci		goto error_1;
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci	socket->sk->sk_allocation = GFP_NOFS;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	/* bind the callback manager's address to make this a server socket */
518c2ecf20Sopenharmony_ci	memset(&srx, 0, sizeof(srx));
528c2ecf20Sopenharmony_ci	srx.srx_family			= AF_RXRPC;
538c2ecf20Sopenharmony_ci	srx.srx_service			= CM_SERVICE;
548c2ecf20Sopenharmony_ci	srx.transport_type		= SOCK_DGRAM;
558c2ecf20Sopenharmony_ci	srx.transport_len		= sizeof(srx.transport.sin6);
568c2ecf20Sopenharmony_ci	srx.transport.sin6.sin6_family	= AF_INET6;
578c2ecf20Sopenharmony_ci	srx.transport.sin6.sin6_port	= htons(AFS_CM_PORT);
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_ci	ret = rxrpc_sock_set_min_security_level(socket->sk,
608c2ecf20Sopenharmony_ci						RXRPC_SECURITY_ENCRYPT);
618c2ecf20Sopenharmony_ci	if (ret < 0)
628c2ecf20Sopenharmony_ci		goto error_2;
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ci	ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
658c2ecf20Sopenharmony_ci	if (ret == -EADDRINUSE) {
668c2ecf20Sopenharmony_ci		srx.transport.sin6.sin6_port = 0;
678c2ecf20Sopenharmony_ci		ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
688c2ecf20Sopenharmony_ci	}
698c2ecf20Sopenharmony_ci	if (ret < 0)
708c2ecf20Sopenharmony_ci		goto error_2;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	srx.srx_service = YFS_CM_SERVICE;
738c2ecf20Sopenharmony_ci	ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
748c2ecf20Sopenharmony_ci	if (ret < 0)
758c2ecf20Sopenharmony_ci		goto error_2;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci	/* Ideally, we'd turn on service upgrade here, but we can't because
788c2ecf20Sopenharmony_ci	 * OpenAFS is buggy and leaks the userStatus field from packet to
798c2ecf20Sopenharmony_ci	 * packet and between FS packets and CB packets - so if we try to do an
808c2ecf20Sopenharmony_ci	 * upgrade on an FS packet, OpenAFS will leak that into the CB packet
818c2ecf20Sopenharmony_ci	 * it sends back to us.
828c2ecf20Sopenharmony_ci	 */
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	rxrpc_kernel_new_call_notification(socket, afs_rx_new_call,
858c2ecf20Sopenharmony_ci					   afs_rx_discard_new_call);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	ret = kernel_listen(socket, INT_MAX);
888c2ecf20Sopenharmony_ci	if (ret < 0)
898c2ecf20Sopenharmony_ci		goto error_2;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	net->socket = socket;
928c2ecf20Sopenharmony_ci	afs_charge_preallocation(&net->charge_preallocation_work);
938c2ecf20Sopenharmony_ci	_leave(" = 0");
948c2ecf20Sopenharmony_ci	return 0;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cierror_2:
978c2ecf20Sopenharmony_ci	sock_release(socket);
988c2ecf20Sopenharmony_cierror_1:
998c2ecf20Sopenharmony_ci	_leave(" = %d", ret);
1008c2ecf20Sopenharmony_ci	return ret;
1018c2ecf20Sopenharmony_ci}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci/*
1048c2ecf20Sopenharmony_ci * close the RxRPC socket AFS was using
1058c2ecf20Sopenharmony_ci */
1068c2ecf20Sopenharmony_civoid afs_close_socket(struct afs_net *net)
1078c2ecf20Sopenharmony_ci{
1088c2ecf20Sopenharmony_ci	_enter("");
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	kernel_listen(net->socket, 0);
1118c2ecf20Sopenharmony_ci	flush_workqueue(afs_async_calls);
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci	if (net->spare_incoming_call) {
1148c2ecf20Sopenharmony_ci		afs_put_call(net->spare_incoming_call);
1158c2ecf20Sopenharmony_ci		net->spare_incoming_call = NULL;
1168c2ecf20Sopenharmony_ci	}
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci	_debug("outstanding %u", atomic_read(&net->nr_outstanding_calls));
1198c2ecf20Sopenharmony_ci	wait_var_event(&net->nr_outstanding_calls,
1208c2ecf20Sopenharmony_ci		       !atomic_read(&net->nr_outstanding_calls));
1218c2ecf20Sopenharmony_ci	_debug("no outstanding calls");
1228c2ecf20Sopenharmony_ci
1238c2ecf20Sopenharmony_ci	kernel_sock_shutdown(net->socket, SHUT_RDWR);
1248c2ecf20Sopenharmony_ci	flush_workqueue(afs_async_calls);
1258c2ecf20Sopenharmony_ci	sock_release(net->socket);
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci	_debug("dework");
1288c2ecf20Sopenharmony_ci	_leave("");
1298c2ecf20Sopenharmony_ci}
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci/*
1328c2ecf20Sopenharmony_ci * Allocate a call.
1338c2ecf20Sopenharmony_ci */
1348c2ecf20Sopenharmony_cistatic struct afs_call *afs_alloc_call(struct afs_net *net,
1358c2ecf20Sopenharmony_ci				       const struct afs_call_type *type,
1368c2ecf20Sopenharmony_ci				       gfp_t gfp)
1378c2ecf20Sopenharmony_ci{
1388c2ecf20Sopenharmony_ci	struct afs_call *call;
1398c2ecf20Sopenharmony_ci	int o;
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	call = kzalloc(sizeof(*call), gfp);
1428c2ecf20Sopenharmony_ci	if (!call)
1438c2ecf20Sopenharmony_ci		return NULL;
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci	call->type = type;
1468c2ecf20Sopenharmony_ci	call->net = net;
1478c2ecf20Sopenharmony_ci	call->debug_id = atomic_inc_return(&rxrpc_debug_id);
1488c2ecf20Sopenharmony_ci	atomic_set(&call->usage, 1);
1498c2ecf20Sopenharmony_ci	INIT_WORK(&call->async_work, afs_process_async_call);
1508c2ecf20Sopenharmony_ci	init_waitqueue_head(&call->waitq);
1518c2ecf20Sopenharmony_ci	spin_lock_init(&call->state_lock);
1528c2ecf20Sopenharmony_ci	call->iter = &call->def_iter;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	o = atomic_inc_return(&net->nr_outstanding_calls);
1558c2ecf20Sopenharmony_ci	trace_afs_call(call, afs_call_trace_alloc, 1, o,
1568c2ecf20Sopenharmony_ci		       __builtin_return_address(0));
1578c2ecf20Sopenharmony_ci	return call;
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci/*
1618c2ecf20Sopenharmony_ci * Dispose of a reference on a call.
1628c2ecf20Sopenharmony_ci */
1638c2ecf20Sopenharmony_civoid afs_put_call(struct afs_call *call)
1648c2ecf20Sopenharmony_ci{
1658c2ecf20Sopenharmony_ci	struct afs_net *net = call->net;
1668c2ecf20Sopenharmony_ci	int n = atomic_dec_return(&call->usage);
1678c2ecf20Sopenharmony_ci	int o = atomic_read(&net->nr_outstanding_calls);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_ci	trace_afs_call(call, afs_call_trace_put, n, o,
1708c2ecf20Sopenharmony_ci		       __builtin_return_address(0));
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	ASSERTCMP(n, >=, 0);
1738c2ecf20Sopenharmony_ci	if (n == 0) {
1748c2ecf20Sopenharmony_ci		ASSERT(!work_pending(&call->async_work));
1758c2ecf20Sopenharmony_ci		ASSERT(call->type->name != NULL);
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci		if (call->rxcall) {
1788c2ecf20Sopenharmony_ci			rxrpc_kernel_end_call(net->socket, call->rxcall);
1798c2ecf20Sopenharmony_ci			call->rxcall = NULL;
1808c2ecf20Sopenharmony_ci		}
1818c2ecf20Sopenharmony_ci		if (call->type->destructor)
1828c2ecf20Sopenharmony_ci			call->type->destructor(call);
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_ci		afs_unuse_server_notime(call->net, call->server, afs_server_trace_put_call);
1858c2ecf20Sopenharmony_ci		afs_put_addrlist(call->alist);
1868c2ecf20Sopenharmony_ci		kfree(call->request);
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci		trace_afs_call(call, afs_call_trace_free, 0, o,
1898c2ecf20Sopenharmony_ci			       __builtin_return_address(0));
1908c2ecf20Sopenharmony_ci		kfree(call);
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci		o = atomic_dec_return(&net->nr_outstanding_calls);
1938c2ecf20Sopenharmony_ci		if (o == 0)
1948c2ecf20Sopenharmony_ci			wake_up_var(&net->nr_outstanding_calls);
1958c2ecf20Sopenharmony_ci	}
1968c2ecf20Sopenharmony_ci}
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_cistatic struct afs_call *afs_get_call(struct afs_call *call,
1998c2ecf20Sopenharmony_ci				     enum afs_call_trace why)
2008c2ecf20Sopenharmony_ci{
2018c2ecf20Sopenharmony_ci	int u = atomic_inc_return(&call->usage);
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	trace_afs_call(call, why, u,
2048c2ecf20Sopenharmony_ci		       atomic_read(&call->net->nr_outstanding_calls),
2058c2ecf20Sopenharmony_ci		       __builtin_return_address(0));
2068c2ecf20Sopenharmony_ci	return call;
2078c2ecf20Sopenharmony_ci}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci/*
2108c2ecf20Sopenharmony_ci * Queue the call for actual work.
2118c2ecf20Sopenharmony_ci */
2128c2ecf20Sopenharmony_cistatic void afs_queue_call_work(struct afs_call *call)
2138c2ecf20Sopenharmony_ci{
2148c2ecf20Sopenharmony_ci	if (call->type->work) {
2158c2ecf20Sopenharmony_ci		INIT_WORK(&call->work, call->type->work);
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci		afs_get_call(call, afs_call_trace_work);
2188c2ecf20Sopenharmony_ci		if (!queue_work(afs_wq, &call->work))
2198c2ecf20Sopenharmony_ci			afs_put_call(call);
2208c2ecf20Sopenharmony_ci	}
2218c2ecf20Sopenharmony_ci}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci/*
2248c2ecf20Sopenharmony_ci * allocate a call with flat request and reply buffers
2258c2ecf20Sopenharmony_ci */
2268c2ecf20Sopenharmony_cistruct afs_call *afs_alloc_flat_call(struct afs_net *net,
2278c2ecf20Sopenharmony_ci				     const struct afs_call_type *type,
2288c2ecf20Sopenharmony_ci				     size_t request_size, size_t reply_max)
2298c2ecf20Sopenharmony_ci{
2308c2ecf20Sopenharmony_ci	struct afs_call *call;
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	call = afs_alloc_call(net, type, GFP_NOFS);
2338c2ecf20Sopenharmony_ci	if (!call)
2348c2ecf20Sopenharmony_ci		goto nomem_call;
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	if (request_size) {
2378c2ecf20Sopenharmony_ci		call->request_size = request_size;
2388c2ecf20Sopenharmony_ci		call->request = kmalloc(request_size, GFP_NOFS);
2398c2ecf20Sopenharmony_ci		if (!call->request)
2408c2ecf20Sopenharmony_ci			goto nomem_free;
2418c2ecf20Sopenharmony_ci	}
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	if (reply_max) {
2448c2ecf20Sopenharmony_ci		call->reply_max = reply_max;
2458c2ecf20Sopenharmony_ci		call->buffer = kmalloc(reply_max, GFP_NOFS);
2468c2ecf20Sopenharmony_ci		if (!call->buffer)
2478c2ecf20Sopenharmony_ci			goto nomem_free;
2488c2ecf20Sopenharmony_ci	}
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	afs_extract_to_buf(call, call->reply_max);
2518c2ecf20Sopenharmony_ci	call->operation_ID = type->op;
2528c2ecf20Sopenharmony_ci	init_waitqueue_head(&call->waitq);
2538c2ecf20Sopenharmony_ci	return call;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cinomem_free:
2568c2ecf20Sopenharmony_ci	afs_put_call(call);
2578c2ecf20Sopenharmony_cinomem_call:
2588c2ecf20Sopenharmony_ci	return NULL;
2598c2ecf20Sopenharmony_ci}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci/*
2628c2ecf20Sopenharmony_ci * clean up a call with flat buffer
2638c2ecf20Sopenharmony_ci */
2648c2ecf20Sopenharmony_civoid afs_flat_call_destructor(struct afs_call *call)
2658c2ecf20Sopenharmony_ci{
2668c2ecf20Sopenharmony_ci	_enter("");
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	kfree(call->request);
2698c2ecf20Sopenharmony_ci	call->request = NULL;
2708c2ecf20Sopenharmony_ci	kfree(call->buffer);
2718c2ecf20Sopenharmony_ci	call->buffer = NULL;
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci#define AFS_BVEC_MAX 8
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci/*
2778c2ecf20Sopenharmony_ci * Load the given bvec with the next few pages.
2788c2ecf20Sopenharmony_ci */
2798c2ecf20Sopenharmony_cistatic void afs_load_bvec(struct afs_call *call, struct msghdr *msg,
2808c2ecf20Sopenharmony_ci			  struct bio_vec *bv, pgoff_t first, pgoff_t last,
2818c2ecf20Sopenharmony_ci			  unsigned offset)
2828c2ecf20Sopenharmony_ci{
2838c2ecf20Sopenharmony_ci	struct afs_operation *op = call->op;
2848c2ecf20Sopenharmony_ci	struct page *pages[AFS_BVEC_MAX];
2858c2ecf20Sopenharmony_ci	unsigned int nr, n, i, to, bytes = 0;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	nr = min_t(pgoff_t, last - first + 1, AFS_BVEC_MAX);
2888c2ecf20Sopenharmony_ci	n = find_get_pages_contig(op->store.mapping, first, nr, pages);
2898c2ecf20Sopenharmony_ci	ASSERTCMP(n, ==, nr);
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	msg->msg_flags |= MSG_MORE;
2928c2ecf20Sopenharmony_ci	for (i = 0; i < nr; i++) {
2938c2ecf20Sopenharmony_ci		to = PAGE_SIZE;
2948c2ecf20Sopenharmony_ci		if (first + i >= last) {
2958c2ecf20Sopenharmony_ci			to = op->store.last_to;
2968c2ecf20Sopenharmony_ci			msg->msg_flags &= ~MSG_MORE;
2978c2ecf20Sopenharmony_ci		}
2988c2ecf20Sopenharmony_ci		bv[i].bv_page = pages[i];
2998c2ecf20Sopenharmony_ci		bv[i].bv_len = to - offset;
3008c2ecf20Sopenharmony_ci		bv[i].bv_offset = offset;
3018c2ecf20Sopenharmony_ci		bytes += to - offset;
3028c2ecf20Sopenharmony_ci		offset = 0;
3038c2ecf20Sopenharmony_ci	}
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	iov_iter_bvec(&msg->msg_iter, WRITE, bv, nr, bytes);
3068c2ecf20Sopenharmony_ci}
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci/*
3098c2ecf20Sopenharmony_ci * Advance the AFS call state when the RxRPC call ends the transmit phase.
3108c2ecf20Sopenharmony_ci */
3118c2ecf20Sopenharmony_cistatic void afs_notify_end_request_tx(struct sock *sock,
3128c2ecf20Sopenharmony_ci				      struct rxrpc_call *rxcall,
3138c2ecf20Sopenharmony_ci				      unsigned long call_user_ID)
3148c2ecf20Sopenharmony_ci{
3158c2ecf20Sopenharmony_ci	struct afs_call *call = (struct afs_call *)call_user_ID;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	afs_set_call_state(call, AFS_CALL_CL_REQUESTING, AFS_CALL_CL_AWAIT_REPLY);
3188c2ecf20Sopenharmony_ci}
3198c2ecf20Sopenharmony_ci
3208c2ecf20Sopenharmony_ci/*
3218c2ecf20Sopenharmony_ci * attach the data from a bunch of pages on an inode to a call
3228c2ecf20Sopenharmony_ci */
3238c2ecf20Sopenharmony_cistatic int afs_send_pages(struct afs_call *call, struct msghdr *msg)
3248c2ecf20Sopenharmony_ci{
3258c2ecf20Sopenharmony_ci	struct afs_operation *op = call->op;
3268c2ecf20Sopenharmony_ci	struct bio_vec bv[AFS_BVEC_MAX];
3278c2ecf20Sopenharmony_ci	unsigned int bytes, nr, loop, offset;
3288c2ecf20Sopenharmony_ci	pgoff_t first = op->store.first, last = op->store.last;
3298c2ecf20Sopenharmony_ci	int ret;
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci	offset = op->store.first_offset;
3328c2ecf20Sopenharmony_ci	op->store.first_offset = 0;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	do {
3358c2ecf20Sopenharmony_ci		afs_load_bvec(call, msg, bv, first, last, offset);
3368c2ecf20Sopenharmony_ci		trace_afs_send_pages(call, msg, first, last, offset);
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_ci		offset = 0;
3398c2ecf20Sopenharmony_ci		bytes = msg->msg_iter.count;
3408c2ecf20Sopenharmony_ci		nr = msg->msg_iter.nr_segs;
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci		ret = rxrpc_kernel_send_data(op->net->socket, call->rxcall, msg,
3438c2ecf20Sopenharmony_ci					     bytes, afs_notify_end_request_tx);
3448c2ecf20Sopenharmony_ci		for (loop = 0; loop < nr; loop++)
3458c2ecf20Sopenharmony_ci			put_page(bv[loop].bv_page);
3468c2ecf20Sopenharmony_ci		if (ret < 0)
3478c2ecf20Sopenharmony_ci			break;
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci		first += nr;
3508c2ecf20Sopenharmony_ci	} while (first <= last);
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	trace_afs_sent_pages(call, op->store.first, last, first, ret);
3538c2ecf20Sopenharmony_ci	return ret;
3548c2ecf20Sopenharmony_ci}
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci/*
3578c2ecf20Sopenharmony_ci * Initiate a call and synchronously queue up the parameters for dispatch.  Any
3588c2ecf20Sopenharmony_ci * error is stored into the call struct, which the caller must check for.
3598c2ecf20Sopenharmony_ci */
3608c2ecf20Sopenharmony_civoid afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp)
3618c2ecf20Sopenharmony_ci{
3628c2ecf20Sopenharmony_ci	struct sockaddr_rxrpc *srx = &ac->alist->addrs[ac->index];
3638c2ecf20Sopenharmony_ci	struct rxrpc_call *rxcall;
3648c2ecf20Sopenharmony_ci	struct msghdr msg;
3658c2ecf20Sopenharmony_ci	struct kvec iov[1];
3668c2ecf20Sopenharmony_ci	s64 tx_total_len;
3678c2ecf20Sopenharmony_ci	int ret;
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	_enter(",{%pISp},", &srx->transport);
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	ASSERT(call->type != NULL);
3728c2ecf20Sopenharmony_ci	ASSERT(call->type->name != NULL);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	_debug("____MAKE %p{%s,%x} [%d]____",
3758c2ecf20Sopenharmony_ci	       call, call->type->name, key_serial(call->key),
3768c2ecf20Sopenharmony_ci	       atomic_read(&call->net->nr_outstanding_calls));
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	call->addr_ix = ac->index;
3798c2ecf20Sopenharmony_ci	call->alist = afs_get_addrlist(ac->alist);
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	/* Work out the length we're going to transmit.  This is awkward for
3828c2ecf20Sopenharmony_ci	 * calls such as FS.StoreData where there's an extra injection of data
3838c2ecf20Sopenharmony_ci	 * after the initial fixed part.
3848c2ecf20Sopenharmony_ci	 */
3858c2ecf20Sopenharmony_ci	tx_total_len = call->request_size;
3868c2ecf20Sopenharmony_ci	if (call->send_pages) {
3878c2ecf20Sopenharmony_ci		struct afs_operation *op = call->op;
3888c2ecf20Sopenharmony_ci
3898c2ecf20Sopenharmony_ci		if (op->store.last == op->store.first) {
3908c2ecf20Sopenharmony_ci			tx_total_len += op->store.last_to - op->store.first_offset;
3918c2ecf20Sopenharmony_ci		} else {
3928c2ecf20Sopenharmony_ci			/* It looks mathematically like you should be able to
3938c2ecf20Sopenharmony_ci			 * combine the following lines with the ones above, but
3948c2ecf20Sopenharmony_ci			 * unsigned arithmetic is fun when it wraps...
3958c2ecf20Sopenharmony_ci			 */
3968c2ecf20Sopenharmony_ci			tx_total_len += PAGE_SIZE - op->store.first_offset;
3978c2ecf20Sopenharmony_ci			tx_total_len += op->store.last_to;
3988c2ecf20Sopenharmony_ci			tx_total_len += (op->store.last - op->store.first - 1) * PAGE_SIZE;
3998c2ecf20Sopenharmony_ci		}
4008c2ecf20Sopenharmony_ci	}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci	/* If the call is going to be asynchronous, we need an extra ref for
4038c2ecf20Sopenharmony_ci	 * the call to hold itself so the caller need not hang on to its ref.
4048c2ecf20Sopenharmony_ci	 */
4058c2ecf20Sopenharmony_ci	if (call->async) {
4068c2ecf20Sopenharmony_ci		afs_get_call(call, afs_call_trace_get);
4078c2ecf20Sopenharmony_ci		call->drop_ref = true;
4088c2ecf20Sopenharmony_ci	}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ci	/* create a call */
4118c2ecf20Sopenharmony_ci	rxcall = rxrpc_kernel_begin_call(call->net->socket, srx, call->key,
4128c2ecf20Sopenharmony_ci					 (unsigned long)call,
4138c2ecf20Sopenharmony_ci					 tx_total_len, gfp,
4148c2ecf20Sopenharmony_ci					 (call->async ?
4158c2ecf20Sopenharmony_ci					  afs_wake_up_async_call :
4168c2ecf20Sopenharmony_ci					  afs_wake_up_call_waiter),
4178c2ecf20Sopenharmony_ci					 call->upgrade,
4188c2ecf20Sopenharmony_ci					 (call->intr ? RXRPC_PREINTERRUPTIBLE :
4198c2ecf20Sopenharmony_ci					  RXRPC_UNINTERRUPTIBLE),
4208c2ecf20Sopenharmony_ci					 call->debug_id);
4218c2ecf20Sopenharmony_ci	if (IS_ERR(rxcall)) {
4228c2ecf20Sopenharmony_ci		ret = PTR_ERR(rxcall);
4238c2ecf20Sopenharmony_ci		call->error = ret;
4248c2ecf20Sopenharmony_ci		goto error_kill_call;
4258c2ecf20Sopenharmony_ci	}
4268c2ecf20Sopenharmony_ci
4278c2ecf20Sopenharmony_ci	call->rxcall = rxcall;
4288c2ecf20Sopenharmony_ci
4298c2ecf20Sopenharmony_ci	if (call->max_lifespan)
4308c2ecf20Sopenharmony_ci		rxrpc_kernel_set_max_life(call->net->socket, rxcall,
4318c2ecf20Sopenharmony_ci					  call->max_lifespan);
4328c2ecf20Sopenharmony_ci	call->issue_time = ktime_get_real();
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	/* send the request */
4358c2ecf20Sopenharmony_ci	iov[0].iov_base	= call->request;
4368c2ecf20Sopenharmony_ci	iov[0].iov_len	= call->request_size;
4378c2ecf20Sopenharmony_ci
4388c2ecf20Sopenharmony_ci	msg.msg_name		= NULL;
4398c2ecf20Sopenharmony_ci	msg.msg_namelen		= 0;
4408c2ecf20Sopenharmony_ci	iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, call->request_size);
4418c2ecf20Sopenharmony_ci	msg.msg_control		= NULL;
4428c2ecf20Sopenharmony_ci	msg.msg_controllen	= 0;
4438c2ecf20Sopenharmony_ci	msg.msg_flags		= MSG_WAITALL | (call->send_pages ? MSG_MORE : 0);
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci	ret = rxrpc_kernel_send_data(call->net->socket, rxcall,
4468c2ecf20Sopenharmony_ci				     &msg, call->request_size,
4478c2ecf20Sopenharmony_ci				     afs_notify_end_request_tx);
4488c2ecf20Sopenharmony_ci	if (ret < 0)
4498c2ecf20Sopenharmony_ci		goto error_do_abort;
4508c2ecf20Sopenharmony_ci
4518c2ecf20Sopenharmony_ci	if (call->send_pages) {
4528c2ecf20Sopenharmony_ci		ret = afs_send_pages(call, &msg);
4538c2ecf20Sopenharmony_ci		if (ret < 0)
4548c2ecf20Sopenharmony_ci			goto error_do_abort;
4558c2ecf20Sopenharmony_ci	}
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	/* Note that at this point, we may have received the reply or an abort
4588c2ecf20Sopenharmony_ci	 * - and an asynchronous call may already have completed.
4598c2ecf20Sopenharmony_ci	 *
4608c2ecf20Sopenharmony_ci	 * afs_wait_for_call_to_complete(call, ac)
4618c2ecf20Sopenharmony_ci	 * must be called to synchronously clean up.
4628c2ecf20Sopenharmony_ci	 */
4638c2ecf20Sopenharmony_ci	return;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_cierror_do_abort:
4668c2ecf20Sopenharmony_ci	if (ret != -ECONNABORTED) {
4678c2ecf20Sopenharmony_ci		rxrpc_kernel_abort_call(call->net->socket, rxcall,
4688c2ecf20Sopenharmony_ci					RX_USER_ABORT, ret, "KSD");
4698c2ecf20Sopenharmony_ci	} else {
4708c2ecf20Sopenharmony_ci		iov_iter_kvec(&msg.msg_iter, READ, NULL, 0, 0);
4718c2ecf20Sopenharmony_ci		rxrpc_kernel_recv_data(call->net->socket, rxcall,
4728c2ecf20Sopenharmony_ci				       &msg.msg_iter, false,
4738c2ecf20Sopenharmony_ci				       &call->abort_code, &call->service_id);
4748c2ecf20Sopenharmony_ci		ac->abort_code = call->abort_code;
4758c2ecf20Sopenharmony_ci		ac->responded = true;
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ci	call->error = ret;
4788c2ecf20Sopenharmony_ci	trace_afs_call_done(call);
4798c2ecf20Sopenharmony_cierror_kill_call:
4808c2ecf20Sopenharmony_ci	if (call->type->done)
4818c2ecf20Sopenharmony_ci		call->type->done(call);
4828c2ecf20Sopenharmony_ci
4838c2ecf20Sopenharmony_ci	/* We need to dispose of the extra ref we grabbed for an async call.
4848c2ecf20Sopenharmony_ci	 * The call, however, might be queued on afs_async_calls and we need to
4858c2ecf20Sopenharmony_ci	 * make sure we don't get any more notifications that might requeue it.
4868c2ecf20Sopenharmony_ci	 */
4878c2ecf20Sopenharmony_ci	if (call->rxcall) {
4888c2ecf20Sopenharmony_ci		rxrpc_kernel_end_call(call->net->socket, call->rxcall);
4898c2ecf20Sopenharmony_ci		call->rxcall = NULL;
4908c2ecf20Sopenharmony_ci	}
4918c2ecf20Sopenharmony_ci	if (call->async) {
4928c2ecf20Sopenharmony_ci		if (cancel_work_sync(&call->async_work))
4938c2ecf20Sopenharmony_ci			afs_put_call(call);
4948c2ecf20Sopenharmony_ci		afs_set_call_complete(call, ret, 0);
4958c2ecf20Sopenharmony_ci	}
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci	ac->error = ret;
4988c2ecf20Sopenharmony_ci	call->state = AFS_CALL_COMPLETE;
4998c2ecf20Sopenharmony_ci	_leave(" = %d", ret);
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci/*
5038c2ecf20Sopenharmony_ci * deliver messages to a call
5048c2ecf20Sopenharmony_ci */
5058c2ecf20Sopenharmony_cistatic void afs_deliver_to_call(struct afs_call *call)
5068c2ecf20Sopenharmony_ci{
5078c2ecf20Sopenharmony_ci	enum afs_call_state state;
5088c2ecf20Sopenharmony_ci	u32 abort_code, remote_abort = 0;
5098c2ecf20Sopenharmony_ci	int ret;
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	_enter("%s", call->type->name);
5128c2ecf20Sopenharmony_ci
5138c2ecf20Sopenharmony_ci	while (state = READ_ONCE(call->state),
5148c2ecf20Sopenharmony_ci	       state == AFS_CALL_CL_AWAIT_REPLY ||
5158c2ecf20Sopenharmony_ci	       state == AFS_CALL_SV_AWAIT_OP_ID ||
5168c2ecf20Sopenharmony_ci	       state == AFS_CALL_SV_AWAIT_REQUEST ||
5178c2ecf20Sopenharmony_ci	       state == AFS_CALL_SV_AWAIT_ACK
5188c2ecf20Sopenharmony_ci	       ) {
5198c2ecf20Sopenharmony_ci		if (state == AFS_CALL_SV_AWAIT_ACK) {
5208c2ecf20Sopenharmony_ci			iov_iter_kvec(&call->def_iter, READ, NULL, 0, 0);
5218c2ecf20Sopenharmony_ci			ret = rxrpc_kernel_recv_data(call->net->socket,
5228c2ecf20Sopenharmony_ci						     call->rxcall, &call->def_iter,
5238c2ecf20Sopenharmony_ci						     false, &remote_abort,
5248c2ecf20Sopenharmony_ci						     &call->service_id);
5258c2ecf20Sopenharmony_ci			trace_afs_receive_data(call, &call->def_iter, false, ret);
5268c2ecf20Sopenharmony_ci
5278c2ecf20Sopenharmony_ci			if (ret == -EINPROGRESS || ret == -EAGAIN)
5288c2ecf20Sopenharmony_ci				return;
5298c2ecf20Sopenharmony_ci			if (ret < 0 || ret == 1) {
5308c2ecf20Sopenharmony_ci				if (ret == 1)
5318c2ecf20Sopenharmony_ci					ret = 0;
5328c2ecf20Sopenharmony_ci				goto call_complete;
5338c2ecf20Sopenharmony_ci			}
5348c2ecf20Sopenharmony_ci			return;
5358c2ecf20Sopenharmony_ci		}
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci		ret = call->type->deliver(call);
5388c2ecf20Sopenharmony_ci		state = READ_ONCE(call->state);
5398c2ecf20Sopenharmony_ci		if (ret == 0 && call->unmarshalling_error)
5408c2ecf20Sopenharmony_ci			ret = -EBADMSG;
5418c2ecf20Sopenharmony_ci		switch (ret) {
5428c2ecf20Sopenharmony_ci		case 0:
5438c2ecf20Sopenharmony_ci			afs_queue_call_work(call);
5448c2ecf20Sopenharmony_ci			if (state == AFS_CALL_CL_PROC_REPLY) {
5458c2ecf20Sopenharmony_ci				if (call->op)
5468c2ecf20Sopenharmony_ci					set_bit(AFS_SERVER_FL_MAY_HAVE_CB,
5478c2ecf20Sopenharmony_ci						&call->op->server->flags);
5488c2ecf20Sopenharmony_ci				goto call_complete;
5498c2ecf20Sopenharmony_ci			}
5508c2ecf20Sopenharmony_ci			ASSERTCMP(state, >, AFS_CALL_CL_PROC_REPLY);
5518c2ecf20Sopenharmony_ci			goto done;
5528c2ecf20Sopenharmony_ci		case -EINPROGRESS:
5538c2ecf20Sopenharmony_ci		case -EAGAIN:
5548c2ecf20Sopenharmony_ci			goto out;
5558c2ecf20Sopenharmony_ci		case -ECONNABORTED:
5568c2ecf20Sopenharmony_ci			ASSERTCMP(state, ==, AFS_CALL_COMPLETE);
5578c2ecf20Sopenharmony_ci			goto done;
5588c2ecf20Sopenharmony_ci		case -ENOTSUPP:
5598c2ecf20Sopenharmony_ci			abort_code = RXGEN_OPCODE;
5608c2ecf20Sopenharmony_ci			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
5618c2ecf20Sopenharmony_ci						abort_code, ret, "KIV");
5628c2ecf20Sopenharmony_ci			goto local_abort;
5638c2ecf20Sopenharmony_ci		case -EIO:
5648c2ecf20Sopenharmony_ci			pr_err("kAFS: Call %u in bad state %u\n",
5658c2ecf20Sopenharmony_ci			       call->debug_id, state);
5668c2ecf20Sopenharmony_ci			fallthrough;
5678c2ecf20Sopenharmony_ci		case -ENODATA:
5688c2ecf20Sopenharmony_ci		case -EBADMSG:
5698c2ecf20Sopenharmony_ci		case -EMSGSIZE:
5708c2ecf20Sopenharmony_ci		case -ENOMEM:
5718c2ecf20Sopenharmony_ci		case -EFAULT:
5728c2ecf20Sopenharmony_ci			abort_code = RXGEN_CC_UNMARSHAL;
5738c2ecf20Sopenharmony_ci			if (state != AFS_CALL_CL_AWAIT_REPLY)
5748c2ecf20Sopenharmony_ci				abort_code = RXGEN_SS_UNMARSHAL;
5758c2ecf20Sopenharmony_ci			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
5768c2ecf20Sopenharmony_ci						abort_code, ret, "KUM");
5778c2ecf20Sopenharmony_ci			goto local_abort;
5788c2ecf20Sopenharmony_ci		default:
5798c2ecf20Sopenharmony_ci			abort_code = RX_CALL_DEAD;
5808c2ecf20Sopenharmony_ci			rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
5818c2ecf20Sopenharmony_ci						abort_code, ret, "KER");
5828c2ecf20Sopenharmony_ci			goto local_abort;
5838c2ecf20Sopenharmony_ci		}
5848c2ecf20Sopenharmony_ci	}
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_cidone:
5878c2ecf20Sopenharmony_ci	if (call->type->done)
5888c2ecf20Sopenharmony_ci		call->type->done(call);
5898c2ecf20Sopenharmony_ciout:
5908c2ecf20Sopenharmony_ci	_leave("");
5918c2ecf20Sopenharmony_ci	return;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_cilocal_abort:
5948c2ecf20Sopenharmony_ci	abort_code = 0;
5958c2ecf20Sopenharmony_cicall_complete:
5968c2ecf20Sopenharmony_ci	afs_set_call_complete(call, ret, remote_abort);
5978c2ecf20Sopenharmony_ci	state = AFS_CALL_COMPLETE;
5988c2ecf20Sopenharmony_ci	goto done;
5998c2ecf20Sopenharmony_ci}
6008c2ecf20Sopenharmony_ci
6018c2ecf20Sopenharmony_ci/*
6028c2ecf20Sopenharmony_ci * Wait synchronously for a call to complete and clean up the call struct.
6038c2ecf20Sopenharmony_ci */
6048c2ecf20Sopenharmony_cilong afs_wait_for_call_to_complete(struct afs_call *call,
6058c2ecf20Sopenharmony_ci				   struct afs_addr_cursor *ac)
6068c2ecf20Sopenharmony_ci{
6078c2ecf20Sopenharmony_ci	long ret;
6088c2ecf20Sopenharmony_ci	bool rxrpc_complete = false;
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	DECLARE_WAITQUEUE(myself, current);
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	_enter("");
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	ret = call->error;
6158c2ecf20Sopenharmony_ci	if (ret < 0)
6168c2ecf20Sopenharmony_ci		goto out;
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	add_wait_queue(&call->waitq, &myself);
6198c2ecf20Sopenharmony_ci	for (;;) {
6208c2ecf20Sopenharmony_ci		set_current_state(TASK_UNINTERRUPTIBLE);
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci		/* deliver any messages that are in the queue */
6238c2ecf20Sopenharmony_ci		if (!afs_check_call_state(call, AFS_CALL_COMPLETE) &&
6248c2ecf20Sopenharmony_ci		    call->need_attention) {
6258c2ecf20Sopenharmony_ci			call->need_attention = false;
6268c2ecf20Sopenharmony_ci			__set_current_state(TASK_RUNNING);
6278c2ecf20Sopenharmony_ci			afs_deliver_to_call(call);
6288c2ecf20Sopenharmony_ci			continue;
6298c2ecf20Sopenharmony_ci		}
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci		if (afs_check_call_state(call, AFS_CALL_COMPLETE))
6328c2ecf20Sopenharmony_ci			break;
6338c2ecf20Sopenharmony_ci
6348c2ecf20Sopenharmony_ci		if (!rxrpc_kernel_check_life(call->net->socket, call->rxcall)) {
6358c2ecf20Sopenharmony_ci			/* rxrpc terminated the call. */
6368c2ecf20Sopenharmony_ci			rxrpc_complete = true;
6378c2ecf20Sopenharmony_ci			break;
6388c2ecf20Sopenharmony_ci		}
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ci		schedule();
6418c2ecf20Sopenharmony_ci	}
6428c2ecf20Sopenharmony_ci
6438c2ecf20Sopenharmony_ci	remove_wait_queue(&call->waitq, &myself);
6448c2ecf20Sopenharmony_ci	__set_current_state(TASK_RUNNING);
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	if (!afs_check_call_state(call, AFS_CALL_COMPLETE)) {
6478c2ecf20Sopenharmony_ci		if (rxrpc_complete) {
6488c2ecf20Sopenharmony_ci			afs_set_call_complete(call, call->error, call->abort_code);
6498c2ecf20Sopenharmony_ci		} else {
6508c2ecf20Sopenharmony_ci			/* Kill off the call if it's still live. */
6518c2ecf20Sopenharmony_ci			_debug("call interrupted");
6528c2ecf20Sopenharmony_ci			if (rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
6538c2ecf20Sopenharmony_ci						    RX_USER_ABORT, -EINTR, "KWI"))
6548c2ecf20Sopenharmony_ci				afs_set_call_complete(call, -EINTR, 0);
6558c2ecf20Sopenharmony_ci		}
6568c2ecf20Sopenharmony_ci	}
6578c2ecf20Sopenharmony_ci
6588c2ecf20Sopenharmony_ci	spin_lock_bh(&call->state_lock);
6598c2ecf20Sopenharmony_ci	ac->abort_code = call->abort_code;
6608c2ecf20Sopenharmony_ci	ac->error = call->error;
6618c2ecf20Sopenharmony_ci	spin_unlock_bh(&call->state_lock);
6628c2ecf20Sopenharmony_ci
6638c2ecf20Sopenharmony_ci	ret = ac->error;
6648c2ecf20Sopenharmony_ci	switch (ret) {
6658c2ecf20Sopenharmony_ci	case 0:
6668c2ecf20Sopenharmony_ci		ret = call->ret0;
6678c2ecf20Sopenharmony_ci		call->ret0 = 0;
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci		fallthrough;
6708c2ecf20Sopenharmony_ci	case -ECONNABORTED:
6718c2ecf20Sopenharmony_ci		ac->responded = true;
6728c2ecf20Sopenharmony_ci		break;
6738c2ecf20Sopenharmony_ci	}
6748c2ecf20Sopenharmony_ci
6758c2ecf20Sopenharmony_ciout:
6768c2ecf20Sopenharmony_ci	_debug("call complete");
6778c2ecf20Sopenharmony_ci	afs_put_call(call);
6788c2ecf20Sopenharmony_ci	_leave(" = %p", (void *)ret);
6798c2ecf20Sopenharmony_ci	return ret;
6808c2ecf20Sopenharmony_ci}
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci/*
6838c2ecf20Sopenharmony_ci * wake up a waiting call
6848c2ecf20Sopenharmony_ci */
6858c2ecf20Sopenharmony_cistatic void afs_wake_up_call_waiter(struct sock *sk, struct rxrpc_call *rxcall,
6868c2ecf20Sopenharmony_ci				    unsigned long call_user_ID)
6878c2ecf20Sopenharmony_ci{
6888c2ecf20Sopenharmony_ci	struct afs_call *call = (struct afs_call *)call_user_ID;
6898c2ecf20Sopenharmony_ci
6908c2ecf20Sopenharmony_ci	call->need_attention = true;
6918c2ecf20Sopenharmony_ci	wake_up(&call->waitq);
6928c2ecf20Sopenharmony_ci}
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci/*
6958c2ecf20Sopenharmony_ci * wake up an asynchronous call
6968c2ecf20Sopenharmony_ci */
6978c2ecf20Sopenharmony_cistatic void afs_wake_up_async_call(struct sock *sk, struct rxrpc_call *rxcall,
6988c2ecf20Sopenharmony_ci				   unsigned long call_user_ID)
6998c2ecf20Sopenharmony_ci{
7008c2ecf20Sopenharmony_ci	struct afs_call *call = (struct afs_call *)call_user_ID;
7018c2ecf20Sopenharmony_ci	int u;
7028c2ecf20Sopenharmony_ci
7038c2ecf20Sopenharmony_ci	trace_afs_notify_call(rxcall, call);
7048c2ecf20Sopenharmony_ci	call->need_attention = true;
7058c2ecf20Sopenharmony_ci
7068c2ecf20Sopenharmony_ci	u = atomic_fetch_add_unless(&call->usage, 1, 0);
7078c2ecf20Sopenharmony_ci	if (u != 0) {
7088c2ecf20Sopenharmony_ci		trace_afs_call(call, afs_call_trace_wake, u + 1,
7098c2ecf20Sopenharmony_ci			       atomic_read(&call->net->nr_outstanding_calls),
7108c2ecf20Sopenharmony_ci			       __builtin_return_address(0));
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci		if (!queue_work(afs_async_calls, &call->async_work))
7138c2ecf20Sopenharmony_ci			afs_put_call(call);
7148c2ecf20Sopenharmony_ci	}
7158c2ecf20Sopenharmony_ci}
7168c2ecf20Sopenharmony_ci
7178c2ecf20Sopenharmony_ci/*
7188c2ecf20Sopenharmony_ci * Perform I/O processing on an asynchronous call.  The work item carries a ref
7198c2ecf20Sopenharmony_ci * to the call struct that we either need to release or to pass on.
7208c2ecf20Sopenharmony_ci */
7218c2ecf20Sopenharmony_cistatic void afs_process_async_call(struct work_struct *work)
7228c2ecf20Sopenharmony_ci{
7238c2ecf20Sopenharmony_ci	struct afs_call *call = container_of(work, struct afs_call, async_work);
7248c2ecf20Sopenharmony_ci
7258c2ecf20Sopenharmony_ci	_enter("");
7268c2ecf20Sopenharmony_ci
7278c2ecf20Sopenharmony_ci	if (call->state < AFS_CALL_COMPLETE && call->need_attention) {
7288c2ecf20Sopenharmony_ci		call->need_attention = false;
7298c2ecf20Sopenharmony_ci		afs_deliver_to_call(call);
7308c2ecf20Sopenharmony_ci	}
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	afs_put_call(call);
7338c2ecf20Sopenharmony_ci	_leave("");
7348c2ecf20Sopenharmony_ci}
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_cistatic void afs_rx_attach(struct rxrpc_call *rxcall, unsigned long user_call_ID)
7378c2ecf20Sopenharmony_ci{
7388c2ecf20Sopenharmony_ci	struct afs_call *call = (struct afs_call *)user_call_ID;
7398c2ecf20Sopenharmony_ci
7408c2ecf20Sopenharmony_ci	call->rxcall = rxcall;
7418c2ecf20Sopenharmony_ci}
7428c2ecf20Sopenharmony_ci
7438c2ecf20Sopenharmony_ci/*
7448c2ecf20Sopenharmony_ci * Charge the incoming call preallocation.
7458c2ecf20Sopenharmony_ci */
7468c2ecf20Sopenharmony_civoid afs_charge_preallocation(struct work_struct *work)
7478c2ecf20Sopenharmony_ci{
7488c2ecf20Sopenharmony_ci	struct afs_net *net =
7498c2ecf20Sopenharmony_ci		container_of(work, struct afs_net, charge_preallocation_work);
7508c2ecf20Sopenharmony_ci	struct afs_call *call = net->spare_incoming_call;
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	for (;;) {
7538c2ecf20Sopenharmony_ci		if (!call) {
7548c2ecf20Sopenharmony_ci			call = afs_alloc_call(net, &afs_RXCMxxxx, GFP_KERNEL);
7558c2ecf20Sopenharmony_ci			if (!call)
7568c2ecf20Sopenharmony_ci				break;
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_ci			call->drop_ref = true;
7598c2ecf20Sopenharmony_ci			call->async = true;
7608c2ecf20Sopenharmony_ci			call->state = AFS_CALL_SV_AWAIT_OP_ID;
7618c2ecf20Sopenharmony_ci			init_waitqueue_head(&call->waitq);
7628c2ecf20Sopenharmony_ci			afs_extract_to_tmp(call);
7638c2ecf20Sopenharmony_ci		}
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_ci		if (rxrpc_kernel_charge_accept(net->socket,
7668c2ecf20Sopenharmony_ci					       afs_wake_up_async_call,
7678c2ecf20Sopenharmony_ci					       afs_rx_attach,
7688c2ecf20Sopenharmony_ci					       (unsigned long)call,
7698c2ecf20Sopenharmony_ci					       GFP_KERNEL,
7708c2ecf20Sopenharmony_ci					       call->debug_id) < 0)
7718c2ecf20Sopenharmony_ci			break;
7728c2ecf20Sopenharmony_ci		call = NULL;
7738c2ecf20Sopenharmony_ci	}
7748c2ecf20Sopenharmony_ci	net->spare_incoming_call = call;
7758c2ecf20Sopenharmony_ci}
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci/*
7788c2ecf20Sopenharmony_ci * Discard a preallocated call when a socket is shut down.
7798c2ecf20Sopenharmony_ci */
7808c2ecf20Sopenharmony_cistatic void afs_rx_discard_new_call(struct rxrpc_call *rxcall,
7818c2ecf20Sopenharmony_ci				    unsigned long user_call_ID)
7828c2ecf20Sopenharmony_ci{
7838c2ecf20Sopenharmony_ci	struct afs_call *call = (struct afs_call *)user_call_ID;
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci	call->rxcall = NULL;
7868c2ecf20Sopenharmony_ci	afs_put_call(call);
7878c2ecf20Sopenharmony_ci}
7888c2ecf20Sopenharmony_ci
7898c2ecf20Sopenharmony_ci/*
7908c2ecf20Sopenharmony_ci * Notification of an incoming call.
7918c2ecf20Sopenharmony_ci */
7928c2ecf20Sopenharmony_cistatic void afs_rx_new_call(struct sock *sk, struct rxrpc_call *rxcall,
7938c2ecf20Sopenharmony_ci			    unsigned long user_call_ID)
7948c2ecf20Sopenharmony_ci{
7958c2ecf20Sopenharmony_ci	struct afs_net *net = afs_sock2net(sk);
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	queue_work(afs_wq, &net->charge_preallocation_work);
7988c2ecf20Sopenharmony_ci}
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci/*
8018c2ecf20Sopenharmony_ci * Grab the operation ID from an incoming cache manager call.  The socket
8028c2ecf20Sopenharmony_ci * buffer is discarded on error or if we don't yet have sufficient data.
8038c2ecf20Sopenharmony_ci */
8048c2ecf20Sopenharmony_cistatic int afs_deliver_cm_op_id(struct afs_call *call)
8058c2ecf20Sopenharmony_ci{
8068c2ecf20Sopenharmony_ci	int ret;
8078c2ecf20Sopenharmony_ci
8088c2ecf20Sopenharmony_ci	_enter("{%zu}", iov_iter_count(call->iter));
8098c2ecf20Sopenharmony_ci
8108c2ecf20Sopenharmony_ci	/* the operation ID forms the first four bytes of the request data */
8118c2ecf20Sopenharmony_ci	ret = afs_extract_data(call, true);
8128c2ecf20Sopenharmony_ci	if (ret < 0)
8138c2ecf20Sopenharmony_ci		return ret;
8148c2ecf20Sopenharmony_ci
8158c2ecf20Sopenharmony_ci	call->operation_ID = ntohl(call->tmp);
8168c2ecf20Sopenharmony_ci	afs_set_call_state(call, AFS_CALL_SV_AWAIT_OP_ID, AFS_CALL_SV_AWAIT_REQUEST);
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_ci	/* ask the cache manager to route the call (it'll change the call type
8198c2ecf20Sopenharmony_ci	 * if successful) */
8208c2ecf20Sopenharmony_ci	if (!afs_cm_incoming_call(call))
8218c2ecf20Sopenharmony_ci		return -ENOTSUPP;
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	trace_afs_cb_call(call);
8248c2ecf20Sopenharmony_ci
8258c2ecf20Sopenharmony_ci	/* pass responsibility for the remainer of this message off to the
8268c2ecf20Sopenharmony_ci	 * cache manager op */
8278c2ecf20Sopenharmony_ci	return call->type->deliver(call);
8288c2ecf20Sopenharmony_ci}
8298c2ecf20Sopenharmony_ci
8308c2ecf20Sopenharmony_ci/*
8318c2ecf20Sopenharmony_ci * Advance the AFS call state when an RxRPC service call ends the transmit
8328c2ecf20Sopenharmony_ci * phase.
8338c2ecf20Sopenharmony_ci */
8348c2ecf20Sopenharmony_cistatic void afs_notify_end_reply_tx(struct sock *sock,
8358c2ecf20Sopenharmony_ci				    struct rxrpc_call *rxcall,
8368c2ecf20Sopenharmony_ci				    unsigned long call_user_ID)
8378c2ecf20Sopenharmony_ci{
8388c2ecf20Sopenharmony_ci	struct afs_call *call = (struct afs_call *)call_user_ID;
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_ci	afs_set_call_state(call, AFS_CALL_SV_REPLYING, AFS_CALL_SV_AWAIT_ACK);
8418c2ecf20Sopenharmony_ci}
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci/*
8448c2ecf20Sopenharmony_ci * send an empty reply
8458c2ecf20Sopenharmony_ci */
8468c2ecf20Sopenharmony_civoid afs_send_empty_reply(struct afs_call *call)
8478c2ecf20Sopenharmony_ci{
8488c2ecf20Sopenharmony_ci	struct afs_net *net = call->net;
8498c2ecf20Sopenharmony_ci	struct msghdr msg;
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	_enter("");
8528c2ecf20Sopenharmony_ci
8538c2ecf20Sopenharmony_ci	rxrpc_kernel_set_tx_length(net->socket, call->rxcall, 0);
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	msg.msg_name		= NULL;
8568c2ecf20Sopenharmony_ci	msg.msg_namelen		= 0;
8578c2ecf20Sopenharmony_ci	iov_iter_kvec(&msg.msg_iter, WRITE, NULL, 0, 0);
8588c2ecf20Sopenharmony_ci	msg.msg_control		= NULL;
8598c2ecf20Sopenharmony_ci	msg.msg_controllen	= 0;
8608c2ecf20Sopenharmony_ci	msg.msg_flags		= 0;
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	switch (rxrpc_kernel_send_data(net->socket, call->rxcall, &msg, 0,
8638c2ecf20Sopenharmony_ci				       afs_notify_end_reply_tx)) {
8648c2ecf20Sopenharmony_ci	case 0:
8658c2ecf20Sopenharmony_ci		_leave(" [replied]");
8668c2ecf20Sopenharmony_ci		return;
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci	case -ENOMEM:
8698c2ecf20Sopenharmony_ci		_debug("oom");
8708c2ecf20Sopenharmony_ci		rxrpc_kernel_abort_call(net->socket, call->rxcall,
8718c2ecf20Sopenharmony_ci					RXGEN_SS_MARSHAL, -ENOMEM, "KOO");
8728c2ecf20Sopenharmony_ci		fallthrough;
8738c2ecf20Sopenharmony_ci	default:
8748c2ecf20Sopenharmony_ci		_leave(" [error]");
8758c2ecf20Sopenharmony_ci		return;
8768c2ecf20Sopenharmony_ci	}
8778c2ecf20Sopenharmony_ci}
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci/*
8808c2ecf20Sopenharmony_ci * send a simple reply
8818c2ecf20Sopenharmony_ci */
8828c2ecf20Sopenharmony_civoid afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
8838c2ecf20Sopenharmony_ci{
8848c2ecf20Sopenharmony_ci	struct afs_net *net = call->net;
8858c2ecf20Sopenharmony_ci	struct msghdr msg;
8868c2ecf20Sopenharmony_ci	struct kvec iov[1];
8878c2ecf20Sopenharmony_ci	int n;
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci	_enter("");
8908c2ecf20Sopenharmony_ci
8918c2ecf20Sopenharmony_ci	rxrpc_kernel_set_tx_length(net->socket, call->rxcall, len);
8928c2ecf20Sopenharmony_ci
8938c2ecf20Sopenharmony_ci	iov[0].iov_base		= (void *) buf;
8948c2ecf20Sopenharmony_ci	iov[0].iov_len		= len;
8958c2ecf20Sopenharmony_ci	msg.msg_name		= NULL;
8968c2ecf20Sopenharmony_ci	msg.msg_namelen		= 0;
8978c2ecf20Sopenharmony_ci	iov_iter_kvec(&msg.msg_iter, WRITE, iov, 1, len);
8988c2ecf20Sopenharmony_ci	msg.msg_control		= NULL;
8998c2ecf20Sopenharmony_ci	msg.msg_controllen	= 0;
9008c2ecf20Sopenharmony_ci	msg.msg_flags		= 0;
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_ci	n = rxrpc_kernel_send_data(net->socket, call->rxcall, &msg, len,
9038c2ecf20Sopenharmony_ci				   afs_notify_end_reply_tx);
9048c2ecf20Sopenharmony_ci	if (n >= 0) {
9058c2ecf20Sopenharmony_ci		/* Success */
9068c2ecf20Sopenharmony_ci		_leave(" [replied]");
9078c2ecf20Sopenharmony_ci		return;
9088c2ecf20Sopenharmony_ci	}
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	if (n == -ENOMEM) {
9118c2ecf20Sopenharmony_ci		_debug("oom");
9128c2ecf20Sopenharmony_ci		rxrpc_kernel_abort_call(net->socket, call->rxcall,
9138c2ecf20Sopenharmony_ci					RXGEN_SS_MARSHAL, -ENOMEM, "KOO");
9148c2ecf20Sopenharmony_ci	}
9158c2ecf20Sopenharmony_ci	_leave(" [error]");
9168c2ecf20Sopenharmony_ci}
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ci/*
9198c2ecf20Sopenharmony_ci * Extract a piece of data from the received data socket buffers.
9208c2ecf20Sopenharmony_ci */
9218c2ecf20Sopenharmony_ciint afs_extract_data(struct afs_call *call, bool want_more)
9228c2ecf20Sopenharmony_ci{
9238c2ecf20Sopenharmony_ci	struct afs_net *net = call->net;
9248c2ecf20Sopenharmony_ci	struct iov_iter *iter = call->iter;
9258c2ecf20Sopenharmony_ci	enum afs_call_state state;
9268c2ecf20Sopenharmony_ci	u32 remote_abort = 0;
9278c2ecf20Sopenharmony_ci	int ret;
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	_enter("{%s,%zu},%d", call->type->name, iov_iter_count(iter), want_more);
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	ret = rxrpc_kernel_recv_data(net->socket, call->rxcall, iter,
9328c2ecf20Sopenharmony_ci				     want_more, &remote_abort,
9338c2ecf20Sopenharmony_ci				     &call->service_id);
9348c2ecf20Sopenharmony_ci	if (ret == 0 || ret == -EAGAIN)
9358c2ecf20Sopenharmony_ci		return ret;
9368c2ecf20Sopenharmony_ci
9378c2ecf20Sopenharmony_ci	state = READ_ONCE(call->state);
9388c2ecf20Sopenharmony_ci	if (ret == 1) {
9398c2ecf20Sopenharmony_ci		switch (state) {
9408c2ecf20Sopenharmony_ci		case AFS_CALL_CL_AWAIT_REPLY:
9418c2ecf20Sopenharmony_ci			afs_set_call_state(call, state, AFS_CALL_CL_PROC_REPLY);
9428c2ecf20Sopenharmony_ci			break;
9438c2ecf20Sopenharmony_ci		case AFS_CALL_SV_AWAIT_REQUEST:
9448c2ecf20Sopenharmony_ci			afs_set_call_state(call, state, AFS_CALL_SV_REPLYING);
9458c2ecf20Sopenharmony_ci			break;
9468c2ecf20Sopenharmony_ci		case AFS_CALL_COMPLETE:
9478c2ecf20Sopenharmony_ci			kdebug("prem complete %d", call->error);
9488c2ecf20Sopenharmony_ci			return afs_io_error(call, afs_io_error_extract);
9498c2ecf20Sopenharmony_ci		default:
9508c2ecf20Sopenharmony_ci			break;
9518c2ecf20Sopenharmony_ci		}
9528c2ecf20Sopenharmony_ci		return 0;
9538c2ecf20Sopenharmony_ci	}
9548c2ecf20Sopenharmony_ci
9558c2ecf20Sopenharmony_ci	afs_set_call_complete(call, ret, remote_abort);
9568c2ecf20Sopenharmony_ci	return ret;
9578c2ecf20Sopenharmony_ci}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci/*
9608c2ecf20Sopenharmony_ci * Log protocol error production.
9618c2ecf20Sopenharmony_ci */
9628c2ecf20Sopenharmony_cinoinline int afs_protocol_error(struct afs_call *call,
9638c2ecf20Sopenharmony_ci				enum afs_eproto_cause cause)
9648c2ecf20Sopenharmony_ci{
9658c2ecf20Sopenharmony_ci	trace_afs_protocol_error(call, cause);
9668c2ecf20Sopenharmony_ci	if (call)
9678c2ecf20Sopenharmony_ci		call->unmarshalling_error = true;
9688c2ecf20Sopenharmony_ci	return -EBADMSG;
9698c2ecf20Sopenharmony_ci}
970