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