1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /* AFS Cache Manager Service
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
5*4882a593Smuzhiyun * Written by David Howells (dhowells@redhat.com)
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <linux/module.h>
9*4882a593Smuzhiyun #include <linux/init.h>
10*4882a593Smuzhiyun #include <linux/slab.h>
11*4882a593Smuzhiyun #include <linux/sched.h>
12*4882a593Smuzhiyun #include <linux/ip.h>
13*4882a593Smuzhiyun #include "internal.h"
14*4882a593Smuzhiyun #include "afs_cm.h"
15*4882a593Smuzhiyun #include "protocol_yfs.h"
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun static int afs_deliver_cb_init_call_back_state(struct afs_call *);
18*4882a593Smuzhiyun static int afs_deliver_cb_init_call_back_state3(struct afs_call *);
19*4882a593Smuzhiyun static int afs_deliver_cb_probe(struct afs_call *);
20*4882a593Smuzhiyun static int afs_deliver_cb_callback(struct afs_call *);
21*4882a593Smuzhiyun static int afs_deliver_cb_probe_uuid(struct afs_call *);
22*4882a593Smuzhiyun static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *);
23*4882a593Smuzhiyun static void afs_cm_destructor(struct afs_call *);
24*4882a593Smuzhiyun static void SRXAFSCB_CallBack(struct work_struct *);
25*4882a593Smuzhiyun static void SRXAFSCB_InitCallBackState(struct work_struct *);
26*4882a593Smuzhiyun static void SRXAFSCB_Probe(struct work_struct *);
27*4882a593Smuzhiyun static void SRXAFSCB_ProbeUuid(struct work_struct *);
28*4882a593Smuzhiyun static void SRXAFSCB_TellMeAboutYourself(struct work_struct *);
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun static int afs_deliver_yfs_cb_callback(struct afs_call *);
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun /*
33*4882a593Smuzhiyun * CB.CallBack operation type
34*4882a593Smuzhiyun */
35*4882a593Smuzhiyun static const struct afs_call_type afs_SRXCBCallBack = {
36*4882a593Smuzhiyun .name = "CB.CallBack",
37*4882a593Smuzhiyun .deliver = afs_deliver_cb_callback,
38*4882a593Smuzhiyun .destructor = afs_cm_destructor,
39*4882a593Smuzhiyun .work = SRXAFSCB_CallBack,
40*4882a593Smuzhiyun };
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /*
43*4882a593Smuzhiyun * CB.InitCallBackState operation type
44*4882a593Smuzhiyun */
45*4882a593Smuzhiyun static const struct afs_call_type afs_SRXCBInitCallBackState = {
46*4882a593Smuzhiyun .name = "CB.InitCallBackState",
47*4882a593Smuzhiyun .deliver = afs_deliver_cb_init_call_back_state,
48*4882a593Smuzhiyun .destructor = afs_cm_destructor,
49*4882a593Smuzhiyun .work = SRXAFSCB_InitCallBackState,
50*4882a593Smuzhiyun };
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun /*
53*4882a593Smuzhiyun * CB.InitCallBackState3 operation type
54*4882a593Smuzhiyun */
55*4882a593Smuzhiyun static const struct afs_call_type afs_SRXCBInitCallBackState3 = {
56*4882a593Smuzhiyun .name = "CB.InitCallBackState3",
57*4882a593Smuzhiyun .deliver = afs_deliver_cb_init_call_back_state3,
58*4882a593Smuzhiyun .destructor = afs_cm_destructor,
59*4882a593Smuzhiyun .work = SRXAFSCB_InitCallBackState,
60*4882a593Smuzhiyun };
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun /*
63*4882a593Smuzhiyun * CB.Probe operation type
64*4882a593Smuzhiyun */
65*4882a593Smuzhiyun static const struct afs_call_type afs_SRXCBProbe = {
66*4882a593Smuzhiyun .name = "CB.Probe",
67*4882a593Smuzhiyun .deliver = afs_deliver_cb_probe,
68*4882a593Smuzhiyun .destructor = afs_cm_destructor,
69*4882a593Smuzhiyun .work = SRXAFSCB_Probe,
70*4882a593Smuzhiyun };
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun /*
73*4882a593Smuzhiyun * CB.ProbeUuid operation type
74*4882a593Smuzhiyun */
75*4882a593Smuzhiyun static const struct afs_call_type afs_SRXCBProbeUuid = {
76*4882a593Smuzhiyun .name = "CB.ProbeUuid",
77*4882a593Smuzhiyun .deliver = afs_deliver_cb_probe_uuid,
78*4882a593Smuzhiyun .destructor = afs_cm_destructor,
79*4882a593Smuzhiyun .work = SRXAFSCB_ProbeUuid,
80*4882a593Smuzhiyun };
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /*
83*4882a593Smuzhiyun * CB.TellMeAboutYourself operation type
84*4882a593Smuzhiyun */
85*4882a593Smuzhiyun static const struct afs_call_type afs_SRXCBTellMeAboutYourself = {
86*4882a593Smuzhiyun .name = "CB.TellMeAboutYourself",
87*4882a593Smuzhiyun .deliver = afs_deliver_cb_tell_me_about_yourself,
88*4882a593Smuzhiyun .destructor = afs_cm_destructor,
89*4882a593Smuzhiyun .work = SRXAFSCB_TellMeAboutYourself,
90*4882a593Smuzhiyun };
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun /*
93*4882a593Smuzhiyun * YFS CB.CallBack operation type
94*4882a593Smuzhiyun */
95*4882a593Smuzhiyun static const struct afs_call_type afs_SRXYFSCB_CallBack = {
96*4882a593Smuzhiyun .name = "YFSCB.CallBack",
97*4882a593Smuzhiyun .deliver = afs_deliver_yfs_cb_callback,
98*4882a593Smuzhiyun .destructor = afs_cm_destructor,
99*4882a593Smuzhiyun .work = SRXAFSCB_CallBack,
100*4882a593Smuzhiyun };
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun /*
103*4882a593Smuzhiyun * route an incoming cache manager call
104*4882a593Smuzhiyun * - return T if supported, F if not
105*4882a593Smuzhiyun */
afs_cm_incoming_call(struct afs_call * call)106*4882a593Smuzhiyun bool afs_cm_incoming_call(struct afs_call *call)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun _enter("{%u, CB.OP %u}", call->service_id, call->operation_ID);
109*4882a593Smuzhiyun
110*4882a593Smuzhiyun switch (call->operation_ID) {
111*4882a593Smuzhiyun case CBCallBack:
112*4882a593Smuzhiyun call->type = &afs_SRXCBCallBack;
113*4882a593Smuzhiyun return true;
114*4882a593Smuzhiyun case CBInitCallBackState:
115*4882a593Smuzhiyun call->type = &afs_SRXCBInitCallBackState;
116*4882a593Smuzhiyun return true;
117*4882a593Smuzhiyun case CBInitCallBackState3:
118*4882a593Smuzhiyun call->type = &afs_SRXCBInitCallBackState3;
119*4882a593Smuzhiyun return true;
120*4882a593Smuzhiyun case CBProbe:
121*4882a593Smuzhiyun call->type = &afs_SRXCBProbe;
122*4882a593Smuzhiyun return true;
123*4882a593Smuzhiyun case CBProbeUuid:
124*4882a593Smuzhiyun call->type = &afs_SRXCBProbeUuid;
125*4882a593Smuzhiyun return true;
126*4882a593Smuzhiyun case CBTellMeAboutYourself:
127*4882a593Smuzhiyun call->type = &afs_SRXCBTellMeAboutYourself;
128*4882a593Smuzhiyun return true;
129*4882a593Smuzhiyun case YFSCBCallBack:
130*4882a593Smuzhiyun if (call->service_id != YFS_CM_SERVICE)
131*4882a593Smuzhiyun return false;
132*4882a593Smuzhiyun call->type = &afs_SRXYFSCB_CallBack;
133*4882a593Smuzhiyun return true;
134*4882a593Smuzhiyun default:
135*4882a593Smuzhiyun return false;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun /*
140*4882a593Smuzhiyun * Find the server record by peer address and record a probe to the cache
141*4882a593Smuzhiyun * manager from a server.
142*4882a593Smuzhiyun */
afs_find_cm_server_by_peer(struct afs_call * call)143*4882a593Smuzhiyun static int afs_find_cm_server_by_peer(struct afs_call *call)
144*4882a593Smuzhiyun {
145*4882a593Smuzhiyun struct sockaddr_rxrpc srx;
146*4882a593Smuzhiyun struct afs_server *server;
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun rxrpc_kernel_get_peer(call->net->socket, call->rxcall, &srx);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun server = afs_find_server(call->net, &srx);
151*4882a593Smuzhiyun if (!server) {
152*4882a593Smuzhiyun trace_afs_cm_no_server(call, &srx);
153*4882a593Smuzhiyun return 0;
154*4882a593Smuzhiyun }
155*4882a593Smuzhiyun
156*4882a593Smuzhiyun call->server = server;
157*4882a593Smuzhiyun return 0;
158*4882a593Smuzhiyun }
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /*
161*4882a593Smuzhiyun * Find the server record by server UUID and record a probe to the cache
162*4882a593Smuzhiyun * manager from a server.
163*4882a593Smuzhiyun */
afs_find_cm_server_by_uuid(struct afs_call * call,struct afs_uuid * uuid)164*4882a593Smuzhiyun static int afs_find_cm_server_by_uuid(struct afs_call *call,
165*4882a593Smuzhiyun struct afs_uuid *uuid)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun struct afs_server *server;
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun rcu_read_lock();
170*4882a593Smuzhiyun server = afs_find_server_by_uuid(call->net, call->request);
171*4882a593Smuzhiyun rcu_read_unlock();
172*4882a593Smuzhiyun if (!server) {
173*4882a593Smuzhiyun trace_afs_cm_no_server_u(call, call->request);
174*4882a593Smuzhiyun return 0;
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun call->server = server;
178*4882a593Smuzhiyun return 0;
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun /*
182*4882a593Smuzhiyun * Clean up a cache manager call.
183*4882a593Smuzhiyun */
afs_cm_destructor(struct afs_call * call)184*4882a593Smuzhiyun static void afs_cm_destructor(struct afs_call *call)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun kfree(call->buffer);
187*4882a593Smuzhiyun call->buffer = NULL;
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun /*
191*4882a593Smuzhiyun * Abort a service call from within an action function.
192*4882a593Smuzhiyun */
afs_abort_service_call(struct afs_call * call,u32 abort_code,int error,const char * why)193*4882a593Smuzhiyun static void afs_abort_service_call(struct afs_call *call, u32 abort_code, int error,
194*4882a593Smuzhiyun const char *why)
195*4882a593Smuzhiyun {
196*4882a593Smuzhiyun rxrpc_kernel_abort_call(call->net->socket, call->rxcall,
197*4882a593Smuzhiyun abort_code, error, why);
198*4882a593Smuzhiyun afs_set_call_complete(call, error, 0);
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun
201*4882a593Smuzhiyun /*
202*4882a593Smuzhiyun * The server supplied a list of callbacks that it wanted to break.
203*4882a593Smuzhiyun */
SRXAFSCB_CallBack(struct work_struct * work)204*4882a593Smuzhiyun static void SRXAFSCB_CallBack(struct work_struct *work)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun struct afs_call *call = container_of(work, struct afs_call, work);
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun _enter("");
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun /* We need to break the callbacks before sending the reply as the
211*4882a593Smuzhiyun * server holds up change visibility till it receives our reply so as
212*4882a593Smuzhiyun * to maintain cache coherency.
213*4882a593Smuzhiyun */
214*4882a593Smuzhiyun if (call->server) {
215*4882a593Smuzhiyun trace_afs_server(call->server,
216*4882a593Smuzhiyun atomic_read(&call->server->ref),
217*4882a593Smuzhiyun atomic_read(&call->server->active),
218*4882a593Smuzhiyun afs_server_trace_callback);
219*4882a593Smuzhiyun afs_break_callbacks(call->server, call->count, call->request);
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun afs_send_empty_reply(call);
223*4882a593Smuzhiyun afs_put_call(call);
224*4882a593Smuzhiyun _leave("");
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun /*
228*4882a593Smuzhiyun * deliver request data to a CB.CallBack call
229*4882a593Smuzhiyun */
afs_deliver_cb_callback(struct afs_call * call)230*4882a593Smuzhiyun static int afs_deliver_cb_callback(struct afs_call *call)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun struct afs_callback_break *cb;
233*4882a593Smuzhiyun __be32 *bp;
234*4882a593Smuzhiyun int ret, loop;
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun _enter("{%u}", call->unmarshall);
237*4882a593Smuzhiyun
238*4882a593Smuzhiyun switch (call->unmarshall) {
239*4882a593Smuzhiyun case 0:
240*4882a593Smuzhiyun afs_extract_to_tmp(call);
241*4882a593Smuzhiyun call->unmarshall++;
242*4882a593Smuzhiyun
243*4882a593Smuzhiyun /* extract the FID array and its count in two steps */
244*4882a593Smuzhiyun fallthrough;
245*4882a593Smuzhiyun case 1:
246*4882a593Smuzhiyun _debug("extract FID count");
247*4882a593Smuzhiyun ret = afs_extract_data(call, true);
248*4882a593Smuzhiyun if (ret < 0)
249*4882a593Smuzhiyun return ret;
250*4882a593Smuzhiyun
251*4882a593Smuzhiyun call->count = ntohl(call->tmp);
252*4882a593Smuzhiyun _debug("FID count: %u", call->count);
253*4882a593Smuzhiyun if (call->count > AFSCBMAX)
254*4882a593Smuzhiyun return afs_protocol_error(call, afs_eproto_cb_fid_count);
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun call->buffer = kmalloc(array3_size(call->count, 3, 4),
257*4882a593Smuzhiyun GFP_KERNEL);
258*4882a593Smuzhiyun if (!call->buffer)
259*4882a593Smuzhiyun return -ENOMEM;
260*4882a593Smuzhiyun afs_extract_to_buf(call, call->count * 3 * 4);
261*4882a593Smuzhiyun call->unmarshall++;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun fallthrough;
264*4882a593Smuzhiyun case 2:
265*4882a593Smuzhiyun _debug("extract FID array");
266*4882a593Smuzhiyun ret = afs_extract_data(call, true);
267*4882a593Smuzhiyun if (ret < 0)
268*4882a593Smuzhiyun return ret;
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun _debug("unmarshall FID array");
271*4882a593Smuzhiyun call->request = kcalloc(call->count,
272*4882a593Smuzhiyun sizeof(struct afs_callback_break),
273*4882a593Smuzhiyun GFP_KERNEL);
274*4882a593Smuzhiyun if (!call->request)
275*4882a593Smuzhiyun return -ENOMEM;
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun cb = call->request;
278*4882a593Smuzhiyun bp = call->buffer;
279*4882a593Smuzhiyun for (loop = call->count; loop > 0; loop--, cb++) {
280*4882a593Smuzhiyun cb->fid.vid = ntohl(*bp++);
281*4882a593Smuzhiyun cb->fid.vnode = ntohl(*bp++);
282*4882a593Smuzhiyun cb->fid.unique = ntohl(*bp++);
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun afs_extract_to_tmp(call);
286*4882a593Smuzhiyun call->unmarshall++;
287*4882a593Smuzhiyun
288*4882a593Smuzhiyun /* extract the callback array and its count in two steps */
289*4882a593Smuzhiyun fallthrough;
290*4882a593Smuzhiyun case 3:
291*4882a593Smuzhiyun _debug("extract CB count");
292*4882a593Smuzhiyun ret = afs_extract_data(call, true);
293*4882a593Smuzhiyun if (ret < 0)
294*4882a593Smuzhiyun return ret;
295*4882a593Smuzhiyun
296*4882a593Smuzhiyun call->count2 = ntohl(call->tmp);
297*4882a593Smuzhiyun _debug("CB count: %u", call->count2);
298*4882a593Smuzhiyun if (call->count2 != call->count && call->count2 != 0)
299*4882a593Smuzhiyun return afs_protocol_error(call, afs_eproto_cb_count);
300*4882a593Smuzhiyun call->iter = &call->def_iter;
301*4882a593Smuzhiyun iov_iter_discard(&call->def_iter, READ, call->count2 * 3 * 4);
302*4882a593Smuzhiyun call->unmarshall++;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun fallthrough;
305*4882a593Smuzhiyun case 4:
306*4882a593Smuzhiyun _debug("extract discard %zu/%u",
307*4882a593Smuzhiyun iov_iter_count(call->iter), call->count2 * 3 * 4);
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun ret = afs_extract_data(call, false);
310*4882a593Smuzhiyun if (ret < 0)
311*4882a593Smuzhiyun return ret;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun call->unmarshall++;
314*4882a593Smuzhiyun case 5:
315*4882a593Smuzhiyun break;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
319*4882a593Smuzhiyun return afs_io_error(call, afs_io_error_cm_reply);
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun /* we'll need the file server record as that tells us which set of
322*4882a593Smuzhiyun * vnodes to operate upon */
323*4882a593Smuzhiyun return afs_find_cm_server_by_peer(call);
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun /*
327*4882a593Smuzhiyun * allow the fileserver to request callback state (re-)initialisation
328*4882a593Smuzhiyun */
SRXAFSCB_InitCallBackState(struct work_struct * work)329*4882a593Smuzhiyun static void SRXAFSCB_InitCallBackState(struct work_struct *work)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun struct afs_call *call = container_of(work, struct afs_call, work);
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun _enter("{%p}", call->server);
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun if (call->server)
336*4882a593Smuzhiyun afs_init_callback_state(call->server);
337*4882a593Smuzhiyun afs_send_empty_reply(call);
338*4882a593Smuzhiyun afs_put_call(call);
339*4882a593Smuzhiyun _leave("");
340*4882a593Smuzhiyun }
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun /*
343*4882a593Smuzhiyun * deliver request data to a CB.InitCallBackState call
344*4882a593Smuzhiyun */
afs_deliver_cb_init_call_back_state(struct afs_call * call)345*4882a593Smuzhiyun static int afs_deliver_cb_init_call_back_state(struct afs_call *call)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun int ret;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun _enter("");
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun afs_extract_discard(call, 0);
352*4882a593Smuzhiyun ret = afs_extract_data(call, false);
353*4882a593Smuzhiyun if (ret < 0)
354*4882a593Smuzhiyun return ret;
355*4882a593Smuzhiyun
356*4882a593Smuzhiyun /* we'll need the file server record as that tells us which set of
357*4882a593Smuzhiyun * vnodes to operate upon */
358*4882a593Smuzhiyun return afs_find_cm_server_by_peer(call);
359*4882a593Smuzhiyun }
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun /*
362*4882a593Smuzhiyun * deliver request data to a CB.InitCallBackState3 call
363*4882a593Smuzhiyun */
afs_deliver_cb_init_call_back_state3(struct afs_call * call)364*4882a593Smuzhiyun static int afs_deliver_cb_init_call_back_state3(struct afs_call *call)
365*4882a593Smuzhiyun {
366*4882a593Smuzhiyun struct afs_uuid *r;
367*4882a593Smuzhiyun unsigned loop;
368*4882a593Smuzhiyun __be32 *b;
369*4882a593Smuzhiyun int ret;
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun _enter("");
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun _enter("{%u}", call->unmarshall);
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun switch (call->unmarshall) {
376*4882a593Smuzhiyun case 0:
377*4882a593Smuzhiyun call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
378*4882a593Smuzhiyun if (!call->buffer)
379*4882a593Smuzhiyun return -ENOMEM;
380*4882a593Smuzhiyun afs_extract_to_buf(call, 11 * sizeof(__be32));
381*4882a593Smuzhiyun call->unmarshall++;
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun fallthrough;
384*4882a593Smuzhiyun case 1:
385*4882a593Smuzhiyun _debug("extract UUID");
386*4882a593Smuzhiyun ret = afs_extract_data(call, false);
387*4882a593Smuzhiyun switch (ret) {
388*4882a593Smuzhiyun case 0: break;
389*4882a593Smuzhiyun case -EAGAIN: return 0;
390*4882a593Smuzhiyun default: return ret;
391*4882a593Smuzhiyun }
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun _debug("unmarshall UUID");
394*4882a593Smuzhiyun call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL);
395*4882a593Smuzhiyun if (!call->request)
396*4882a593Smuzhiyun return -ENOMEM;
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun b = call->buffer;
399*4882a593Smuzhiyun r = call->request;
400*4882a593Smuzhiyun r->time_low = b[0];
401*4882a593Smuzhiyun r->time_mid = htons(ntohl(b[1]));
402*4882a593Smuzhiyun r->time_hi_and_version = htons(ntohl(b[2]));
403*4882a593Smuzhiyun r->clock_seq_hi_and_reserved = ntohl(b[3]);
404*4882a593Smuzhiyun r->clock_seq_low = ntohl(b[4]);
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun for (loop = 0; loop < 6; loop++)
407*4882a593Smuzhiyun r->node[loop] = ntohl(b[loop + 5]);
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun call->unmarshall++;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun case 2:
412*4882a593Smuzhiyun break;
413*4882a593Smuzhiyun }
414*4882a593Smuzhiyun
415*4882a593Smuzhiyun if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
416*4882a593Smuzhiyun return afs_io_error(call, afs_io_error_cm_reply);
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun /* we'll need the file server record as that tells us which set of
419*4882a593Smuzhiyun * vnodes to operate upon */
420*4882a593Smuzhiyun return afs_find_cm_server_by_uuid(call, call->request);
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun /*
424*4882a593Smuzhiyun * allow the fileserver to see if the cache manager is still alive
425*4882a593Smuzhiyun */
SRXAFSCB_Probe(struct work_struct * work)426*4882a593Smuzhiyun static void SRXAFSCB_Probe(struct work_struct *work)
427*4882a593Smuzhiyun {
428*4882a593Smuzhiyun struct afs_call *call = container_of(work, struct afs_call, work);
429*4882a593Smuzhiyun
430*4882a593Smuzhiyun _enter("");
431*4882a593Smuzhiyun afs_send_empty_reply(call);
432*4882a593Smuzhiyun afs_put_call(call);
433*4882a593Smuzhiyun _leave("");
434*4882a593Smuzhiyun }
435*4882a593Smuzhiyun
436*4882a593Smuzhiyun /*
437*4882a593Smuzhiyun * deliver request data to a CB.Probe call
438*4882a593Smuzhiyun */
afs_deliver_cb_probe(struct afs_call * call)439*4882a593Smuzhiyun static int afs_deliver_cb_probe(struct afs_call *call)
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun int ret;
442*4882a593Smuzhiyun
443*4882a593Smuzhiyun _enter("");
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun afs_extract_discard(call, 0);
446*4882a593Smuzhiyun ret = afs_extract_data(call, false);
447*4882a593Smuzhiyun if (ret < 0)
448*4882a593Smuzhiyun return ret;
449*4882a593Smuzhiyun
450*4882a593Smuzhiyun if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
451*4882a593Smuzhiyun return afs_io_error(call, afs_io_error_cm_reply);
452*4882a593Smuzhiyun return afs_find_cm_server_by_peer(call);
453*4882a593Smuzhiyun }
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun /*
456*4882a593Smuzhiyun * Allow the fileserver to quickly find out if the cache manager has been
457*4882a593Smuzhiyun * rebooted.
458*4882a593Smuzhiyun */
SRXAFSCB_ProbeUuid(struct work_struct * work)459*4882a593Smuzhiyun static void SRXAFSCB_ProbeUuid(struct work_struct *work)
460*4882a593Smuzhiyun {
461*4882a593Smuzhiyun struct afs_call *call = container_of(work, struct afs_call, work);
462*4882a593Smuzhiyun struct afs_uuid *r = call->request;
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun _enter("");
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun if (memcmp(r, &call->net->uuid, sizeof(call->net->uuid)) == 0)
467*4882a593Smuzhiyun afs_send_empty_reply(call);
468*4882a593Smuzhiyun else
469*4882a593Smuzhiyun afs_abort_service_call(call, 1, 1, "K-1");
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun afs_put_call(call);
472*4882a593Smuzhiyun _leave("");
473*4882a593Smuzhiyun }
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun /*
476*4882a593Smuzhiyun * deliver request data to a CB.ProbeUuid call
477*4882a593Smuzhiyun */
afs_deliver_cb_probe_uuid(struct afs_call * call)478*4882a593Smuzhiyun static int afs_deliver_cb_probe_uuid(struct afs_call *call)
479*4882a593Smuzhiyun {
480*4882a593Smuzhiyun struct afs_uuid *r;
481*4882a593Smuzhiyun unsigned loop;
482*4882a593Smuzhiyun __be32 *b;
483*4882a593Smuzhiyun int ret;
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun _enter("{%u}", call->unmarshall);
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun switch (call->unmarshall) {
488*4882a593Smuzhiyun case 0:
489*4882a593Smuzhiyun call->buffer = kmalloc_array(11, sizeof(__be32), GFP_KERNEL);
490*4882a593Smuzhiyun if (!call->buffer)
491*4882a593Smuzhiyun return -ENOMEM;
492*4882a593Smuzhiyun afs_extract_to_buf(call, 11 * sizeof(__be32));
493*4882a593Smuzhiyun call->unmarshall++;
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun fallthrough;
496*4882a593Smuzhiyun case 1:
497*4882a593Smuzhiyun _debug("extract UUID");
498*4882a593Smuzhiyun ret = afs_extract_data(call, false);
499*4882a593Smuzhiyun switch (ret) {
500*4882a593Smuzhiyun case 0: break;
501*4882a593Smuzhiyun case -EAGAIN: return 0;
502*4882a593Smuzhiyun default: return ret;
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun
505*4882a593Smuzhiyun _debug("unmarshall UUID");
506*4882a593Smuzhiyun call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL);
507*4882a593Smuzhiyun if (!call->request)
508*4882a593Smuzhiyun return -ENOMEM;
509*4882a593Smuzhiyun
510*4882a593Smuzhiyun b = call->buffer;
511*4882a593Smuzhiyun r = call->request;
512*4882a593Smuzhiyun r->time_low = b[0];
513*4882a593Smuzhiyun r->time_mid = htons(ntohl(b[1]));
514*4882a593Smuzhiyun r->time_hi_and_version = htons(ntohl(b[2]));
515*4882a593Smuzhiyun r->clock_seq_hi_and_reserved = ntohl(b[3]);
516*4882a593Smuzhiyun r->clock_seq_low = ntohl(b[4]);
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun for (loop = 0; loop < 6; loop++)
519*4882a593Smuzhiyun r->node[loop] = ntohl(b[loop + 5]);
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun call->unmarshall++;
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun case 2:
524*4882a593Smuzhiyun break;
525*4882a593Smuzhiyun }
526*4882a593Smuzhiyun
527*4882a593Smuzhiyun if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
528*4882a593Smuzhiyun return afs_io_error(call, afs_io_error_cm_reply);
529*4882a593Smuzhiyun return afs_find_cm_server_by_peer(call);
530*4882a593Smuzhiyun }
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun /*
533*4882a593Smuzhiyun * allow the fileserver to ask about the cache manager's capabilities
534*4882a593Smuzhiyun */
SRXAFSCB_TellMeAboutYourself(struct work_struct * work)535*4882a593Smuzhiyun static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
536*4882a593Smuzhiyun {
537*4882a593Smuzhiyun struct afs_call *call = container_of(work, struct afs_call, work);
538*4882a593Smuzhiyun int loop;
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun struct {
541*4882a593Smuzhiyun struct /* InterfaceAddr */ {
542*4882a593Smuzhiyun __be32 nifs;
543*4882a593Smuzhiyun __be32 uuid[11];
544*4882a593Smuzhiyun __be32 ifaddr[32];
545*4882a593Smuzhiyun __be32 netmask[32];
546*4882a593Smuzhiyun __be32 mtu[32];
547*4882a593Smuzhiyun } ia;
548*4882a593Smuzhiyun struct /* Capabilities */ {
549*4882a593Smuzhiyun __be32 capcount;
550*4882a593Smuzhiyun __be32 caps[1];
551*4882a593Smuzhiyun } cap;
552*4882a593Smuzhiyun } reply;
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun _enter("");
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun memset(&reply, 0, sizeof(reply));
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun reply.ia.uuid[0] = call->net->uuid.time_low;
559*4882a593Smuzhiyun reply.ia.uuid[1] = htonl(ntohs(call->net->uuid.time_mid));
560*4882a593Smuzhiyun reply.ia.uuid[2] = htonl(ntohs(call->net->uuid.time_hi_and_version));
561*4882a593Smuzhiyun reply.ia.uuid[3] = htonl((s8) call->net->uuid.clock_seq_hi_and_reserved);
562*4882a593Smuzhiyun reply.ia.uuid[4] = htonl((s8) call->net->uuid.clock_seq_low);
563*4882a593Smuzhiyun for (loop = 0; loop < 6; loop++)
564*4882a593Smuzhiyun reply.ia.uuid[loop + 5] = htonl((s8) call->net->uuid.node[loop]);
565*4882a593Smuzhiyun
566*4882a593Smuzhiyun reply.cap.capcount = htonl(1);
567*4882a593Smuzhiyun reply.cap.caps[0] = htonl(AFS_CAP_ERROR_TRANSLATION);
568*4882a593Smuzhiyun afs_send_simple_reply(call, &reply, sizeof(reply));
569*4882a593Smuzhiyun afs_put_call(call);
570*4882a593Smuzhiyun _leave("");
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun /*
574*4882a593Smuzhiyun * deliver request data to a CB.TellMeAboutYourself call
575*4882a593Smuzhiyun */
afs_deliver_cb_tell_me_about_yourself(struct afs_call * call)576*4882a593Smuzhiyun static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call)
577*4882a593Smuzhiyun {
578*4882a593Smuzhiyun int ret;
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun _enter("");
581*4882a593Smuzhiyun
582*4882a593Smuzhiyun afs_extract_discard(call, 0);
583*4882a593Smuzhiyun ret = afs_extract_data(call, false);
584*4882a593Smuzhiyun if (ret < 0)
585*4882a593Smuzhiyun return ret;
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
588*4882a593Smuzhiyun return afs_io_error(call, afs_io_error_cm_reply);
589*4882a593Smuzhiyun return afs_find_cm_server_by_peer(call);
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun /*
593*4882a593Smuzhiyun * deliver request data to a YFS CB.CallBack call
594*4882a593Smuzhiyun */
afs_deliver_yfs_cb_callback(struct afs_call * call)595*4882a593Smuzhiyun static int afs_deliver_yfs_cb_callback(struct afs_call *call)
596*4882a593Smuzhiyun {
597*4882a593Smuzhiyun struct afs_callback_break *cb;
598*4882a593Smuzhiyun struct yfs_xdr_YFSFid *bp;
599*4882a593Smuzhiyun size_t size;
600*4882a593Smuzhiyun int ret, loop;
601*4882a593Smuzhiyun
602*4882a593Smuzhiyun _enter("{%u}", call->unmarshall);
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun switch (call->unmarshall) {
605*4882a593Smuzhiyun case 0:
606*4882a593Smuzhiyun afs_extract_to_tmp(call);
607*4882a593Smuzhiyun call->unmarshall++;
608*4882a593Smuzhiyun
609*4882a593Smuzhiyun /* extract the FID array and its count in two steps */
610*4882a593Smuzhiyun fallthrough;
611*4882a593Smuzhiyun case 1:
612*4882a593Smuzhiyun _debug("extract FID count");
613*4882a593Smuzhiyun ret = afs_extract_data(call, true);
614*4882a593Smuzhiyun if (ret < 0)
615*4882a593Smuzhiyun return ret;
616*4882a593Smuzhiyun
617*4882a593Smuzhiyun call->count = ntohl(call->tmp);
618*4882a593Smuzhiyun _debug("FID count: %u", call->count);
619*4882a593Smuzhiyun if (call->count > YFSCBMAX)
620*4882a593Smuzhiyun return afs_protocol_error(call, afs_eproto_cb_fid_count);
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun size = array_size(call->count, sizeof(struct yfs_xdr_YFSFid));
623*4882a593Smuzhiyun call->buffer = kmalloc(size, GFP_KERNEL);
624*4882a593Smuzhiyun if (!call->buffer)
625*4882a593Smuzhiyun return -ENOMEM;
626*4882a593Smuzhiyun afs_extract_to_buf(call, size);
627*4882a593Smuzhiyun call->unmarshall++;
628*4882a593Smuzhiyun
629*4882a593Smuzhiyun fallthrough;
630*4882a593Smuzhiyun case 2:
631*4882a593Smuzhiyun _debug("extract FID array");
632*4882a593Smuzhiyun ret = afs_extract_data(call, false);
633*4882a593Smuzhiyun if (ret < 0)
634*4882a593Smuzhiyun return ret;
635*4882a593Smuzhiyun
636*4882a593Smuzhiyun _debug("unmarshall FID array");
637*4882a593Smuzhiyun call->request = kcalloc(call->count,
638*4882a593Smuzhiyun sizeof(struct afs_callback_break),
639*4882a593Smuzhiyun GFP_KERNEL);
640*4882a593Smuzhiyun if (!call->request)
641*4882a593Smuzhiyun return -ENOMEM;
642*4882a593Smuzhiyun
643*4882a593Smuzhiyun cb = call->request;
644*4882a593Smuzhiyun bp = call->buffer;
645*4882a593Smuzhiyun for (loop = call->count; loop > 0; loop--, cb++) {
646*4882a593Smuzhiyun cb->fid.vid = xdr_to_u64(bp->volume);
647*4882a593Smuzhiyun cb->fid.vnode = xdr_to_u64(bp->vnode.lo);
648*4882a593Smuzhiyun cb->fid.vnode_hi = ntohl(bp->vnode.hi);
649*4882a593Smuzhiyun cb->fid.unique = ntohl(bp->vnode.unique);
650*4882a593Smuzhiyun bp++;
651*4882a593Smuzhiyun }
652*4882a593Smuzhiyun
653*4882a593Smuzhiyun afs_extract_to_tmp(call);
654*4882a593Smuzhiyun call->unmarshall++;
655*4882a593Smuzhiyun
656*4882a593Smuzhiyun case 3:
657*4882a593Smuzhiyun break;
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun if (!afs_check_call_state(call, AFS_CALL_SV_REPLYING))
661*4882a593Smuzhiyun return afs_io_error(call, afs_io_error_cm_reply);
662*4882a593Smuzhiyun
663*4882a593Smuzhiyun /* We'll need the file server record as that tells us which set of
664*4882a593Smuzhiyun * vnodes to operate upon.
665*4882a593Smuzhiyun */
666*4882a593Smuzhiyun return afs_find_cm_server_by_peer(call);
667*4882a593Smuzhiyun }
668