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 = nlm3svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false); 905 if (!host) 906 return rpc_system_err; 907 908 return nlmsvc_callback(rqstp, host, NLMPROC_GRANTED_RES, 909 __nlmsvc_proc_granted_msg); 910 } 911 912 /** 913 * nlmsvc_proc_granted_res - GRANTED_RES: Lock Granted result 914 * @rqstp: RPC transaction context 915 * 916 * Returns: 917 * %rpc_success: RPC executed successfully. 918 * 919 * RPC synopsis: 920 * void NLMPROC_GRANTED_RES(nlm_res) = 15; 921 */ 922 static __be32 nlmsvc_proc_granted_res(struct svc_rqst *rqstp) 923 { 924 struct nlm_res_wrapper *argp = rqstp->rq_argp; 925 926 if (!nlmsvc_ops) 927 return rpc_success; 928 929 if (nlm_netobj_to_cookie(&argp->cookie, &argp->xdrgen.cookie)) 930 return rpc_success; 931 nlmsvc_grant_reply(&argp->cookie, argp->xdrgen.stat.stat); 932 933 return rpc_success; 934 } 935 936 /** 937 * nlmsvc_proc_sm_notify - SM_NOTIFY: Peer has rebooted 938 * @rqstp: RPC transaction context 939 * 940 * Returns: 941 * %rpc_success: RPC executed successfully. 942 * %rpc_system_err: RPC execution failed. 943 * 944 * The SM_NOTIFY procedure is a private callback from Linux statd and is 945 * not part of the official NLM protocol. 946 * 947 * RPC synopsis: 948 * void NLM_SM_NOTIFY(nlm_notifyargs) = 16; 949 */ 950 static __be32 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp) 951 { 952 struct nlm_notifyargs_wrapper *argp = rqstp->rq_argp; 953 struct lockd_reboot *reboot = &argp->reboot; 954 955 if (!nlm_privileged_requester(rqstp)) { 956 char buf[RPC_MAX_ADDRBUFLEN]; 957 958 pr_warn("lockd: rejected NSM callback from %s\n", 959 svc_print_addr(rqstp, buf, sizeof(buf))); 960 return rpc_system_err; 961 } 962 963 reboot->len = argp->xdrgen.notify.name.len; 964 reboot->mon = (char *)argp->xdrgen.notify.name.data; 965 reboot->state = argp->xdrgen.notify.state; 966 memcpy(&reboot->priv.data, argp->xdrgen.private, 967 sizeof(reboot->priv.data)); 968 969 nlm_host_rebooted(SVC_NET(rqstp), reboot); 970 971 return rpc_success; 972 } 973 974 /** 975 * nlmsvc_proc_unused - stub for unused procedures 976 * @rqstp: RPC transaction context 977 * 978 * Returns: 979 * %rpc_proc_unavail: Program can't support procedure. 980 */ 981 static __be32 nlmsvc_proc_unused(struct svc_rqst *rqstp) 982 { 983 return rpc_proc_unavail; 984 } 985 986 /** 987 * nlmsvc_proc_share - SHARE: Open a file using DOS file-sharing modes 988 * @rqstp: RPC transaction context 989 * 990 * Returns: 991 * %rpc_success: RPC executed successfully. 992 * %rpc_drop_reply: Do not send an RPC reply. 993 * 994 * RPC synopsis: 995 * nlm_shareres NLM_SHARE(nlm_shareargs) = 20; 996 * 997 * Permissible procedure status codes: 998 * %LCK_GRANTED: The requested share lock was granted. 999 * %LCK_DENIED: The requested lock conflicted with existing 1000 * lock reservations for the file. 1001 * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is 1002 * re-establishing existing locks, and is not 1003 * yet ready to accept normal service requests. 1004 * 1005 * The Linux NLM server implementation also returns: 1006 * %LCK_DENIED_NOLOCKS: A needed resource could not be allocated. 1007 */ 1008 static __be32 nlmsvc_proc_share(struct svc_rqst *rqstp) 1009 { 1010 struct nlm_shareargs_wrapper *argp = rqstp->rq_argp; 1011 struct nlm_shareres_wrapper *resp = rqstp->rq_resp; 1012 struct lockd_lock *lock = &argp->lock; 1013 struct nlm_host *host = NULL; 1014 struct nlm_file *file = NULL; 1015 struct nlm_lock xdr_lock = { 1016 .fh = argp->xdrgen.share.fh, 1017 .oh = argp->xdrgen.share.oh, 1018 .uppid = LOCKD_SHARE_SVID, 1019 }; 1020 1021 resp->xdrgen.cookie = argp->xdrgen.cookie; 1022 1023 resp->xdrgen.stat = nlm_lck_denied_grace_period; 1024 if (locks_in_grace(SVC_NET(rqstp)) && !argp->xdrgen.reclaim) 1025 goto out; 1026 1027 resp->xdrgen.stat = nlm_lck_denied_nolocks; 1028 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.share.caller_name, false); 1029 if (!host) 1030 goto out; 1031 1032 resp->xdrgen.stat = nlm3svc_lookup_file(rqstp, host, lock, &file, 1033 &xdr_lock, F_RDLCK); 1034 if (resp->xdrgen.stat) 1035 goto out; 1036 1037 resp->xdrgen.stat = nlmsvc_share_file(host, file, &lock->oh, 1038 argp->xdrgen.share.access, 1039 argp->xdrgen.share.mode); 1040 1041 nlmsvc_release_lockowner(lock); 1042 1043 out: 1044 if (file) 1045 nlm_release_file(file); 1046 nlmsvc_release_host(host); 1047 return resp->xdrgen.stat == nlm__int__drop_reply ? 1048 rpc_drop_reply : rpc_success; 1049 } 1050 1051 /** 1052 * nlmsvc_proc_unshare - UNSHARE: Release a share reservation 1053 * @rqstp: RPC transaction context 1054 * 1055 * Returns: 1056 * %rpc_success: RPC executed successfully. 1057 * %rpc_drop_reply: Do not send an RPC reply. 1058 * 1059 * RPC synopsis: 1060 * nlm_shareres NLM_UNSHARE(nlm_shareargs) = 21; 1061 * 1062 * Permissible procedure status codes: 1063 * %LCK_GRANTED: The share reservation was released. 1064 * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is 1065 * re-establishing existing locks, and is not 1066 * yet ready to accept normal service requests. 1067 * 1068 * The Linux NLM server implementation also returns: 1069 * %LCK_DENIED_NOLOCKS: A needed resource could not be allocated. 1070 */ 1071 static __be32 nlmsvc_proc_unshare(struct svc_rqst *rqstp) 1072 { 1073 struct nlm_shareargs_wrapper *argp = rqstp->rq_argp; 1074 struct nlm_shareres_wrapper *resp = rqstp->rq_resp; 1075 struct lockd_lock *lock = &argp->lock; 1076 struct nlm_lock xdr_lock = { 1077 .fh = argp->xdrgen.share.fh, 1078 .oh = argp->xdrgen.share.oh, 1079 .uppid = LOCKD_SHARE_SVID, 1080 }; 1081 struct nlm_host *host = NULL; 1082 struct nlm_file *file = NULL; 1083 1084 resp->xdrgen.cookie = argp->xdrgen.cookie; 1085 1086 resp->xdrgen.stat = nlm_lck_denied_grace_period; 1087 if (locks_in_grace(SVC_NET(rqstp))) 1088 goto out; 1089 1090 resp->xdrgen.stat = nlm_lck_denied_nolocks; 1091 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.share.caller_name, false); 1092 if (!host) 1093 goto out; 1094 1095 resp->xdrgen.stat = nlm3svc_lookup_file(rqstp, host, lock, &file, 1096 &xdr_lock, F_RDLCK); 1097 if (resp->xdrgen.stat) 1098 goto out; 1099 1100 resp->xdrgen.stat = nlmsvc_unshare_file(host, file, &lock->oh); 1101 1102 nlmsvc_release_lockowner(lock); 1103 1104 out: 1105 if (file) 1106 nlm_release_file(file); 1107 nlmsvc_release_host(host); 1108 return resp->xdrgen.stat == nlm__int__drop_reply ? 1109 rpc_drop_reply : rpc_success; 1110 } 1111 1112 /** 1113 * nlmsvc_proc_nm_lock - NM_LOCK: Establish a non-monitored lock 1114 * @rqstp: RPC transaction context 1115 * 1116 * Returns: 1117 * %rpc_success: RPC executed successfully. 1118 * %rpc_drop_reply: Do not send an RPC reply. 1119 * 1120 * RPC synopsis: 1121 * nlm_res NLM_NM_LOCK(nlm_lockargs) = 22; 1122 * 1123 * Permissible procedure status codes: 1124 * %LCK_GRANTED: The requested lock was granted. 1125 * %LCK_DENIED: The requested lock conflicted with existing 1126 * lock reservations for the file. 1127 * %LCK_DENIED_NOLOCKS: The server could not allocate the resources 1128 * needed to process the request. 1129 * %LCK_BLOCKED: The blocking request cannot be granted 1130 * immediately. The server will send an 1131 * NLM_GRANTED callback to the client when 1132 * the lock can be granted. 1133 * %LCK_DENIED_GRACE_PERIOD: The server has recently restarted and is 1134 * re-establishing existing locks, and is not 1135 * yet ready to accept normal service requests. 1136 */ 1137 static __be32 nlmsvc_proc_nm_lock(struct svc_rqst *rqstp) 1138 { 1139 return nlmsvc_do_lock(rqstp, false); 1140 } 1141 1142 /** 1143 * nlmsvc_proc_free_all - FREE_ALL: Discard client's lock and share state 1144 * @rqstp: RPC transaction context 1145 * 1146 * Returns: 1147 * %rpc_success: RPC executed successfully. 1148 * 1149 * RPC synopsis: 1150 * void NLMPROC_FREE_ALL(nlm_notify) = 23; 1151 */ 1152 static __be32 nlmsvc_proc_free_all(struct svc_rqst *rqstp) 1153 { 1154 struct nlm_notify_wrapper *argp = rqstp->rq_argp; 1155 struct nlm_host *host; 1156 1157 host = nlm3svc_lookup_host(rqstp, argp->xdrgen.name, false); 1158 if (!host) 1159 goto out; 1160 1161 nlmsvc_free_host_resources(host); 1162 1163 nlmsvc_release_host(host); 1164 1165 out: 1166 return rpc_success; 1167 } 1168 1169 /* 1170 * NLMv3 Server procedures. 1171 */ 1172 1173 static const struct svc_procedure nlmsvc_procedures[24] = { 1174 [NLM_NULL] = { 1175 .pc_func = nlmsvc_proc_null, 1176 .pc_decode = nlm_svc_decode_void, 1177 .pc_encode = nlm_svc_encode_void, 1178 .pc_argsize = XDR_void, 1179 .pc_argzero = 0, 1180 .pc_ressize = 0, 1181 .pc_xdrressize = XDR_void, 1182 .pc_name = "NULL", 1183 }, 1184 [NLM_TEST] = { 1185 .pc_func = nlmsvc_proc_test, 1186 .pc_decode = nlm_svc_decode_nlm_testargs, 1187 .pc_encode = nlm_svc_encode_nlm_testres, 1188 .pc_argsize = sizeof(struct nlm_testargs_wrapper), 1189 .pc_argzero = 0, 1190 .pc_ressize = sizeof(struct nlm_testres_wrapper), 1191 .pc_xdrressize = NLM3_nlm_testres_sz, 1192 .pc_name = "TEST", 1193 }, 1194 [NLM_LOCK] = { 1195 .pc_func = nlmsvc_proc_lock, 1196 .pc_decode = nlm_svc_decode_nlm_lockargs, 1197 .pc_encode = nlm_svc_encode_nlm_res, 1198 .pc_argsize = sizeof(struct nlm_lockargs_wrapper), 1199 .pc_argzero = 0, 1200 .pc_ressize = sizeof(struct nlm_res_wrapper), 1201 .pc_xdrressize = NLM3_nlm_res_sz, 1202 .pc_name = "LOCK", 1203 }, 1204 [NLM_CANCEL] = { 1205 .pc_func = nlmsvc_proc_cancel, 1206 .pc_decode = nlm_svc_decode_nlm_cancargs, 1207 .pc_encode = nlm_svc_encode_nlm_res, 1208 .pc_argsize = sizeof(struct nlm_cancargs_wrapper), 1209 .pc_argzero = 0, 1210 .pc_ressize = sizeof(struct nlm_res_wrapper), 1211 .pc_xdrressize = NLM3_nlm_res_sz, 1212 .pc_name = "CANCEL", 1213 }, 1214 [NLM_UNLOCK] = { 1215 .pc_func = nlmsvc_proc_unlock, 1216 .pc_decode = nlm_svc_decode_nlm_unlockargs, 1217 .pc_encode = nlm_svc_encode_nlm_res, 1218 .pc_argsize = sizeof(struct nlm_unlockargs_wrapper), 1219 .pc_argzero = 0, 1220 .pc_ressize = sizeof(struct nlm_res_wrapper), 1221 .pc_xdrressize = NLM3_nlm_res_sz, 1222 .pc_name = "UNLOCK", 1223 }, 1224 [NLM_GRANTED] = { 1225 .pc_func = nlmsvc_proc_granted, 1226 .pc_decode = nlm_svc_decode_nlm_testargs, 1227 .pc_encode = nlm_svc_encode_nlm_res, 1228 .pc_argsize = sizeof(struct nlm_testargs_wrapper), 1229 .pc_argzero = 0, 1230 .pc_ressize = sizeof(struct nlm_res_wrapper), 1231 .pc_xdrressize = NLM3_nlm_res_sz, 1232 .pc_name = "GRANTED", 1233 }, 1234 [NLM_TEST_MSG] = { 1235 .pc_func = nlmsvc_proc_test_msg, 1236 .pc_decode = nlm_svc_decode_nlm_testargs, 1237 .pc_encode = nlm_svc_encode_void, 1238 .pc_argsize = sizeof(struct nlm_testargs_wrapper), 1239 .pc_argzero = 0, 1240 .pc_ressize = 0, 1241 .pc_xdrressize = XDR_void, 1242 .pc_name = "TEST_MSG", 1243 }, 1244 [NLM_LOCK_MSG] = { 1245 .pc_func = nlmsvc_proc_lock_msg, 1246 .pc_decode = nlm_svc_decode_nlm_lockargs, 1247 .pc_encode = nlm_svc_encode_void, 1248 .pc_argsize = sizeof(struct nlm_lockargs_wrapper), 1249 .pc_argzero = 0, 1250 .pc_ressize = 0, 1251 .pc_xdrressize = XDR_void, 1252 .pc_name = "LOCK_MSG", 1253 }, 1254 [NLM_CANCEL_MSG] = { 1255 .pc_func = nlmsvc_proc_cancel_msg, 1256 .pc_decode = nlm_svc_decode_nlm_cancargs, 1257 .pc_encode = nlm_svc_encode_void, 1258 .pc_argsize = sizeof(struct nlm_cancargs_wrapper), 1259 .pc_argzero = 0, 1260 .pc_ressize = 0, 1261 .pc_xdrressize = XDR_void, 1262 .pc_name = "CANCEL_MSG", 1263 }, 1264 [NLM_UNLOCK_MSG] = { 1265 .pc_func = nlmsvc_proc_unlock_msg, 1266 .pc_decode = nlm_svc_decode_nlm_unlockargs, 1267 .pc_encode = nlm_svc_encode_void, 1268 .pc_argsize = sizeof(struct nlm_unlockargs_wrapper), 1269 .pc_argzero = 0, 1270 .pc_ressize = 0, 1271 .pc_xdrressize = XDR_void, 1272 .pc_name = "UNLOCK_MSG", 1273 }, 1274 [NLM_GRANTED_MSG] = { 1275 .pc_func = nlmsvc_proc_granted_msg, 1276 .pc_decode = nlm_svc_decode_nlm_testargs, 1277 .pc_encode = nlm_svc_encode_void, 1278 .pc_argsize = sizeof(struct nlm_testargs_wrapper), 1279 .pc_argzero = 0, 1280 .pc_ressize = 0, 1281 .pc_xdrressize = XDR_void, 1282 .pc_name = "GRANTED_MSG", 1283 }, 1284 [NLM_TEST_RES] = { 1285 .pc_func = nlmsvc_proc_null, 1286 .pc_decode = nlm_svc_decode_nlm_testres, 1287 .pc_encode = nlm_svc_encode_void, 1288 .pc_argsize = sizeof(struct nlm_testres), 1289 .pc_argzero = 0, 1290 .pc_ressize = 0, 1291 .pc_xdrressize = XDR_void, 1292 .pc_name = "TEST_RES", 1293 }, 1294 [NLM_LOCK_RES] = { 1295 .pc_func = nlmsvc_proc_null, 1296 .pc_decode = nlm_svc_decode_nlm_res, 1297 .pc_encode = nlm_svc_encode_void, 1298 .pc_argsize = sizeof(struct nlm_res), 1299 .pc_argzero = 0, 1300 .pc_ressize = 0, 1301 .pc_xdrressize = XDR_void, 1302 .pc_name = "LOCK_RES", 1303 }, 1304 [NLM_CANCEL_RES] = { 1305 .pc_func = nlmsvc_proc_null, 1306 .pc_decode = nlm_svc_decode_nlm_res, 1307 .pc_encode = nlm_svc_encode_void, 1308 .pc_argsize = sizeof(struct nlm_res), 1309 .pc_argzero = 0, 1310 .pc_ressize = 0, 1311 .pc_xdrressize = XDR_void, 1312 .pc_name = "CANCEL_RES", 1313 }, 1314 [NLM_UNLOCK_RES] = { 1315 .pc_func = nlmsvc_proc_null, 1316 .pc_decode = nlm_svc_decode_nlm_res, 1317 .pc_encode = nlm_svc_encode_void, 1318 .pc_argsize = sizeof(struct nlm_res), 1319 .pc_argzero = 0, 1320 .pc_ressize = 0, 1321 .pc_xdrressize = XDR_void, 1322 .pc_name = "UNLOCK_RES", 1323 }, 1324 [NLM_GRANTED_RES] = { 1325 .pc_func = nlmsvc_proc_granted_res, 1326 .pc_decode = nlm_svc_decode_nlm_res, 1327 .pc_encode = nlm_svc_encode_void, 1328 .pc_argsize = sizeof(struct nlm_res_wrapper), 1329 .pc_argzero = 0, 1330 .pc_ressize = 0, 1331 .pc_xdrressize = XDR_void, 1332 .pc_name = "GRANTED_RES", 1333 }, 1334 [NLM_SM_NOTIFY] = { 1335 .pc_func = nlmsvc_proc_sm_notify, 1336 .pc_decode = nlm_svc_decode_nlm_notifyargs, 1337 .pc_encode = nlm_svc_encode_void, 1338 .pc_argsize = sizeof(struct nlm_notifyargs_wrapper), 1339 .pc_argzero = 0, 1340 .pc_ressize = 0, 1341 .pc_xdrressize = XDR_void, 1342 .pc_name = "SM_NOTIFY", 1343 }, 1344 [17] = { 1345 .pc_func = nlmsvc_proc_unused, 1346 .pc_decode = nlm_svc_decode_void, 1347 .pc_encode = nlm_svc_encode_void, 1348 .pc_argsize = 0, 1349 .pc_argzero = 0, 1350 .pc_ressize = 0, 1351 .pc_xdrressize = XDR_void, 1352 .pc_name = "UNUSED", 1353 }, 1354 [18] = { 1355 .pc_func = nlmsvc_proc_unused, 1356 .pc_decode = nlm_svc_decode_void, 1357 .pc_encode = nlm_svc_encode_void, 1358 .pc_argsize = 0, 1359 .pc_argzero = 0, 1360 .pc_ressize = 0, 1361 .pc_xdrressize = XDR_void, 1362 .pc_name = "UNUSED", 1363 }, 1364 [19] = { 1365 .pc_func = nlmsvc_proc_unused, 1366 .pc_decode = nlm_svc_decode_void, 1367 .pc_encode = nlm_svc_encode_void, 1368 .pc_argsize = 0, 1369 .pc_argzero = 0, 1370 .pc_ressize = 0, 1371 .pc_xdrressize = XDR_void, 1372 .pc_name = "UNUSED", 1373 }, 1374 [NLM_SHARE] = { 1375 .pc_func = nlmsvc_proc_share, 1376 .pc_decode = nlm_svc_decode_nlm_shareargs, 1377 .pc_encode = nlm_svc_encode_nlm_shareres, 1378 .pc_argsize = sizeof(struct nlm_shareargs_wrapper), 1379 .pc_argzero = 0, 1380 .pc_ressize = sizeof(struct nlm_shareres_wrapper), 1381 .pc_xdrressize = NLM3_nlm_shareres_sz, 1382 .pc_name = "SHARE", 1383 }, 1384 [NLM_UNSHARE] = { 1385 .pc_func = nlmsvc_proc_unshare, 1386 .pc_decode = nlm_svc_decode_nlm_shareargs, 1387 .pc_encode = nlm_svc_encode_nlm_shareres, 1388 .pc_argsize = sizeof(struct nlm_shareargs_wrapper), 1389 .pc_argzero = 0, 1390 .pc_ressize = sizeof(struct nlm_shareres_wrapper), 1391 .pc_xdrressize = NLM3_nlm_shareres_sz, 1392 .pc_name = "UNSHARE", 1393 }, 1394 [NLM_NM_LOCK] = { 1395 .pc_func = nlmsvc_proc_nm_lock, 1396 .pc_decode = nlm_svc_decode_nlm_lockargs, 1397 .pc_encode = nlm_svc_encode_nlm_res, 1398 .pc_argsize = sizeof(struct nlm_lockargs_wrapper), 1399 .pc_argzero = 0, 1400 .pc_ressize = sizeof(struct nlm_res_wrapper), 1401 .pc_xdrressize = NLM3_nlm_res_sz, 1402 .pc_name = "NM_LOCK", 1403 }, 1404 [NLM_FREE_ALL] = { 1405 .pc_func = nlmsvc_proc_free_all, 1406 .pc_decode = nlm_svc_decode_nlm_notify, 1407 .pc_encode = nlm_svc_encode_void, 1408 .pc_argsize = sizeof(struct nlm_notify_wrapper), 1409 .pc_argzero = 0, 1410 .pc_ressize = 0, 1411 .pc_xdrressize = XDR_void, 1412 .pc_name = "FREE_ALL", 1413 }, 1414 }; 1415 1416 /* 1417 * Storage requirements for XDR arguments and results 1418 */ 1419 union nlmsvc_xdrstore { 1420 struct nlm_testargs_wrapper testargs; 1421 struct nlm_lockargs_wrapper lockargs; 1422 struct nlm_cancargs_wrapper cancargs; 1423 struct nlm_unlockargs_wrapper unlockargs; 1424 struct nlm_notifyargs_wrapper notifyargs; 1425 struct nlm_shareargs_wrapper shareargs; 1426 struct nlm_notify_wrapper notify; 1427 struct nlm_testres_wrapper testres; 1428 struct nlm_res_wrapper res; 1429 struct nlm_shareres_wrapper shareres; 1430 }; 1431 1432 /* 1433 * NLMv1 defines only procedures 1 - 15. Linux lockd also implements 1434 * procedures 0 (NULL) and 16 (SM_NOTIFY). 1435 */ 1436 static DEFINE_PER_CPU_ALIGNED(unsigned long, nlm1svc_call_counters[17]); 1437 1438 const struct svc_version nlmsvc_version1 = { 1439 .vs_vers = 1, 1440 .vs_nproc = 17, 1441 .vs_proc = nlmsvc_procedures, 1442 .vs_count = nlm1svc_call_counters, 1443 .vs_dispatch = nlmsvc_dispatch, 1444 .vs_xdrsize = sizeof(union nlmsvc_xdrstore), 1445 }; 1446 1447 static DEFINE_PER_CPU_ALIGNED(unsigned long, 1448 nlm3svc_call_counters[ARRAY_SIZE(nlmsvc_procedures)]); 1449 1450 const struct svc_version nlmsvc_version3 = { 1451 .vs_vers = 3, 1452 .vs_nproc = ARRAY_SIZE(nlmsvc_procedures), 1453 .vs_proc = nlmsvc_procedures, 1454 .vs_count = nlm3svc_call_counters, 1455 .vs_dispatch = nlmsvc_dispatch, 1456 .vs_xdrsize = sizeof(union nlmsvc_xdrstore), 1457 }; 1458