diff options
Diffstat (limited to 'fs/afs/cmservice.c')
-rw-r--r-- | fs/afs/cmservice.c | 133 |
1 files changed, 120 insertions, 13 deletions
diff --git a/fs/afs/cmservice.c b/fs/afs/cmservice.c index 47b71c8947f9..eb765489164f 100644 --- a/fs/afs/cmservice.c +++ b/fs/afs/cmservice.c | |||
@@ -26,8 +26,9 @@ 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_get_capabilities(struct afs_call *, struct sk_buff *, | 29 | static int afs_deliver_cb_probe_uuid(struct afs_call *, struct sk_buff *, bool); |
30 | bool); | 30 | static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *, |
31 | struct sk_buff *, bool); | ||
31 | static void afs_cm_destructor(struct afs_call *); | 32 | static void afs_cm_destructor(struct afs_call *); |
32 | 33 | ||
33 | /* | 34 | /* |
@@ -71,11 +72,21 @@ static const struct afs_call_type afs_SRXCBProbe = { | |||
71 | }; | 72 | }; |
72 | 73 | ||
73 | /* | 74 | /* |
74 | * CB.GetCapabilities operation type | 75 | * CB.ProbeUuid operation type |
75 | */ | 76 | */ |
76 | static const struct afs_call_type afs_SRXCBGetCapabilites = { | 77 | static const struct afs_call_type afs_SRXCBProbeUuid = { |
77 | .name = "CB.GetCapabilities", | 78 | .name = "CB.ProbeUuid", |
78 | .deliver = afs_deliver_cb_get_capabilities, | 79 | .deliver = afs_deliver_cb_probe_uuid, |
80 | .abort_to_error = afs_abort_to_error, | ||
81 | .destructor = afs_cm_destructor, | ||
82 | }; | ||
83 | |||
84 | /* | ||
85 | * CB.TellMeAboutYourself operation type | ||
86 | */ | ||
87 | static const struct afs_call_type afs_SRXCBTellMeAboutYourself = { | ||
88 | .name = "CB.TellMeAboutYourself", | ||
89 | .deliver = afs_deliver_cb_tell_me_about_yourself, | ||
79 | .abort_to_error = afs_abort_to_error, | 90 | .abort_to_error = afs_abort_to_error, |
80 | .destructor = afs_cm_destructor, | 91 | .destructor = afs_cm_destructor, |
81 | }; | 92 | }; |
@@ -103,8 +114,8 @@ bool afs_cm_incoming_call(struct afs_call *call) | |||
103 | case CBProbe: | 114 | case CBProbe: |
104 | call->type = &afs_SRXCBProbe; | 115 | call->type = &afs_SRXCBProbe; |
105 | return true; | 116 | return true; |
106 | case CBGetCapabilities: | 117 | case CBTellMeAboutYourself: |
107 | call->type = &afs_SRXCBGetCapabilites; | 118 | call->type = &afs_SRXCBTellMeAboutYourself; |
108 | return true; | 119 | return true; |
109 | default: | 120 | default: |
110 | return false; | 121 | return false; |
@@ -393,9 +404,105 @@ 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_GetCapabilities(struct work_struct *work) | 505 | static void SRXAFSCB_TellMeAboutYourself(struct work_struct *work) |
399 | { | 506 | { |
400 | struct afs_interface *ifs; | 507 | struct afs_interface *ifs; |
401 | struct afs_call *call = container_of(work, struct afs_call, work); | 508 | struct afs_call *call = container_of(work, struct afs_call, work); |
@@ -456,10 +563,10 @@ static void SRXAFSCB_GetCapabilities(struct work_struct *work) | |||
456 | } | 563 | } |
457 | 564 | ||
458 | /* | 565 | /* |
459 | * deliver request data to a CB.GetCapabilities call | 566 | * deliver request data to a CB.TellMeAboutYourself call |
460 | */ | 567 | */ |
461 | static int afs_deliver_cb_get_capabilities(struct afs_call *call, | 568 | static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *call, |
462 | struct sk_buff *skb, bool last) | 569 | struct sk_buff *skb, bool last) |
463 | { | 570 | { |
464 | _enter(",{%u},%d", skb->len, last); | 571 | _enter(",{%u},%d", skb->len, last); |
465 | 572 | ||
@@ -471,7 +578,7 @@ static int afs_deliver_cb_get_capabilities(struct afs_call *call, | |||
471 | /* no unmarshalling required */ | 578 | /* no unmarshalling required */ |
472 | call->state = AFS_CALL_REPLYING; | 579 | call->state = AFS_CALL_REPLYING; |
473 | 580 | ||
474 | INIT_WORK(&call->work, SRXAFSCB_GetCapabilities); | 581 | INIT_WORK(&call->work, SRXAFSCB_TellMeAboutYourself); |
475 | schedule_work(&call->work); | 582 | schedule_work(&call->work); |
476 | return 0; | 583 | return 0; |
477 | } | 584 | } |