[AF_RXRPC]: Make the in-kernel AFS filesystem use AF_RXRPC.
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / fs / afs / cmservice.c
blobc7141175391b77cd40e61d809689d3a8c4f644e7
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>
15 #include <linux/ip.h>
16 #include "internal.h"
17 #include "afs_cm.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) {
65 case CBCallBack:
66 call->type = &afs_SRXCBCallBack;
67 return true;
68 case CBInitCallBackState:
69 call->type = &afs_SRXCBInitCallBackState;
70 return true;
71 case CBProbe:
72 call->type = &afs_SRXCBProbe;
73 return true;
74 default:
75 return false;
80 * clean up a cache manager call
82 static void afs_cm_destructor(struct afs_call *call)
84 _enter("");
86 afs_put_server(call->server);
87 call->server = NULL;
88 kfree(call->buffer);
89 call->buffer = NULL;
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);
99 _enter("");
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
105 * yet */
106 afs_send_empty_reply(call);
108 afs_break_callbacks(call->server, call->count, call->request);
109 _leave("");
113 * deliver request data to a CB.CallBack call
115 static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
116 bool last)
118 struct afs_callback *cb;
119 struct afs_server *server;
120 struct in_addr addr;
121 __be32 *bp;
122 u32 tmp;
123 int ret, loop;
125 _enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
127 switch (call->unmarshall) {
128 case 0:
129 call->offset = 0;
130 call->unmarshall++;
132 /* extract the FID array and its count in two steps */
133 case 1:
134 _debug("extract FID count");
135 ret = afs_extract_data(call, skb, last, &call->tmp, 4);
136 switch (ret) {
137 case 0: break;
138 case -EAGAIN: return 0;
139 default: return ret;
142 call->count = ntohl(call->tmp);
143 _debug("FID count: %u", call->count);
144 if (call->count > AFSCBMAX)
145 return -EBADMSG;
147 call->buffer = kmalloc(call->count * 3 * 4, GFP_KERNEL);
148 if (!call->buffer)
149 return -ENOMEM;
150 call->offset = 0;
151 call->unmarshall++;
153 case 2:
154 _debug("extract FID array");
155 ret = afs_extract_data(call, skb, last, call->buffer,
156 call->count * 3 * 4);
157 switch (ret) {
158 case 0: break;
159 case -EAGAIN: return 0;
160 default: return ret;
163 _debug("unmarshall FID array");
164 call->request = kcalloc(call->count,
165 sizeof(struct afs_callback),
166 GFP_KERNEL);
167 if (!call->request)
168 return -ENOMEM;
170 cb = call->request;
171 bp = call->buffer;
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;
179 call->offset = 0;
180 call->unmarshall++;
182 /* extract the callback array and its count in two steps */
183 case 3:
184 _debug("extract CB count");
185 ret = afs_extract_data(call, skb, last, &call->tmp, 4);
186 switch (ret) {
187 case 0: break;
188 case -EAGAIN: return 0;
189 default: return ret;
192 tmp = ntohl(call->tmp);
193 _debug("CB count: %u", tmp);
194 if (tmp != call->count && tmp != 0)
195 return -EBADMSG;
196 call->offset = 0;
197 call->unmarshall++;
198 if (tmp == 0)
199 goto empty_cb_array;
201 case 4:
202 _debug("extract CB array");
203 ret = afs_extract_data(call, skb, last, call->request,
204 call->count * 3 * 4);
205 switch (ret) {
206 case 0: break;
207 case -EAGAIN: return 0;
208 default: return ret;
211 _debug("unmarshall CB array");
212 cb = call->request;
213 bp = call->buffer;
214 for (loop = call->count; loop > 0; loop--, cb++) {
215 cb->version = ntohl(*bp++);
216 cb->expiry = ntohl(*bp++);
217 cb->type = ntohl(*bp++);
220 empty_cb_array:
221 call->offset = 0;
222 call->unmarshall++;
224 case 5:
225 _debug("trailer");
226 if (skb->len != 0)
227 return -EBADMSG;
228 break;
231 if (!last)
232 return 0;
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);
240 if (!server)
241 return -ENOTCONN;
242 call->server = server;
244 INIT_WORK(&call->work, SRXAFSCB_CallBack);
245 schedule_work(&call->work);
246 return 0;
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);
260 _leave("");
264 * deliver request data to a CB.InitCallBackState call
266 static int afs_deliver_cb_init_call_back_state(struct afs_call *call,
267 struct sk_buff *skb,
268 bool last)
270 struct afs_server *server;
271 struct in_addr addr;
273 _enter(",{%u},%d", skb->len, last);
275 if (skb->len > 0)
276 return -EBADMSG;
277 if (!last)
278 return 0;
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);
287 if (!server)
288 return -ENOTCONN;
289 call->server = server;
291 INIT_WORK(&call->work, SRXAFSCB_InitCallBackState);
292 schedule_work(&call->work);
293 return 0;
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);
303 _enter("");
304 afs_send_empty_reply(call);
305 _leave("");
309 * deliver request data to a CB.Probe call
311 static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb,
312 bool last)
314 _enter(",{%u},%d", skb->len, last);
316 if (skb->len > 0)
317 return -EBADMSG;
318 if (!last)
319 return 0;
321 /* no unmarshalling required */
322 call->state = AFS_CALL_REPLYING;
324 INIT_WORK(&call->work, SRXAFSCB_Probe);
325 schedule_work(&call->work);
326 return 0;