xref: /openbmc/linux/fs/afs/cmservice.c (revision c35eccb1f614954b10cba3f74b7c301993b2f42e)
1 /* AFS Cache Manager Service
2  *
3  * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  */
11 
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/sched.h>
15 #include <linux/ip.h>
16 #include "internal.h"
17 #include "afs_cm.h"
18 
19 struct workqueue_struct *afs_cm_workqueue;
20 
21 static int afs_deliver_cb_init_call_back_state(struct afs_call *,
22 					       struct sk_buff *, bool);
23 static int afs_deliver_cb_init_call_back_state3(struct afs_call *,
24 						struct sk_buff *, bool);
25 static int afs_deliver_cb_probe(struct afs_call *, struct sk_buff *, bool);
26 static int afs_deliver_cb_callback(struct afs_call *, struct sk_buff *, bool);
27 static int afs_deliver_cb_get_capabilities(struct afs_call *, struct sk_buff *,
28 					   bool);
29 static void afs_cm_destructor(struct afs_call *);
30 
31 /*
32  * CB.CallBack operation type
33  */
34 static const struct afs_call_type afs_SRXCBCallBack = {
35 	.name		= "CB.CallBack",
36 	.deliver	= afs_deliver_cb_callback,
37 	.abort_to_error	= afs_abort_to_error,
38 	.destructor	= afs_cm_destructor,
39 };
40 
41 /*
42  * CB.InitCallBackState operation type
43  */
44 static const struct afs_call_type afs_SRXCBInitCallBackState = {
45 	.name		= "CB.InitCallBackState",
46 	.deliver	= afs_deliver_cb_init_call_back_state,
47 	.abort_to_error	= afs_abort_to_error,
48 	.destructor	= afs_cm_destructor,
49 };
50 
51 /*
52  * CB.InitCallBackState3 operation type
53  */
54 static const struct afs_call_type afs_SRXCBInitCallBackState3 = {
55 	.name		= "CB.InitCallBackState3",
56 	.deliver	= afs_deliver_cb_init_call_back_state3,
57 	.abort_to_error	= afs_abort_to_error,
58 	.destructor	= afs_cm_destructor,
59 };
60 
61 /*
62  * CB.Probe operation type
63  */
64 static const struct afs_call_type afs_SRXCBProbe = {
65 	.name		= "CB.Probe",
66 	.deliver	= afs_deliver_cb_probe,
67 	.abort_to_error	= afs_abort_to_error,
68 	.destructor	= afs_cm_destructor,
69 };
70 
71 /*
72  * CB.GetCapabilities operation type
73  */
74 static const struct afs_call_type afs_SRXCBGetCapabilites = {
75 	.name		= "CB.GetCapabilities",
76 	.deliver	= afs_deliver_cb_get_capabilities,
77 	.abort_to_error	= afs_abort_to_error,
78 	.destructor	= afs_cm_destructor,
79 };
80 
81 /*
82  * route an incoming cache manager call
83  * - return T if supported, F if not
84  */
85 bool afs_cm_incoming_call(struct afs_call *call)
86 {
87 	u32 operation_id = ntohl(call->operation_ID);
88 
89 	_enter("{CB.OP %u}", operation_id);
90 
91 	switch (operation_id) {
92 	case CBCallBack:
93 		call->type = &afs_SRXCBCallBack;
94 		return true;
95 	case CBInitCallBackState:
96 		call->type = &afs_SRXCBInitCallBackState;
97 		return true;
98 	case CBInitCallBackState3:
99 		call->type = &afs_SRXCBInitCallBackState3;
100 		return true;
101 	case CBProbe:
102 		call->type = &afs_SRXCBProbe;
103 		return true;
104 	case CBGetCapabilities:
105 		call->type = &afs_SRXCBGetCapabilites;
106 		return true;
107 	default:
108 		return false;
109 	}
110 }
111 
112 /*
113  * clean up a cache manager call
114  */
115 static void afs_cm_destructor(struct afs_call *call)
116 {
117 	_enter("");
118 
119 	afs_put_server(call->server);
120 	call->server = NULL;
121 	kfree(call->buffer);
122 	call->buffer = NULL;
123 }
124 
125 /*
126  * allow the fileserver to see if the cache manager is still alive
127  */
128 static void SRXAFSCB_CallBack(struct work_struct *work)
129 {
130 	struct afs_call *call = container_of(work, struct afs_call, work);
131 
132 	_enter("");
133 
134 	/* be sure to send the reply *before* attempting to spam the AFS server
135 	 * with FSFetchStatus requests on the vnodes with broken callbacks lest
136 	 * the AFS server get into a vicious cycle of trying to break further
137 	 * callbacks because it hadn't received completion of the CBCallBack op
138 	 * yet */
139 	afs_send_empty_reply(call);
140 
141 	afs_break_callbacks(call->server, call->count, call->request);
142 	_leave("");
143 }
144 
145 /*
146  * deliver request data to a CB.CallBack call
147  */
148 static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
149 				   bool last)
150 {
151 	struct afs_callback *cb;
152 	struct afs_server *server;
153 	struct in_addr addr;
154 	__be32 *bp;
155 	u32 tmp;
156 	int ret, loop;
157 
158 	_enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
159 
160 	switch (call->unmarshall) {
161 	case 0:
162 		call->offset = 0;
163 		call->unmarshall++;
164 
165 		/* extract the FID array and its count in two steps */
166 	case 1:
167 		_debug("extract FID count");
168 		ret = afs_extract_data(call, skb, last, &call->tmp, 4);
169 		switch (ret) {
170 		case 0:		break;
171 		case -EAGAIN:	return 0;
172 		default:	return ret;
173 		}
174 
175 		call->count = ntohl(call->tmp);
176 		_debug("FID count: %u", call->count);
177 		if (call->count > AFSCBMAX)
178 			return -EBADMSG;
179 
180 		call->buffer = kmalloc(call->count * 3 * 4, GFP_KERNEL);
181 		if (!call->buffer)
182 			return -ENOMEM;
183 		call->offset = 0;
184 		call->unmarshall++;
185 
186 	case 2:
187 		_debug("extract FID array");
188 		ret = afs_extract_data(call, skb, last, call->buffer,
189 				       call->count * 3 * 4);
190 		switch (ret) {
191 		case 0:		break;
192 		case -EAGAIN:	return 0;
193 		default:	return ret;
194 		}
195 
196 		_debug("unmarshall FID array");
197 		call->request = kcalloc(call->count,
198 					sizeof(struct afs_callback),
199 					GFP_KERNEL);
200 		if (!call->request)
201 			return -ENOMEM;
202 
203 		cb = call->request;
204 		bp = call->buffer;
205 		for (loop = call->count; loop > 0; loop--, cb++) {
206 			cb->fid.vid	= ntohl(*bp++);
207 			cb->fid.vnode	= ntohl(*bp++);
208 			cb->fid.unique	= ntohl(*bp++);
209 			cb->type	= AFSCM_CB_UNTYPED;
210 		}
211 
212 		call->offset = 0;
213 		call->unmarshall++;
214 
215 		/* extract the callback array and its count in two steps */
216 	case 3:
217 		_debug("extract CB count");
218 		ret = afs_extract_data(call, skb, last, &call->tmp, 4);
219 		switch (ret) {
220 		case 0:		break;
221 		case -EAGAIN:	return 0;
222 		default:	return ret;
223 		}
224 
225 		tmp = ntohl(call->tmp);
226 		_debug("CB count: %u", tmp);
227 		if (tmp != call->count && tmp != 0)
228 			return -EBADMSG;
229 		call->offset = 0;
230 		call->unmarshall++;
231 		if (tmp == 0)
232 			goto empty_cb_array;
233 
234 	case 4:
235 		_debug("extract CB array");
236 		ret = afs_extract_data(call, skb, last, call->request,
237 				       call->count * 3 * 4);
238 		switch (ret) {
239 		case 0:		break;
240 		case -EAGAIN:	return 0;
241 		default:	return ret;
242 		}
243 
244 		_debug("unmarshall CB array");
245 		cb = call->request;
246 		bp = call->buffer;
247 		for (loop = call->count; loop > 0; loop--, cb++) {
248 			cb->version	= ntohl(*bp++);
249 			cb->expiry	= ntohl(*bp++);
250 			cb->type	= ntohl(*bp++);
251 		}
252 
253 	empty_cb_array:
254 		call->offset = 0;
255 		call->unmarshall++;
256 
257 	case 5:
258 		_debug("trailer");
259 		if (skb->len != 0)
260 			return -EBADMSG;
261 		break;
262 	}
263 
264 	if (!last)
265 		return 0;
266 
267 	call->state = AFS_CALL_REPLYING;
268 
269 	/* we'll need the file server record as that tells us which set of
270 	 * vnodes to operate upon */
271 	memcpy(&addr, &ip_hdr(skb)->saddr, 4);
272 	server = afs_find_server(&addr);
273 	if (!server)
274 		return -ENOTCONN;
275 	call->server = server;
276 
277 	INIT_WORK(&call->work, SRXAFSCB_CallBack);
278 	schedule_work(&call->work);
279 	return 0;
280 }
281 
282 /*
283  * allow the fileserver to request callback state (re-)initialisation
284  */
285 static void SRXAFSCB_InitCallBackState(struct work_struct *work)
286 {
287 	struct afs_call *call = container_of(work, struct afs_call, work);
288 
289 	_enter("{%p}", call->server);
290 
291 	afs_init_callback_state(call->server);
292 	afs_send_empty_reply(call);
293 	_leave("");
294 }
295 
296 /*
297  * deliver request data to a CB.InitCallBackState call
298  */
299 static int afs_deliver_cb_init_call_back_state(struct afs_call *call,
300 					       struct sk_buff *skb,
301 					       bool last)
302 {
303 	struct afs_server *server;
304 	struct in_addr addr;
305 
306 	_enter(",{%u},%d", skb->len, last);
307 
308 	if (skb->len > 0)
309 		return -EBADMSG;
310 	if (!last)
311 		return 0;
312 
313 	/* no unmarshalling required */
314 	call->state = AFS_CALL_REPLYING;
315 
316 	/* we'll need the file server record as that tells us which set of
317 	 * vnodes to operate upon */
318 	memcpy(&addr, &ip_hdr(skb)->saddr, 4);
319 	server = afs_find_server(&addr);
320 	if (!server)
321 		return -ENOTCONN;
322 	call->server = server;
323 
324 	INIT_WORK(&call->work, SRXAFSCB_InitCallBackState);
325 	schedule_work(&call->work);
326 	return 0;
327 }
328 
329 /*
330  * deliver request data to a CB.InitCallBackState3 call
331  */
332 static int afs_deliver_cb_init_call_back_state3(struct afs_call *call,
333 						struct sk_buff *skb,
334 						bool last)
335 {
336 	struct afs_server *server;
337 	struct in_addr addr;
338 
339 	_enter(",{%u},%d", skb->len, last);
340 
341 	if (!last)
342 		return 0;
343 
344 	/* no unmarshalling required */
345 	call->state = AFS_CALL_REPLYING;
346 
347 	/* we'll need the file server record as that tells us which set of
348 	 * vnodes to operate upon */
349 	memcpy(&addr, &ip_hdr(skb)->saddr, 4);
350 	server = afs_find_server(&addr);
351 	if (!server)
352 		return -ENOTCONN;
353 	call->server = server;
354 
355 	INIT_WORK(&call->work, SRXAFSCB_InitCallBackState);
356 	schedule_work(&call->work);
357 	return 0;
358 }
359 
360 /*
361  * allow the fileserver to see if the cache manager is still alive
362  */
363 static void SRXAFSCB_Probe(struct work_struct *work)
364 {
365 	struct afs_call *call = container_of(work, struct afs_call, work);
366 
367 	_enter("");
368 	afs_send_empty_reply(call);
369 	_leave("");
370 }
371 
372 /*
373  * deliver request data to a CB.Probe call
374  */
375 static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb,
376 				bool last)
377 {
378 	_enter(",{%u},%d", skb->len, last);
379 
380 	if (skb->len > 0)
381 		return -EBADMSG;
382 	if (!last)
383 		return 0;
384 
385 	/* no unmarshalling required */
386 	call->state = AFS_CALL_REPLYING;
387 
388 	INIT_WORK(&call->work, SRXAFSCB_Probe);
389 	schedule_work(&call->work);
390 	return 0;
391 }
392 
393 /*
394  * allow the fileserver to ask about the cache manager's capabilities
395  */
396 static void SRXAFSCB_GetCapabilities(struct work_struct *work)
397 {
398 	struct afs_interface *ifs;
399 	struct afs_call *call = container_of(work, struct afs_call, work);
400 	int loop, nifs;
401 
402 	struct {
403 		struct /* InterfaceAddr */ {
404 			__be32 nifs;
405 			__be32 uuid[11];
406 			__be32 ifaddr[32];
407 			__be32 netmask[32];
408 			__be32 mtu[32];
409 		} ia;
410 		struct /* Capabilities */ {
411 			__be32 capcount;
412 			__be32 caps[1];
413 		} cap;
414 	} reply;
415 
416 	_enter("");
417 
418 	nifs = 0;
419 	ifs = kcalloc(32, sizeof(*ifs), GFP_KERNEL);
420 	if (ifs) {
421 		nifs = afs_get_ipv4_interfaces(ifs, 32, false);
422 		if (nifs < 0) {
423 			kfree(ifs);
424 			ifs = NULL;
425 			nifs = 0;
426 		}
427 	}
428 
429 	memset(&reply, 0, sizeof(reply));
430 	reply.ia.nifs = htonl(nifs);
431 
432 	reply.ia.uuid[0] = htonl(afs_uuid.time_low);
433 	reply.ia.uuid[1] = htonl(afs_uuid.time_mid);
434 	reply.ia.uuid[2] = htonl(afs_uuid.time_hi_and_version);
435 	reply.ia.uuid[3] = htonl((s8) afs_uuid.clock_seq_hi_and_reserved);
436 	reply.ia.uuid[4] = htonl((s8) afs_uuid.clock_seq_low);
437 	for (loop = 0; loop < 6; loop++)
438 		reply.ia.uuid[loop + 5] = htonl((s8) afs_uuid.node[loop]);
439 
440 	if (ifs) {
441 		for (loop = 0; loop < nifs; loop++) {
442 			reply.ia.ifaddr[loop] = ifs[loop].address.s_addr;
443 			reply.ia.netmask[loop] = ifs[loop].netmask.s_addr;
444 			reply.ia.mtu[loop] = htonl(ifs[loop].mtu);
445 		}
446 	}
447 
448 	reply.cap.capcount = htonl(1);
449 	reply.cap.caps[0] = htonl(AFS_CAP_ERROR_TRANSLATION);
450 	afs_send_simple_reply(call, &reply, sizeof(reply));
451 
452 	_leave("");
453 }
454 
455 /*
456  * deliver request data to a CB.GetCapabilities call
457  */
458 static int afs_deliver_cb_get_capabilities(struct afs_call *call,
459 					   struct sk_buff *skb, bool last)
460 {
461 	_enter(",{%u},%d", skb->len, last);
462 
463 	if (skb->len > 0)
464 		return -EBADMSG;
465 	if (!last)
466 		return 0;
467 
468 	/* no unmarshalling required */
469 	call->state = AFS_CALL_REPLYING;
470 
471 	INIT_WORK(&call->work, SRXAFSCB_GetCapabilities);
472 	schedule_work(&call->work);
473 	return 0;
474 }
475