1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * linux/fs/lockd/svcproc.c 4 * 5 * Lockd server procedures. We don't implement the NLM_*_RES 6 * procedures because we don't use the async procedures. 7 * 8 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de> 9 */ 10 11 #include <linux/types.h> 12 #include <linux/time.h> 13 #include <linux/lockd/lockd.h> 14 #include <linux/lockd/share.h> 15 #include <linux/sunrpc/svc_xprt.h> 16 17 #define NLMDBG_FACILITY NLMDBG_CLIENT 18 19 #ifdef CONFIG_LOCKD_V4 20 static __be32 21 cast_to_nlm(__be32 status, u32 vers) 22 { 23 /* Note: status is assumed to be in network byte order !!! */ 24 if (vers != 4){ 25 switch (status) { 26 case nlm_granted: 27 case nlm_lck_denied: 28 case nlm_lck_denied_nolocks: 29 case nlm_lck_blocked: 30 case nlm_lck_denied_grace_period: 31 case nlm_drop_reply: 32 break; 33 case nlm4_deadlock: 34 status = nlm_lck_denied; 35 break; 36 default: 37 status = nlm_lck_denied_nolocks; 38 } 39 } 40 41 return (status); 42 } 43 #define cast_status(status) (cast_to_nlm(status, rqstp->rq_vers)) 44 #else 45 #define cast_status(status) (status) 46 #endif 47 48 /* 49 * Obtain client and file from arguments 50 */ 51 static __be32 52 nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp, 53 struct nlm_host **hostp, struct nlm_file **filp) 54 { 55 struct nlm_host *host = NULL; 56 struct nlm_file *file = NULL; 57 struct nlm_lock *lock = &argp->lock; 58 int mode; 59 __be32 error = 0; 60 61 /* nfsd callbacks must have been installed for this procedure */ 62 if (!nlmsvc_ops) 63 return nlm_lck_denied_nolocks; 64 65 /* Obtain host handle */ 66 if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len)) 67 || (argp->monitor && nsm_monitor(host) < 0)) 68 goto no_locks; 69 *hostp = host; 70 71 /* Obtain file pointer. Not used by FREE_ALL call. */ 72 if (filp != NULL) { 73 error = cast_status(nlm_lookup_file(rqstp, &file, lock)); 74 if (error != 0) 75 goto no_locks; 76 *filp = file; 77 78 /* Set up the missing parts of the file_lock structure */ 79 mode = lock_to_openmode(&lock->fl); 80 lock->fl.fl_flags = FL_POSIX; 81 lock->fl.fl_file = file->f_file[mode]; 82 lock->fl.fl_pid = current->tgid; 83 lock->fl.fl_lmops = &nlmsvc_lock_operations; 84 nlmsvc_locks_init_private(&lock->fl, host, (pid_t)lock->svid); 85 if (!lock->fl.fl_owner) { 86 /* lockowner allocation has failed */ 87 nlmsvc_release_host(host); 88 return nlm_lck_denied_nolocks; 89 } 90 } 91 92 return 0; 93 94 no_locks: 95 nlmsvc_release_host(host); 96 if (error) 97 return error; 98 return nlm_lck_denied_nolocks; 99 } 100 101 /* 102 * NULL: Test for presence of service 103 */ 104 static __be32 105 nlmsvc_proc_null(struct svc_rqst *rqstp) 106 { 107 dprintk("lockd: NULL called\n"); 108 return rpc_success; 109 } 110 111 /* 112 * TEST: Check for conflicting lock 113 */ 114 static __be32 115 __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp) 116 { 117 struct nlm_args *argp = rqstp->rq_argp; 118 struct nlm_host *host; 119 struct nlm_file *file; 120 struct nlm_lockowner *test_owner; 121 __be32 rc = rpc_success; 122 123 dprintk("lockd: TEST called\n"); 124 resp->cookie = argp->cookie; 125 126 /* Obtain client and file */ 127 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 128 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 129 130 test_owner = argp->lock.fl.fl_owner; 131 132 /* Now check for conflicting locks */ 133 resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie)); 134 if (resp->status == nlm_drop_reply) 135 rc = rpc_drop_reply; 136 else 137 dprintk("lockd: TEST status %d vers %d\n", 138 ntohl(resp->status), rqstp->rq_vers); 139 140 nlmsvc_put_lockowner(test_owner); 141 nlmsvc_release_host(host); 142 nlm_release_file(file); 143 return rc; 144 } 145 146 static __be32 147 nlmsvc_proc_test(struct svc_rqst *rqstp) 148 { 149 return __nlmsvc_proc_test(rqstp, rqstp->rq_resp); 150 } 151 152 static __be32 153 __nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp) 154 { 155 struct nlm_args *argp = rqstp->rq_argp; 156 struct nlm_host *host; 157 struct nlm_file *file; 158 __be32 rc = rpc_success; 159 160 dprintk("lockd: LOCK called\n"); 161 162 resp->cookie = argp->cookie; 163 164 /* Obtain client and file */ 165 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 166 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 167 168 #if 0 169 /* If supplied state doesn't match current state, we assume it's 170 * an old request that time-warped somehow. Any error return would 171 * do in this case because it's irrelevant anyway. 172 * 173 * NB: We don't retrieve the remote host's state yet. 174 */ 175 if (host->h_nsmstate && host->h_nsmstate != argp->state) { 176 resp->status = nlm_lck_denied_nolocks; 177 } else 178 #endif 179 180 /* Now try to lock the file */ 181 resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock, 182 argp->block, &argp->cookie, 183 argp->reclaim)); 184 if (resp->status == nlm_drop_reply) 185 rc = rpc_drop_reply; 186 else 187 dprintk("lockd: LOCK status %d\n", ntohl(resp->status)); 188 189 nlmsvc_release_lockowner(&argp->lock); 190 nlmsvc_release_host(host); 191 nlm_release_file(file); 192 return rc; 193 } 194 195 static __be32 196 nlmsvc_proc_lock(struct svc_rqst *rqstp) 197 { 198 return __nlmsvc_proc_lock(rqstp, rqstp->rq_resp); 199 } 200 201 static __be32 202 __nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_res *resp) 203 { 204 struct nlm_args *argp = rqstp->rq_argp; 205 struct nlm_host *host; 206 struct nlm_file *file; 207 struct net *net = SVC_NET(rqstp); 208 209 dprintk("lockd: CANCEL called\n"); 210 211 resp->cookie = argp->cookie; 212 213 /* Don't accept requests during grace period */ 214 if (locks_in_grace(net)) { 215 resp->status = nlm_lck_denied_grace_period; 216 return rpc_success; 217 } 218 219 /* Obtain client and file */ 220 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 221 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 222 223 /* Try to cancel request. */ 224 resp->status = cast_status(nlmsvc_cancel_blocked(net, file, &argp->lock)); 225 226 dprintk("lockd: CANCEL status %d\n", ntohl(resp->status)); 227 nlmsvc_release_lockowner(&argp->lock); 228 nlmsvc_release_host(host); 229 nlm_release_file(file); 230 return rpc_success; 231 } 232 233 static __be32 234 nlmsvc_proc_cancel(struct svc_rqst *rqstp) 235 { 236 return __nlmsvc_proc_cancel(rqstp, rqstp->rq_resp); 237 } 238 239 /* 240 * UNLOCK: release a lock 241 */ 242 static __be32 243 __nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_res *resp) 244 { 245 struct nlm_args *argp = rqstp->rq_argp; 246 struct nlm_host *host; 247 struct nlm_file *file; 248 struct net *net = SVC_NET(rqstp); 249 250 dprintk("lockd: UNLOCK called\n"); 251 252 resp->cookie = argp->cookie; 253 254 /* Don't accept new lock requests during grace period */ 255 if (locks_in_grace(net)) { 256 resp->status = nlm_lck_denied_grace_period; 257 return rpc_success; 258 } 259 260 /* Obtain client and file */ 261 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 262 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 263 264 /* Now try to remove the lock */ 265 resp->status = cast_status(nlmsvc_unlock(net, file, &argp->lock)); 266 267 dprintk("lockd: UNLOCK status %d\n", ntohl(resp->status)); 268 nlmsvc_release_lockowner(&argp->lock); 269 nlmsvc_release_host(host); 270 nlm_release_file(file); 271 return rpc_success; 272 } 273 274 static __be32 275 nlmsvc_proc_unlock(struct svc_rqst *rqstp) 276 { 277 return __nlmsvc_proc_unlock(rqstp, rqstp->rq_resp); 278 } 279 280 /* 281 * GRANTED: A server calls us to tell that a process' lock request 282 * was granted 283 */ 284 static __be32 285 __nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_res *resp) 286 { 287 struct nlm_args *argp = rqstp->rq_argp; 288 289 resp->cookie = argp->cookie; 290 291 dprintk("lockd: GRANTED called\n"); 292 resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock); 293 dprintk("lockd: GRANTED status %d\n", ntohl(resp->status)); 294 return rpc_success; 295 } 296 297 static __be32 298 nlmsvc_proc_granted(struct svc_rqst *rqstp) 299 { 300 return __nlmsvc_proc_granted(rqstp, rqstp->rq_resp); 301 } 302 303 /* 304 * This is the generic lockd callback for async RPC calls 305 */ 306 static void nlmsvc_callback_exit(struct rpc_task *task, void *data) 307 { 308 } 309 310 void nlmsvc_release_call(struct nlm_rqst *call) 311 { 312 if (!refcount_dec_and_test(&call->a_count)) 313 return; 314 nlmsvc_release_host(call->a_host); 315 kfree(call); 316 } 317 318 static void nlmsvc_callback_release(void *data) 319 { 320 nlmsvc_release_call(data); 321 } 322 323 static const struct rpc_call_ops nlmsvc_callback_ops = { 324 .rpc_call_done = nlmsvc_callback_exit, 325 .rpc_release = nlmsvc_callback_release, 326 }; 327 328 /* 329 * `Async' versions of the above service routines. They aren't really, 330 * because we send the callback before the reply proper. I hope this 331 * doesn't break any clients. 332 */ 333 static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc, 334 __be32 (*func)(struct svc_rqst *, struct nlm_res *)) 335 { 336 struct nlm_args *argp = rqstp->rq_argp; 337 struct nlm_host *host; 338 struct nlm_rqst *call; 339 __be32 stat; 340 341 host = nlmsvc_lookup_host(rqstp, 342 argp->lock.caller, 343 argp->lock.len); 344 if (host == NULL) 345 return rpc_system_err; 346 347 call = nlm_alloc_call(host); 348 nlmsvc_release_host(host); 349 if (call == NULL) 350 return rpc_system_err; 351 352 stat = func(rqstp, &call->a_res); 353 if (stat != 0) { 354 nlmsvc_release_call(call); 355 return stat; 356 } 357 358 call->a_flags = RPC_TASK_ASYNC; 359 if (nlm_async_reply(call, proc, &nlmsvc_callback_ops) < 0) 360 return rpc_system_err; 361 return rpc_success; 362 } 363 364 static __be32 nlmsvc_proc_test_msg(struct svc_rqst *rqstp) 365 { 366 dprintk("lockd: TEST_MSG called\n"); 367 return nlmsvc_callback(rqstp, NLMPROC_TEST_RES, __nlmsvc_proc_test); 368 } 369 370 static __be32 nlmsvc_proc_lock_msg(struct svc_rqst *rqstp) 371 { 372 dprintk("lockd: LOCK_MSG called\n"); 373 return nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, __nlmsvc_proc_lock); 374 } 375 376 static __be32 nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp) 377 { 378 dprintk("lockd: CANCEL_MSG called\n"); 379 return nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, __nlmsvc_proc_cancel); 380 } 381 382 static __be32 383 nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp) 384 { 385 dprintk("lockd: UNLOCK_MSG called\n"); 386 return nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, __nlmsvc_proc_unlock); 387 } 388 389 static __be32 390 nlmsvc_proc_granted_msg(struct svc_rqst *rqstp) 391 { 392 dprintk("lockd: GRANTED_MSG called\n"); 393 return nlmsvc_callback(rqstp, NLMPROC_GRANTED_RES, __nlmsvc_proc_granted); 394 } 395 396 /* 397 * SHARE: create a DOS share or alter existing share. 398 */ 399 static __be32 400 nlmsvc_proc_share(struct svc_rqst *rqstp) 401 { 402 struct nlm_args *argp = rqstp->rq_argp; 403 struct nlm_res *resp = rqstp->rq_resp; 404 struct nlm_host *host; 405 struct nlm_file *file; 406 407 dprintk("lockd: SHARE called\n"); 408 409 resp->cookie = argp->cookie; 410 411 /* Don't accept new lock requests during grace period */ 412 if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) { 413 resp->status = nlm_lck_denied_grace_period; 414 return rpc_success; 415 } 416 417 /* Obtain client and file */ 418 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 419 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 420 421 /* Now try to create the share */ 422 resp->status = cast_status(nlmsvc_share_file(host, file, argp)); 423 424 dprintk("lockd: SHARE status %d\n", ntohl(resp->status)); 425 nlmsvc_release_lockowner(&argp->lock); 426 nlmsvc_release_host(host); 427 nlm_release_file(file); 428 return rpc_success; 429 } 430 431 /* 432 * UNSHARE: Release a DOS share. 433 */ 434 static __be32 435 nlmsvc_proc_unshare(struct svc_rqst *rqstp) 436 { 437 struct nlm_args *argp = rqstp->rq_argp; 438 struct nlm_res *resp = rqstp->rq_resp; 439 struct nlm_host *host; 440 struct nlm_file *file; 441 442 dprintk("lockd: UNSHARE called\n"); 443 444 resp->cookie = argp->cookie; 445 446 /* Don't accept requests during grace period */ 447 if (locks_in_grace(SVC_NET(rqstp))) { 448 resp->status = nlm_lck_denied_grace_period; 449 return rpc_success; 450 } 451 452 /* Obtain client and file */ 453 if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file))) 454 return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success; 455 456 /* Now try to unshare the file */ 457 resp->status = cast_status(nlmsvc_unshare_file(host, file, argp)); 458 459 dprintk("lockd: UNSHARE status %d\n", ntohl(resp->status)); 460 nlmsvc_release_lockowner(&argp->lock); 461 nlmsvc_release_host(host); 462 nlm_release_file(file); 463 return rpc_success; 464 } 465 466 /* 467 * NM_LOCK: Create an unmonitored lock 468 */ 469 static __be32 470 nlmsvc_proc_nm_lock(struct svc_rqst *rqstp) 471 { 472 struct nlm_args *argp = rqstp->rq_argp; 473 474 dprintk("lockd: NM_LOCK called\n"); 475 476 argp->monitor = 0; /* just clean the monitor flag */ 477 return nlmsvc_proc_lock(rqstp); 478 } 479 480 /* 481 * FREE_ALL: Release all locks and shares held by client 482 */ 483 static __be32 484 nlmsvc_proc_free_all(struct svc_rqst *rqstp) 485 { 486 struct nlm_args *argp = rqstp->rq_argp; 487 struct nlm_host *host; 488 489 /* Obtain client */ 490 if (nlmsvc_retrieve_args(rqstp, argp, &host, NULL)) 491 return rpc_success; 492 493 nlmsvc_free_host_resources(host); 494 nlmsvc_release_host(host); 495 return rpc_success; 496 } 497 498 /* 499 * SM_NOTIFY: private callback from statd (not part of official NLM proto) 500 */ 501 static __be32 502 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp) 503 { 504 struct nlm_reboot *argp = rqstp->rq_argp; 505 506 dprintk("lockd: SM_NOTIFY called\n"); 507 508 if (!nlm_privileged_requester(rqstp)) { 509 char buf[RPC_MAX_ADDRBUFLEN]; 510 printk(KERN_WARNING "lockd: rejected NSM callback from %s\n", 511 svc_print_addr(rqstp, buf, sizeof(buf))); 512 return rpc_system_err; 513 } 514 515 nlm_host_rebooted(SVC_NET(rqstp), argp); 516 return rpc_success; 517 } 518 519 /* 520 * client sent a GRANTED_RES, let's remove the associated block 521 */ 522 static __be32 523 nlmsvc_proc_granted_res(struct svc_rqst *rqstp) 524 { 525 struct nlm_res *argp = rqstp->rq_argp; 526 527 if (!nlmsvc_ops) 528 return rpc_success; 529 530 dprintk("lockd: GRANTED_RES called\n"); 531 532 nlmsvc_grant_reply(&argp->cookie, argp->status); 533 return rpc_success; 534 } 535 536 static __be32 537 nlmsvc_proc_unused(struct svc_rqst *rqstp) 538 { 539 return rpc_proc_unavail; 540 } 541 542 /* 543 * NLM Server procedures. 544 */ 545 546 struct nlm_void { int dummy; }; 547 548 #define Ck (1+XDR_QUADLEN(NLM_MAXCOOKIELEN)) /* cookie */ 549 #define St 1 /* status */ 550 #define No (1+1024/4) /* Net Obj */ 551 #define Rg 2 /* range - offset + size */ 552 553 const struct svc_procedure nlmsvc_procedures[24] = { 554 [NLMPROC_NULL] = { 555 .pc_func = nlmsvc_proc_null, 556 .pc_decode = nlmsvc_decode_void, 557 .pc_encode = nlmsvc_encode_void, 558 .pc_argsize = sizeof(struct nlm_void), 559 .pc_argzero = sizeof(struct nlm_void), 560 .pc_ressize = sizeof(struct nlm_void), 561 .pc_xdrressize = St, 562 .pc_name = "NULL", 563 }, 564 [NLMPROC_TEST] = { 565 .pc_func = nlmsvc_proc_test, 566 .pc_decode = nlmsvc_decode_testargs, 567 .pc_encode = nlmsvc_encode_testres, 568 .pc_argsize = sizeof(struct nlm_args), 569 .pc_argzero = sizeof(struct nlm_args), 570 .pc_ressize = sizeof(struct nlm_res), 571 .pc_xdrressize = Ck+St+2+No+Rg, 572 .pc_name = "TEST", 573 }, 574 [NLMPROC_LOCK] = { 575 .pc_func = nlmsvc_proc_lock, 576 .pc_decode = nlmsvc_decode_lockargs, 577 .pc_encode = nlmsvc_encode_res, 578 .pc_argsize = sizeof(struct nlm_args), 579 .pc_argzero = sizeof(struct nlm_args), 580 .pc_ressize = sizeof(struct nlm_res), 581 .pc_xdrressize = Ck+St, 582 .pc_name = "LOCK", 583 }, 584 [NLMPROC_CANCEL] = { 585 .pc_func = nlmsvc_proc_cancel, 586 .pc_decode = nlmsvc_decode_cancargs, 587 .pc_encode = nlmsvc_encode_res, 588 .pc_argsize = sizeof(struct nlm_args), 589 .pc_argzero = sizeof(struct nlm_args), 590 .pc_ressize = sizeof(struct nlm_res), 591 .pc_xdrressize = Ck+St, 592 .pc_name = "CANCEL", 593 }, 594 [NLMPROC_UNLOCK] = { 595 .pc_func = nlmsvc_proc_unlock, 596 .pc_decode = nlmsvc_decode_unlockargs, 597 .pc_encode = nlmsvc_encode_res, 598 .pc_argsize = sizeof(struct nlm_args), 599 .pc_argzero = sizeof(struct nlm_args), 600 .pc_ressize = sizeof(struct nlm_res), 601 .pc_xdrressize = Ck+St, 602 .pc_name = "UNLOCK", 603 }, 604 [NLMPROC_GRANTED] = { 605 .pc_func = nlmsvc_proc_granted, 606 .pc_decode = nlmsvc_decode_testargs, 607 .pc_encode = nlmsvc_encode_res, 608 .pc_argsize = sizeof(struct nlm_args), 609 .pc_argzero = sizeof(struct nlm_args), 610 .pc_ressize = sizeof(struct nlm_res), 611 .pc_xdrressize = Ck+St, 612 .pc_name = "GRANTED", 613 }, 614 [NLMPROC_TEST_MSG] = { 615 .pc_func = nlmsvc_proc_test_msg, 616 .pc_decode = nlmsvc_decode_testargs, 617 .pc_encode = nlmsvc_encode_void, 618 .pc_argsize = sizeof(struct nlm_args), 619 .pc_argzero = sizeof(struct nlm_args), 620 .pc_ressize = sizeof(struct nlm_void), 621 .pc_xdrressize = St, 622 .pc_name = "TEST_MSG", 623 }, 624 [NLMPROC_LOCK_MSG] = { 625 .pc_func = nlmsvc_proc_lock_msg, 626 .pc_decode = nlmsvc_decode_lockargs, 627 .pc_encode = nlmsvc_encode_void, 628 .pc_argsize = sizeof(struct nlm_args), 629 .pc_argzero = sizeof(struct nlm_args), 630 .pc_ressize = sizeof(struct nlm_void), 631 .pc_xdrressize = St, 632 .pc_name = "LOCK_MSG", 633 }, 634 [NLMPROC_CANCEL_MSG] = { 635 .pc_func = nlmsvc_proc_cancel_msg, 636 .pc_decode = nlmsvc_decode_cancargs, 637 .pc_encode = nlmsvc_encode_void, 638 .pc_argsize = sizeof(struct nlm_args), 639 .pc_argzero = sizeof(struct nlm_args), 640 .pc_ressize = sizeof(struct nlm_void), 641 .pc_xdrressize = St, 642 .pc_name = "CANCEL_MSG", 643 }, 644 [NLMPROC_UNLOCK_MSG] = { 645 .pc_func = nlmsvc_proc_unlock_msg, 646 .pc_decode = nlmsvc_decode_unlockargs, 647 .pc_encode = nlmsvc_encode_void, 648 .pc_argsize = sizeof(struct nlm_args), 649 .pc_argzero = sizeof(struct nlm_args), 650 .pc_ressize = sizeof(struct nlm_void), 651 .pc_xdrressize = St, 652 .pc_name = "UNLOCK_MSG", 653 }, 654 [NLMPROC_GRANTED_MSG] = { 655 .pc_func = nlmsvc_proc_granted_msg, 656 .pc_decode = nlmsvc_decode_testargs, 657 .pc_encode = nlmsvc_encode_void, 658 .pc_argsize = sizeof(struct nlm_args), 659 .pc_argzero = sizeof(struct nlm_args), 660 .pc_ressize = sizeof(struct nlm_void), 661 .pc_xdrressize = St, 662 .pc_name = "GRANTED_MSG", 663 }, 664 [NLMPROC_TEST_RES] = { 665 .pc_func = nlmsvc_proc_null, 666 .pc_decode = nlmsvc_decode_void, 667 .pc_encode = nlmsvc_encode_void, 668 .pc_argsize = sizeof(struct nlm_res), 669 .pc_argzero = sizeof(struct nlm_res), 670 .pc_ressize = sizeof(struct nlm_void), 671 .pc_xdrressize = St, 672 .pc_name = "TEST_RES", 673 }, 674 [NLMPROC_LOCK_RES] = { 675 .pc_func = nlmsvc_proc_null, 676 .pc_decode = nlmsvc_decode_void, 677 .pc_encode = nlmsvc_encode_void, 678 .pc_argsize = sizeof(struct nlm_res), 679 .pc_argzero = sizeof(struct nlm_res), 680 .pc_ressize = sizeof(struct nlm_void), 681 .pc_xdrressize = St, 682 .pc_name = "LOCK_RES", 683 }, 684 [NLMPROC_CANCEL_RES] = { 685 .pc_func = nlmsvc_proc_null, 686 .pc_decode = nlmsvc_decode_void, 687 .pc_encode = nlmsvc_encode_void, 688 .pc_argsize = sizeof(struct nlm_res), 689 .pc_argzero = sizeof(struct nlm_res), 690 .pc_ressize = sizeof(struct nlm_void), 691 .pc_xdrressize = St, 692 .pc_name = "CANCEL_RES", 693 }, 694 [NLMPROC_UNLOCK_RES] = { 695 .pc_func = nlmsvc_proc_null, 696 .pc_decode = nlmsvc_decode_void, 697 .pc_encode = nlmsvc_encode_void, 698 .pc_argsize = sizeof(struct nlm_res), 699 .pc_argzero = sizeof(struct nlm_res), 700 .pc_ressize = sizeof(struct nlm_void), 701 .pc_xdrressize = St, 702 .pc_name = "UNLOCK_RES", 703 }, 704 [NLMPROC_GRANTED_RES] = { 705 .pc_func = nlmsvc_proc_granted_res, 706 .pc_decode = nlmsvc_decode_res, 707 .pc_encode = nlmsvc_encode_void, 708 .pc_argsize = sizeof(struct nlm_res), 709 .pc_argzero = sizeof(struct nlm_res), 710 .pc_ressize = sizeof(struct nlm_void), 711 .pc_xdrressize = St, 712 .pc_name = "GRANTED_RES", 713 }, 714 [NLMPROC_NSM_NOTIFY] = { 715 .pc_func = nlmsvc_proc_sm_notify, 716 .pc_decode = nlmsvc_decode_reboot, 717 .pc_encode = nlmsvc_encode_void, 718 .pc_argsize = sizeof(struct nlm_reboot), 719 .pc_argzero = sizeof(struct nlm_reboot), 720 .pc_ressize = sizeof(struct nlm_void), 721 .pc_xdrressize = St, 722 .pc_name = "SM_NOTIFY", 723 }, 724 [17] = { 725 .pc_func = nlmsvc_proc_unused, 726 .pc_decode = nlmsvc_decode_void, 727 .pc_encode = nlmsvc_encode_void, 728 .pc_argsize = sizeof(struct nlm_void), 729 .pc_argzero = sizeof(struct nlm_void), 730 .pc_ressize = sizeof(struct nlm_void), 731 .pc_xdrressize = St, 732 .pc_name = "UNUSED", 733 }, 734 [18] = { 735 .pc_func = nlmsvc_proc_unused, 736 .pc_decode = nlmsvc_decode_void, 737 .pc_encode = nlmsvc_encode_void, 738 .pc_argsize = sizeof(struct nlm_void), 739 .pc_argzero = sizeof(struct nlm_void), 740 .pc_ressize = sizeof(struct nlm_void), 741 .pc_xdrressize = St, 742 .pc_name = "UNUSED", 743 }, 744 [19] = { 745 .pc_func = nlmsvc_proc_unused, 746 .pc_decode = nlmsvc_decode_void, 747 .pc_encode = nlmsvc_encode_void, 748 .pc_argsize = sizeof(struct nlm_void), 749 .pc_argzero = sizeof(struct nlm_void), 750 .pc_ressize = sizeof(struct nlm_void), 751 .pc_xdrressize = St, 752 .pc_name = "UNUSED", 753 }, 754 [NLMPROC_SHARE] = { 755 .pc_func = nlmsvc_proc_share, 756 .pc_decode = nlmsvc_decode_shareargs, 757 .pc_encode = nlmsvc_encode_shareres, 758 .pc_argsize = sizeof(struct nlm_args), 759 .pc_argzero = sizeof(struct nlm_args), 760 .pc_ressize = sizeof(struct nlm_res), 761 .pc_xdrressize = Ck+St+1, 762 .pc_name = "SHARE", 763 }, 764 [NLMPROC_UNSHARE] = { 765 .pc_func = nlmsvc_proc_unshare, 766 .pc_decode = nlmsvc_decode_shareargs, 767 .pc_encode = nlmsvc_encode_shareres, 768 .pc_argsize = sizeof(struct nlm_args), 769 .pc_argzero = sizeof(struct nlm_args), 770 .pc_ressize = sizeof(struct nlm_res), 771 .pc_xdrressize = Ck+St+1, 772 .pc_name = "UNSHARE", 773 }, 774 [NLMPROC_NM_LOCK] = { 775 .pc_func = nlmsvc_proc_nm_lock, 776 .pc_decode = nlmsvc_decode_lockargs, 777 .pc_encode = nlmsvc_encode_res, 778 .pc_argsize = sizeof(struct nlm_args), 779 .pc_argzero = sizeof(struct nlm_args), 780 .pc_ressize = sizeof(struct nlm_res), 781 .pc_xdrressize = Ck+St, 782 .pc_name = "NM_LOCK", 783 }, 784 [NLMPROC_FREE_ALL] = { 785 .pc_func = nlmsvc_proc_free_all, 786 .pc_decode = nlmsvc_decode_notify, 787 .pc_encode = nlmsvc_encode_void, 788 .pc_argsize = sizeof(struct nlm_args), 789 .pc_argzero = sizeof(struct nlm_args), 790 .pc_ressize = sizeof(struct nlm_void), 791 .pc_xdrressize = 0, 792 .pc_name = "FREE_ALL", 793 }, 794 }; 795