Commit 9396d496d74587d46a74b93a8b6b41659d2daf2e
Committed by
Linus Torvalds
1 parent
7c80bcce34
Exists in
master
and in
4 other branches
afs: support the CB.ProbeUuid RPC op
Add support for the CB.ProbeUuid cache manager RPC op. This allows a modern OpenAFS server to quickly ask if the client has been rebooted. Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 2 changed files with 108 additions and 0 deletions Side-by-side Diff
fs/afs/afs_cm.h
... | ... | @@ -24,6 +24,7 @@ |
24 | 24 | CBGetXStatsVersion = 209, /* get version of extended statistics */ |
25 | 25 | CBGetXStats = 210, /* get contents of extended statistics data */ |
26 | 26 | CBInitCallBackState3 = 213, /* initialise callback state, version 3 */ |
27 | + CBProbeUuid = 214, /* check the client hasn't rebooted */ | |
27 | 28 | CBTellMeAboutYourself = 65538, /* get client capabilities */ |
28 | 29 | }; |
29 | 30 |
fs/afs/cmservice.c
... | ... | @@ -26,6 +26,7 @@ |
26 | 26 | struct sk_buff *, bool); |
27 | 27 | static int afs_deliver_cb_probe(struct afs_call *, struct sk_buff *, bool); |
28 | 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 | 30 | static int afs_deliver_cb_tell_me_about_yourself(struct afs_call *, |
30 | 31 | struct sk_buff *, bool); |
31 | 32 | static void afs_cm_destructor(struct afs_call *); |
... | ... | @@ -71,6 +72,16 @@ |
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 | 85 | * CB.TellMeAboutYourself operation type |
75 | 86 | */ |
76 | 87 | static const struct afs_call_type afs_SRXCBTellMeAboutYourself = { |
... | ... | @@ -388,6 +399,102 @@ |
388 | 399 | call->state = AFS_CALL_REPLYING; |
389 | 400 | |
390 | 401 | INIT_WORK(&call->work, SRXAFSCB_Probe); |
402 | + schedule_work(&call->work); | |
403 | + return 0; | |
404 | +} | |
405 | + | |
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); | |
391 | 498 | schedule_work(&call->work); |
392 | 499 | return 0; |
393 | 500 | } |