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