1 /* AFS Cache Manager Service
3 * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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.
12 #include <linux/module.h>
13 #include <linux/init.h>
14 #include <linux/sched.h>
19 struct workqueue_struct
*afs_cm_workqueue
;
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
*,
29 static void afs_cm_destructor(struct afs_call
*);
32 * CB.CallBack operation type
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
,
42 * CB.InitCallBackState operation type
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
,
52 * CB.InitCallBackState3 operation type
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
,
62 * CB.Probe operation type
64 static const struct afs_call_type afs_SRXCBProbe
= {
66 .deliver
= afs_deliver_cb_probe
,
67 .abort_to_error
= afs_abort_to_error
,
68 .destructor
= afs_cm_destructor
,
72 * CB.GetCapabilities operation type
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
,
82 * route an incoming cache manager call
83 * - return T if supported, F if not
85 bool afs_cm_incoming_call(struct afs_call
*call
)
87 u32 operation_id
= ntohl(call
->operation_ID
);
89 _enter("{CB.OP %u}", operation_id
);
91 switch (operation_id
) {
93 call
->type
= &afs_SRXCBCallBack
;
95 case CBInitCallBackState
:
96 call
->type
= &afs_SRXCBInitCallBackState
;
98 case CBInitCallBackState3
:
99 call
->type
= &afs_SRXCBInitCallBackState3
;
102 call
->type
= &afs_SRXCBProbe
;
104 case CBGetCapabilities
:
105 call
->type
= &afs_SRXCBGetCapabilites
;
113 * clean up a cache manager call
115 static void afs_cm_destructor(struct afs_call
*call
)
119 afs_put_server(call
->server
);
126 * allow the fileserver to see if the cache manager is still alive
128 static void SRXAFSCB_CallBack(struct work_struct
*work
)
130 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
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
139 afs_send_empty_reply(call
);
141 afs_break_callbacks(call
->server
, call
->count
, call
->request
);
146 * deliver request data to a CB.CallBack call
148 static int afs_deliver_cb_callback(struct afs_call
*call
, struct sk_buff
*skb
,
151 struct afs_callback
*cb
;
152 struct afs_server
*server
;
158 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
160 switch (call
->unmarshall
) {
165 /* extract the FID array and its count in two steps */
167 _debug("extract FID count");
168 ret
= afs_extract_data(call
, skb
, last
, &call
->tmp
, 4);
171 case -EAGAIN
: return 0;
175 call
->count
= ntohl(call
->tmp
);
176 _debug("FID count: %u", call
->count
);
177 if (call
->count
> AFSCBMAX
)
180 call
->buffer
= kmalloc(call
->count
* 3 * 4, GFP_KERNEL
);
187 _debug("extract FID array");
188 ret
= afs_extract_data(call
, skb
, last
, call
->buffer
,
189 call
->count
* 3 * 4);
192 case -EAGAIN
: return 0;
196 _debug("unmarshall FID array");
197 call
->request
= kcalloc(call
->count
,
198 sizeof(struct afs_callback
),
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
;
215 /* extract the callback array and its count in two steps */
217 _debug("extract CB count");
218 ret
= afs_extract_data(call
, skb
, last
, &call
->tmp
, 4);
221 case -EAGAIN
: return 0;
225 tmp
= ntohl(call
->tmp
);
226 _debug("CB count: %u", tmp
);
227 if (tmp
!= call
->count
&& tmp
!= 0)
235 _debug("extract CB array");
236 ret
= afs_extract_data(call
, skb
, last
, call
->request
,
237 call
->count
* 3 * 4);
240 case -EAGAIN
: return 0;
244 _debug("unmarshall CB array");
247 for (loop
= call
->count
; loop
> 0; loop
--, cb
++) {
248 cb
->version
= ntohl(*bp
++);
249 cb
->expiry
= ntohl(*bp
++);
250 cb
->type
= ntohl(*bp
++);
267 call
->state
= AFS_CALL_REPLYING
;
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
);
275 call
->server
= server
;
277 INIT_WORK(&call
->work
, SRXAFSCB_CallBack
);
278 schedule_work(&call
->work
);
283 * allow the fileserver to request callback state (re-)initialisation
285 static void SRXAFSCB_InitCallBackState(struct work_struct
*work
)
287 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
289 _enter("{%p}", call
->server
);
291 afs_init_callback_state(call
->server
);
292 afs_send_empty_reply(call
);
297 * deliver request data to a CB.InitCallBackState call
299 static int afs_deliver_cb_init_call_back_state(struct afs_call
*call
,
303 struct afs_server
*server
;
306 _enter(",{%u},%d", skb
->len
, last
);
313 /* no unmarshalling required */
314 call
->state
= AFS_CALL_REPLYING
;
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
);
322 call
->server
= server
;
324 INIT_WORK(&call
->work
, SRXAFSCB_InitCallBackState
);
325 schedule_work(&call
->work
);
330 * deliver request data to a CB.InitCallBackState3 call
332 static int afs_deliver_cb_init_call_back_state3(struct afs_call
*call
,
336 struct afs_server
*server
;
339 _enter(",{%u},%d", skb
->len
, last
);
344 /* no unmarshalling required */
345 call
->state
= AFS_CALL_REPLYING
;
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
);
353 call
->server
= server
;
355 INIT_WORK(&call
->work
, SRXAFSCB_InitCallBackState
);
356 schedule_work(&call
->work
);
361 * allow the fileserver to see if the cache manager is still alive
363 static void SRXAFSCB_Probe(struct work_struct
*work
)
365 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
368 afs_send_empty_reply(call
);
373 * deliver request data to a CB.Probe call
375 static int afs_deliver_cb_probe(struct afs_call
*call
, struct sk_buff
*skb
,
378 _enter(",{%u},%d", skb
->len
, last
);
385 /* no unmarshalling required */
386 call
->state
= AFS_CALL_REPLYING
;
388 INIT_WORK(&call
->work
, SRXAFSCB_Probe
);
389 schedule_work(&call
->work
);
394 * allow the fileserver to ask about the cache manager's capabilities
396 static void SRXAFSCB_GetCapabilities(struct work_struct
*work
)
398 struct afs_interface
*ifs
;
399 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
403 struct /* InterfaceAddr */ {
410 struct /* Capabilities */ {
419 ifs
= kcalloc(32, sizeof(*ifs
), GFP_KERNEL
);
421 nifs
= afs_get_ipv4_interfaces(ifs
, 32, false);
429 memset(&reply
, 0, sizeof(reply
));
430 reply
.ia
.nifs
= htonl(nifs
);
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
]);
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
);
449 reply
.cap
.capcount
= htonl(1);
450 reply
.cap
.caps
[0] = htonl(AFS_CAP_ERROR_TRANSLATION
);
451 afs_send_simple_reply(call
, &reply
, sizeof(reply
));
457 * deliver request data to a CB.GetCapabilities call
459 static int afs_deliver_cb_get_capabilities(struct afs_call
*call
,
460 struct sk_buff
*skb
, bool last
)
462 _enter(",{%u},%d", skb
->len
, last
);
469 /* no unmarshalling required */
470 call
->state
= AFS_CALL_REPLYING
;
472 INIT_WORK(&call
->work
, SRXAFSCB_GetCapabilities
);
473 schedule_work(&call
->work
);