Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

David Howells and committed by
Linus Torvalds
9396d496 7c80bcce

+108
+1
fs/afs/afs_cm.h
··· 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
+107
fs/afs/cmservice.c
··· 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 *); ··· 67 66 static const struct afs_call_type afs_SRXCBProbe = { 68 67 .name = "CB.Probe", 69 68 .deliver = afs_deliver_cb_probe, 69 + .abort_to_error = afs_abort_to_error, 70 + .destructor = afs_cm_destructor, 71 + }; 72 + 73 + /* 74 + * CB.ProbeUuid operation type 75 + */ 76 + static const struct afs_call_type afs_SRXCBProbeUuid = { 77 + .name = "CB.ProbeUuid", 78 + .deliver = afs_deliver_cb_probe_uuid, 70 79 .abort_to_error = afs_abort_to_error, 71 80 .destructor = afs_cm_destructor, 72 81 }; ··· 399 388 call->state = AFS_CALL_REPLYING; 400 389 401 390 INIT_WORK(&call->work, SRXAFSCB_Probe); 391 + schedule_work(&call->work); 392 + return 0; 393 + } 394 + 395 + /* 396 + * allow the fileserver to quickly find out if the fileserver has been rebooted 397 + */ 398 + static void SRXAFSCB_ProbeUuid(struct work_struct *work) 399 + { 400 + struct afs_call *call = container_of(work, struct afs_call, work); 401 + struct afs_uuid *r = call->request; 402 + 403 + struct { 404 + __be32 match; 405 + } reply; 406 + 407 + _enter(""); 408 + 409 + 410 + if (memcmp(r, &afs_uuid, sizeof(afs_uuid)) == 0) 411 + reply.match = htonl(0); 412 + else 413 + reply.match = htonl(1); 414 + 415 + afs_send_simple_reply(call, &reply, sizeof(reply)); 416 + _leave(""); 417 + } 418 + 419 + /* 420 + * deliver request data to a CB.ProbeUuid call 421 + */ 422 + static int afs_deliver_cb_probe_uuid(struct afs_call *call, struct sk_buff *skb, 423 + bool last) 424 + { 425 + struct afs_uuid *r; 426 + unsigned loop; 427 + __be32 *b; 428 + int ret; 429 + 430 + _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); 431 + 432 + if (skb->len > 0) 433 + return -EBADMSG; 434 + if (!last) 435 + return 0; 436 + 437 + switch (call->unmarshall) { 438 + case 0: 439 + call->offset = 0; 440 + call->buffer = kmalloc(11 * sizeof(__be32), GFP_KERNEL); 441 + if (!call->buffer) 442 + return -ENOMEM; 443 + call->unmarshall++; 444 + 445 + case 1: 446 + _debug("extract UUID"); 447 + ret = afs_extract_data(call, skb, last, call->buffer, 448 + 11 * sizeof(__be32)); 449 + switch (ret) { 450 + case 0: break; 451 + case -EAGAIN: return 0; 452 + default: return ret; 453 + } 454 + 455 + _debug("unmarshall UUID"); 456 + call->request = kmalloc(sizeof(struct afs_uuid), GFP_KERNEL); 457 + if (!call->request) 458 + return -ENOMEM; 459 + 460 + b = call->buffer; 461 + r = call->request; 462 + r->time_low = ntohl(b[0]); 463 + r->time_mid = ntohl(b[1]); 464 + r->time_hi_and_version = ntohl(b[2]); 465 + r->clock_seq_hi_and_reserved = ntohl(b[3]); 466 + r->clock_seq_low = ntohl(b[4]); 467 + 468 + for (loop = 0; loop < 6; loop++) 469 + r->node[loop] = ntohl(b[loop + 5]); 470 + 471 + call->offset = 0; 472 + call->unmarshall++; 473 + 474 + case 2: 475 + _debug("trailer"); 476 + if (skb->len != 0) 477 + return -EBADMSG; 478 + break; 479 + } 480 + 481 + if (!last) 482 + return 0; 483 + 484 + call->state = AFS_CALL_REPLYING; 485 + 486 + INIT_WORK(&call->work, SRXAFSCB_ProbeUuid); 402 487 schedule_work(&call->work); 403 488 return 0; 404 489 }