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