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 17 /* 18 * xdr.h defines SM_PRIV_SIZE as a macro. nlm3xdr_gen.h defines 19 * it as an enum constant. Undefine the macro before including 20 * the generated header. 21 */ 22 #undef SM_PRIV_SIZE 23 24 #include "share.h" 25 #include "nlm3xdr_gen.h" 26 27 /* 28 * Size of an NFSv2 file handle, in bytes, which is 32. 29 * Defined locally to avoid including uapi/linux/nfs2.h. 30 */ 31 #define NLM3_FHSIZE 32 32 33 /* 34 * Wrapper structures combine xdrgen types with legacy lockd_lock. 35 * The xdrgen field must be first so the structure can be cast 36 * to its XDR type for the RPC dispatch layer. 37 */ 38 struct nlm_testargs_wrapper { 39 struct nlm_testargs xdrgen; 40 struct lockd_lock lock; 41 }; 42 43 static_assert(offsetof(struct nlm_testargs_wrapper, xdrgen) == 0); 44 45 struct nlm_testres_wrapper { 46 struct nlm_testres xdrgen; 47 struct lockd_lock lock; 48 }; 49 50 static_assert(offsetof(struct nlm_testres_wrapper, xdrgen) == 0); 51 52 struct nlm_lockargs_wrapper { 53 struct nlm_lockargs xdrgen; 54 struct lockd_cookie cookie; 55 struct lockd_lock lock; 56 }; 57 58 static_assert(offsetof(struct nlm_lockargs_wrapper, xdrgen) == 0); 59 60 struct nlm_res_wrapper { 61 struct nlm_res xdrgen; 62 struct lockd_cookie cookie; 63 }; 64 65 static_assert(offsetof(struct nlm_res_wrapper, xdrgen) == 0); 66 67 struct nlm_cancargs_wrapper { 68 struct nlm_cancargs xdrgen; 69 struct lockd_lock lock; 70 }; 71 72 static_assert(offsetof(struct nlm_cancargs_wrapper, xdrgen) == 0); 73 74 struct nlm_unlockargs_wrapper { 75 struct nlm_unlockargs xdrgen; 76 struct lockd_lock lock; 77 }; 78 79 static_assert(offsetof(struct nlm_unlockargs_wrapper, xdrgen) == 0); 80 81 struct nlm_notifyargs_wrapper { 82 struct nlm_notifyargs xdrgen; 83 struct lockd_reboot reboot; 84 }; 85 86 static_assert(offsetof(struct nlm_notifyargs_wrapper, xdrgen) == 0); 87 88 struct nlm_shareargs_wrapper { 89 struct nlm_shareargs xdrgen; 90 struct lockd_lock lock; 91 }; 92 93 static_assert(offsetof(struct nlm_shareargs_wrapper, xdrgen) == 0); 94 95 struct nlm_shareres_wrapper { 96 struct nlm_shareres xdrgen; 97 }; 98 99 static_assert(offsetof(struct nlm_shareres_wrapper, xdrgen) == 0); 100 101 struct nlm_notify_wrapper { 102 struct nlm_notify xdrgen; 103 }; 104 105 static_assert(offsetof(struct nlm_notify_wrapper, xdrgen) == 0); 106 107 static __be32 108 nlm_netobj_to_cookie(struct lockd_cookie *cookie, netobj *object) 109 { 110 if (object->len > NLM_MAXCOOKIELEN) 111 return nlm_lck_denied_nolocks; 112 cookie->len = object->len; 113 memcpy(cookie->data, object->data, object->len); 114 return nlm_granted; 115 } 116 117 static __be32 118 nlm_lock_to_lockd_lock(struct lockd_lock *lock, struct nlm_lock *alock) 119 { 120 if (alock->fh.len != NLM3_FHSIZE) 121 return nlm_lck_denied; 122 lock->fh.size = alock->fh.len; 123 memcpy(lock->fh.data, alock->fh.data, alock->fh.len); 124 lock->oh.len = alock->oh.len; 125 lock->oh.data = alock->oh.data; 126 lock->svid = alock->uppid; 127 lockd_set_file_lock_range3(&lock->fl, alock->l_offset, alock->l_len); 128 return nlm_granted; 129 } 130 131 static struct nlm_host * 132 nlm3svc_lookup_host(struct svc_rqst *rqstp, string caller, bool monitored) 133 { 134 struct nlm_host *host; 135 136 if (!nlmsvc_ops) 137 return NULL; 138 host = nlmsvc_lookup_host(rqstp, caller.data, caller.len); 139 if (!host) 140 return NULL; 141 if (monitored && nsm_monitor(host) < 0) { 142 nlmsvc_release_host(host); 143 return NULL; 144 } 145 return host; 146 } 147 148 static __be32 149 nlm3svc_lookup_file(struct svc_rqst *rqstp, struct nlm_host *host, 150 struct lockd_lock *lock, struct nlm_file **filp, 151 struct nlm_lock *xdr_lock, unsigned char type) 152 { 153 bool is_test = (rqstp->rq_proc == NLMPROC_TEST || 154 rqstp->rq_proc == NLMPROC_TEST_MSG); 155 struct file_lock *fl = &lock->fl; 156 struct nlm_file *file = NULL; 157 __be32 error; 158 int mode; 159 160 if (xdr_lock->fh.len != NLM3_FHSIZE) 161 return nlm_lck_denied_nolocks; 162 lock->fh.size = xdr_lock->fh.len; 163 memcpy(lock->fh.data, xdr_lock->fh.data, xdr_lock->fh.len); 164 165 lock->oh.len = xdr_lock->oh.len; 166 lock->oh.data = xdr_lock->oh.data; 167 168 lock->svid = xdr_lock->uppid; 169 lock->lock_start = xdr_lock->l_offset; 170 lock->lock_len = xdr_lock->l_len; 171 172 locks_init_lock(fl); 173 fl->c.flc_type = type; 174 lockd_set_file_lock_range3(fl, lock->lock_start, lock->lock_len); 175 176 mode = lock_to_openmode(fl); 177 if (is_test) 178 mode = O_RDWR; 179 180 error = nlm_lookup_file(rqstp, &file, lock, mode); 181 switch (error) { 182 case nlm_granted: 183 break; 184 case nlm__int__stale_fh: 185 case nlm__int__failed: 186 return nlm_lck_denied_nolocks; 187 default: 188 return error; 189 } 190 *filp = file; 191 192 fl->c.flc_flags = FL_POSIX; 193 if (is_test) 194 fl->c.flc_file = nlmsvc_file_file(file); 195 else 196 fl->c.flc_file = file->f_file[mode]; 197 fl->c.flc_pid = current->tgid; 198 fl->fl_lmops = &nlmsvc_lock_operations; 199 nlmsvc_locks_init_private(fl, host, (pid_t)lock->svid); 200 if (!fl->c.flc_owner) 201 return nlm_lck_denied_nolocks; 202 203 return nlm_granted; 204 } 205 206 static inline __be32 cast_status(__be32 status) 207 { 208 switch (status) { 209 case nlm_granted: 210 case nlm_lck_denied: 211 case nlm_lck_denied_nolocks: 212 case nlm_lck_blocked: 213 case nlm_lck_denied_grace_period: 214 case nlm__int__drop_reply: 215 break; 216 case nlm__int__deadlock: 217 status = nlm_lck_denied; 218 break; 219 default: 220 pr_warn_once("lockd: unhandled internal status %u\n", 221 be32_to_cpu(status)); 222 status = nlm_lck_denied_nolocks; 223 break; 224 } 225 return status; 226 } 227 228 /** 229 * nlmsvc_proc_null - NULL: Test for presence of service 230 * @rqstp: RPC transaction context 231 * 232 * Return: 233 * %rpc_success: RPC executed successfully 234 * 235 * RPC synopsis: 236 * void NLM_NULL(void) = 0; 237 */ 238 static __be32 nlmsvc_proc_null(struct svc_rqst *rqstp) 239 { 240 return rpc_success; 241 } 242 243 /** 244 * nlmsvc_proc_test - TEST: Check for conflicting lock 245 * @rqstp: RPC transaction context 246 * 247 * Returns: 248 * %rpc_success: RPC executed successfully. 249 * %rpc_drop_reply: Do not send an RPC reply. 250 * 251 * RPC synopsis: 252 * nlm_testres NLM_TEST(nlm_testargs) = 1; 253 * 254 * Permissible procedure status codes: 255 * %LCK_GRANTED: The server would be able to grant the 256 * requested lock. 257 * %LCK_DENIED: The requested lock conflicted with existing 258 * lock reservations for the file. 259 * %LCK_DENIED_NOLOCKS: The server could not allocate the resources 260 * needed to process the request. 261 * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is 262 * re-establishing existing locks, and is not 263 * yet ready to accept normal service requests. 264 */ 265 static __be32 nlmsvc_proc_test(struct svc_rqst *rqstp) 266 { 267 struct nlm_testargs_wrapper *argp = rqstp->rq_argp; 268 unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK; 269 struct nlm_testres_wrapper *resp = rqstp->rq_resp; 270 struct nlm_file *file = NULL; 271 struct nlm_host *host; 272 273 resp->xdrgen.cookie = argp->xdrgen.cookie; 274 275 resp->xdrgen.test_stat.stat = nlm_lck_denied_nolocks; 276 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false); 277 if (!host) 278 goto out; 279 280 resp->xdrgen.test_stat.stat = 281 nlm3svc_lookup_file(rqstp, host, &argp->lock, &file, 282 &argp->xdrgen.alock, type); 283 if (resp->xdrgen.test_stat.stat) 284 goto out; 285 286 resp->xdrgen.test_stat.stat = 287 cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, 288 &resp->lock)); 289 nlmsvc_release_lockowner(&argp->lock); 290 291 if (resp->xdrgen.test_stat.stat == nlm_lck_denied) { 292 struct lockd_lock *conf = &resp->lock; 293 struct nlm_holder *holder = &resp->xdrgen.test_stat.u.holder; 294 295 holder->exclusive = (conf->fl.c.flc_type != F_RDLCK); 296 holder->uppid = conf->svid; 297 holder->oh.len = conf->oh.len; 298 holder->oh.data = conf->oh.data; 299 holder->l_offset = min_t(loff_t, conf->fl.fl_start, 300 NLM_OFFSET_MAX); 301 if (conf->fl.fl_end == OFFSET_MAX) 302 holder->l_len = 0; 303 else 304 holder->l_len = min_t(loff_t, 305 conf->fl.fl_end - 306 conf->fl.fl_start + 1, 307 NLM_OFFSET_MAX); 308 } 309 310 out: 311 if (file) 312 nlm_release_file(file); 313 nlmsvc_release_host(host); 314 return resp->xdrgen.test_stat.stat == nlm__int__drop_reply ? 315 rpc_drop_reply : rpc_success; 316 } 317 318 static __be32 319 nlmsvc_do_lock(struct svc_rqst *rqstp, bool monitored) 320 { 321 struct nlm_lockargs_wrapper *argp = rqstp->rq_argp; 322 unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK; 323 struct nlm_res_wrapper *resp = rqstp->rq_resp; 324 struct nlm_file *file = NULL; 325 struct nlm_host *host = NULL; 326 327 resp->xdrgen.cookie = argp->xdrgen.cookie; 328 329 resp->xdrgen.stat.stat = nlm_netobj_to_cookie(&argp->cookie, 330 &argp->xdrgen.cookie); 331 if (resp->xdrgen.stat.stat) 332 goto out; 333 334 resp->xdrgen.stat.stat = nlm_lck_denied_nolocks; 335 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, 336 monitored); 337 if (!host) 338 goto out; 339 340 resp->xdrgen.stat.stat = nlm3svc_lookup_file(rqstp, host, &argp->lock, 341 &file, &argp->xdrgen.alock, 342 type); 343 if (resp->xdrgen.stat.stat) 344 goto out; 345 346 resp->xdrgen.stat.stat = cast_status(nlmsvc_lock(rqstp, file, host, 347 &argp->lock, 348 argp->xdrgen.block, 349 &argp->cookie, 350 argp->xdrgen.reclaim)); 351 352 nlmsvc_release_lockowner(&argp->lock); 353 354 out: 355 if (file) 356 nlm_release_file(file); 357 nlmsvc_release_host(host); 358 return resp->xdrgen.stat.stat == nlm__int__drop_reply ? 359 rpc_drop_reply : rpc_success; 360 } 361 362 /** 363 * nlmsvc_proc_lock - LOCK: Establish a monitored lock 364 * @rqstp: RPC transaction context 365 * 366 * Returns: 367 * %rpc_success: RPC executed successfully. 368 * %rpc_drop_reply: Do not send an RPC reply. 369 * 370 * RPC synopsis: 371 * nlm_res NLM_LOCK(nlm_lockargs) = 2; 372 * 373 * Permissible procedure status codes: 374 * %LCK_GRANTED: The requested lock was granted. 375 * %LCK_DENIED: The requested lock conflicted with existing 376 * lock reservations for the file. 377 * %LCK_DENIED_NOLOCKS: The server could not allocate the resources 378 * needed to process the request. 379 * %LCK_BLOCKED: The blocking request cannot be granted 380 * immediately. The server will send an 381 * NLM_GRANTED callback to the client when 382 * the lock can be granted. 383 * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is 384 * re-establishing existing locks, and is not 385 * yet ready to accept normal service requests. 386 */ 387 static __be32 388 nlmsvc_proc_lock(struct svc_rqst *rqstp) 389 { 390 return nlmsvc_do_lock(rqstp, true); 391 } 392 393 /** 394 * nlmsvc_proc_cancel - CANCEL: Cancel an outstanding blocked lock request 395 * @rqstp: RPC transaction context 396 * 397 * Returns: 398 * %rpc_success: RPC executed successfully. 399 * %rpc_drop_reply: Do not send an RPC reply. 400 * 401 * RPC synopsis: 402 * nlm_res NLM_CANCEL(nlm_cancargs) = 3; 403 * 404 * Permissible procedure status codes: 405 * %LCK_GRANTED: The requested lock was canceled. 406 * %LCK_DENIED: There was no lock to cancel. 407 * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is 408 * re-establishing existing locks, and is not 409 * yet ready to accept normal service requests. 410 * 411 * The Linux NLM server implementation also returns: 412 * %LCK_DENIED_NOLOCKS: A needed resource could not be allocated. 413 */ 414 static __be32 415 nlmsvc_proc_cancel(struct svc_rqst *rqstp) 416 { 417 struct nlm_cancargs_wrapper *argp = rqstp->rq_argp; 418 unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK; 419 struct nlm_res_wrapper *resp = rqstp->rq_resp; 420 struct net *net = SVC_NET(rqstp); 421 struct nlm_host *host = NULL; 422 struct nlm_file *file = NULL; 423 424 resp->xdrgen.cookie = argp->xdrgen.cookie; 425 426 resp->xdrgen.stat.stat = nlm_lck_denied_grace_period; 427 if (locks_in_grace(net)) 428 goto out; 429 430 resp->xdrgen.stat.stat = nlm_lck_denied_nolocks; 431 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false); 432 if (!host) 433 goto out; 434 435 resp->xdrgen.stat.stat = nlm3svc_lookup_file(rqstp, host, &argp->lock, 436 &file, &argp->xdrgen.alock, 437 type); 438 if (resp->xdrgen.stat.stat) 439 goto out; 440 441 resp->xdrgen.stat.stat = nlmsvc_cancel_blocked(net, file, &argp->lock); 442 nlmsvc_release_lockowner(&argp->lock); 443 444 out: 445 if (file) 446 nlm_release_file(file); 447 nlmsvc_release_host(host); 448 return resp->xdrgen.stat.stat == nlm__int__drop_reply ? 449 rpc_drop_reply : rpc_success; 450 } 451 452 /** 453 * nlmsvc_proc_unlock - UNLOCK: Remove a lock 454 * @rqstp: RPC transaction context 455 * 456 * Returns: 457 * %rpc_success: RPC executed successfully. 458 * %rpc_drop_reply: Do not send an RPC reply. 459 * 460 * RPC synopsis: 461 * nlm_res NLM_UNLOCK(nlm_unlockargs) = 4; 462 * 463 * Permissible procedure status codes: 464 * %LCK_GRANTED: The requested lock was released. 465 * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is 466 * re-establishing existing locks, and is not 467 * yet ready to accept normal service requests. 468 * 469 * The Linux NLM server implementation also returns: 470 * %LCK_DENIED_NOLOCKS: A needed resource could not be allocated. 471 */ 472 static __be32 473 nlmsvc_proc_unlock(struct svc_rqst *rqstp) 474 { 475 struct nlm_unlockargs_wrapper *argp = rqstp->rq_argp; 476 struct nlm_res_wrapper *resp = rqstp->rq_resp; 477 struct net *net = SVC_NET(rqstp); 478 struct nlm_host *host = NULL; 479 struct nlm_file *file = NULL; 480 481 resp->xdrgen.cookie = argp->xdrgen.cookie; 482 483 resp->xdrgen.stat.stat = nlm_lck_denied_grace_period; 484 if (locks_in_grace(net)) 485 goto out; 486 487 resp->xdrgen.stat.stat = nlm_lck_denied_nolocks; 488 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false); 489 if (!host) 490 goto out; 491 492 resp->xdrgen.stat.stat = nlm3svc_lookup_file(rqstp, host, &argp->lock, 493 &file, &argp->xdrgen.alock, 494 F_UNLCK); 495 if (resp->xdrgen.stat.stat) 496 goto out; 497 498 resp->xdrgen.stat.stat = nlmsvc_unlock(net, file, &argp->lock); 499 nlmsvc_release_lockowner(&argp->lock); 500 501 out: 502 if (file) 503 nlm_release_file(file); 504 nlmsvc_release_host(host); 505 return resp->xdrgen.stat.stat == nlm__int__drop_reply ? 506 rpc_drop_reply : rpc_success; 507 } 508 509 /** 510 * nlmsvc_proc_granted - GRANTED: Blocked lock has been granted 511 * @rqstp: RPC transaction context 512 * 513 * Returns: 514 * %rpc_success: RPC executed successfully. 515 * 516 * RPC synopsis: 517 * nlm_res NLM_GRANTED(nlm_testargs) = 5; 518 * 519 * Permissible procedure status codes: 520 * %LCK_GRANTED: The granted lock was accepted. 521 * %LCK_DENIED: The procedure failed, possibly due to 522 * internal resource constraints. 523 * %LCK_DENIED_GRACE_PERIOD: The client host recently restarted and 524 * its NLM is re-establishing existing locks, 525 * so it is not yet ready to accept callbacks. 526 */ 527 static __be32 528 nlmsvc_proc_granted(struct svc_rqst *rqstp) 529 { 530 struct nlm_testargs_wrapper *argp = rqstp->rq_argp; 531 struct nlm_res_wrapper *resp = rqstp->rq_resp; 532 533 resp->xdrgen.cookie = argp->xdrgen.cookie; 534 535 resp->xdrgen.stat.stat = nlm_lock_to_lockd_lock(&argp->lock, 536 &argp->xdrgen.alock); 537 if (resp->xdrgen.stat.stat) 538 goto out; 539 540 resp->xdrgen.stat.stat = nlmclnt_grant(svc_addr(rqstp), &argp->lock); 541 542 out: 543 return rpc_success; 544 } 545 546 /* 547 * This is the generic lockd callback for async RPC calls 548 */ 549 static void nlmsvc_callback_exit(struct rpc_task *task, void *data) 550 { 551 } 552 553 void nlmsvc_release_call(struct nlm_rqst *call) 554 { 555 if (!refcount_dec_and_test(&call->a_count)) 556 return; 557 nlmsvc_release_host(call->a_host); 558 kfree(call); 559 } 560 561 static void nlmsvc_callback_release(void *data) 562 { 563 nlmsvc_release_call(data); 564 } 565 566 static const struct rpc_call_ops nlmsvc_callback_ops = { 567 .rpc_call_done = nlmsvc_callback_exit, 568 .rpc_release = nlmsvc_callback_release, 569 }; 570 571 /* 572 * `Async' versions of the above service routines. They aren't really, 573 * because we send the callback before the reply proper. I hope this 574 * doesn't break any clients. 575 */ 576 static __be32 577 nlmsvc_callback(struct svc_rqst *rqstp, struct nlm_host *host, u32 proc, 578 __be32 (*func)(struct svc_rqst *, struct lockd_res *)) 579 { 580 struct nlm_rqst *call; 581 __be32 stat; 582 583 call = nlm_alloc_call(host); 584 nlmsvc_release_host(host); 585 if (call == NULL) 586 return rpc_system_err; 587 588 stat = func(rqstp, &call->a_res); 589 if (stat != 0) { 590 nlmsvc_release_call(call); 591 return stat; 592 } 593 594 call->a_flags = RPC_TASK_ASYNC; 595 if (nlm_async_reply(call, proc, &nlmsvc_callback_ops) < 0) 596 return rpc_system_err; 597 return rpc_success; 598 } 599 600 static __be32 601 __nlmsvc_proc_test_msg(struct svc_rqst *rqstp, struct lockd_res *resp) 602 { 603 struct nlm_testargs_wrapper *argp = rqstp->rq_argp; 604 unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK; 605 struct nlm_lockowner *owner; 606 struct nlm_file *file = NULL; 607 struct nlm_host *host = NULL; 608 609 resp->status = nlm_lck_denied_nolocks; 610 if (nlm_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie)) 611 goto out; 612 613 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false); 614 if (!host) 615 goto out; 616 617 resp->status = nlm3svc_lookup_file(rqstp, host, &argp->lock, 618 &file, &argp->xdrgen.alock, type); 619 if (resp->status) 620 goto out; 621 622 owner = argp->lock.fl.c.flc_owner; 623 resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, 624 &argp->lock, &resp->lock)); 625 nlmsvc_put_lockowner(owner); 626 627 out: 628 if (file) 629 nlm_release_file(file); 630 nlmsvc_release_host(host); 631 return resp->status == nlm__int__drop_reply ? rpc_drop_reply : rpc_success; 632 } 633 634 /** 635 * nlmsvc_proc_test_msg - TEST_MSG: Check for conflicting lock 636 * @rqstp: RPC transaction context 637 * 638 * Returns: 639 * %rpc_success: RPC executed successfully. 640 * %rpc_drop_reply: Do not send an RPC reply. 641 * %rpc_garbage_args: The request arguments are malformed. 642 * %rpc_system_err: RPC execution failed. 643 * 644 * RPC synopsis: 645 * void NLMPROC_TEST_MSG(nlm_testargs) = 6; 646 * 647 * The response to this request is delivered via the TEST_RES procedure. 648 */ 649 static __be32 nlmsvc_proc_test_msg(struct svc_rqst *rqstp) 650 { 651 struct nlm_testargs_wrapper *argp = rqstp->rq_argp; 652 struct nlm_host *host; 653 654 if (argp->xdrgen.cookie.len > NLM_MAXCOOKIELEN) 655 return rpc_garbage_args; 656 657 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false); 658 if (!host) 659 return rpc_system_err; 660 661 return nlmsvc_callback(rqstp, host, NLMPROC_TEST_RES, 662 __nlmsvc_proc_test_msg); 663 } 664 665 static __be32 666 __nlmsvc_proc_lock_msg(struct svc_rqst *rqstp, struct lockd_res *resp) 667 { 668 struct nlm_lockargs_wrapper *argp = rqstp->rq_argp; 669 unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK; 670 struct nlm_file *file = NULL; 671 struct nlm_host *host = NULL; 672 673 resp->status = nlm_lck_denied_nolocks; 674 if (nlm_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie)) 675 goto out; 676 677 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, true); 678 if (!host) 679 goto out; 680 681 resp->status = nlm3svc_lookup_file(rqstp, host, &argp->lock, 682 &file, &argp->xdrgen.alock, type); 683 if (resp->status) 684 goto out; 685 686 resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock, 687 argp->xdrgen.block, &resp->cookie, 688 argp->xdrgen.reclaim)); 689 nlmsvc_release_lockowner(&argp->lock); 690 691 out: 692 if (file) 693 nlm_release_file(file); 694 nlmsvc_release_host(host); 695 return resp->status == nlm__int__drop_reply ? rpc_drop_reply : rpc_success; 696 } 697 698 /** 699 * nlmsvc_proc_lock_msg - LOCK_MSG: Establish a monitored lock 700 * @rqstp: RPC transaction context 701 * 702 * Returns: 703 * %rpc_success: RPC executed successfully. 704 * %rpc_drop_reply: Do not send an RPC reply. 705 * %rpc_garbage_args: The request arguments are malformed. 706 * %rpc_system_err: RPC execution failed. 707 * 708 * RPC synopsis: 709 * void NLMPROC_LOCK_MSG(nlm_lockargs) = 7; 710 * 711 * The response to this request is delivered via the LOCK_RES procedure. 712 */ 713 static __be32 nlmsvc_proc_lock_msg(struct svc_rqst *rqstp) 714 { 715 struct nlm_lockargs_wrapper *argp = rqstp->rq_argp; 716 struct nlm_host *host; 717 718 if (argp->xdrgen.cookie.len > NLM_MAXCOOKIELEN) 719 return rpc_garbage_args; 720 721 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false); 722 if (!host) 723 return rpc_system_err; 724 725 return nlmsvc_callback(rqstp, host, NLMPROC_LOCK_RES, 726 __nlmsvc_proc_lock_msg); 727 } 728 729 static __be32 730 __nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp, struct lockd_res *resp) 731 { 732 struct nlm_cancargs_wrapper *argp = rqstp->rq_argp; 733 unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK; 734 struct net *net = SVC_NET(rqstp); 735 struct nlm_file *file = NULL; 736 struct nlm_host *host = NULL; 737 738 resp->status = nlm_lck_denied_nolocks; 739 if (nlm_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie)) 740 goto out; 741 742 resp->status = nlm_lck_denied_grace_period; 743 if (locks_in_grace(net)) 744 goto out; 745 746 resp->status = nlm_lck_denied_nolocks; 747 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false); 748 if (!host) 749 goto out; 750 751 resp->status = nlm3svc_lookup_file(rqstp, host, &argp->lock, 752 &file, &argp->xdrgen.alock, type); 753 if (resp->status) 754 goto out; 755 756 resp->status = nlmsvc_cancel_blocked(net, file, &argp->lock); 757 nlmsvc_release_lockowner(&argp->lock); 758 759 out: 760 if (file) 761 nlm_release_file(file); 762 nlmsvc_release_host(host); 763 return resp->status == nlm__int__drop_reply ? rpc_drop_reply : rpc_success; 764 } 765 766 /** 767 * nlmsvc_proc_cancel_msg - CANCEL_MSG: Cancel an outstanding lock request 768 * @rqstp: RPC transaction context 769 * 770 * Returns: 771 * %rpc_success: RPC executed successfully. 772 * %rpc_drop_reply: Do not send an RPC reply. 773 * %rpc_garbage_args: The request arguments are malformed. 774 * %rpc_system_err: RPC execution failed. 775 * 776 * RPC synopsis: 777 * void NLMPROC_CANCEL_MSG(nlm_cancargs) = 8; 778 * 779 * The response to this request is delivered via the CANCEL_RES procedure. 780 */ 781 static __be32 nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp) 782 { 783 struct nlm_cancargs_wrapper *argp = rqstp->rq_argp; 784 struct nlm_host *host; 785 786 if (argp->xdrgen.cookie.len > NLM_MAXCOOKIELEN) 787 return rpc_garbage_args; 788 789 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false); 790 if (!host) 791 return rpc_system_err; 792 793 return nlmsvc_callback(rqstp, host, NLMPROC_CANCEL_RES, 794 __nlmsvc_proc_cancel_msg); 795 } 796 797 static __be32 798 __nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp, struct lockd_res *resp) 799 { 800 struct nlm_unlockargs_wrapper *argp = rqstp->rq_argp; 801 struct net *net = SVC_NET(rqstp); 802 struct nlm_file *file = NULL; 803 struct nlm_host *host = NULL; 804 805 resp->status = nlm_lck_denied_nolocks; 806 if (nlm_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie)) 807 goto out; 808 809 resp->status = nlm_lck_denied_grace_period; 810 if (locks_in_grace(net)) 811 goto out; 812 813 resp->status = nlm_lck_denied_nolocks; 814 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false); 815 if (!host) 816 goto out; 817 818 resp->status = nlm3svc_lookup_file(rqstp, host, &argp->lock, 819 &file, &argp->xdrgen.alock, F_UNLCK); 820 if (resp->status) 821 goto out; 822 823 resp->status = nlmsvc_unlock(net, file, &argp->lock); 824 nlmsvc_release_lockowner(&argp->lock); 825 826 out: 827 if (file) 828 nlm_release_file(file); 829 nlmsvc_release_host(host); 830 return resp->status == nlm__int__drop_reply ? rpc_drop_reply : rpc_success; 831 } 832 833 /** 834 * nlmsvc_proc_unlock_msg - UNLOCK_MSG: Remove an existing lock 835 * @rqstp: RPC transaction context 836 * 837 * Returns: 838 * %rpc_success: RPC executed successfully. 839 * %rpc_drop_reply: Do not send an RPC reply. 840 * %rpc_garbage_args: The request arguments are malformed. 841 * %rpc_system_err: RPC execution failed. 842 * 843 * RPC synopsis: 844 * void NLMPROC_UNLOCK_MSG(nlm_unlockargs) = 9; 845 * 846 * The response to this request is delivered via the UNLOCK_RES procedure. 847 */ 848 static __be32 nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp) 849 { 850 struct nlm_unlockargs_wrapper *argp = rqstp->rq_argp; 851 struct nlm_host *host; 852 853 if (argp->xdrgen.cookie.len > NLM_MAXCOOKIELEN) 854 return rpc_garbage_args; 855 856 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false); 857 if (!host) 858 return rpc_system_err; 859 860 return nlmsvc_callback(rqstp, host, NLMPROC_UNLOCK_RES, 861 __nlmsvc_proc_unlock_msg); 862 } 863 864 static __be32 865 __nlmsvc_proc_granted_msg(struct svc_rqst *rqstp, struct lockd_res *resp) 866 { 867 struct nlm_testargs_wrapper *argp = rqstp->rq_argp; 868 869 resp->status = nlm_lck_denied; 870 if (nlm_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie)) 871 goto out; 872 873 if (nlm_lock_to_lockd_lock(&argp->lock, &argp->xdrgen.alock)) 874 goto out; 875 876 resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock); 877 878 out: 879 return rpc_success; 880 } 881 882 /** 883 * nlmsvc_proc_granted_msg - GRANTED_MSG: Blocked lock has been granted 884 * @rqstp: RPC transaction context 885 * 886 * Returns: 887 * %rpc_success: RPC executed successfully. 888 * %rpc_garbage_args: The request arguments are malformed. 889 * %rpc_system_err: RPC execution failed. 890 * 891 * RPC synopsis: 892 * void NLMPROC_GRANTED_MSG(nlm_testargs) = 10; 893 * 894 * The response to this request is delivered via the GRANTED_RES procedure. 895 */ 896 static __be32 nlmsvc_proc_granted_msg(struct svc_rqst *rqstp) 897 { 898 struct nlm_testargs_wrapper *argp = rqstp->rq_argp; 899 struct nlm_host *host; 900 901 if (argp->xdrgen.cookie.len > NLM_MAXCOOKIELEN) 902 return rpc_garbage_args; 903 904 host = nlmsvc_lookup_host(rqstp, argp->xdrgen.alock.caller_name.data, 905 argp->xdrgen.alock.caller_name.len); 906 if (!host) 907 return rpc_system_err; 908 909 return nlmsvc_callback(rqstp, host, NLMPROC_GRANTED_RES, 910 __nlmsvc_proc_granted_msg); 911 } 912 913 /** 914 * nlmsvc_proc_granted_res - GRANTED_RES: Lock Granted result 915 * @rqstp: RPC transaction context 916 * 917 * Returns: 918 * %rpc_success: RPC executed successfully. 919 * 920 * RPC synopsis: 921 * void NLMPROC_GRANTED_RES(nlm_res) = 15; 922 */ 923 static __be32 nlmsvc_proc_granted_res(struct svc_rqst *rqstp) 924 { 925 struct nlm_res_wrapper *argp = rqstp->rq_argp; 926 927 if (!nlmsvc_ops) 928 return rpc_success; 929 930 if (nlm_netobj_to_cookie(&argp->cookie, &argp->xdrgen.cookie)) 931 return rpc_success; 932 nlmsvc_grant_reply(&argp->cookie, argp->xdrgen.stat.stat); 933 934 return rpc_success; 935 } 936 937 /** 938 * nlmsvc_proc_sm_notify - SM_NOTIFY: Peer has rebooted 939 * @rqstp: RPC transaction context 940 * 941 * Returns: 942 * %rpc_success: RPC executed successfully. 943 * %rpc_system_err: RPC execution failed. 944 * 945 * The SM_NOTIFY procedure is a private callback from Linux statd and is 946 * not part of the official NLM protocol. 947 * 948 * RPC synopsis: 949 * void NLM_SM_NOTIFY(nlm_notifyargs) = 16; 950 */ 951 static __be32 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp) 952 { 953 struct nlm_notifyargs_wrapper *argp = rqstp->rq_argp; 954 struct lockd_reboot *reboot = &argp->reboot; 955 956 if (!nlm_privileged_requester(rqstp)) { 957 char buf[RPC_MAX_ADDRBUFLEN]; 958 959 pr_warn("lockd: rejected NSM callback from %s\n", 960 svc_print_addr(rqstp, buf, sizeof(buf))); 961 return rpc_system_err; 962 } 963 964 reboot->len = argp->xdrgen.notify.name.len; 965 reboot->mon = (char *)argp->xdrgen.notify.name.data; 966 reboot->state = argp->xdrgen.notify.state; 967 memcpy(&reboot->priv.data, argp->xdrgen.private, 968 sizeof(reboot->priv.data)); 969 970 nlm_host_rebooted(SVC_NET(rqstp), reboot); 971 972 return rpc_success; 973 } 974 975 /** 976 * nlmsvc_proc_unused - stub for unused procedures 977 * @rqstp: RPC transaction context 978 * 979 * Returns: 980 * %rpc_proc_unavail: Program can't support procedure. 981 */ 982 static __be32 nlmsvc_proc_unused(struct svc_rqst *rqstp) 983 { 984 return rpc_proc_unavail; 985 } 986 987 /** 988 * nlmsvc_proc_share - SHARE: Open a file using DOS file-sharing modes 989 * @rqstp: RPC transaction context 990 * 991 * Returns: 992 * %rpc_success: RPC executed successfully. 993 * %rpc_drop_reply: Do not send an RPC reply. 994 * 995 * RPC synopsis: 996 * nlm_shareres NLM_SHARE(nlm_shareargs) = 20; 997 * 998 * Permissible procedure status codes: 999 * %LCK_GRANTED: The requested share lock was granted. 1000 * %LCK_DENIED: The requested lock conflicted with existing 1001 * lock reservations for the file. 1002 * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is 1003 * re-establishing existing locks, and is not 1004 * yet ready to accept normal service requests. 1005 * 1006 * The Linux NLM server implementation also returns: 1007 * %LCK_DENIED_NOLOCKS: A needed resource could not be allocated. 1008 */ 1009 static __be32 nlmsvc_proc_share(struct svc_rqst *rqstp) 1010 { 1011 struct nlm_shareargs_wrapper *argp = rqstp->rq_argp; 1012 struct nlm_shareres_wrapper *resp = rqstp->rq_resp; 1013 struct lockd_lock *lock = &argp->lock; 1014 struct nlm_host *host = NULL; 1015 struct nlm_file *file = NULL; 1016 struct nlm_lock xdr_lock = { 1017 .fh = argp->xdrgen.share.fh, 1018 .oh = argp->xdrgen.share.oh, 1019 .uppid = LOCKD_SHARE_SVID, 1020 }; 1021 1022 resp->xdrgen.cookie = argp->xdrgen.cookie; 1023 1024 resp->xdrgen.stat = nlm_lck_denied_grace_period; 1025 if (locks_in_grace(SVC_NET(rqstp)) && !argp->xdrgen.reclaim) 1026 goto out; 1027 1028 resp->xdrgen.stat = nlm_lck_denied_nolocks; 1029 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.share.caller_name, false); 1030 if (!host) 1031 goto out; 1032 1033 resp->xdrgen.stat = nlm3svc_lookup_file(rqstp, host, lock, &file, 1034 &xdr_lock, F_RDLCK); 1035 if (resp->xdrgen.stat) 1036 goto out; 1037 1038 resp->xdrgen.stat = nlmsvc_share_file(host, file, &lock->oh, 1039 argp->xdrgen.share.access, 1040 argp->xdrgen.share.mode); 1041 1042 nlmsvc_release_lockowner(lock); 1043 1044 out: 1045 if (file) 1046 nlm_release_file(file); 1047 nlmsvc_release_host(host); 1048 return resp->xdrgen.stat == nlm__int__drop_reply ? 1049 rpc_drop_reply : rpc_success; 1050 } 1051 1052 /** 1053 * nlmsvc_proc_unshare - UNSHARE: Release a share reservation 1054 * @rqstp: RPC transaction context 1055 * 1056 * Returns: 1057 * %rpc_success: RPC executed successfully. 1058 * %rpc_drop_reply: Do not send an RPC reply. 1059 * 1060 * RPC synopsis: 1061 * nlm_shareres NLM_UNSHARE(nlm_shareargs) = 21; 1062 * 1063 * Permissible procedure status codes: 1064 * %LCK_GRANTED: The share reservation was released. 1065 * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is 1066 * re-establishing existing locks, and is not 1067 * yet ready to accept normal service requests. 1068 * 1069 * The Linux NLM server implementation also returns: 1070 * %LCK_DENIED_NOLOCKS: A needed resource could not be allocated. 1071 */ 1072 static __be32 nlmsvc_proc_unshare(struct svc_rqst *rqstp) 1073 { 1074 struct nlm_shareargs_wrapper *argp = rqstp->rq_argp; 1075 struct nlm_shareres_wrapper *resp = rqstp->rq_resp; 1076 struct lockd_lock *lock = &argp->lock; 1077 struct nlm_lock xdr_lock = { 1078 .fh = argp->xdrgen.share.fh, 1079 .oh = argp->xdrgen.share.oh, 1080 .uppid = LOCKD_SHARE_SVID, 1081 }; 1082 struct nlm_host *host = NULL; 1083 struct nlm_file *file = NULL; 1084 1085 resp->xdrgen.cookie = argp->xdrgen.cookie; 1086 1087 resp->xdrgen.stat = nlm_lck_denied_grace_period; 1088 if (locks_in_grace(SVC_NET(rqstp))) 1089 goto out; 1090 1091 resp->xdrgen.stat = nlm_lck_denied_nolocks; 1092 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.share.caller_name, false); 1093 if (!host) 1094 goto out; 1095 1096 resp->xdrgen.stat = nlm3svc_lookup_file(rqstp, host, lock, &file, 1097 &xdr_lock, F_RDLCK); 1098 if (resp->xdrgen.stat) 1099 goto out; 1100 1101 resp->xdrgen.stat = nlmsvc_unshare_file(host, file, &lock->oh); 1102 1103 nlmsvc_release_lockowner(lock); 1104 1105 out: 1106 if (file) 1107 nlm_release_file(file); 1108 nlmsvc_release_host(host); 1109 return resp->xdrgen.stat == nlm__int__drop_reply ? 1110 rpc_drop_reply : rpc_success; 1111 } 1112 1113 /** 1114 * nlmsvc_proc_nm_lock - NM_LOCK: Establish a non-monitored lock 1115 * @rqstp: RPC transaction context 1116 * 1117 * Returns: 1118 * %rpc_success: RPC executed successfully. 1119 * %rpc_drop_reply: Do not send an RPC reply. 1120 * 1121 * RPC synopsis: 1122 * nlm_res NLM_NM_LOCK(nlm_lockargs) = 22; 1123 * 1124 * Permissible procedure status codes: 1125 * %LCK_GRANTED: The requested lock was granted. 1126 * %LCK_DENIED: The requested lock conflicted with existing 1127 * lock reservations for the file. 1128 * %LCK_DENIED_NOLOCKS: The server could not allocate the resources 1129 * needed to process the request. 1130 * %LCK_BLOCKED: The blocking request cannot be granted 1131 * immediately. The server will send an 1132 * NLM_GRANTED callback to the client when 1133 * the lock can be granted. 1134 * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is 1135 * re-establishing existing locks, and is not 1136 * yet ready to accept normal service requests. 1137 */ 1138 static __be32 nlmsvc_proc_nm_lock(struct svc_rqst *rqstp) 1139 { 1140 return nlmsvc_do_lock(rqstp, false); 1141 } 1142 1143 /** 1144 * nlmsvc_proc_free_all - FREE_ALL: Discard client's lock and share state 1145 * @rqstp: RPC transaction context 1146 * 1147 * Returns: 1148 * %rpc_success: RPC executed successfully. 1149 * 1150 * RPC synopsis: 1151 * void NLMPROC_FREE_ALL(nlm_notify) = 23; 1152 */ 1153 static __be32 nlmsvc_proc_free_all(struct svc_rqst *rqstp) 1154 { 1155 struct nlm_notify_wrapper *argp = rqstp->rq_argp; 1156 struct nlm_host *host; 1157 1158 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.name, false); 1159 if (!host) 1160 goto out; 1161 1162 nlmsvc_free_host_resources(host); 1163 1164 nlmsvc_release_host(host); 1165 1166 out: 1167 return rpc_success; 1168 } 1169 1170 /* 1171 * NLMv3 Server procedures. 1172 */ 1173 1174 static const struct svc_procedure nlmsvc_procedures[24] = { 1175 [NLM_NULL] = { 1176 .pc_func = nlmsvc_proc_null, 1177 .pc_decode = nlm_svc_decode_void, 1178 .pc_encode = nlm_svc_encode_void, 1179 .pc_argsize = XDR_void, 1180 .pc_argzero = 0, 1181 .pc_ressize = 0, 1182 .pc_xdrressize = XDR_void, 1183 .pc_name = "NULL", 1184 }, 1185 [NLM_TEST] = { 1186 .pc_func = nlmsvc_proc_test, 1187 .pc_decode = nlm_svc_decode_nlm_testargs, 1188 .pc_encode = nlm_svc_encode_nlm_testres, 1189 .pc_argsize = sizeof(struct nlm_testargs_wrapper), 1190 .pc_argzero = 0, 1191 .pc_ressize = sizeof(struct nlm_testres_wrapper), 1192 .pc_xdrressize = NLM3_nlm_testres_sz, 1193 .pc_name = "TEST", 1194 }, 1195 [NLM_LOCK] = { 1196 .pc_func = nlmsvc_proc_lock, 1197 .pc_decode = nlm_svc_decode_nlm_lockargs, 1198 .pc_encode = nlm_svc_encode_nlm_res, 1199 .pc_argsize = sizeof(struct nlm_lockargs_wrapper), 1200 .pc_argzero = 0, 1201 .pc_ressize = sizeof(struct nlm_res_wrapper), 1202 .pc_xdrressize = NLM3_nlm_res_sz, 1203 .pc_name = "LOCK", 1204 }, 1205 [NLM_CANCEL] = { 1206 .pc_func = nlmsvc_proc_cancel, 1207 .pc_decode = nlm_svc_decode_nlm_cancargs, 1208 .pc_encode = nlm_svc_encode_nlm_res, 1209 .pc_argsize = sizeof(struct nlm_cancargs_wrapper), 1210 .pc_argzero = 0, 1211 .pc_ressize = sizeof(struct nlm_res_wrapper), 1212 .pc_xdrressize = NLM3_nlm_res_sz, 1213 .pc_name = "CANCEL", 1214 }, 1215 [NLM_UNLOCK] = { 1216 .pc_func = nlmsvc_proc_unlock, 1217 .pc_decode = nlm_svc_decode_nlm_unlockargs, 1218 .pc_encode = nlm_svc_encode_nlm_res, 1219 .pc_argsize = sizeof(struct nlm_unlockargs_wrapper), 1220 .pc_argzero = 0, 1221 .pc_ressize = sizeof(struct nlm_res_wrapper), 1222 .pc_xdrressize = NLM3_nlm_res_sz, 1223 .pc_name = "UNLOCK", 1224 }, 1225 [NLM_GRANTED] = { 1226 .pc_func = nlmsvc_proc_granted, 1227 .pc_decode = nlm_svc_decode_nlm_testargs, 1228 .pc_encode = nlm_svc_encode_nlm_res, 1229 .pc_argsize = sizeof(struct nlm_testargs_wrapper), 1230 .pc_argzero = 0, 1231 .pc_ressize = sizeof(struct nlm_res_wrapper), 1232 .pc_xdrressize = NLM3_nlm_res_sz, 1233 .pc_name = "GRANTED", 1234 }, 1235 [NLM_TEST_MSG] = { 1236 .pc_func = nlmsvc_proc_test_msg, 1237 .pc_decode = nlm_svc_decode_nlm_testargs, 1238 .pc_encode = nlm_svc_encode_void, 1239 .pc_argsize = sizeof(struct nlm_testargs_wrapper), 1240 .pc_argzero = 0, 1241 .pc_ressize = 0, 1242 .pc_xdrressize = XDR_void, 1243 .pc_name = "TEST_MSG", 1244 }, 1245 [NLM_LOCK_MSG] = { 1246 .pc_func = nlmsvc_proc_lock_msg, 1247 .pc_decode = nlm_svc_decode_nlm_lockargs, 1248 .pc_encode = nlm_svc_encode_void, 1249 .pc_argsize = sizeof(struct nlm_lockargs_wrapper), 1250 .pc_argzero = 0, 1251 .pc_ressize = 0, 1252 .pc_xdrressize = XDR_void, 1253 .pc_name = "LOCK_MSG", 1254 }, 1255 [NLM_CANCEL_MSG] = { 1256 .pc_func = nlmsvc_proc_cancel_msg, 1257 .pc_decode = nlm_svc_decode_nlm_cancargs, 1258 .pc_encode = nlm_svc_encode_void, 1259 .pc_argsize = sizeof(struct nlm_cancargs_wrapper), 1260 .pc_argzero = 0, 1261 .pc_ressize = 0, 1262 .pc_xdrressize = XDR_void, 1263 .pc_name = "CANCEL_MSG", 1264 }, 1265 [NLM_UNLOCK_MSG] = { 1266 .pc_func = nlmsvc_proc_unlock_msg, 1267 .pc_decode = nlm_svc_decode_nlm_unlockargs, 1268 .pc_encode = nlm_svc_encode_void, 1269 .pc_argsize = sizeof(struct nlm_unlockargs_wrapper), 1270 .pc_argzero = 0, 1271 .pc_ressize = 0, 1272 .pc_xdrressize = XDR_void, 1273 .pc_name = "UNLOCK_MSG", 1274 }, 1275 [NLM_GRANTED_MSG] = { 1276 .pc_func = nlmsvc_proc_granted_msg, 1277 .pc_decode = nlm_svc_decode_nlm_testargs, 1278 .pc_encode = nlm_svc_encode_void, 1279 .pc_argsize = sizeof(struct nlm_testargs_wrapper), 1280 .pc_argzero = 0, 1281 .pc_ressize = 0, 1282 .pc_xdrressize = XDR_void, 1283 .pc_name = "GRANTED_MSG", 1284 }, 1285 [NLM_TEST_RES] = { 1286 .pc_func = nlmsvc_proc_null, 1287 .pc_decode = nlm_svc_decode_nlm_testres, 1288 .pc_encode = nlm_svc_encode_void, 1289 .pc_argsize = sizeof(struct nlm_testres), 1290 .pc_argzero = 0, 1291 .pc_ressize = 0, 1292 .pc_xdrressize = XDR_void, 1293 .pc_name = "TEST_RES", 1294 }, 1295 [NLM_LOCK_RES] = { 1296 .pc_func = nlmsvc_proc_null, 1297 .pc_decode = nlm_svc_decode_nlm_res, 1298 .pc_encode = nlm_svc_encode_void, 1299 .pc_argsize = sizeof(struct nlm_res), 1300 .pc_argzero = 0, 1301 .pc_ressize = 0, 1302 .pc_xdrressize = XDR_void, 1303 .pc_name = "LOCK_RES", 1304 }, 1305 [NLM_CANCEL_RES] = { 1306 .pc_func = nlmsvc_proc_null, 1307 .pc_decode = nlm_svc_decode_nlm_res, 1308 .pc_encode = nlm_svc_encode_void, 1309 .pc_argsize = sizeof(struct nlm_res), 1310 .pc_argzero = 0, 1311 .pc_ressize = 0, 1312 .pc_xdrressize = XDR_void, 1313 .pc_name = "CANCEL_RES", 1314 }, 1315 [NLM_UNLOCK_RES] = { 1316 .pc_func = nlmsvc_proc_null, 1317 .pc_decode = nlm_svc_decode_nlm_res, 1318 .pc_encode = nlm_svc_encode_void, 1319 .pc_argsize = sizeof(struct nlm_res), 1320 .pc_argzero = 0, 1321 .pc_ressize = 0, 1322 .pc_xdrressize = XDR_void, 1323 .pc_name = "UNLOCK_RES", 1324 }, 1325 [NLM_GRANTED_RES] = { 1326 .pc_func = nlmsvc_proc_granted_res, 1327 .pc_decode = nlm_svc_decode_nlm_res, 1328 .pc_encode = nlm_svc_encode_void, 1329 .pc_argsize = sizeof(struct nlm_res_wrapper), 1330 .pc_argzero = 0, 1331 .pc_ressize = 0, 1332 .pc_xdrressize = XDR_void, 1333 .pc_name = "GRANTED_RES", 1334 }, 1335 [NLM_SM_NOTIFY] = { 1336 .pc_func = nlmsvc_proc_sm_notify, 1337 .pc_decode = nlm_svc_decode_nlm_notifyargs, 1338 .pc_encode = nlm_svc_encode_void, 1339 .pc_argsize = sizeof(struct nlm_notifyargs_wrapper), 1340 .pc_argzero = 0, 1341 .pc_ressize = 0, 1342 .pc_xdrressize = XDR_void, 1343 .pc_name = "SM_NOTIFY", 1344 }, 1345 [17] = { 1346 .pc_func = nlmsvc_proc_unused, 1347 .pc_decode = nlm_svc_decode_void, 1348 .pc_encode = nlm_svc_encode_void, 1349 .pc_argsize = 0, 1350 .pc_argzero = 0, 1351 .pc_ressize = 0, 1352 .pc_xdrressize = XDR_void, 1353 .pc_name = "UNUSED", 1354 }, 1355 [18] = { 1356 .pc_func = nlmsvc_proc_unused, 1357 .pc_decode = nlm_svc_decode_void, 1358 .pc_encode = nlm_svc_encode_void, 1359 .pc_argsize = 0, 1360 .pc_argzero = 0, 1361 .pc_ressize = 0, 1362 .pc_xdrressize = XDR_void, 1363 .pc_name = "UNUSED", 1364 }, 1365 [19] = { 1366 .pc_func = nlmsvc_proc_unused, 1367 .pc_decode = nlm_svc_decode_void, 1368 .pc_encode = nlm_svc_encode_void, 1369 .pc_argsize = 0, 1370 .pc_argzero = 0, 1371 .pc_ressize = 0, 1372 .pc_xdrressize = XDR_void, 1373 .pc_name = "UNUSED", 1374 }, 1375 [NLM_SHARE] = { 1376 .pc_func = nlmsvc_proc_share, 1377 .pc_decode = nlm_svc_decode_nlm_shareargs, 1378 .pc_encode = nlm_svc_encode_nlm_shareres, 1379 .pc_argsize = sizeof(struct nlm_shareargs_wrapper), 1380 .pc_argzero = 0, 1381 .pc_ressize = sizeof(struct nlm_shareres_wrapper), 1382 .pc_xdrressize = NLM3_nlm_shareres_sz, 1383 .pc_name = "SHARE", 1384 }, 1385 [NLM_UNSHARE] = { 1386 .pc_func = nlmsvc_proc_unshare, 1387 .pc_decode = nlm_svc_decode_nlm_shareargs, 1388 .pc_encode = nlm_svc_encode_nlm_shareres, 1389 .pc_argsize = sizeof(struct nlm_shareargs_wrapper), 1390 .pc_argzero = 0, 1391 .pc_ressize = sizeof(struct nlm_shareres_wrapper), 1392 .pc_xdrressize = NLM3_nlm_shareres_sz, 1393 .pc_name = "UNSHARE", 1394 }, 1395 [NLM_NM_LOCK] = { 1396 .pc_func = nlmsvc_proc_nm_lock, 1397 .pc_decode = nlm_svc_decode_nlm_lockargs, 1398 .pc_encode = nlm_svc_encode_nlm_res, 1399 .pc_argsize = sizeof(struct nlm_lockargs_wrapper), 1400 .pc_argzero = 0, 1401 .pc_ressize = sizeof(struct nlm_res_wrapper), 1402 .pc_xdrressize = NLM3_nlm_res_sz, 1403 .pc_name = "NM_LOCK", 1404 }, 1405 [NLM_FREE_ALL] = { 1406 .pc_func = nlmsvc_proc_free_all, 1407 .pc_decode = nlm_svc_decode_nlm_notify, 1408 .pc_encode = nlm_svc_encode_void, 1409 .pc_argsize = sizeof(struct nlm_notify_wrapper), 1410 .pc_argzero = 0, 1411 .pc_ressize = 0, 1412 .pc_xdrressize = XDR_void, 1413 .pc_name = "FREE_ALL", 1414 }, 1415 }; 1416 1417 /* 1418 * Storage requirements for XDR arguments and results 1419 */ 1420 union nlmsvc_xdrstore { 1421 struct nlm_testargs_wrapper testargs; 1422 struct nlm_lockargs_wrapper lockargs; 1423 struct nlm_cancargs_wrapper cancargs; 1424 struct nlm_unlockargs_wrapper unlockargs; 1425 struct nlm_notifyargs_wrapper notifyargs; 1426 struct nlm_shareargs_wrapper shareargs; 1427 struct nlm_notify_wrapper notify; 1428 struct nlm_testres_wrapper testres; 1429 struct nlm_res_wrapper res; 1430 struct nlm_shareres_wrapper shareres; 1431 }; 1432 1433 /* 1434 * NLMv1 defines only procedures 1 - 15. Linux lockd also implements 1435 * procedures 0 (NULL) and 16 (SM_NOTIFY). 1436 */ 1437 static DEFINE_PER_CPU_ALIGNED(unsigned long, nlm1svc_call_counters[17]); 1438 1439 const struct svc_version nlmsvc_version1 = { 1440 .vs_vers = 1, 1441 .vs_nproc = 17, 1442 .vs_proc = nlmsvc_procedures, 1443 .vs_count = nlm1svc_call_counters, 1444 .vs_dispatch = nlmsvc_dispatch, 1445 .vs_xdrsize = sizeof(union nlmsvc_xdrstore), 1446 }; 1447 1448 static DEFINE_PER_CPU_ALIGNED(unsigned long, 1449 nlm3svc_call_counters[ARRAY_SIZE(nlmsvc_procedures)]); 1450 1451 const struct svc_version nlmsvc_version3 = { 1452 .vs_vers = 3, 1453 .vs_nproc = ARRAY_SIZE(nlmsvc_procedures), 1454 .vs_proc = nlmsvc_procedures, 1455 .vs_count = nlm3svc_call_counters, 1456 .vs_dispatch = nlmsvc_dispatch, 1457 .vs_xdrsize = sizeof(union nlmsvc_xdrstore), 1458 }; 1459