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>
20 struct workqueue_struct
*afs_cm_workqueue
;
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
*,
31 static void afs_cm_destructor(struct afs_call
*);
34 * CB.CallBack operation type
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
,
44 * CB.InitCallBackState operation type
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
,
54 * CB.InitCallBackState3 operation type
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
,
64 * CB.Probe operation type
66 static const struct afs_call_type afs_SRXCBProbe
= {
68 .deliver
= afs_deliver_cb_probe
,
69 .abort_to_error
= afs_abort_to_error
,
70 .destructor
= afs_cm_destructor
,
74 * CB.GetCapabilities operation type
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
,
84 * route an incoming cache manager call
85 * - return T if supported, F if not
87 bool afs_cm_incoming_call(struct afs_call
*call
)
89 u32 operation_id
= ntohl(call
->operation_ID
);
91 _enter("{CB.OP %u}", operation_id
);
93 switch (operation_id
) {
95 call
->type
= &afs_SRXCBCallBack
;
97 case CBInitCallBackState
:
98 call
->type
= &afs_SRXCBInitCallBackState
;
100 case CBInitCallBackState3
:
101 call
->type
= &afs_SRXCBInitCallBackState3
;
104 call
->type
= &afs_SRXCBProbe
;
106 case CBGetCapabilities
:
107 call
->type
= &afs_SRXCBGetCapabilites
;
115 * clean up a cache manager call
117 static void afs_cm_destructor(struct afs_call
*call
)
121 afs_put_server(call
->server
);
128 * allow the fileserver to see if the cache manager is still alive
130 static void SRXAFSCB_CallBack(struct work_struct
*work
)
132 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
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
141 afs_send_empty_reply(call
);
143 afs_break_callbacks(call
->server
, call
->count
, call
->request
);
148 * deliver request data to a CB.CallBack call
150 static int afs_deliver_cb_callback(struct afs_call
*call
, struct sk_buff
*skb
,
153 struct afs_callback
*cb
;
154 struct afs_server
*server
;
160 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
162 switch (call
->unmarshall
) {
167 /* extract the FID array and its count in two steps */
169 _debug("extract FID count");
170 ret
= afs_extract_data(call
, skb
, last
, &call
->tmp
, 4);
173 case -EAGAIN
: return 0;
177 call
->count
= ntohl(call
->tmp
);
178 _debug("FID count: %u", call
->count
);
179 if (call
->count
> AFSCBMAX
)
182 call
->buffer
= kmalloc(call
->count
* 3 * 4, GFP_KERNEL
);
189 _debug("extract FID array");
190 ret
= afs_extract_data(call
, skb
, last
, call
->buffer
,
191 call
->count
* 3 * 4);
194 case -EAGAIN
: return 0;
198 _debug("unmarshall FID array");
199 call
->request
= kcalloc(call
->count
,
200 sizeof(struct afs_callback
),
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
;
217 /* extract the callback array and its count in two steps */
219 _debug("extract CB count");
220 ret
= afs_extract_data(call
, skb
, last
, &call
->tmp
, 4);
223 case -EAGAIN
: return 0;
227 tmp
= ntohl(call
->tmp
);
228 _debug("CB count: %u", tmp
);
229 if (tmp
!= call
->count
&& tmp
!= 0)
237 _debug("extract CB array");
238 ret
= afs_extract_data(call
, skb
, last
, call
->request
,
239 call
->count
* 3 * 4);
242 case -EAGAIN
: return 0;
246 _debug("unmarshall CB array");
249 for (loop
= call
->count
; loop
> 0; loop
--, cb
++) {
250 cb
->version
= ntohl(*bp
++);
251 cb
->expiry
= ntohl(*bp
++);
252 cb
->type
= ntohl(*bp
++);
269 call
->state
= AFS_CALL_REPLYING
;
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
);
277 call
->server
= server
;
279 INIT_WORK(&call
->work
, SRXAFSCB_CallBack
);
280 schedule_work(&call
->work
);
285 * allow the fileserver to request callback state (re-)initialisation
287 static void SRXAFSCB_InitCallBackState(struct work_struct
*work
)
289 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
291 _enter("{%p}", call
->server
);
293 afs_init_callback_state(call
->server
);
294 afs_send_empty_reply(call
);
299 * deliver request data to a CB.InitCallBackState call
301 static int afs_deliver_cb_init_call_back_state(struct afs_call
*call
,
305 struct afs_server
*server
;
308 _enter(",{%u},%d", skb
->len
, last
);
315 /* no unmarshalling required */
316 call
->state
= AFS_CALL_REPLYING
;
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
);
324 call
->server
= server
;
326 INIT_WORK(&call
->work
, SRXAFSCB_InitCallBackState
);
327 schedule_work(&call
->work
);
332 * deliver request data to a CB.InitCallBackState3 call
334 static int afs_deliver_cb_init_call_back_state3(struct afs_call
*call
,
338 struct afs_server
*server
;
341 _enter(",{%u},%d", skb
->len
, last
);
346 /* no unmarshalling required */
347 call
->state
= AFS_CALL_REPLYING
;
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
);
355 call
->server
= server
;
357 INIT_WORK(&call
->work
, SRXAFSCB_InitCallBackState
);
358 schedule_work(&call
->work
);
363 * allow the fileserver to see if the cache manager is still alive
365 static void SRXAFSCB_Probe(struct work_struct
*work
)
367 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
370 afs_send_empty_reply(call
);
375 * deliver request data to a CB.Probe call
377 static int afs_deliver_cb_probe(struct afs_call
*call
, struct sk_buff
*skb
,
380 _enter(",{%u},%d", skb
->len
, last
);
387 /* no unmarshalling required */
388 call
->state
= AFS_CALL_REPLYING
;
390 INIT_WORK(&call
->work
, SRXAFSCB_Probe
);
391 schedule_work(&call
->work
);
396 * allow the fileserver to ask about the cache manager's capabilities
398 static void SRXAFSCB_GetCapabilities(struct work_struct
*work
)
400 struct afs_interface
*ifs
;
401 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
405 struct /* InterfaceAddr */ {
412 struct /* Capabilities */ {
421 ifs
= kcalloc(32, sizeof(*ifs
), GFP_KERNEL
);
423 nifs
= afs_get_ipv4_interfaces(ifs
, 32, false);
431 memset(&reply
, 0, sizeof(reply
));
432 reply
.ia
.nifs
= htonl(nifs
);
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
]);
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
);
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
));
459 * deliver request data to a CB.GetCapabilities call
461 static int afs_deliver_cb_get_capabilities(struct afs_call
*call
,
462 struct sk_buff
*skb
, bool last
)
464 _enter(",{%u},%d", skb
->len
, last
);
471 /* no unmarshalling required */
472 call
->state
= AFS_CALL_REPLYING
;
474 INIT_WORK(&call
->work
, SRXAFSCB_GetCapabilities
);
475 schedule_work(&call
->work
);