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 void afs_cm_destructor(struct afs_call
*);
28 * CB.CallBack operation type
30 static const struct afs_call_type afs_SRXCBCallBack
= {
31 .deliver
= afs_deliver_cb_callback
,
32 .abort_to_error
= afs_abort_to_error
,
33 .destructor
= afs_cm_destructor
,
37 * CB.InitCallBackState operation type
39 static const struct afs_call_type afs_SRXCBInitCallBackState
= {
40 .deliver
= afs_deliver_cb_init_call_back_state
,
41 .abort_to_error
= afs_abort_to_error
,
42 .destructor
= afs_cm_destructor
,
46 * CB.Probe operation type
48 static const struct afs_call_type afs_SRXCBProbe
= {
49 .deliver
= afs_deliver_cb_probe
,
50 .abort_to_error
= afs_abort_to_error
,
51 .destructor
= afs_cm_destructor
,
55 * route an incoming cache manager call
56 * - return T if supported, F if not
58 bool afs_cm_incoming_call(struct afs_call
*call
)
60 u32 operation_id
= ntohl(call
->operation_ID
);
62 _enter("{CB.OP %u}", operation_id
);
64 switch (operation_id
) {
66 call
->type
= &afs_SRXCBCallBack
;
68 case CBInitCallBackState
:
69 call
->type
= &afs_SRXCBInitCallBackState
;
72 call
->type
= &afs_SRXCBProbe
;
80 * clean up a cache manager call
82 static void afs_cm_destructor(struct afs_call
*call
)
86 afs_put_server(call
->server
);
93 * allow the fileserver to see if the cache manager is still alive
95 static void SRXAFSCB_CallBack(struct work_struct
*work
)
97 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
101 /* be sure to send the reply *before* attempting to spam the AFS server
102 * with FSFetchStatus requests on the vnodes with broken callbacks lest
103 * the AFS server get into a vicious cycle of trying to break further
104 * callbacks because it hadn't received completion of the CBCallBack op
106 afs_send_empty_reply(call
);
108 afs_break_callbacks(call
->server
, call
->count
, call
->request
);
113 * deliver request data to a CB.CallBack call
115 static int afs_deliver_cb_callback(struct afs_call
*call
, struct sk_buff
*skb
,
118 struct afs_callback
*cb
;
119 struct afs_server
*server
;
125 _enter("{%u},{%u},%d", call
->unmarshall
, skb
->len
, last
);
127 switch (call
->unmarshall
) {
132 /* extract the FID array and its count in two steps */
134 _debug("extract FID count");
135 ret
= afs_extract_data(call
, skb
, last
, &call
->tmp
, 4);
138 case -EAGAIN
: return 0;
142 call
->count
= ntohl(call
->tmp
);
143 _debug("FID count: %u", call
->count
);
144 if (call
->count
> AFSCBMAX
)
147 call
->buffer
= kmalloc(call
->count
* 3 * 4, GFP_KERNEL
);
154 _debug("extract FID array");
155 ret
= afs_extract_data(call
, skb
, last
, call
->buffer
,
156 call
->count
* 3 * 4);
159 case -EAGAIN
: return 0;
163 _debug("unmarshall FID array");
164 call
->request
= kcalloc(call
->count
,
165 sizeof(struct afs_callback
),
172 for (loop
= call
->count
; loop
> 0; loop
--, cb
++) {
173 cb
->fid
.vid
= ntohl(*bp
++);
174 cb
->fid
.vnode
= ntohl(*bp
++);
175 cb
->fid
.unique
= ntohl(*bp
++);
176 cb
->type
= AFSCM_CB_UNTYPED
;
182 /* extract the callback array and its count in two steps */
184 _debug("extract CB count");
185 ret
= afs_extract_data(call
, skb
, last
, &call
->tmp
, 4);
188 case -EAGAIN
: return 0;
192 tmp
= ntohl(call
->tmp
);
193 _debug("CB count: %u", tmp
);
194 if (tmp
!= call
->count
&& tmp
!= 0)
202 _debug("extract CB array");
203 ret
= afs_extract_data(call
, skb
, last
, call
->request
,
204 call
->count
* 3 * 4);
207 case -EAGAIN
: return 0;
211 _debug("unmarshall CB array");
214 for (loop
= call
->count
; loop
> 0; loop
--, cb
++) {
215 cb
->version
= ntohl(*bp
++);
216 cb
->expiry
= ntohl(*bp
++);
217 cb
->type
= ntohl(*bp
++);
234 call
->state
= AFS_CALL_REPLYING
;
236 /* we'll need the file server record as that tells us which set of
237 * vnodes to operate upon */
238 memcpy(&addr
, &ip_hdr(skb
)->saddr
, 4);
239 server
= afs_find_server(&addr
);
242 call
->server
= server
;
244 INIT_WORK(&call
->work
, SRXAFSCB_CallBack
);
245 schedule_work(&call
->work
);
250 * allow the fileserver to request callback state (re-)initialisation
252 static void SRXAFSCB_InitCallBackState(struct work_struct
*work
)
254 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
256 _enter("{%p}", call
->server
);
258 afs_init_callback_state(call
->server
);
259 afs_send_empty_reply(call
);
264 * deliver request data to a CB.InitCallBackState call
266 static int afs_deliver_cb_init_call_back_state(struct afs_call
*call
,
270 struct afs_server
*server
;
273 _enter(",{%u},%d", skb
->len
, last
);
280 /* no unmarshalling required */
281 call
->state
= AFS_CALL_REPLYING
;
283 /* we'll need the file server record as that tells us which set of
284 * vnodes to operate upon */
285 memcpy(&addr
, &ip_hdr(skb
)->saddr
, 4);
286 server
= afs_find_server(&addr
);
289 call
->server
= server
;
291 INIT_WORK(&call
->work
, SRXAFSCB_InitCallBackState
);
292 schedule_work(&call
->work
);
297 * allow the fileserver to see if the cache manager is still alive
299 static void SRXAFSCB_Probe(struct work_struct
*work
)
301 struct afs_call
*call
= container_of(work
, struct afs_call
, work
);
304 afs_send_empty_reply(call
);
309 * deliver request data to a CB.Probe call
311 static int afs_deliver_cb_probe(struct afs_call
*call
, struct sk_buff
*skb
,
314 _enter(",{%u},%d", skb
->len
, last
);
321 /* no unmarshalling required */
322 call
->state
= AFS_CALL_REPLYING
;
324 INIT_WORK(&call
->work
, SRXAFSCB_Probe
);
325 schedule_work(&call
->work
);