12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
208e0e7c8SDavid Howells /* Maintain an RxRPC server socket to do AFS communications through
308e0e7c8SDavid Howells *
408e0e7c8SDavid Howells * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
508e0e7c8SDavid Howells * Written by David Howells (dhowells@redhat.com)
608e0e7c8SDavid Howells */
708e0e7c8SDavid Howells
85a0e3ad6STejun Heo #include <linux/slab.h>
9174cd4b1SIngo Molnar #include <linux/sched/signal.h>
10174cd4b1SIngo Molnar
1108e0e7c8SDavid Howells #include <net/sock.h>
1208e0e7c8SDavid Howells #include <net/af_rxrpc.h>
1308e0e7c8SDavid Howells #include "internal.h"
1408e0e7c8SDavid Howells #include "afs_cm.h"
1535dbfba3SDavid Howells #include "protocol_yfs.h"
1657af281eSDavid Howells #define RXRPC_TRACE_ONLY_DEFINE_ENUMS
1757af281eSDavid Howells #include <trace/events/rxrpc.h>
1808e0e7c8SDavid Howells
19f044c884SDavid Howells struct workqueue_struct *afs_async_calls;
2008e0e7c8SDavid Howells
21d001648eSDavid Howells static void afs_wake_up_call_waiter(struct sock *, struct rxrpc_call *, unsigned long);
22d001648eSDavid Howells static void afs_wake_up_async_call(struct sock *, struct rxrpc_call *, unsigned long);
23d001648eSDavid Howells static void afs_process_async_call(struct work_struct *);
2400e90712SDavid Howells static void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned long);
2500e90712SDavid Howells static void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long);
26d001648eSDavid Howells static int afs_deliver_cm_op_id(struct afs_call *);
2708e0e7c8SDavid Howells
2808e0e7c8SDavid Howells /* asynchronous incoming call initial processing */
2908e0e7c8SDavid Howells static const struct afs_call_type afs_RXCMxxxx = {
3000d3b7a4SDavid Howells .name = "CB.xxxx",
3108e0e7c8SDavid Howells .deliver = afs_deliver_cm_op_id,
3208e0e7c8SDavid Howells };
3308e0e7c8SDavid Howells
3408e0e7c8SDavid Howells /*
3508e0e7c8SDavid Howells * open an RxRPC socket and bind it to be a server for callback notifications
3608e0e7c8SDavid Howells * - the socket is left in blocking mode and non-blocking ops use MSG_DONTWAIT
3708e0e7c8SDavid Howells */
afs_open_socket(struct afs_net * net)38f044c884SDavid Howells int afs_open_socket(struct afs_net *net)
3908e0e7c8SDavid Howells {
4008e0e7c8SDavid Howells struct sockaddr_rxrpc srx;
4108e0e7c8SDavid Howells struct socket *socket;
4208e0e7c8SDavid Howells int ret;
4308e0e7c8SDavid Howells
4408e0e7c8SDavid Howells _enter("");
4508e0e7c8SDavid Howells
465b86d4ffSDavid Howells ret = sock_create_kern(net->net, AF_RXRPC, SOCK_DGRAM, PF_INET6, &socket);
470e119b41SDavid Howells if (ret < 0)
480e119b41SDavid Howells goto error_1;
4908e0e7c8SDavid Howells
5008e0e7c8SDavid Howells socket->sk->sk_allocation = GFP_NOFS;
5108e0e7c8SDavid Howells
5208e0e7c8SDavid Howells /* bind the callback manager's address to make this a server socket */
533838d3ecSDavid Howells memset(&srx, 0, sizeof(srx));
5408e0e7c8SDavid Howells srx.srx_family = AF_RXRPC;
5508e0e7c8SDavid Howells srx.srx_service = CM_SERVICE;
5608e0e7c8SDavid Howells srx.transport_type = SOCK_DGRAM;
573838d3ecSDavid Howells srx.transport_len = sizeof(srx.transport.sin6);
583838d3ecSDavid Howells srx.transport.sin6.sin6_family = AF_INET6;
593838d3ecSDavid Howells srx.transport.sin6.sin6_port = htons(AFS_CM_PORT);
6008e0e7c8SDavid Howells
61298cd88aSChristoph Hellwig ret = rxrpc_sock_set_min_security_level(socket->sk,
62298cd88aSChristoph Hellwig RXRPC_SECURITY_ENCRYPT);
634776cab4SDavid Howells if (ret < 0)
644776cab4SDavid Howells goto error_2;
654776cab4SDavid Howells
6608e0e7c8SDavid Howells ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
6783732ec5SMarc Dionne if (ret == -EADDRINUSE) {
6883732ec5SMarc Dionne srx.transport.sin6.sin6_port = 0;
6983732ec5SMarc Dionne ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
7083732ec5SMarc Dionne }
710e119b41SDavid Howells if (ret < 0)
720e119b41SDavid Howells goto error_2;
730e119b41SDavid Howells
7435dbfba3SDavid Howells srx.srx_service = YFS_CM_SERVICE;
7535dbfba3SDavid Howells ret = kernel_bind(socket, (struct sockaddr *) &srx, sizeof(srx));
7635dbfba3SDavid Howells if (ret < 0)
7735dbfba3SDavid Howells goto error_2;
7835dbfba3SDavid Howells
793bf0fb6fSDavid Howells /* Ideally, we'd turn on service upgrade here, but we can't because
803bf0fb6fSDavid Howells * OpenAFS is buggy and leaks the userStatus field from packet to
813bf0fb6fSDavid Howells * packet and between FS packets and CB packets - so if we try to do an
823bf0fb6fSDavid Howells * upgrade on an FS packet, OpenAFS will leak that into the CB packet
833bf0fb6fSDavid Howells * it sends back to us.
843bf0fb6fSDavid Howells */
8535dbfba3SDavid Howells
8600e90712SDavid Howells rxrpc_kernel_new_call_notification(socket, afs_rx_new_call,
8700e90712SDavid Howells afs_rx_discard_new_call);
88d001648eSDavid Howells
890e119b41SDavid Howells ret = kernel_listen(socket, INT_MAX);
900e119b41SDavid Howells if (ret < 0)
910e119b41SDavid Howells goto error_2;
9208e0e7c8SDavid Howells
93f044c884SDavid Howells net->socket = socket;
94f044c884SDavid Howells afs_charge_preallocation(&net->charge_preallocation_work);
9508e0e7c8SDavid Howells _leave(" = 0");
9608e0e7c8SDavid Howells return 0;
970e119b41SDavid Howells
980e119b41SDavid Howells error_2:
990e119b41SDavid Howells sock_release(socket);
1000e119b41SDavid Howells error_1:
1010e119b41SDavid Howells _leave(" = %d", ret);
1020e119b41SDavid Howells return ret;
10308e0e7c8SDavid Howells }
10408e0e7c8SDavid Howells
10508e0e7c8SDavid Howells /*
10608e0e7c8SDavid Howells * close the RxRPC socket AFS was using
10708e0e7c8SDavid Howells */
afs_close_socket(struct afs_net * net)108f044c884SDavid Howells void afs_close_socket(struct afs_net *net)
10908e0e7c8SDavid Howells {
11008e0e7c8SDavid Howells _enter("");
11108e0e7c8SDavid Howells
112f044c884SDavid Howells kernel_listen(net->socket, 0);
113341f741fSDavid Howells flush_workqueue(afs_async_calls);
114341f741fSDavid Howells
115f044c884SDavid Howells if (net->spare_incoming_call) {
116f044c884SDavid Howells afs_put_call(net->spare_incoming_call);
117f044c884SDavid Howells net->spare_incoming_call = NULL;
11800e90712SDavid Howells }
11900e90712SDavid Howells
120f044c884SDavid Howells _debug("outstanding %u", atomic_read(&net->nr_outstanding_calls));
121ab1fbe32SPeter Zijlstra wait_var_event(&net->nr_outstanding_calls,
122ab1fbe32SPeter Zijlstra !atomic_read(&net->nr_outstanding_calls));
1232f02f7aeSDavid Howells _debug("no outstanding calls");
1242f02f7aeSDavid Howells
125f044c884SDavid Howells kernel_sock_shutdown(net->socket, SHUT_RDWR);
126248f219cSDavid Howells flush_workqueue(afs_async_calls);
127f044c884SDavid Howells sock_release(net->socket);
12808e0e7c8SDavid Howells
12908e0e7c8SDavid Howells _debug("dework");
13008e0e7c8SDavid Howells _leave("");
13108e0e7c8SDavid Howells }
13208e0e7c8SDavid Howells
13308e0e7c8SDavid Howells /*
134341f741fSDavid Howells * Allocate a call.
13500d3b7a4SDavid Howells */
afs_alloc_call(struct afs_net * net,const struct afs_call_type * type,gfp_t gfp)136f044c884SDavid Howells static struct afs_call *afs_alloc_call(struct afs_net *net,
137f044c884SDavid Howells const struct afs_call_type *type,
138341f741fSDavid Howells gfp_t gfp)
13900d3b7a4SDavid Howells {
140341f741fSDavid Howells struct afs_call *call;
141341f741fSDavid Howells int o;
14200d3b7a4SDavid Howells
143341f741fSDavid Howells call = kzalloc(sizeof(*call), gfp);
144341f741fSDavid Howells if (!call)
145341f741fSDavid Howells return NULL;
14600d3b7a4SDavid Howells
147341f741fSDavid Howells call->type = type;
148f044c884SDavid Howells call->net = net;
149a25e21f0SDavid Howells call->debug_id = atomic_inc_return(&rxrpc_debug_id);
150c56f9ec8SDavid Howells refcount_set(&call->ref, 1);
151341f741fSDavid Howells INIT_WORK(&call->async_work, afs_process_async_call);
152341f741fSDavid Howells init_waitqueue_head(&call->waitq);
15398bf40cdSDavid Howells spin_lock_init(&call->state_lock);
154fc276122SDavid Howells call->iter = &call->def_iter;
1552f02f7aeSDavid Howells
156f044c884SDavid Howells o = atomic_inc_return(&net->nr_outstanding_calls);
1572757a4dcSDavid Howells trace_afs_call(call->debug_id, afs_call_trace_alloc, 1, o,
158341f741fSDavid Howells __builtin_return_address(0));
159341f741fSDavid Howells return call;
16000d3b7a4SDavid Howells }
16100d3b7a4SDavid Howells
16200d3b7a4SDavid Howells /*
163341f741fSDavid Howells * Dispose of a reference on a call.
1646c67c7c3SDavid Howells */
afs_put_call(struct afs_call * call)165341f741fSDavid Howells void afs_put_call(struct afs_call *call)
1666c67c7c3SDavid Howells {
167f044c884SDavid Howells struct afs_net *net = call->net;
1682757a4dcSDavid Howells unsigned int debug_id = call->debug_id;
169c56f9ec8SDavid Howells bool zero;
170c56f9ec8SDavid Howells int r, o;
171341f741fSDavid Howells
172c56f9ec8SDavid Howells zero = __refcount_dec_and_test(&call->ref, &r);
173c56f9ec8SDavid Howells o = atomic_read(&net->nr_outstanding_calls);
1742757a4dcSDavid Howells trace_afs_call(debug_id, afs_call_trace_put, r - 1, o,
175341f741fSDavid Howells __builtin_return_address(0));
176341f741fSDavid Howells
177c56f9ec8SDavid Howells if (zero) {
178341f741fSDavid Howells ASSERT(!work_pending(&call->async_work));
179341f741fSDavid Howells ASSERT(call->type->name != NULL);
180341f741fSDavid Howells
1816c67c7c3SDavid Howells if (call->rxcall) {
182e0416e7dSDavid Howells rxrpc_kernel_shutdown_call(net->socket, call->rxcall);
183e0416e7dSDavid Howells rxrpc_kernel_put_call(net->socket, call->rxcall);
1846c67c7c3SDavid Howells call->rxcall = NULL;
1856c67c7c3SDavid Howells }
1866cf12869SNathaniel Wesley Filardo if (call->type->destructor)
1876c67c7c3SDavid Howells call->type->destructor(call);
188341f741fSDavid Howells
189977e5f8eSDavid Howells afs_unuse_server_notime(call->net, call->server, afs_server_trace_put_call);
1903bf0fb6fSDavid Howells afs_put_addrlist(call->alist);
191341f741fSDavid Howells kfree(call->request);
192a25e21f0SDavid Howells
1932757a4dcSDavid Howells trace_afs_call(call->debug_id, afs_call_trace_free, 0, o,
194a25e21f0SDavid Howells __builtin_return_address(0));
195341f741fSDavid Howells kfree(call);
196341f741fSDavid Howells
197f044c884SDavid Howells o = atomic_dec_return(&net->nr_outstanding_calls);
198341f741fSDavid Howells if (o == 0)
199ab1fbe32SPeter Zijlstra wake_up_var(&net->nr_outstanding_calls);
200341f741fSDavid Howells }
2016cf12869SNathaniel Wesley Filardo }
2026cf12869SNathaniel Wesley Filardo
afs_get_call(struct afs_call * call,enum afs_call_trace why)2037a75b007SDavid Howells static struct afs_call *afs_get_call(struct afs_call *call,
2047a75b007SDavid Howells enum afs_call_trace why)
2057a75b007SDavid Howells {
206c56f9ec8SDavid Howells int r;
2077a75b007SDavid Howells
208c56f9ec8SDavid Howells __refcount_inc(&call->ref, &r);
209c56f9ec8SDavid Howells
2102757a4dcSDavid Howells trace_afs_call(call->debug_id, why, r + 1,
2117a75b007SDavid Howells atomic_read(&call->net->nr_outstanding_calls),
2127a75b007SDavid Howells __builtin_return_address(0));
2137a75b007SDavid Howells return call;
2147a75b007SDavid Howells }
2157a75b007SDavid Howells
2166cf12869SNathaniel Wesley Filardo /*
2173bf0fb6fSDavid Howells * Queue the call for actual work.
2186cf12869SNathaniel Wesley Filardo */
afs_queue_call_work(struct afs_call * call)2193bf0fb6fSDavid Howells static void afs_queue_call_work(struct afs_call *call)
2206cf12869SNathaniel Wesley Filardo {
2213bf0fb6fSDavid Howells if (call->type->work) {
222341f741fSDavid Howells INIT_WORK(&call->work, call->type->work);
223341f741fSDavid Howells
2247a75b007SDavid Howells afs_get_call(call, afs_call_trace_work);
225341f741fSDavid Howells if (!queue_work(afs_wq, &call->work))
226341f741fSDavid Howells afs_put_call(call);
2273bf0fb6fSDavid Howells }
2286c67c7c3SDavid Howells }
2296c67c7c3SDavid Howells
2306c67c7c3SDavid Howells /*
23108e0e7c8SDavid Howells * allocate a call with flat request and reply buffers
23208e0e7c8SDavid Howells */
afs_alloc_flat_call(struct afs_net * net,const struct afs_call_type * type,size_t request_size,size_t reply_max)233f044c884SDavid Howells struct afs_call *afs_alloc_flat_call(struct afs_net *net,
234f044c884SDavid Howells const struct afs_call_type *type,
235d001648eSDavid Howells size_t request_size, size_t reply_max)
23608e0e7c8SDavid Howells {
23708e0e7c8SDavid Howells struct afs_call *call;
23808e0e7c8SDavid Howells
239f044c884SDavid Howells call = afs_alloc_call(net, type, GFP_NOFS);
24008e0e7c8SDavid Howells if (!call)
24108e0e7c8SDavid Howells goto nomem_call;
24208e0e7c8SDavid Howells
24300d3b7a4SDavid Howells if (request_size) {
244341f741fSDavid Howells call->request_size = request_size;
24500d3b7a4SDavid Howells call->request = kmalloc(request_size, GFP_NOFS);
24600d3b7a4SDavid Howells if (!call->request)
24700d3b7a4SDavid Howells goto nomem_free;
24800d3b7a4SDavid Howells }
24900d3b7a4SDavid Howells
250d001648eSDavid Howells if (reply_max) {
251341f741fSDavid Howells call->reply_max = reply_max;
252d001648eSDavid Howells call->buffer = kmalloc(reply_max, GFP_NOFS);
25300d3b7a4SDavid Howells if (!call->buffer)
25400d3b7a4SDavid Howells goto nomem_free;
25500d3b7a4SDavid Howells }
25600d3b7a4SDavid Howells
25712bdcf33SDavid Howells afs_extract_to_buf(call, call->reply_max);
258025db80cSDavid Howells call->operation_ID = type->op;
25908e0e7c8SDavid Howells init_waitqueue_head(&call->waitq);
26008e0e7c8SDavid Howells return call;
26108e0e7c8SDavid Howells
26200d3b7a4SDavid Howells nomem_free:
263341f741fSDavid Howells afs_put_call(call);
26408e0e7c8SDavid Howells nomem_call:
26508e0e7c8SDavid Howells return NULL;
26608e0e7c8SDavid Howells }
26708e0e7c8SDavid Howells
26808e0e7c8SDavid Howells /*
26908e0e7c8SDavid Howells * clean up a call with flat buffer
27008e0e7c8SDavid Howells */
afs_flat_call_destructor(struct afs_call * call)27108e0e7c8SDavid Howells void afs_flat_call_destructor(struct afs_call *call)
27208e0e7c8SDavid Howells {
27308e0e7c8SDavid Howells _enter("");
27408e0e7c8SDavid Howells
27508e0e7c8SDavid Howells kfree(call->request);
27608e0e7c8SDavid Howells call->request = NULL;
27708e0e7c8SDavid Howells kfree(call->buffer);
27808e0e7c8SDavid Howells call->buffer = NULL;
27908e0e7c8SDavid Howells }
28008e0e7c8SDavid Howells
28108e0e7c8SDavid Howells /*
282e833251aSDavid Howells * Advance the AFS call state when the RxRPC call ends the transmit phase.
283e833251aSDavid Howells */
afs_notify_end_request_tx(struct sock * sock,struct rxrpc_call * rxcall,unsigned long call_user_ID)284e833251aSDavid Howells static void afs_notify_end_request_tx(struct sock *sock,
285e833251aSDavid Howells struct rxrpc_call *rxcall,
286e833251aSDavid Howells unsigned long call_user_ID)
287e833251aSDavid Howells {
288e833251aSDavid Howells struct afs_call *call = (struct afs_call *)call_user_ID;
289e833251aSDavid Howells
29098bf40cdSDavid Howells afs_set_call_state(call, AFS_CALL_CL_REQUESTING, AFS_CALL_CL_AWAIT_REPLY);
291e833251aSDavid Howells }
292e833251aSDavid Howells
293e833251aSDavid Howells /*
2940b9bf381SDavid Howells * Initiate a call and synchronously queue up the parameters for dispatch. Any
2950b9bf381SDavid Howells * error is stored into the call struct, which the caller must check for.
29608e0e7c8SDavid Howells */
afs_make_call(struct afs_addr_cursor * ac,struct afs_call * call,gfp_t gfp)2970b9bf381SDavid Howells void afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call, gfp_t gfp)
29808e0e7c8SDavid Howells {
2992feeaf84SDavid Howells struct sockaddr_rxrpc *srx = &ac->alist->addrs[ac->index];
30008e0e7c8SDavid Howells struct rxrpc_call *rxcall;
30108e0e7c8SDavid Howells struct msghdr msg;
30208e0e7c8SDavid Howells struct kvec iov[1];
303f105da1aSDavid Howells size_t len;
304e754eba6SDavid Howells s64 tx_total_len;
30508e0e7c8SDavid Howells int ret;
30608e0e7c8SDavid Howells
3074d9df986SDavid Howells _enter(",{%pISp},", &srx->transport);
30808e0e7c8SDavid Howells
30900d3b7a4SDavid Howells ASSERT(call->type != NULL);
31000d3b7a4SDavid Howells ASSERT(call->type->name != NULL);
31100d3b7a4SDavid Howells
31231143d5dSDavid Howells _debug("____MAKE %p{%s,%x} [%d]____",
31331143d5dSDavid Howells call, call->type->name, key_serial(call->key),
314f044c884SDavid Howells atomic_read(&call->net->nr_outstanding_calls));
31500d3b7a4SDavid Howells
3163bf0fb6fSDavid Howells call->addr_ix = ac->index;
3173bf0fb6fSDavid Howells call->alist = afs_get_addrlist(ac->alist);
31808e0e7c8SDavid Howells
319e754eba6SDavid Howells /* Work out the length we're going to transmit. This is awkward for
320e754eba6SDavid Howells * calls such as FS.StoreData where there's an extra injection of data
321e754eba6SDavid Howells * after the initial fixed part.
322e754eba6SDavid Howells */
323e754eba6SDavid Howells tx_total_len = call->request_size;
324bd80d8a8SDavid Howells if (call->write_iter)
325bd80d8a8SDavid Howells tx_total_len += iov_iter_count(call->write_iter);
326e754eba6SDavid Howells
32734fa4761SDavid Howells /* If the call is going to be asynchronous, we need an extra ref for
32834fa4761SDavid Howells * the call to hold itself so the caller need not hang on to its ref.
32934fa4761SDavid Howells */
330dde9f095SDavid Howells if (call->async) {
33134fa4761SDavid Howells afs_get_call(call, afs_call_trace_get);
332dde9f095SDavid Howells call->drop_ref = true;
333dde9f095SDavid Howells }
33434fa4761SDavid Howells
33508e0e7c8SDavid Howells /* create a call */
3364d9df986SDavid Howells rxcall = rxrpc_kernel_begin_call(call->net->socket, srx, call->key,
337e754eba6SDavid Howells (unsigned long)call,
338db099c62SDavid Howells tx_total_len,
339db099c62SDavid Howells call->max_lifespan,
340db099c62SDavid Howells gfp,
3410b9bf381SDavid Howells (call->async ?
34256ff9c83SDavid Howells afs_wake_up_async_call :
343a68f4a27SDavid Howells afs_wake_up_call_waiter),
344a25e21f0SDavid Howells call->upgrade,
345e138aa7dSDavid Howells (call->intr ? RXRPC_PREINTERRUPTIBLE :
346e138aa7dSDavid Howells RXRPC_UNINTERRUPTIBLE),
347a25e21f0SDavid Howells call->debug_id);
34808e0e7c8SDavid Howells if (IS_ERR(rxcall)) {
34908e0e7c8SDavid Howells ret = PTR_ERR(rxcall);
3503bf0fb6fSDavid Howells call->error = ret;
35108e0e7c8SDavid Howells goto error_kill_call;
35208e0e7c8SDavid Howells }
35308e0e7c8SDavid Howells
35408e0e7c8SDavid Howells call->rxcall = rxcall;
3557903192cSDavid Howells call->issue_time = ktime_get_real();
35694f699c9SDavid Howells
35708e0e7c8SDavid Howells /* send the request */
35808e0e7c8SDavid Howells iov[0].iov_base = call->request;
35908e0e7c8SDavid Howells iov[0].iov_len = call->request_size;
36008e0e7c8SDavid Howells
36108e0e7c8SDavid Howells msg.msg_name = NULL;
36208e0e7c8SDavid Howells msg.msg_namelen = 0;
363de4eda9dSAl Viro iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, iov, 1, call->request_size);
36408e0e7c8SDavid Howells msg.msg_control = NULL;
36508e0e7c8SDavid Howells msg.msg_controllen = 0;
366bd80d8a8SDavid Howells msg.msg_flags = MSG_WAITALL | (call->write_iter ? MSG_MORE : 0);
36708e0e7c8SDavid Howells
368f044c884SDavid Howells ret = rxrpc_kernel_send_data(call->net->socket, rxcall,
369e833251aSDavid Howells &msg, call->request_size,
370e833251aSDavid Howells afs_notify_end_request_tx);
37108e0e7c8SDavid Howells if (ret < 0)
37208e0e7c8SDavid Howells goto error_do_abort;
37308e0e7c8SDavid Howells
374bd80d8a8SDavid Howells if (call->write_iter) {
375bd80d8a8SDavid Howells msg.msg_iter = *call->write_iter;
376bd80d8a8SDavid Howells msg.msg_flags &= ~MSG_MORE;
377bd80d8a8SDavid Howells trace_afs_send_data(call, &msg);
378bd80d8a8SDavid Howells
379bd80d8a8SDavid Howells ret = rxrpc_kernel_send_data(call->net->socket,
380bd80d8a8SDavid Howells call->rxcall, &msg,
381bd80d8a8SDavid Howells iov_iter_count(&msg.msg_iter),
382bd80d8a8SDavid Howells afs_notify_end_request_tx);
383bd80d8a8SDavid Howells *call->write_iter = msg.msg_iter;
384bd80d8a8SDavid Howells
385bd80d8a8SDavid Howells trace_afs_sent_data(call, &msg, ret);
38631143d5dSDavid Howells if (ret < 0)
38731143d5dSDavid Howells goto error_do_abort;
38831143d5dSDavid Howells }
38931143d5dSDavid Howells
39034fa4761SDavid Howells /* Note that at this point, we may have received the reply or an abort
39134fa4761SDavid Howells * - and an asynchronous call may already have completed.
3920b9bf381SDavid Howells *
3930b9bf381SDavid Howells * afs_wait_for_call_to_complete(call, ac)
3940b9bf381SDavid Howells * must be called to synchronously clean up.
39534fa4761SDavid Howells */
3960b9bf381SDavid Howells return;
39708e0e7c8SDavid Howells
39808e0e7c8SDavid Howells error_do_abort:
399*a5e15707SDavid Howells if (ret != -ECONNABORTED)
400f044c884SDavid Howells rxrpc_kernel_abort_call(call->net->socket, rxcall,
40157af281eSDavid Howells RX_USER_ABORT, ret,
40257af281eSDavid Howells afs_abort_send_data_error);
403*a5e15707SDavid Howells if (call->async) {
404*a5e15707SDavid Howells afs_see_call(call, afs_call_trace_async_abort);
405*a5e15707SDavid Howells return;
406*a5e15707SDavid Howells }
407*a5e15707SDavid Howells
408*a5e15707SDavid Howells if (ret == -ECONNABORTED) {
409f105da1aSDavid Howells len = 0;
410de4eda9dSAl Viro iov_iter_kvec(&msg.msg_iter, ITER_DEST, NULL, 0, 0);
411eb9950ebSDavid Howells rxrpc_kernel_recv_data(call->net->socket, rxcall,
412f105da1aSDavid Howells &msg.msg_iter, &len, false,
413eb9950ebSDavid Howells &call->abort_code, &call->service_id);
414d2ddc776SDavid Howells ac->abort_code = call->abort_code;
415d2ddc776SDavid Howells ac->responded = true;
41670af0e3bSDavid Howells }
417025db80cSDavid Howells call->error = ret;
418025db80cSDavid Howells trace_afs_call_done(call);
41908e0e7c8SDavid Howells error_kill_call:
420*a5e15707SDavid Howells if (call->async)
421*a5e15707SDavid Howells afs_see_call(call, afs_call_trace_async_kill);
4223bf0fb6fSDavid Howells if (call->type->done)
4233bf0fb6fSDavid Howells call->type->done(call);
42434fa4761SDavid Howells
42534fa4761SDavid Howells /* We need to dispose of the extra ref we grabbed for an async call.
42634fa4761SDavid Howells * The call, however, might be queued on afs_async_calls and we need to
42734fa4761SDavid Howells * make sure we don't get any more notifications that might requeue it.
42834fa4761SDavid Howells */
429e0416e7dSDavid Howells if (call->rxcall)
430e0416e7dSDavid Howells rxrpc_kernel_shutdown_call(call->net->socket, call->rxcall);
43134fa4761SDavid Howells if (call->async) {
43234fa4761SDavid Howells if (cancel_work_sync(&call->async_work))
433341f741fSDavid Howells afs_put_call(call);
4348715fe2fSDavid Howells afs_set_call_complete(call, ret, 0);
43534fa4761SDavid Howells }
43634fa4761SDavid Howells
437d2ddc776SDavid Howells ac->error = ret;
43834fa4761SDavid Howells call->state = AFS_CALL_COMPLETE;
43908e0e7c8SDavid Howells _leave(" = %d", ret);
44008e0e7c8SDavid Howells }
44108e0e7c8SDavid Howells
44208e0e7c8SDavid Howells /*
44305092755SDavid Howells * Log remote abort codes that indicate that we have a protocol disagreement
44405092755SDavid Howells * with the server.
44505092755SDavid Howells */
afs_log_error(struct afs_call * call,s32 remote_abort)44605092755SDavid Howells static void afs_log_error(struct afs_call *call, s32 remote_abort)
44705092755SDavid Howells {
44805092755SDavid Howells static int max = 0;
44905092755SDavid Howells const char *msg;
45005092755SDavid Howells int m;
45105092755SDavid Howells
45205092755SDavid Howells switch (remote_abort) {
45305092755SDavid Howells case RX_EOF: msg = "unexpected EOF"; break;
45405092755SDavid Howells case RXGEN_CC_MARSHAL: msg = "client marshalling"; break;
45505092755SDavid Howells case RXGEN_CC_UNMARSHAL: msg = "client unmarshalling"; break;
45605092755SDavid Howells case RXGEN_SS_MARSHAL: msg = "server marshalling"; break;
45705092755SDavid Howells case RXGEN_SS_UNMARSHAL: msg = "server unmarshalling"; break;
45805092755SDavid Howells case RXGEN_DECODE: msg = "opcode decode"; break;
45905092755SDavid Howells case RXGEN_SS_XDRFREE: msg = "server XDR cleanup"; break;
46005092755SDavid Howells case RXGEN_CC_XDRFREE: msg = "client XDR cleanup"; break;
46105092755SDavid Howells case -32: msg = "insufficient data"; break;
46205092755SDavid Howells default:
46305092755SDavid Howells return;
46405092755SDavid Howells }
46505092755SDavid Howells
46605092755SDavid Howells m = max;
46705092755SDavid Howells if (m < 3) {
46805092755SDavid Howells max = m + 1;
46905092755SDavid Howells pr_notice("kAFS: Peer reported %s failure on %s [%pISp]\n",
47005092755SDavid Howells msg, call->type->name,
47105092755SDavid Howells &call->alist->addrs[call->addr_ix].transport);
47205092755SDavid Howells }
47305092755SDavid Howells }
47405092755SDavid Howells
47505092755SDavid Howells /*
47608e0e7c8SDavid Howells * deliver messages to a call
47708e0e7c8SDavid Howells */
afs_deliver_to_call(struct afs_call * call)47808e0e7c8SDavid Howells static void afs_deliver_to_call(struct afs_call *call)
47908e0e7c8SDavid Howells {
48098bf40cdSDavid Howells enum afs_call_state state;
481f105da1aSDavid Howells size_t len;
48298bf40cdSDavid Howells u32 abort_code, remote_abort = 0;
48308e0e7c8SDavid Howells int ret;
48408e0e7c8SDavid Howells
485d001648eSDavid Howells _enter("%s", call->type->name);
48608e0e7c8SDavid Howells
48798bf40cdSDavid Howells while (state = READ_ONCE(call->state),
48898bf40cdSDavid Howells state == AFS_CALL_CL_AWAIT_REPLY ||
48998bf40cdSDavid Howells state == AFS_CALL_SV_AWAIT_OP_ID ||
49098bf40cdSDavid Howells state == AFS_CALL_SV_AWAIT_REQUEST ||
49198bf40cdSDavid Howells state == AFS_CALL_SV_AWAIT_ACK
492d001648eSDavid Howells ) {
49398bf40cdSDavid Howells if (state == AFS_CALL_SV_AWAIT_ACK) {
494f105da1aSDavid Howells len = 0;
495de4eda9dSAl Viro iov_iter_kvec(&call->def_iter, ITER_DEST, NULL, 0, 0);
496f044c884SDavid Howells ret = rxrpc_kernel_recv_data(call->net->socket,
497fc276122SDavid Howells call->rxcall, &call->def_iter,
498f105da1aSDavid Howells &len, false, &remote_abort,
499a68f4a27SDavid Howells &call->service_id);
500fc276122SDavid Howells trace_afs_receive_data(call, &call->def_iter, false, ret);
5018e8d7f13SDavid Howells
502d001648eSDavid Howells if (ret == -EINPROGRESS || ret == -EAGAIN)
503d001648eSDavid Howells return;
50498bf40cdSDavid Howells if (ret < 0 || ret == 1) {
50598bf40cdSDavid Howells if (ret == 1)
50698bf40cdSDavid Howells ret = 0;
507025db80cSDavid Howells goto call_complete;
50898bf40cdSDavid Howells }
509d001648eSDavid Howells return;
510d001648eSDavid Howells }
511d001648eSDavid Howells
512d001648eSDavid Howells ret = call->type->deliver(call);
51398bf40cdSDavid Howells state = READ_ONCE(call->state);
51438355eecSDavid Howells if (ret == 0 && call->unmarshalling_error)
51538355eecSDavid Howells ret = -EBADMSG;
516d001648eSDavid Howells switch (ret) {
51708e0e7c8SDavid Howells case 0:
5183bf0fb6fSDavid Howells afs_queue_call_work(call);
519f2686b09SDavid Howells if (state == AFS_CALL_CL_PROC_REPLY) {
52020325960SDavid Howells if (call->op)
521f2686b09SDavid Howells set_bit(AFS_SERVER_FL_MAY_HAVE_CB,
52220325960SDavid Howells &call->op->server->flags);
523025db80cSDavid Howells goto call_complete;
524f2686b09SDavid Howells }
52598bf40cdSDavid Howells ASSERTCMP(state, >, AFS_CALL_CL_PROC_REPLY);
526d001648eSDavid Howells goto done;
527d001648eSDavid Howells case -EINPROGRESS:
528d001648eSDavid Howells case -EAGAIN:
529d001648eSDavid Howells goto out;
53070af0e3bSDavid Howells case -ECONNABORTED:
53198bf40cdSDavid Howells ASSERTCMP(state, ==, AFS_CALL_COMPLETE);
53205092755SDavid Howells afs_log_error(call, call->abort_code);
53398bf40cdSDavid Howells goto done;
53408e0e7c8SDavid Howells case -ENOTSUPP:
5351157f153SDavid Howells abort_code = RXGEN_OPCODE;
536f044c884SDavid Howells rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
53757af281eSDavid Howells abort_code, ret,
53857af281eSDavid Howells afs_abort_op_not_supported);
53998bf40cdSDavid Howells goto local_abort;
5404ac15ea5SDavid Howells case -EIO:
5414ac15ea5SDavid Howells pr_err("kAFS: Call %u in bad state %u\n",
5424ac15ea5SDavid Howells call->debug_id, state);
543df561f66SGustavo A. R. Silva fallthrough;
544d001648eSDavid Howells case -ENODATA:
545d001648eSDavid Howells case -EBADMSG:
546d001648eSDavid Howells case -EMSGSIZE:
547de696c47SDavid Howells case -ENOMEM:
548de696c47SDavid Howells case -EFAULT:
54908e0e7c8SDavid Howells abort_code = RXGEN_CC_UNMARSHAL;
55098bf40cdSDavid Howells if (state != AFS_CALL_CL_AWAIT_REPLY)
55108e0e7c8SDavid Howells abort_code = RXGEN_SS_UNMARSHAL;
552f044c884SDavid Howells rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
55357af281eSDavid Howells abort_code, ret,
55457af281eSDavid Howells afs_abort_unmarshal_error);
55598bf40cdSDavid Howells goto local_abort;
5568022c4b9SDavid Howells default:
557de696c47SDavid Howells abort_code = RX_CALL_DEAD;
5588022c4b9SDavid Howells rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
55957af281eSDavid Howells abort_code, ret,
56057af281eSDavid Howells afs_abort_general_error);
5618022c4b9SDavid Howells goto local_abort;
56208e0e7c8SDavid Howells }
56308e0e7c8SDavid Howells }
56408e0e7c8SDavid Howells
565d001648eSDavid Howells done:
5663bf0fb6fSDavid Howells if (call->type->done)
5673bf0fb6fSDavid Howells call->type->done(call);
568d001648eSDavid Howells out:
56908e0e7c8SDavid Howells _leave("");
570d001648eSDavid Howells return;
571d001648eSDavid Howells
57298bf40cdSDavid Howells local_abort:
57398bf40cdSDavid Howells abort_code = 0;
574025db80cSDavid Howells call_complete:
57598bf40cdSDavid Howells afs_set_call_complete(call, ret, remote_abort);
576d001648eSDavid Howells goto done;
57708e0e7c8SDavid Howells }
57808e0e7c8SDavid Howells
57908e0e7c8SDavid Howells /*
5800b9bf381SDavid Howells * Wait synchronously for a call to complete and clean up the call struct.
58108e0e7c8SDavid Howells */
afs_wait_for_call_to_complete(struct afs_call * call,struct afs_addr_cursor * ac)5820b9bf381SDavid Howells long afs_wait_for_call_to_complete(struct afs_call *call,
583d2ddc776SDavid Howells struct afs_addr_cursor *ac)
58408e0e7c8SDavid Howells {
58533cd7f2bSDavid Howells long ret;
586f7f1dd31SMarc Dionne bool rxrpc_complete = false;
58708e0e7c8SDavid Howells
58808e0e7c8SDavid Howells DECLARE_WAITQUEUE(myself, current);
58908e0e7c8SDavid Howells
59008e0e7c8SDavid Howells _enter("");
59108e0e7c8SDavid Howells
5920b9bf381SDavid Howells ret = call->error;
5930b9bf381SDavid Howells if (ret < 0)
5940b9bf381SDavid Howells goto out;
5950b9bf381SDavid Howells
59608e0e7c8SDavid Howells add_wait_queue(&call->waitq, &myself);
59708e0e7c8SDavid Howells for (;;) {
598bc5e3a54SDavid Howells set_current_state(TASK_UNINTERRUPTIBLE);
59908e0e7c8SDavid Howells
60008e0e7c8SDavid Howells /* deliver any messages that are in the queue */
60198bf40cdSDavid Howells if (!afs_check_call_state(call, AFS_CALL_COMPLETE) &&
60298bf40cdSDavid Howells call->need_attention) {
603d001648eSDavid Howells call->need_attention = false;
60408e0e7c8SDavid Howells __set_current_state(TASK_RUNNING);
60508e0e7c8SDavid Howells afs_deliver_to_call(call);
60608e0e7c8SDavid Howells continue;
60708e0e7c8SDavid Howells }
60808e0e7c8SDavid Howells
60998bf40cdSDavid Howells if (afs_check_call_state(call, AFS_CALL_COMPLETE))
61008e0e7c8SDavid Howells break;
611bc5e3a54SDavid Howells
6127d7587dbSDavid Howells if (!rxrpc_kernel_check_life(call->net->socket, call->rxcall)) {
613f7f1dd31SMarc Dionne /* rxrpc terminated the call. */
614f7f1dd31SMarc Dionne rxrpc_complete = true;
615f7f1dd31SMarc Dionne break;
616f7f1dd31SMarc Dionne }
617f7f1dd31SMarc Dionne
6187d7587dbSDavid Howells schedule();
61908e0e7c8SDavid Howells }
62008e0e7c8SDavid Howells
62108e0e7c8SDavid Howells remove_wait_queue(&call->waitq, &myself);
62208e0e7c8SDavid Howells __set_current_state(TASK_RUNNING);
62308e0e7c8SDavid Howells
62498bf40cdSDavid Howells if (!afs_check_call_state(call, AFS_CALL_COMPLETE)) {
625f7f1dd31SMarc Dionne if (rxrpc_complete) {
626f7f1dd31SMarc Dionne afs_set_call_complete(call, call->error, call->abort_code);
627f7f1dd31SMarc Dionne } else {
628f7f1dd31SMarc Dionne /* Kill off the call if it's still live. */
629954cd6dcSDavid Howells _debug("call interrupted");
630d2ddc776SDavid Howells if (rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
63157af281eSDavid Howells RX_USER_ABORT, -EINTR,
63257af281eSDavid Howells afs_abort_interrupted))
63398bf40cdSDavid Howells afs_set_call_complete(call, -EINTR, 0);
63408e0e7c8SDavid Howells }
635f7f1dd31SMarc Dionne }
63608e0e7c8SDavid Howells
63798bf40cdSDavid Howells spin_lock_bh(&call->state_lock);
638d2ddc776SDavid Howells ac->abort_code = call->abort_code;
639d2ddc776SDavid Howells ac->error = call->error;
64098bf40cdSDavid Howells spin_unlock_bh(&call->state_lock);
641d2ddc776SDavid Howells
642d2ddc776SDavid Howells ret = ac->error;
643d2ddc776SDavid Howells switch (ret) {
644d2ddc776SDavid Howells case 0:
645ffba718eSDavid Howells ret = call->ret0;
646ffba718eSDavid Howells call->ret0 = 0;
647ffba718eSDavid Howells
648df561f66SGustavo A. R. Silva fallthrough;
649d2ddc776SDavid Howells case -ECONNABORTED:
650d2ddc776SDavid Howells ac->responded = true;
651d2ddc776SDavid Howells break;
652d2ddc776SDavid Howells }
65333cd7f2bSDavid Howells
6540b9bf381SDavid Howells out:
65508e0e7c8SDavid Howells _debug("call complete");
656341f741fSDavid Howells afs_put_call(call);
65733cd7f2bSDavid Howells _leave(" = %p", (void *)ret);
65808e0e7c8SDavid Howells return ret;
65908e0e7c8SDavid Howells }
66008e0e7c8SDavid Howells
66108e0e7c8SDavid Howells /*
66208e0e7c8SDavid Howells * wake up a waiting call
66308e0e7c8SDavid Howells */
afs_wake_up_call_waiter(struct sock * sk,struct rxrpc_call * rxcall,unsigned long call_user_ID)664d001648eSDavid Howells static void afs_wake_up_call_waiter(struct sock *sk, struct rxrpc_call *rxcall,
665d001648eSDavid Howells unsigned long call_user_ID)
66608e0e7c8SDavid Howells {
667d001648eSDavid Howells struct afs_call *call = (struct afs_call *)call_user_ID;
668d001648eSDavid Howells
669d001648eSDavid Howells call->need_attention = true;
67008e0e7c8SDavid Howells wake_up(&call->waitq);
67108e0e7c8SDavid Howells }
67208e0e7c8SDavid Howells
67308e0e7c8SDavid Howells /*
67408e0e7c8SDavid Howells * wake up an asynchronous call
67508e0e7c8SDavid Howells */
afs_wake_up_async_call(struct sock * sk,struct rxrpc_call * rxcall,unsigned long call_user_ID)676d001648eSDavid Howells static void afs_wake_up_async_call(struct sock *sk, struct rxrpc_call *rxcall,
677d001648eSDavid Howells unsigned long call_user_ID)
67808e0e7c8SDavid Howells {
679d001648eSDavid Howells struct afs_call *call = (struct afs_call *)call_user_ID;
680c56f9ec8SDavid Howells int r;
681d001648eSDavid Howells
6828e8d7f13SDavid Howells trace_afs_notify_call(rxcall, call);
683d001648eSDavid Howells call->need_attention = true;
684341f741fSDavid Howells
685c56f9ec8SDavid Howells if (__refcount_inc_not_zero(&call->ref, &r)) {
6862757a4dcSDavid Howells trace_afs_call(call->debug_id, afs_call_trace_wake, r + 1,
687f044c884SDavid Howells atomic_read(&call->net->nr_outstanding_calls),
688341f741fSDavid Howells __builtin_return_address(0));
689341f741fSDavid Howells
690341f741fSDavid Howells if (!queue_work(afs_async_calls, &call->async_work))
691341f741fSDavid Howells afs_put_call(call);
692341f741fSDavid Howells }
69308e0e7c8SDavid Howells }
69408e0e7c8SDavid Howells
69508e0e7c8SDavid Howells /*
696341f741fSDavid Howells * Perform I/O processing on an asynchronous call. The work item carries a ref
697341f741fSDavid Howells * to the call struct that we either need to release or to pass on.
69808e0e7c8SDavid Howells */
afs_process_async_call(struct work_struct * work)699d001648eSDavid Howells static void afs_process_async_call(struct work_struct *work)
70008e0e7c8SDavid Howells {
701d001648eSDavid Howells struct afs_call *call = container_of(work, struct afs_call, async_work);
702d001648eSDavid Howells
70308e0e7c8SDavid Howells _enter("");
70408e0e7c8SDavid Howells
705d001648eSDavid Howells if (call->state < AFS_CALL_COMPLETE && call->need_attention) {
706d001648eSDavid Howells call->need_attention = false;
70708e0e7c8SDavid Howells afs_deliver_to_call(call);
708d001648eSDavid Howells }
70908e0e7c8SDavid Howells
710341f741fSDavid Howells afs_put_call(call);
71108e0e7c8SDavid Howells _leave("");
71208e0e7c8SDavid Howells }
71308e0e7c8SDavid Howells
afs_rx_attach(struct rxrpc_call * rxcall,unsigned long user_call_ID)71400e90712SDavid Howells static void afs_rx_attach(struct rxrpc_call *rxcall, unsigned long user_call_ID)
71500e90712SDavid Howells {
71600e90712SDavid Howells struct afs_call *call = (struct afs_call *)user_call_ID;
71700e90712SDavid Howells
71800e90712SDavid Howells call->rxcall = rxcall;
71900e90712SDavid Howells }
72000e90712SDavid Howells
72100e90712SDavid Howells /*
72200e90712SDavid Howells * Charge the incoming call preallocation.
72300e90712SDavid Howells */
afs_charge_preallocation(struct work_struct * work)724f044c884SDavid Howells void afs_charge_preallocation(struct work_struct *work)
72500e90712SDavid Howells {
726f044c884SDavid Howells struct afs_net *net =
727f044c884SDavid Howells container_of(work, struct afs_net, charge_preallocation_work);
728f044c884SDavid Howells struct afs_call *call = net->spare_incoming_call;
72900e90712SDavid Howells
73000e90712SDavid Howells for (;;) {
73100e90712SDavid Howells if (!call) {
732f044c884SDavid Howells call = afs_alloc_call(net, &afs_RXCMxxxx, GFP_KERNEL);
73300e90712SDavid Howells if (!call)
73400e90712SDavid Howells break;
73500e90712SDavid Howells
736dde9f095SDavid Howells call->drop_ref = true;
73756ff9c83SDavid Howells call->async = true;
73898bf40cdSDavid Howells call->state = AFS_CALL_SV_AWAIT_OP_ID;
73956ff9c83SDavid Howells init_waitqueue_head(&call->waitq);
74012bdcf33SDavid Howells afs_extract_to_tmp(call);
74100e90712SDavid Howells }
74200e90712SDavid Howells
743f044c884SDavid Howells if (rxrpc_kernel_charge_accept(net->socket,
74400e90712SDavid Howells afs_wake_up_async_call,
74500e90712SDavid Howells afs_rx_attach,
74600e90712SDavid Howells (unsigned long)call,
747a25e21f0SDavid Howells GFP_KERNEL,
748a25e21f0SDavid Howells call->debug_id) < 0)
74900e90712SDavid Howells break;
75000e90712SDavid Howells call = NULL;
75100e90712SDavid Howells }
752f044c884SDavid Howells net->spare_incoming_call = call;
75300e90712SDavid Howells }
75400e90712SDavid Howells
75500e90712SDavid Howells /*
75600e90712SDavid Howells * Discard a preallocated call when a socket is shut down.
75700e90712SDavid Howells */
afs_rx_discard_new_call(struct rxrpc_call * rxcall,unsigned long user_call_ID)75800e90712SDavid Howells static void afs_rx_discard_new_call(struct rxrpc_call *rxcall,
75900e90712SDavid Howells unsigned long user_call_ID)
76000e90712SDavid Howells {
76100e90712SDavid Howells struct afs_call *call = (struct afs_call *)user_call_ID;
76200e90712SDavid Howells
76300e90712SDavid Howells call->rxcall = NULL;
764341f741fSDavid Howells afs_put_call(call);
76500e90712SDavid Howells }
76600e90712SDavid Howells
76708e0e7c8SDavid Howells /*
768d001648eSDavid Howells * Notification of an incoming call.
769d001648eSDavid Howells */
afs_rx_new_call(struct sock * sk,struct rxrpc_call * rxcall,unsigned long user_call_ID)77000e90712SDavid Howells static void afs_rx_new_call(struct sock *sk, struct rxrpc_call *rxcall,
77100e90712SDavid Howells unsigned long user_call_ID)
772d001648eSDavid Howells {
773f044c884SDavid Howells struct afs_net *net = afs_sock2net(sk);
774f044c884SDavid Howells
775f044c884SDavid Howells queue_work(afs_wq, &net->charge_preallocation_work);
776d001648eSDavid Howells }
777d001648eSDavid Howells
778d001648eSDavid Howells /*
779372ee163SDavid Howells * Grab the operation ID from an incoming cache manager call. The socket
780372ee163SDavid Howells * buffer is discarded on error or if we don't yet have sufficient data.
78108e0e7c8SDavid Howells */
afs_deliver_cm_op_id(struct afs_call * call)782d001648eSDavid Howells static int afs_deliver_cm_op_id(struct afs_call *call)
78308e0e7c8SDavid Howells {
784d001648eSDavid Howells int ret;
78508e0e7c8SDavid Howells
786fc276122SDavid Howells _enter("{%zu}", iov_iter_count(call->iter));
78708e0e7c8SDavid Howells
78808e0e7c8SDavid Howells /* the operation ID forms the first four bytes of the request data */
78912bdcf33SDavid Howells ret = afs_extract_data(call, true);
790d001648eSDavid Howells if (ret < 0)
791d001648eSDavid Howells return ret;
79208e0e7c8SDavid Howells
79350a2c953SDavid Howells call->operation_ID = ntohl(call->tmp);
79498bf40cdSDavid Howells afs_set_call_state(call, AFS_CALL_SV_AWAIT_OP_ID, AFS_CALL_SV_AWAIT_REQUEST);
79508e0e7c8SDavid Howells
79608e0e7c8SDavid Howells /* ask the cache manager to route the call (it'll change the call type
79708e0e7c8SDavid Howells * if successful) */
79808e0e7c8SDavid Howells if (!afs_cm_incoming_call(call))
79908e0e7c8SDavid Howells return -ENOTSUPP;
80008e0e7c8SDavid Howells
8018e8d7f13SDavid Howells trace_afs_cb_call(call);
8028e8d7f13SDavid Howells
80308e0e7c8SDavid Howells /* pass responsibility for the remainer of this message off to the
80408e0e7c8SDavid Howells * cache manager op */
805d001648eSDavid Howells return call->type->deliver(call);
80608e0e7c8SDavid Howells }
80708e0e7c8SDavid Howells
80808e0e7c8SDavid Howells /*
809e833251aSDavid Howells * Advance the AFS call state when an RxRPC service call ends the transmit
810e833251aSDavid Howells * phase.
811e833251aSDavid Howells */
afs_notify_end_reply_tx(struct sock * sock,struct rxrpc_call * rxcall,unsigned long call_user_ID)812e833251aSDavid Howells static void afs_notify_end_reply_tx(struct sock *sock,
813e833251aSDavid Howells struct rxrpc_call *rxcall,
814e833251aSDavid Howells unsigned long call_user_ID)
815e833251aSDavid Howells {
816e833251aSDavid Howells struct afs_call *call = (struct afs_call *)call_user_ID;
817e833251aSDavid Howells
81898bf40cdSDavid Howells afs_set_call_state(call, AFS_CALL_SV_REPLYING, AFS_CALL_SV_AWAIT_ACK);
819e833251aSDavid Howells }
820e833251aSDavid Howells
821e833251aSDavid Howells /*
82208e0e7c8SDavid Howells * send an empty reply
82308e0e7c8SDavid Howells */
afs_send_empty_reply(struct afs_call * call)82408e0e7c8SDavid Howells void afs_send_empty_reply(struct afs_call *call)
82508e0e7c8SDavid Howells {
826f044c884SDavid Howells struct afs_net *net = call->net;
82708e0e7c8SDavid Howells struct msghdr msg;
82808e0e7c8SDavid Howells
82908e0e7c8SDavid Howells _enter("");
83008e0e7c8SDavid Howells
831f044c884SDavid Howells rxrpc_kernel_set_tx_length(net->socket, call->rxcall, 0);
832e754eba6SDavid Howells
83308e0e7c8SDavid Howells msg.msg_name = NULL;
83408e0e7c8SDavid Howells msg.msg_namelen = 0;
835de4eda9dSAl Viro iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, NULL, 0, 0);
83608e0e7c8SDavid Howells msg.msg_control = NULL;
83708e0e7c8SDavid Howells msg.msg_controllen = 0;
83808e0e7c8SDavid Howells msg.msg_flags = 0;
83908e0e7c8SDavid Howells
840f044c884SDavid Howells switch (rxrpc_kernel_send_data(net->socket, call->rxcall, &msg, 0,
841e833251aSDavid Howells afs_notify_end_reply_tx)) {
84208e0e7c8SDavid Howells case 0:
84308e0e7c8SDavid Howells _leave(" [replied]");
84408e0e7c8SDavid Howells return;
84508e0e7c8SDavid Howells
84608e0e7c8SDavid Howells case -ENOMEM:
84708e0e7c8SDavid Howells _debug("oom");
848f044c884SDavid Howells rxrpc_kernel_abort_call(net->socket, call->rxcall,
84957af281eSDavid Howells RXGEN_SS_MARSHAL, -ENOMEM,
85057af281eSDavid Howells afs_abort_oom);
851df561f66SGustavo A. R. Silva fallthrough;
85208e0e7c8SDavid Howells default:
85308e0e7c8SDavid Howells _leave(" [error]");
85408e0e7c8SDavid Howells return;
85508e0e7c8SDavid Howells }
85608e0e7c8SDavid Howells }
85708e0e7c8SDavid Howells
85808e0e7c8SDavid Howells /*
859b908fe6bSDavid Howells * send a simple reply
860b908fe6bSDavid Howells */
afs_send_simple_reply(struct afs_call * call,const void * buf,size_t len)861b908fe6bSDavid Howells void afs_send_simple_reply(struct afs_call *call, const void *buf, size_t len)
862b908fe6bSDavid Howells {
863f044c884SDavid Howells struct afs_net *net = call->net;
864b908fe6bSDavid Howells struct msghdr msg;
8652e90b1c4SAl Viro struct kvec iov[1];
866bd6dc742SDavid Howells int n;
867b908fe6bSDavid Howells
868b908fe6bSDavid Howells _enter("");
869b908fe6bSDavid Howells
870f044c884SDavid Howells rxrpc_kernel_set_tx_length(net->socket, call->rxcall, len);
871e754eba6SDavid Howells
872b908fe6bSDavid Howells iov[0].iov_base = (void *) buf;
873b908fe6bSDavid Howells iov[0].iov_len = len;
874b908fe6bSDavid Howells msg.msg_name = NULL;
875b908fe6bSDavid Howells msg.msg_namelen = 0;
876de4eda9dSAl Viro iov_iter_kvec(&msg.msg_iter, ITER_SOURCE, iov, 1, len);
877b908fe6bSDavid Howells msg.msg_control = NULL;
878b908fe6bSDavid Howells msg.msg_controllen = 0;
879b908fe6bSDavid Howells msg.msg_flags = 0;
880b908fe6bSDavid Howells
881f044c884SDavid Howells n = rxrpc_kernel_send_data(net->socket, call->rxcall, &msg, len,
882e833251aSDavid Howells afs_notify_end_reply_tx);
883bd6dc742SDavid Howells if (n >= 0) {
8846c67c7c3SDavid Howells /* Success */
885b908fe6bSDavid Howells _leave(" [replied]");
886b908fe6bSDavid Howells return;
887bd6dc742SDavid Howells }
8886c67c7c3SDavid Howells
889bd6dc742SDavid Howells if (n == -ENOMEM) {
890b908fe6bSDavid Howells _debug("oom");
891f044c884SDavid Howells rxrpc_kernel_abort_call(net->socket, call->rxcall,
89257af281eSDavid Howells RXGEN_SS_MARSHAL, -ENOMEM,
89357af281eSDavid Howells afs_abort_oom);
894bd6dc742SDavid Howells }
895b908fe6bSDavid Howells _leave(" [error]");
896b908fe6bSDavid Howells }
897b908fe6bSDavid Howells
898b908fe6bSDavid Howells /*
899372ee163SDavid Howells * Extract a piece of data from the received data socket buffers.
90008e0e7c8SDavid Howells */
afs_extract_data(struct afs_call * call,bool want_more)90112bdcf33SDavid Howells int afs_extract_data(struct afs_call *call, bool want_more)
90208e0e7c8SDavid Howells {
903f044c884SDavid Howells struct afs_net *net = call->net;
904fc276122SDavid Howells struct iov_iter *iter = call->iter;
90598bf40cdSDavid Howells enum afs_call_state state;
9067888da95SDan Carpenter u32 remote_abort = 0;
907d001648eSDavid Howells int ret;
90808e0e7c8SDavid Howells
909f105da1aSDavid Howells _enter("{%s,%zu,%zu},%d",
910f105da1aSDavid Howells call->type->name, call->iov_len, iov_iter_count(iter), want_more);
91108e0e7c8SDavid Howells
91212bdcf33SDavid Howells ret = rxrpc_kernel_recv_data(net->socket, call->rxcall, iter,
913f105da1aSDavid Howells &call->iov_len, want_more, &remote_abort,
914a68f4a27SDavid Howells &call->service_id);
91593368b6bSDavid Howells trace_afs_receive_data(call, call->iter, want_more, ret);
916d001648eSDavid Howells if (ret == 0 || ret == -EAGAIN)
917d001648eSDavid Howells return ret;
91808e0e7c8SDavid Howells
91998bf40cdSDavid Howells state = READ_ONCE(call->state);
920d001648eSDavid Howells if (ret == 1) {
92198bf40cdSDavid Howells switch (state) {
92298bf40cdSDavid Howells case AFS_CALL_CL_AWAIT_REPLY:
92398bf40cdSDavid Howells afs_set_call_state(call, state, AFS_CALL_CL_PROC_REPLY);
924d001648eSDavid Howells break;
92598bf40cdSDavid Howells case AFS_CALL_SV_AWAIT_REQUEST:
92698bf40cdSDavid Howells afs_set_call_state(call, state, AFS_CALL_SV_REPLYING);
927d001648eSDavid Howells break;
92898bf40cdSDavid Howells case AFS_CALL_COMPLETE:
92998bf40cdSDavid Howells kdebug("prem complete %d", call->error);
930f51375cdSDavid Howells return afs_io_error(call, afs_io_error_extract);
931d001648eSDavid Howells default:
932d001648eSDavid Howells break;
93308e0e7c8SDavid Howells }
93408e0e7c8SDavid Howells return 0;
93508e0e7c8SDavid Howells }
936d001648eSDavid Howells
93798bf40cdSDavid Howells afs_set_call_complete(call, ret, remote_abort);
938d001648eSDavid Howells return ret;
939d001648eSDavid Howells }
9405f702c8eSDavid Howells
9415f702c8eSDavid Howells /*
9425f702c8eSDavid Howells * Log protocol error production.
9435f702c8eSDavid Howells */
afs_protocol_error(struct afs_call * call,enum afs_eproto_cause cause)9447126ead9SDavid Howells noinline int afs_protocol_error(struct afs_call *call,
945160cb957SDavid Howells enum afs_eproto_cause cause)
9465f702c8eSDavid Howells {
9477126ead9SDavid Howells trace_afs_protocol_error(call, cause);
94838355eecSDavid Howells if (call)
94938355eecSDavid Howells call->unmarshalling_error = true;
9507126ead9SDavid Howells return -EBADMSG;
9515f702c8eSDavid Howells }
952