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