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