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