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_probe(struct afs_call
*, struct sk_buff
*, bool);
24 static int afs_deliver_cb_callback(struct afs_call
*, struct sk_buff
*, bool);
25 static int afs_deliver_cb_get_capabilities(struct afs_call
*, struct sk_buff
*,
27 static void afs_cm_destructor(struct afs_call
*);
30 * CB.CallBack operation type
32 static const struct afs_call_type afs_SRXCBCallBack
= {
33 .name
= "CB.CallBack",
34 .deliver
= afs_deliver_cb_callback
,
35 .abort_to_error
= afs_abort_to_error
,
36 .destructor
= afs_cm_destructor
,
40 * CB.InitCallBackState operation type
42 static const struct afs_call_type afs_SRXCBInitCallBackState
= {
43 .name
= "CB.InitCallBackState",
44 .deliver
= afs_deliver_cb_init_call_back_state
,
45 .abort_to_error
= afs_abort_to_error
,
46 .destructor
= afs_cm_destructor
,
50 * CB.Probe operation type
52 static const struct afs_call_type afs_SRXCBProbe
= {
54 .deliver
= afs_deliver_cb_probe
,
55 .abort_to_error
= afs_abort_to_error
,
56 .destructor
= afs_cm_destructor
,
60 * CB.GetCapabilities operation type
62 static const struct afs_call_type afs_SRXCBGetCapabilites
= {
63 .name
= "CB.GetCapabilities",
64 .deliver
= afs_deliver_cb_get_capabilities
,
65 .abort_to_error
= afs_abort_to_error
,
66 .destructor
= afs_cm_destructor
,
70 * route an incoming cache manager call
71 * - return T if supported, F if not
73 bool afs_cm_incoming_call(struct afs_call
*call
)
75 u32 operation_id
= ntohl(call
->operation_ID
);
77 _enter("{CB.OP %u}", operation_id
);
79 switch (operation_id
) {
81 call
->type
= &afs_SRXCBCallBack
;
83 case CBInitCallBackState
:
84 call
->type
= &afs_SRXCBInitCallBackState
;
87 call
->type
= &afs_SRXCBProbe
;
89 case CBGetCapabilities
:
90 call
->type
= &afs_SRXCBGetCapabilites
;
98 * clean up a cache manager call
100 static void afs_cm_destructor(struct afs_call
*call
)
104 afs_put_server(call
->server
);
111 * allow the fileserver to see if the cache manager is still alive
113 static void SRXAFSCB_CallBack(struct work_struct
*work
)
115 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
119 /* be sure to send the reply *before* attempting to spam the AFS server
120 * with FSFetchStatus requests on the vnodes with broken callbacks lest
121 * the AFS server get into a vicious cycle of trying to break further
122 * callbacks because it hadn't received completion of the CBCallBack op
124 afs_send_empty_reply(call
);
126 afs_break_callbacks(call
->server
, call
->count
, call
->request
);
131 * deliver request data to a CB.CallBack call
133 static int afs_deliver_cb_callback(struct afs_call
*call
, struct sk_buff
*skb
,
136 struct afs_callback
*cb
;
137 struct afs_server
*server
;
143 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
145 switch (call
->unmarshall
) {
150 /* extract the FID array and its count in two steps */
152 _debug("extract FID count");
153 ret
= afs_extract_data(call
, skb
, last
, &call
->tmp
, 4);
156 case -EAGAIN
: return 0;
160 call
->count
= ntohl(call
->tmp
);
161 _debug("FID count: %u", call
->count
);
162 if (call
->count
> AFSCBMAX
)
165 call
->buffer
= kmalloc(call
->count
* 3 * 4, GFP_KERNEL
);
172 _debug("extract FID array");
173 ret
= afs_extract_data(call
, skb
, last
, call
->buffer
,
174 call
->count
* 3 * 4);
177 case -EAGAIN
: return 0;
181 _debug("unmarshall FID array");
182 call
->request
= kcalloc(call
->count
,
183 sizeof(struct afs_callback
),
190 for (loop
= call
->count
; loop
> 0; loop
--, cb
++) {
191 cb
->fid
.vid
= ntohl(*bp
++);
192 cb
->fid
.vnode
= ntohl(*bp
++);
193 cb
->fid
.unique
= ntohl(*bp
++);
194 cb
->type
= AFSCM_CB_UNTYPED
;
200 /* extract the callback array and its count in two steps */
202 _debug("extract CB count");
203 ret
= afs_extract_data(call
, skb
, last
, &call
->tmp
, 4);
206 case -EAGAIN
: return 0;
210 tmp
= ntohl(call
->tmp
);
211 _debug("CB count: %u", tmp
);
212 if (tmp
!= call
->count
&& tmp
!= 0)
220 _debug("extract CB array");
221 ret
= afs_extract_data(call
, skb
, last
, call
->request
,
222 call
->count
* 3 * 4);
225 case -EAGAIN
: return 0;
229 _debug("unmarshall CB array");
232 for (loop
= call
->count
; loop
> 0; loop
--, cb
++) {
233 cb
->version
= ntohl(*bp
++);
234 cb
->expiry
= ntohl(*bp
++);
235 cb
->type
= ntohl(*bp
++);
252 call
->state
= AFS_CALL_REPLYING
;
254 /* we'll need the file server record as that tells us which set of
255 * vnodes to operate upon */
256 memcpy(&addr
, &ip_hdr(skb
)->saddr
, 4);
257 server
= afs_find_server(&addr
);
260 call
->server
= server
;
262 INIT_WORK(&call
->work
, SRXAFSCB_CallBack
);
263 schedule_work(&call
->work
);
268 * allow the fileserver to request callback state (re-)initialisation
270 static void SRXAFSCB_InitCallBackState(struct work_struct
*work
)
272 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
274 _enter("{%p}", call
->server
);
276 afs_init_callback_state(call
->server
);
277 afs_send_empty_reply(call
);
282 * deliver request data to a CB.InitCallBackState call
284 static int afs_deliver_cb_init_call_back_state(struct afs_call
*call
,
288 struct afs_server
*server
;
291 _enter(",{%u},%d", skb
->len
, last
);
298 /* no unmarshalling required */
299 call
->state
= AFS_CALL_REPLYING
;
301 /* we'll need the file server record as that tells us which set of
302 * vnodes to operate upon */
303 memcpy(&addr
, &ip_hdr(skb
)->saddr
, 4);
304 server
= afs_find_server(&addr
);
307 call
->server
= server
;
309 INIT_WORK(&call
->work
, SRXAFSCB_InitCallBackState
);
310 schedule_work(&call
->work
);
315 * allow the fileserver to see if the cache manager is still alive
317 static void SRXAFSCB_Probe(struct work_struct
*work
)
319 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
322 afs_send_empty_reply(call
);
327 * deliver request data to a CB.Probe call
329 static int afs_deliver_cb_probe(struct afs_call
*call
, struct sk_buff
*skb
,
332 _enter(",{%u},%d", skb
->len
, last
);
339 /* no unmarshalling required */
340 call
->state
= AFS_CALL_REPLYING
;
342 INIT_WORK(&call
->work
, SRXAFSCB_Probe
);
343 schedule_work(&call
->work
);
348 * allow the fileserver to ask about the cache manager's capabilities
350 static void SRXAFSCB_GetCapabilities(struct work_struct
*work
)
352 struct afs_interface
*ifs
;
353 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
357 struct /* InterfaceAddr */ {
364 struct /* Capabilities */ {
373 ifs
= kcalloc(32, sizeof(*ifs
), GFP_KERNEL
);
375 nifs
= afs_get_ipv4_interfaces(ifs
, 32, false);
383 memset(&reply
, 0, sizeof(reply
));
384 reply
.ia
.nifs
= htonl(nifs
);
386 reply
.ia
.uuid
[0] = htonl(afs_uuid
.time_low
);
387 reply
.ia
.uuid
[1] = htonl(afs_uuid
.time_mid
);
388 reply
.ia
.uuid
[2] = htonl(afs_uuid
.time_hi_and_version
);
389 reply
.ia
.uuid
[3] = htonl((s8
) afs_uuid
.clock_seq_hi_and_reserved
);
390 reply
.ia
.uuid
[4] = htonl((s8
) afs_uuid
.clock_seq_low
);
391 for (loop
= 0; loop
< 6; loop
++)
392 reply
.ia
.uuid
[loop
+ 5] = htonl((s8
) afs_uuid
.node
[loop
]);
395 for (loop
= 0; loop
< nifs
; loop
++) {
396 reply
.ia
.ifaddr
[loop
] = ifs
[loop
].address
.s_addr
;
397 reply
.ia
.netmask
[loop
] = ifs
[loop
].netmask
.s_addr
;
398 reply
.ia
.mtu
[loop
] = htonl(ifs
[loop
].mtu
);
402 reply
.cap
.capcount
= htonl(1);
403 reply
.cap
.caps
[0] = htonl(AFS_CAP_ERROR_TRANSLATION
);
404 afs_send_simple_reply(call
, &reply
, sizeof(reply
));
410 * deliver request data to a CB.GetCapabilities call
412 static int afs_deliver_cb_get_capabilities(struct afs_call
*call
,
413 struct sk_buff
*skb
, bool last
)
415 _enter(",{%u},%d", skb
->len
, last
);
422 /* no unmarshalling required */
423 call
->state
= AFS_CALL_REPLYING
;
425 INIT_WORK(&call
->work
, SRXAFSCB_GetCapabilities
);
426 schedule_work(&call
->work
);