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