Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/fs/afs/cmservice.c
15109 views
1
/* AFS Cache Manager Service
2
*
3
* Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4
* Written by David Howells ([email protected])
5
*
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.
10
*/
11
12
#include <linux/module.h>
13
#include <linux/init.h>
14
#include <linux/slab.h>
15
#include <linux/sched.h>
16
#include <linux/ip.h>
17
#include "internal.h"
18
#include "afs_cm.h"
19
20
#if 0
21
struct workqueue_struct *afs_cm_workqueue;
22
#endif /* 0 */
23
24
static int afs_deliver_cb_init_call_back_state(struct afs_call *,
25
struct sk_buff *, bool);
26
static int afs_deliver_cb_init_call_back_state3(struct afs_call *,
27
struct sk_buff *, bool);
28
static int afs_deliver_cb_probe(struct afs_call *, struct sk_buff *, bool);
29
static int afs_deliver_cb_callback(struct afs_call *, struct sk_buff *, bool);
30
static int afs_deliver_cb_probe_uuid(struct afs_call *, struct sk_buff *, bool);
31
static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *,
32
struct sk_buff *, bool);
33
static void afs_cm_destructor(struct afs_call *);
34
35
/*
36
* CB.CallBack operation type
37
*/
38
static const struct afs_call_type afs_SRXCBCallBack = {
39
.name = "CB.CallBack",
40
.deliver = afs_deliver_cb_callback,
41
.abort_to_error = afs_abort_to_error,
42
.destructor = afs_cm_destructor,
43
};
44
45
/*
46
* CB.InitCallBackState operation type
47
*/
48
static const struct afs_call_type afs_SRXCBInitCallBackState = {
49
.name = "CB.InitCallBackState",
50
.deliver = afs_deliver_cb_init_call_back_state,
51
.abort_to_error = afs_abort_to_error,
52
.destructor = afs_cm_destructor,
53
};
54
55
/*
56
* CB.InitCallBackState3 operation type
57
*/
58
static const struct afs_call_type afs_SRXCBInitCallBackState3 = {
59
.name = "CB.InitCallBackState3",
60
.deliver = afs_deliver_cb_init_call_back_state3,
61
.abort_to_error = afs_abort_to_error,
62
.destructor = afs_cm_destructor,
63
};
64
65
/*
66
* CB.Probe operation type
67
*/
68
static const struct afs_call_type afs_SRXCBProbe = {
69
.name = "CB.Probe",
70
.deliver = afs_deliver_cb_probe,
71
.abort_to_error = afs_abort_to_error,
72
.destructor = afs_cm_destructor,
73
};
74
75
/*
76
* CB.ProbeUuid operation type
77
*/
78
static const struct afs_call_type afs_SRXCBProbeUuid = {
79
.name = "CB.ProbeUuid",
80
.deliver = afs_deliver_cb_probe_uuid,
81
.abort_to_error = afs_abort_to_error,
82
.destructor = afs_cm_destructor,
83
};
84
85
/*
86
* CB.TellMeAboutYourself operation type
87
*/
88
static const struct afs_call_type afs_SRXCBTellMeAboutYourself = {
89
.name = "CB.TellMeAboutYourself",
90
.deliver = afs_deliver_cb_tell_me_about_yourself,
91
.abort_to_error = afs_abort_to_error,
92
.destructor = afs_cm_destructor,
93
};
94
95
/*
96
* route an incoming cache manager call
97
* - return T if supported, F if not
98
*/
99
bool afs_cm_incoming_call(struct afs_call *call)
100
{
101
u32 operation_id = ntohl(call->operation_ID);
102
103
_enter("{CB.OP %u}", operation_id);
104
105
switch (operation_id) {
106
case CBCallBack:
107
call->type = &afs_SRXCBCallBack;
108
return true;
109
case CBInitCallBackState:
110
call->type = &afs_SRXCBInitCallBackState;
111
return true;
112
case CBInitCallBackState3:
113
call->type = &afs_SRXCBInitCallBackState3;
114
return true;
115
case CBProbe:
116
call->type = &afs_SRXCBProbe;
117
return true;
118
case CBTellMeAboutYourself:
119
call->type = &afs_SRXCBTellMeAboutYourself;
120
return true;
121
default:
122
return false;
123
}
124
}
125
126
/*
127
* clean up a cache manager call
128
*/
129
static void afs_cm_destructor(struct afs_call *call)
130
{
131
_enter("");
132
133
afs_put_server(call->server);
134
call->server = NULL;
135
kfree(call->buffer);
136
call->buffer = NULL;
137
}
138
139
/*
140
* allow the fileserver to see if the cache manager is still alive
141
*/
142
static void SRXAFSCB_CallBack(struct work_struct *work)
143
{
144
struct afs_call *call = container_of(work, struct afs_call, work);
145
146
_enter("");
147
148
/* be sure to send the reply *before* attempting to spam the AFS server
149
* with FSFetchStatus requests on the vnodes with broken callbacks lest
150
* the AFS server get into a vicious cycle of trying to break further
151
* callbacks because it hadn't received completion of the CBCallBack op
152
* yet */
153
afs_send_empty_reply(call);
154
155
afs_break_callbacks(call->server, call->count, call->request);
156
_leave("");
157
}
158
159
/*
160
* deliver request data to a CB.CallBack call
161
*/
162
static int afs_deliver_cb_callback(struct afs_call *call, struct sk_buff *skb,
163
bool last)
164
{
165
struct afs_callback *cb;
166
struct afs_server *server;
167
struct in_addr addr;
168
__be32 *bp;
169
u32 tmp;
170
int ret, loop;
171
172
_enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
173
174
switch (call->unmarshall) {
175
case 0:
176
call->offset = 0;
177
call->unmarshall++;
178
179
/* extract the FID array and its count in two steps */
180
case 1:
181
_debug("extract FID count");
182
ret = afs_extract_data(call, skb, last, &call->tmp, 4);
183
switch (ret) {
184
case 0: break;
185
case -EAGAIN: return 0;
186
default: return ret;
187
}
188
189
call->count = ntohl(call->tmp);
190
_debug("FID count: %u", call->count);
191
if (call->count > AFSCBMAX)
192
return -EBADMSG;
193
194
call->buffer = kmalloc(call->count * 3 * 4, GFP_KERNEL);
195
if (!call->buffer)
196
return -ENOMEM;
197
call->offset = 0;
198
call->unmarshall++;
199
200
case 2:
201
_debug("extract FID array");
202
ret = afs_extract_data(call, skb, last, call->buffer,
203
call->count * 3 * 4);
204
switch (ret) {
205
case 0: break;
206
case -EAGAIN: return 0;
207
default: return ret;
208
}
209
210
_debug("unmarshall FID array");
211
call->request = kcalloc(call->count,
212
sizeof(struct afs_callback),
213
GFP_KERNEL);
214
if (!call->request)
215
return -ENOMEM;
216
217
cb = call->request;
218
bp = call->buffer;
219
for (loop = call->count; loop > 0; loop--, cb++) {
220
cb->fid.vid = ntohl(*bp++);
221
cb->fid.vnode = ntohl(*bp++);
222
cb->fid.unique = ntohl(*bp++);
223
cb->type = AFSCM_CB_UNTYPED;
224
}
225
226
call->offset = 0;
227
call->unmarshall++;
228
229
/* extract the callback array and its count in two steps */
230
case 3:
231
_debug("extract CB count");
232
ret = afs_extract_data(call, skb, last, &call->tmp, 4);
233
switch (ret) {
234
case 0: break;
235
case -EAGAIN: return 0;
236
default: return ret;
237
}
238
239
tmp = ntohl(call->tmp);
240
_debug("CB count: %u", tmp);
241
if (tmp != call->count && tmp != 0)
242
return -EBADMSG;
243
call->offset = 0;
244
call->unmarshall++;
245
if (tmp == 0)
246
goto empty_cb_array;
247
248
case 4:
249
_debug("extract CB array");
250
ret = afs_extract_data(call, skb, last, call->request,
251
call->count * 3 * 4);
252
switch (ret) {
253
case 0: break;
254
case -EAGAIN: return 0;
255
default: return ret;
256
}
257
258
_debug("unmarshall CB array");
259
cb = call->request;
260
bp = call->buffer;
261
for (loop = call->count; loop > 0; loop--, cb++) {
262
cb->version = ntohl(*bp++);
263
cb->expiry = ntohl(*bp++);
264
cb->type = ntohl(*bp++);
265
}
266
267
empty_cb_array:
268
call->offset = 0;
269
call->unmarshall++;
270
271
case 5:
272
_debug("trailer");
273
if (skb->len != 0)
274
return -EBADMSG;
275
break;
276
}
277
278
if (!last)
279
return 0;
280
281
call->state = AFS_CALL_REPLYING;
282
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;
290
291
INIT_WORK(&call->work, SRXAFSCB_CallBack);
292
queue_work(afs_wq, &call->work);
293
return 0;
294
}
295
296
/*
297
* allow the fileserver to request callback state (re-)initialisation
298
*/
299
static void SRXAFSCB_InitCallBackState(struct work_struct *work)
300
{
301
struct afs_call *call = container_of(work, struct afs_call, work);
302
303
_enter("{%p}", call->server);
304
305
afs_init_callback_state(call->server);
306
afs_send_empty_reply(call);
307
_leave("");
308
}
309
310
/*
311
* deliver request data to a CB.InitCallBackState call
312
*/
313
static int afs_deliver_cb_init_call_back_state(struct afs_call *call,
314
struct sk_buff *skb,
315
bool last)
316
{
317
struct afs_server *server;
318
struct in_addr addr;
319
320
_enter(",{%u},%d", skb->len, last);
321
322
if (skb->len > 0)
323
return -EBADMSG;
324
if (!last)
325
return 0;
326
327
/* no unmarshalling required */
328
call->state = AFS_CALL_REPLYING;
329
330
/* we'll need the file server record as that tells us which set of
331
* vnodes to operate upon */
332
memcpy(&addr, &ip_hdr(skb)->saddr, 4);
333
server = afs_find_server(&addr);
334
if (!server)
335
return -ENOTCONN;
336
call->server = server;
337
338
INIT_WORK(&call->work, SRXAFSCB_InitCallBackState);
339
queue_work(afs_wq, &call->work);
340
return 0;
341
}
342
343
/*
344
* deliver request data to a CB.InitCallBackState3 call
345
*/
346
static int afs_deliver_cb_init_call_back_state3(struct afs_call *call,
347
struct sk_buff *skb,
348
bool last)
349
{
350
struct afs_server *server;
351
struct in_addr addr;
352
353
_enter(",{%u},%d", skb->len, last);
354
355
if (!last)
356
return 0;
357
358
/* no unmarshalling required */
359
call->state = AFS_CALL_REPLYING;
360
361
/* we'll need the file server record as that tells us which set of
362
* vnodes to operate upon */
363
memcpy(&addr, &ip_hdr(skb)->saddr, 4);
364
server = afs_find_server(&addr);
365
if (!server)
366
return -ENOTCONN;
367
call->server = server;
368
369
INIT_WORK(&call->work, SRXAFSCB_InitCallBackState);
370
queue_work(afs_wq, &call->work);
371
return 0;
372
}
373
374
/*
375
* allow the fileserver to see if the cache manager is still alive
376
*/
377
static void SRXAFSCB_Probe(struct work_struct *work)
378
{
379
struct afs_call *call = container_of(work, struct afs_call, work);
380
381
_enter("");
382
afs_send_empty_reply(call);
383
_leave("");
384
}
385
386
/*
387
* deliver request data to a CB.Probe call
388
*/
389
static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb,
390
bool last)
391
{
392
_enter(",{%u},%d", skb->len, last);
393
394
if (skb->len > 0)
395
return -EBADMSG;
396
if (!last)
397
return 0;
398
399
/* no unmarshalling required */
400
call->state = AFS_CALL_REPLYING;
401
402
INIT_WORK(&call->work, SRXAFSCB_Probe);
403
queue_work(afs_wq, &call->work);
404
return 0;
405
}
406
407
/*
408
* allow the fileserver to quickly find out if the fileserver has been rebooted
409
*/
410
static void SRXAFSCB_ProbeUuid(struct work_struct *work)
411
{
412
struct afs_call *call = container_of(work, struct afs_call, work);
413
struct afs_uuid *r = call->request;
414
415
struct {
416
__be32 match;
417
} reply;
418
419
_enter("");
420
421
422
if (memcmp(r, &afs_uuid, sizeof(afs_uuid)) == 0)
423
reply.match = htonl(0);
424
else
425
reply.match = htonl(1);
426
427
afs_send_simple_reply(call, &reply, sizeof(reply));
428
_leave("");
429
}
430
431
/*
432
* deliver request data to a CB.ProbeUuid call
433
*/
434
static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb,
435
bool last)
436
{
437
struct afs_uuid *r;
438
unsigned loop;
439
__be32 *b;
440
int ret;
441
442
_enter("{%u},{%u},%d", call->unmarshall, skb->len, last);
443
444
if (skb->len > 0)
445
return -EBADMSG;
446
if (!last)
447
return 0;
448
449
switch (call->unmarshall) {
450
case 0:
451
call->offset = 0;
452
call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL);
453
if (!call->buffer)
454
return -ENOMEM;
455
call->unmarshall++;
456
457
case 1:
458
_debug("extract UUID");
459
ret = afs_extract_data(call, skb, last, call->buffer,
460
11 * sizeof(__be32));
461
switch (ret) {
462
case 0: break;
463
case -EAGAIN: return 0;
464
default: return ret;
465
}
466
467
_debug("unmarshall UUID");
468
call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL);
469
if (!call->request)
470
return -ENOMEM;
471
472
b = call->buffer;
473
r = call->request;
474
r->time_low = ntohl(b[0]);
475
r->time_mid = ntohl(b[1]);
476
r->time_hi_and_version = ntohl(b[2]);
477
r->clock_seq_hi_and_reserved = ntohl(b[3]);
478
r->clock_seq_low = ntohl(b[4]);
479
480
for (loop = 0; loop < 6; loop++)
481
r->node[loop] = ntohl(b[loop + 5]);
482
483
call->offset = 0;
484
call->unmarshall++;
485
486
case 2:
487
_debug("trailer");
488
if (skb->len != 0)
489
return -EBADMSG;
490
break;
491
}
492
493
if (!last)
494
return 0;
495
496
call->state = AFS_CALL_REPLYING;
497
498
INIT_WORK(&call->work, SRXAFSCB_ProbeUuid);
499
queue_work(afs_wq, &call->work);
500
return 0;
501
}
502
503
/*
504
* allow the fileserver to ask about the cache manager's capabilities
505
*/
506
static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work)
507
{
508
struct afs_interface *ifs;
509
struct afs_call *call = container_of(work, struct afs_call, work);
510
int loop, nifs;
511
512
struct {
513
struct /* InterfaceAddr */ {
514
__be32 nifs;
515
__be32 uuid[11];
516
__be32 ifaddr[32];
517
__be32 netmask[32];
518
__be32 mtu[32];
519
} ia;
520
struct /* Capabilities */ {
521
__be32 capcount;
522
__be32 caps[1];
523
} cap;
524
} reply;
525
526
_enter("");
527
528
nifs = 0;
529
ifs = kcalloc(32, sizeof(*ifs), GFP_KERNEL);
530
if (ifs) {
531
nifs = afs_get_ipv4_interfaces(ifs, 32, false);
532
if (nifs < 0) {
533
kfree(ifs);
534
ifs = NULL;
535
nifs = 0;
536
}
537
}
538
539
memset(&reply, 0, sizeof(reply));
540
reply.ia.nifs = htonl(nifs);
541
542
reply.ia.uuid[0] = htonl(afs_uuid.time_low);
543
reply.ia.uuid[1] = htonl(afs_uuid.time_mid);
544
reply.ia.uuid[2] = htonl(afs_uuid.time_hi_and_version);
545
reply.ia.uuid[3] = htonl((s8) afs_uuid.clock_seq_hi_and_reserved);
546
reply.ia.uuid[4] = htonl((s8) afs_uuid.clock_seq_low);
547
for (loop = 0; loop < 6; loop++)
548
reply.ia.uuid[loop + 5] = htonl((s8) afs_uuid.node[loop]);
549
550
if (ifs) {
551
for (loop = 0; loop < nifs; loop++) {
552
reply.ia.ifaddr[loop] = ifs[loop].address.s_addr;
553
reply.ia.netmask[loop] = ifs[loop].netmask.s_addr;
554
reply.ia.mtu[loop] = htonl(ifs[loop].mtu);
555
}
556
kfree(ifs);
557
}
558
559
reply.cap.capcount = htonl(1);
560
reply.cap.caps[0] = htonl(AFS_CAP_ERROR_TRANSLATION);
561
afs_send_simple_reply(call, &reply, sizeof(reply));
562
563
_leave("");
564
}
565
566
/*
567
* deliver request data to a CB.TellMeAboutYourself call
568
*/
569
static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call,
570
struct sk_buff *skb, bool last)
571
{
572
_enter(",{%u},%d", skb->len, last);
573
574
if (skb->len > 0)
575
return -EBADMSG;
576
if (!last)
577
return 0;
578
579
/* no unmarshalling required */
580
call->state = AFS_CALL_REPLYING;
581
582
INIT_WORK(&call->work, SRXAFSCB_TellMeAboutYourself);
583
queue_work(afs_wq, &call->work);
584
return 0;
585
}
586
587