Commit 9396d496d74587d46a74b93a8b6b41659d2daf2e

Authored by David Howells
Committed by Linus Torvalds
1 parent 7c80bcce34

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

... ... @@ -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  
... ... @@ -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 }