diff options
Diffstat (limited to 'fs/afs')
-rw-r--r-- | fs/afs/afs_cm.h | 1 | ||||
-rw-r--r-- | fs/afs/cmservice.c | 107 |
2 files changed, 108 insertions, 0 deletions
diff --git a/fs/afs/afs_cm.h b/fs/afs/afs_cm.h index 5f62f3ea563e..255f5dd6040c 100644 --- a/fs/afs/afs_cm.h +++ b/fs/afs/afs_cm.h | |||
@@ -24,6 +24,7 @@ enum AFS_CM_Operations { | |||
24 | CBGetXStatsVersion = 209, /* get version of extended statistics */ | 24 | CBGetXStatsVersion = 209, /* get version of extended statistics */ |
25 | CBGetXStats = 210, /* get contents of extended statistics data */ | 25 | CBGetXStats = 210, /* get contents of extended statistics data */ |
26 | CBInitCallBackState3 = 213, /* initialise callback state, version 3 */ | 26 | CBInitCallBackState3 = 213, /* initialise callback state, version 3 */ |
27 | CBProbeUuid = 214, /* check the client hasn't rebooted */ | ||
27 | CBTellMeAboutYourself = 65538, /* get client capabilities */ | 28 | CBTellMeAboutYourself = 65538, /* get client capabilities */ |
28 | }; | 29 | }; |
29 | 30 | ||
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index 75da3d04612c..eb765489164f 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c | |||
@@ -26,6 +26,7 @@ static int afs_deliver_cb_init_call_back_state3(struct afs_call *, | |||
26 | struct sk_buff *, bool); | 26 | struct sk_buff *, bool); |
27 | static int afs_deliver_cb_probe(struct afs_call *, 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); | 28 | static int afs_deliver_cb_callback(struct afs_call *, struct sk_buff *, bool); |
29 | static int afs_deliver_cb_probe_uuid(struct afs_call *, struct sk_buff *, bool); | ||
29 | static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *, | 30 | static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *, |
30 | struct sk_buff *, bool); | 31 | struct sk_buff *, bool); |
31 | static void afs_cm_destructor(struct afs_call *); | 32 | static void afs_cm_destructor(struct afs_call *); |
@@ -71,6 +72,16 @@ static const struct afs_call_type afs_SRXCBProbe = { | |||
71 | }; | 72 | }; |
72 | 73 | ||
73 | /* | 74 | /* |
75 | * CB.ProbeUuid operation type | ||
76 | */ | ||
77 | static const struct afs_call_type afs_SRXCBProbeUuid = { | ||
78 | .name = "CB.ProbeUuid", | ||
79 | .deliver = afs_deliver_cb_probe_uuid, | ||
80 | .abort_to_error = afs_abort_to_error, | ||
81 | .destructor = afs_cm_destructor, | ||
82 | }; | ||
83 | |||
84 | /* | ||
74 | * CB.TellMeAboutYourself operation type | 85 | * CB.TellMeAboutYourself operation type |
75 | */ | 86 | */ |
76 | static const struct afs_call_type afs_SRXCBTellMeAboutYourself = { | 87 | static const struct afs_call_type afs_SRXCBTellMeAboutYourself = { |
@@ -393,6 +404,102 @@ static int afs_deliver_cb_probe(struct afs_call *call, struct sk_buff *skb, | |||
393 | } | 404 | } |
394 | 405 | ||
395 | /* | 406 | /* |
407 | * allow the fileserver to quickly find out if the fileserver has been rebooted | ||
408 | */ | ||
409 | static void SRXAFSCB_ProbeUuid(struct work_struct *work) | ||
410 | { | ||
411 | struct afs_call *call = container_of(work, struct afs_call, work); | ||
412 | struct afs_uuid *r = call->request; | ||
413 | |||
414 | struct { | ||
415 | __be32 match; | ||
416 | } reply; | ||
417 | |||
418 | _enter(""); | ||
419 | |||
420 | |||
421 | if (memcmp(r, &afs_uuid, sizeof(afs_uuid)) == 0) | ||
422 | reply.match = htonl(0); | ||
423 | else | ||
424 | reply.match = htonl(1); | ||
425 | |||
426 | afs_send_simple_reply(call, &reply, sizeof(reply)); | ||
427 | _leave(""); | ||
428 | } | ||
429 | |||
430 | /* | ||
431 | * deliver request data to a CB.ProbeUuid call | ||
432 | */ | ||
433 | static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb, | ||
434 | bool last) | ||
435 | { | ||
436 | struct afs_uuid *r; | ||
437 | unsigned loop; | ||
438 | __be32 *b; | ||
439 | int ret; | ||
440 | |||
441 | _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); | ||
442 | |||
443 | if (skb->len > 0) | ||
444 | return -EBADMSG; | ||
445 | if (!last) | ||
446 | return 0; | ||
447 | |||
448 | switch (call->unmarshall) { | ||
449 | case 0: | ||
450 | call->offset = 0; | ||
451 | call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL); | ||
452 | if (!call->buffer) | ||
453 | return -ENOMEM; | ||
454 | call->unmarshall++; | ||
455 | |||
456 | case 1: | ||
457 | _debug("extract UUID"); | ||
458 | ret = afs_extract_data(call, skb, last, call->buffer, | ||
459 | 11 * sizeof(__be32)); | ||
460 | switch (ret) { | ||
461 | case 0: break; | ||
462 | case -EAGAIN: return 0; | ||
463 | default: return ret; | ||
464 | } | ||
465 | |||
466 | _debug("unmarshall UUID"); | ||
467 | call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL); | ||
468 | if (!call->request) | ||
469 | return -ENOMEM; | ||
470 | |||
471 | b = call->buffer; | ||
472 | r = call->request; | ||
473 | r->time_low = ntohl(b[0]); | ||
474 | r->time_mid = ntohl(b[1]); | ||
475 | r->time_hi_and_version = ntohl(b[2]); | ||
476 | r->clock_seq_hi_and_reserved = ntohl(b[3]); | ||
477 | r->clock_seq_low = ntohl(b[4]); | ||
478 | |||
479 | for (loop = 0; loop < 6; loop++) | ||
480 | r->node[loop] = ntohl(b[loop + 5]); | ||
481 | |||
482 | call->offset = 0; | ||
483 | call->unmarshall++; | ||
484 | |||
485 | case 2: | ||
486 | _debug("trailer"); | ||
487 | if (skb->len != 0) | ||
488 | return -EBADMSG; | ||
489 | break; | ||
490 | } | ||
491 | |||
492 | if (!last) | ||
493 | return 0; | ||
494 | |||
495 | call->state = AFS_CALL_REPLYING; | ||
496 | |||
497 | INIT_WORK(&call->work, SRXAFSCB_ProbeUuid); | ||
498 | schedule_work(&call->work); | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | /* | ||
396 | * allow the fileserver to ask about the cache manager's capabilities | 503 | * allow the fileserver to ask about the cache manager's capabilities |
397 | */ | 504 | */ |
398 | static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work) | 505 | static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work) |