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 (!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 = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false); 876 if (!host) 877 return rpc_system_err; 878 879 return nlm4svc_callback(rqstp, host, NLMPROC4_GRANTED_RES, 880 __nlm4svc_proc_granted_msg); 881 } 882 883 /** 884 * nlm4svc_proc_granted_res - GRANTED_RES: Lock Granted result 885 * @rqstp: RPC transaction context 886 * 887 * Returns: 888 * %rpc_success: RPC executed successfully. 889 * 890 * RPC synopsis: 891 * void NLMPROC4_GRANTED_RES(nlm4_res) = 15; 892 */ 893 static __be32 nlm4svc_proc_granted_res(struct svc_rqst *rqstp) 894 { 895 struct nlm4_res_wrapper *argp = rqstp->rq_argp; 896 897 if (!nlmsvc_ops) 898 return rpc_success; 899 900 if (nlm4_netobj_to_cookie(&argp->cookie, &argp->xdrgen.cookie)) 901 return rpc_success; 902 nlmsvc_grant_reply(&argp->cookie, argp->xdrgen.stat.stat); 903 904 return rpc_success; 905 } 906 907 /** 908 * nlm4svc_proc_sm_notify - SM_NOTIFY: Peer has rebooted 909 * @rqstp: RPC transaction context 910 * 911 * Returns: 912 * %rpc_success: RPC executed successfully. 913 * %rpc_system_err: RPC execution failed. 914 * 915 * The SM_NOTIFY procedure is a private callback from Linux statd and is 916 * not part of the official NLM protocol. 917 * 918 * RPC synopsis: 919 * void NLMPROC4_SM_NOTIFY(nlm4_notifyargs) = 16; 920 */ 921 static __be32 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp) 922 { 923 struct nlm4_notifyargs_wrapper *argp = rqstp->rq_argp; 924 struct lockd_reboot *reboot = &argp->reboot; 925 926 if (!nlm_privileged_requester(rqstp)) { 927 char buf[RPC_MAX_ADDRBUFLEN]; 928 929 pr_warn("lockd: rejected NSM callback from %s\n", 930 svc_print_addr(rqstp, buf, sizeof(buf))); 931 return rpc_system_err; 932 } 933 934 reboot->len = argp->xdrgen.notify.name.len; 935 reboot->mon = (char *)argp->xdrgen.notify.name.data; 936 reboot->state = argp->xdrgen.notify.state; 937 memcpy(&reboot->priv.data, argp->xdrgen.private, 938 sizeof(reboot->priv.data)); 939 940 nlm_host_rebooted(SVC_NET(rqstp), reboot); 941 942 return rpc_success; 943 } 944 945 /** 946 * nlm4svc_proc_unused - stub for unused procedures 947 * @rqstp: RPC transaction context 948 * 949 * Returns: 950 * %rpc_proc_unavail: Program can't support procedure. 951 */ 952 static __be32 nlm4svc_proc_unused(struct svc_rqst *rqstp) 953 { 954 return rpc_proc_unavail; 955 } 956 957 /** 958 * nlm4svc_proc_share - SHARE: Open a file using DOS file-sharing modes 959 * @rqstp: RPC transaction context 960 * 961 * Returns: 962 * %rpc_success: RPC executed successfully. 963 * %rpc_drop_reply: Do not send an RPC reply. 964 * 965 * RPC synopsis: 966 * nlm4_shareres NLMPROC4_SHARE(nlm4_shareargs) = 20; 967 * 968 * Permissible procedure status codes: 969 * %NLM4_GRANTED: The requested share lock was granted. 970 * %NLM4_DENIED: The requested lock conflicted with existing 971 * lock reservations for the file. 972 * %NLM4_DENIED_GRACE_PERIOD: The server has recently restarted and is 973 * re-establishing existing locks, and is not 974 * yet ready to accept normal service requests. 975 * 976 * The Linux NLM server implementation also returns: 977 * %NLM4_DENIED_NOLOCKS: A needed resource could not be allocated. 978 * %NLM4_STALE_FH: The request specified an invalid file handle. 979 * %NLM4_FBIG: The request specified a length or offset 980 * that exceeds the range supported by the 981 * server. 982 * %NLM4_FAILED: The request failed for an unspecified reason. 983 */ 984 static __be32 nlm4svc_proc_share(struct svc_rqst *rqstp) 985 { 986 struct nlm4_shareargs_wrapper *argp = rqstp->rq_argp; 987 struct nlm4_shareres_wrapper *resp = rqstp->rq_resp; 988 struct lockd_lock *lock = &argp->lock; 989 struct nlm_host *host = NULL; 990 struct nlm_file *file = NULL; 991 struct nlm4_lock xdr_lock = { 992 .fh = argp->xdrgen.share.fh, 993 .oh = argp->xdrgen.share.oh, 994 .svid = LOCKD_SHARE_SVID, 995 }; 996 997 resp->xdrgen.cookie = argp->xdrgen.cookie; 998 999 resp->xdrgen.stat = nlm_lck_denied_grace_period; 1000 if (locks_in_grace(SVC_NET(rqstp)) && !argp->xdrgen.reclaim) 1001 goto out; 1002 1003 resp->xdrgen.stat = nlm_lck_denied_nolocks; 1004 host = nlm4svc_lookup_host(rqstp, argp->xdrgen.share.caller_name, true); 1005 if (!host) 1006 goto out; 1007 1008 resp->xdrgen.stat = nlm4svc_lookup_file(rqstp, host, lock, &file, 1009 &xdr_lock, F_RDLCK); 1010 if (resp->xdrgen.stat) 1011 goto out; 1012 1013 resp->xdrgen.stat = nlmsvc_share_file(host, file, &lock->oh, 1014 argp->xdrgen.share.access, 1015 argp->xdrgen.share.mode); 1016 1017 nlmsvc_release_lockowner(lock); 1018 1019 out: 1020 if (file) 1021 nlm_release_file(file); 1022 nlmsvc_release_host(host); 1023 return resp->xdrgen.stat == nlm__int__drop_reply ? 1024 rpc_drop_reply : rpc_success; 1025 } 1026 1027 /** 1028 * nlm4svc_proc_unshare - UNSHARE: Release a share reservation 1029 * @rqstp: RPC transaction context 1030 * 1031 * Returns: 1032 * %rpc_success: RPC executed successfully. 1033 * %rpc_drop_reply: Do not send an RPC reply. 1034 * 1035 * RPC synopsis: 1036 * nlm4_shareres NLMPROC4_UNSHARE(nlm4_shareargs) = 21; 1037 * 1038 * Permissible procedure status codes: 1039 * %NLM4_GRANTED: The share reservation was released. 1040 * %NLM4_DENIED_GRACE_PERIOD: The server has recently restarted and is 1041 * re-establishing existing locks, and is not 1042 * yet ready to accept normal service requests. 1043 * 1044 * The Linux NLM server implementation also returns: 1045 * %NLM4_DENIED_NOLOCKS: A needed resource could not be allocated. 1046 * %NLM4_STALE_FH: The request specified an invalid file handle. 1047 * %NLM4_FBIG: The request specified a length or offset 1048 * that exceeds the range supported by the 1049 * server. 1050 * %NLM4_FAILED: The request failed for an unspecified reason. 1051 */ 1052 static __be32 nlm4svc_proc_unshare(struct svc_rqst *rqstp) 1053 { 1054 struct nlm4_shareargs_wrapper *argp = rqstp->rq_argp; 1055 struct nlm4_shareres_wrapper *resp = rqstp->rq_resp; 1056 struct lockd_lock *lock = &argp->lock; 1057 struct nlm4_lock xdr_lock = { 1058 .fh = argp->xdrgen.share.fh, 1059 .oh = argp->xdrgen.share.oh, 1060 .svid = LOCKD_SHARE_SVID, 1061 }; 1062 struct nlm_host *host = NULL; 1063 struct nlm_file *file = NULL; 1064 1065 resp->xdrgen.cookie = argp->xdrgen.cookie; 1066 1067 resp->xdrgen.stat = nlm_lck_denied_grace_period; 1068 if (locks_in_grace(SVC_NET(rqstp))) 1069 goto out; 1070 1071 resp->xdrgen.stat = nlm_lck_denied_nolocks; 1072 host = nlm4svc_lookup_host(rqstp, argp->xdrgen.share.caller_name, true); 1073 if (!host) 1074 goto out; 1075 1076 resp->xdrgen.stat = nlm4svc_lookup_file(rqstp, host, lock, &file, 1077 &xdr_lock, F_RDLCK); 1078 if (resp->xdrgen.stat) 1079 goto out; 1080 1081 resp->xdrgen.stat = nlmsvc_unshare_file(host, file, &lock->oh); 1082 1083 nlmsvc_release_lockowner(lock); 1084 1085 out: 1086 if (file) 1087 nlm_release_file(file); 1088 nlmsvc_release_host(host); 1089 return resp->xdrgen.stat == nlm__int__drop_reply ? 1090 rpc_drop_reply : rpc_success; 1091 } 1092 1093 /** 1094 * nlm4svc_proc_nm_lock - NM_LOCK: Establish a non-monitored lock 1095 * @rqstp: RPC transaction context 1096 * 1097 * Returns: 1098 * %rpc_success: RPC executed successfully. 1099 * %rpc_drop_reply: Do not send an RPC reply. 1100 * 1101 * RPC synopsis: 1102 * nlm4_res NLMPROC4_NM_LOCK(nlm4_lockargs) = 22; 1103 * 1104 * Permissible procedure status codes: 1105 * %NLM4_GRANTED: The requested lock was granted. 1106 * %NLM4_DENIED: The requested lock conflicted with existing 1107 * lock reservations for the file. 1108 * %NLM4_DENIED_NOLOCKS: The server could not allocate the resources 1109 * needed to process the request. 1110 * %NLM4_BLOCKED: The blocking request cannot be granted 1111 * immediately. The server will send an 1112 * NLMPROC4_GRANTED callback to the client when 1113 * the lock can be granted. 1114 * %NLM4_DENIED_GRACE_PERIOD: The server has recently restarted and is 1115 * re-establishing existing locks, and is not 1116 * yet ready to accept normal service requests. 1117 * 1118 * The Linux NLM server implementation also returns: 1119 * %NLM4_DEADLCK: The request could not be granted and 1120 * blocking would cause a deadlock. 1121 * %NLM4_STALE_FH: The request specified an invalid file handle. 1122 * %NLM4_FBIG: The request specified a length or offset 1123 * that exceeds the range supported by the 1124 * server. 1125 * %NLM4_FAILED: The request failed for an unspecified reason. 1126 */ 1127 static __be32 nlm4svc_proc_nm_lock(struct svc_rqst *rqstp) 1128 { 1129 return nlm4svc_do_lock(rqstp, false); 1130 } 1131 1132 /** 1133 * nlm4svc_proc_free_all - FREE_ALL: Discard client's lock and share state 1134 * @rqstp: RPC transaction context 1135 * 1136 * Returns: 1137 * %rpc_success: RPC executed successfully. 1138 * 1139 * RPC synopsis: 1140 * void NLMPROC4_FREE_ALL(nlm4_notify) = 23; 1141 */ 1142 static __be32 nlm4svc_proc_free_all(struct svc_rqst *rqstp) 1143 { 1144 struct nlm4_notify_wrapper *argp = rqstp->rq_argp; 1145 struct nlm_host *host; 1146 1147 host = nlm4svc_lookup_host(rqstp, argp->xdrgen.name, false); 1148 if (!host) 1149 goto out; 1150 1151 nlmsvc_free_host_resources(host); 1152 1153 nlmsvc_release_host(host); 1154 1155 out: 1156 return rpc_success; 1157 } 1158 1159 1160 /* 1161 * NLMv4 Server procedures. 1162 */ 1163 1164 static const struct svc_procedure nlm4svc_procedures[24] = { 1165 [NLMPROC4_NULL] = { 1166 .pc_func = nlm4svc_proc_null, 1167 .pc_decode = nlm4_svc_decode_void, 1168 .pc_encode = nlm4_svc_encode_void, 1169 .pc_argsize = XDR_void, 1170 .pc_argzero = 0, 1171 .pc_ressize = 0, 1172 .pc_xdrressize = XDR_void, 1173 .pc_name = "NULL", 1174 }, 1175 [NLMPROC4_TEST] = { 1176 .pc_func = nlm4svc_proc_test, 1177 .pc_decode = nlm4_svc_decode_nlm4_testargs, 1178 .pc_encode = nlm4_svc_encode_nlm4_testres, 1179 .pc_argsize = sizeof(struct nlm4_testargs_wrapper), 1180 .pc_argzero = 0, 1181 .pc_ressize = sizeof(struct nlm4_testres_wrapper), 1182 .pc_xdrressize = NLM4_nlm4_testres_sz, 1183 .pc_name = "TEST", 1184 }, 1185 [NLMPROC4_LOCK] = { 1186 .pc_func = nlm4svc_proc_lock, 1187 .pc_decode = nlm4_svc_decode_nlm4_lockargs, 1188 .pc_encode = nlm4_svc_encode_nlm4_res, 1189 .pc_argsize = sizeof(struct nlm4_lockargs_wrapper), 1190 .pc_argzero = 0, 1191 .pc_ressize = sizeof(struct nlm4_res_wrapper), 1192 .pc_xdrressize = NLM4_nlm4_res_sz, 1193 .pc_name = "LOCK", 1194 }, 1195 [NLMPROC4_CANCEL] = { 1196 .pc_func = nlm4svc_proc_cancel, 1197 .pc_decode = nlm4_svc_decode_nlm4_cancargs, 1198 .pc_encode = nlm4_svc_encode_nlm4_res, 1199 .pc_argsize = sizeof(struct nlm4_cancargs_wrapper), 1200 .pc_argzero = 0, 1201 .pc_ressize = sizeof(struct nlm4_res_wrapper), 1202 .pc_xdrressize = NLM4_nlm4_res_sz, 1203 .pc_name = "CANCEL", 1204 }, 1205 [NLMPROC4_UNLOCK] = { 1206 .pc_func = nlm4svc_proc_unlock, 1207 .pc_decode = nlm4_svc_decode_nlm4_unlockargs, 1208 .pc_encode = nlm4_svc_encode_nlm4_res, 1209 .pc_argsize = sizeof(struct nlm4_unlockargs_wrapper), 1210 .pc_argzero = 0, 1211 .pc_ressize = sizeof(struct nlm4_res_wrapper), 1212 .pc_xdrressize = NLM4_nlm4_res_sz, 1213 .pc_name = "UNLOCK", 1214 }, 1215 [NLMPROC4_GRANTED] = { 1216 .pc_func = nlm4svc_proc_granted, 1217 .pc_decode = nlm4_svc_decode_nlm4_testargs, 1218 .pc_encode = nlm4_svc_encode_nlm4_res, 1219 .pc_argsize = sizeof(struct nlm4_testargs_wrapper), 1220 .pc_argzero = 0, 1221 .pc_ressize = sizeof(struct nlm4_res_wrapper), 1222 .pc_xdrressize = NLM4_nlm4_res_sz, 1223 .pc_name = "GRANTED", 1224 }, 1225 [NLMPROC4_TEST_MSG] = { 1226 .pc_func = nlm4svc_proc_test_msg, 1227 .pc_decode = nlm4_svc_decode_nlm4_testargs, 1228 .pc_encode = nlm4_svc_encode_void, 1229 .pc_argsize = sizeof(struct nlm4_testargs_wrapper), 1230 .pc_argzero = 0, 1231 .pc_ressize = 0, 1232 .pc_xdrressize = XDR_void, 1233 .pc_name = "TEST_MSG", 1234 }, 1235 [NLMPROC4_LOCK_MSG] = { 1236 .pc_func = nlm4svc_proc_lock_msg, 1237 .pc_decode = nlm4_svc_decode_nlm4_lockargs, 1238 .pc_encode = nlm4_svc_encode_void, 1239 .pc_argsize = sizeof(struct nlm4_lockargs_wrapper), 1240 .pc_argzero = 0, 1241 .pc_ressize = 0, 1242 .pc_xdrressize = XDR_void, 1243 .pc_name = "LOCK_MSG", 1244 }, 1245 [NLMPROC4_CANCEL_MSG] = { 1246 .pc_func = nlm4svc_proc_cancel_msg, 1247 .pc_decode = nlm4_svc_decode_nlm4_cancargs, 1248 .pc_encode = nlm4_svc_encode_void, 1249 .pc_argsize = sizeof(struct nlm4_cancargs_wrapper), 1250 .pc_argzero = 0, 1251 .pc_ressize = 0, 1252 .pc_xdrressize = XDR_void, 1253 .pc_name = "CANCEL_MSG", 1254 }, 1255 [NLMPROC4_UNLOCK_MSG] = { 1256 .pc_func = nlm4svc_proc_unlock_msg, 1257 .pc_decode = nlm4_svc_decode_nlm4_unlockargs, 1258 .pc_encode = nlm4_svc_encode_void, 1259 .pc_argsize = sizeof(struct nlm4_unlockargs_wrapper), 1260 .pc_argzero = 0, 1261 .pc_ressize = 0, 1262 .pc_xdrressize = XDR_void, 1263 .pc_name = "UNLOCK_MSG", 1264 }, 1265 [NLMPROC4_GRANTED_MSG] = { 1266 .pc_func = nlm4svc_proc_granted_msg, 1267 .pc_decode = nlm4_svc_decode_nlm4_testargs, 1268 .pc_encode = nlm4_svc_encode_void, 1269 .pc_argsize = sizeof(struct nlm4_testargs_wrapper), 1270 .pc_argzero = 0, 1271 .pc_ressize = 0, 1272 .pc_xdrressize = XDR_void, 1273 .pc_name = "GRANTED_MSG", 1274 }, 1275 [NLMPROC4_TEST_RES] = { 1276 .pc_func = nlm4svc_proc_null, 1277 .pc_decode = nlm4_svc_decode_nlm4_testres, 1278 .pc_encode = nlm4_svc_encode_void, 1279 .pc_argsize = sizeof(struct nlm4_testres), 1280 .pc_argzero = 0, 1281 .pc_ressize = 0, 1282 .pc_xdrressize = XDR_void, 1283 .pc_name = "TEST_RES", 1284 }, 1285 [NLMPROC4_LOCK_RES] = { 1286 .pc_func = nlm4svc_proc_null, 1287 .pc_decode = nlm4_svc_decode_nlm4_res, 1288 .pc_encode = nlm4_svc_encode_void, 1289 .pc_argsize = sizeof(struct nlm4_res), 1290 .pc_argzero = 0, 1291 .pc_ressize = 0, 1292 .pc_xdrressize = XDR_void, 1293 .pc_name = "LOCK_RES", 1294 }, 1295 [NLMPROC4_CANCEL_RES] = { 1296 .pc_func = nlm4svc_proc_null, 1297 .pc_decode = nlm4_svc_decode_nlm4_res, 1298 .pc_encode = nlm4_svc_encode_void, 1299 .pc_argsize = sizeof(struct nlm4_res), 1300 .pc_argzero = 0, 1301 .pc_ressize = 0, 1302 .pc_xdrressize = XDR_void, 1303 .pc_name = "CANCEL_RES", 1304 }, 1305 [NLMPROC4_UNLOCK_RES] = { 1306 .pc_func = nlm4svc_proc_null, 1307 .pc_decode = nlm4_svc_decode_nlm4_res, 1308 .pc_encode = nlm4_svc_encode_void, 1309 .pc_argsize = sizeof(struct nlm4_res), 1310 .pc_argzero = 0, 1311 .pc_ressize = 0, 1312 .pc_xdrressize = XDR_void, 1313 .pc_name = "UNLOCK_RES", 1314 }, 1315 [NLMPROC4_GRANTED_RES] = { 1316 .pc_func = nlm4svc_proc_granted_res, 1317 .pc_decode = nlm4_svc_decode_nlm4_res, 1318 .pc_encode = nlm4_svc_encode_void, 1319 .pc_argsize = sizeof(struct nlm4_res_wrapper), 1320 .pc_argzero = 0, 1321 .pc_ressize = 0, 1322 .pc_xdrressize = XDR_void, 1323 .pc_name = "GRANTED_RES", 1324 }, 1325 [NLMPROC4_SM_NOTIFY] = { 1326 .pc_func = nlm4svc_proc_sm_notify, 1327 .pc_decode = nlm4_svc_decode_nlm4_notifyargs, 1328 .pc_encode = nlm4_svc_encode_void, 1329 .pc_argsize = sizeof(struct nlm4_notifyargs_wrapper), 1330 .pc_argzero = 0, 1331 .pc_ressize = 0, 1332 .pc_xdrressize = XDR_void, 1333 .pc_name = "SM_NOTIFY", 1334 }, 1335 [17] = { 1336 .pc_func = nlm4svc_proc_unused, 1337 .pc_decode = nlm4_svc_decode_void, 1338 .pc_encode = nlm4_svc_encode_void, 1339 .pc_argsize = 0, 1340 .pc_argzero = 0, 1341 .pc_ressize = 0, 1342 .pc_xdrressize = XDR_void, 1343 .pc_name = "UNUSED", 1344 }, 1345 [18] = { 1346 .pc_func = nlm4svc_proc_unused, 1347 .pc_decode = nlm4_svc_decode_void, 1348 .pc_encode = nlm4_svc_encode_void, 1349 .pc_argsize = 0, 1350 .pc_argzero = 0, 1351 .pc_ressize = 0, 1352 .pc_xdrressize = XDR_void, 1353 .pc_name = "UNUSED", 1354 }, 1355 [19] = { 1356 .pc_func = nlm4svc_proc_unused, 1357 .pc_decode = nlm4_svc_decode_void, 1358 .pc_encode = nlm4_svc_encode_void, 1359 .pc_argsize = 0, 1360 .pc_argzero = 0, 1361 .pc_ressize = 0, 1362 .pc_xdrressize = XDR_void, 1363 .pc_name = "UNUSED", 1364 }, 1365 [NLMPROC4_SHARE] = { 1366 .pc_func = nlm4svc_proc_share, 1367 .pc_decode = nlm4_svc_decode_nlm4_shareargs, 1368 .pc_encode = nlm4_svc_encode_nlm4_shareres, 1369 .pc_argsize = sizeof(struct nlm4_shareargs_wrapper), 1370 .pc_argzero = 0, 1371 .pc_ressize = sizeof(struct nlm4_shareres_wrapper), 1372 .pc_xdrressize = NLM4_nlm4_shareres_sz, 1373 .pc_name = "SHARE", 1374 }, 1375 [NLMPROC4_UNSHARE] = { 1376 .pc_func = nlm4svc_proc_unshare, 1377 .pc_decode = nlm4_svc_decode_nlm4_shareargs, 1378 .pc_encode = nlm4_svc_encode_nlm4_shareres, 1379 .pc_argsize = sizeof(struct nlm4_shareargs_wrapper), 1380 .pc_argzero = 0, 1381 .pc_ressize = sizeof(struct nlm4_shareres_wrapper), 1382 .pc_xdrressize = NLM4_nlm4_shareres_sz, 1383 .pc_name = "UNSHARE", 1384 }, 1385 [NLMPROC4_NM_LOCK] = { 1386 .pc_func = nlm4svc_proc_nm_lock, 1387 .pc_decode = nlm4_svc_decode_nlm4_lockargs, 1388 .pc_encode = nlm4_svc_encode_nlm4_res, 1389 .pc_argsize = sizeof(struct nlm4_lockargs_wrapper), 1390 .pc_argzero = 0, 1391 .pc_ressize = sizeof(struct nlm4_res_wrapper), 1392 .pc_xdrressize = NLM4_nlm4_res_sz, 1393 .pc_name = "NM_LOCK", 1394 }, 1395 [NLMPROC4_FREE_ALL] = { 1396 .pc_func = nlm4svc_proc_free_all, 1397 .pc_decode = nlm4_svc_decode_nlm4_notify, 1398 .pc_encode = nlm4_svc_encode_void, 1399 .pc_argsize = sizeof(struct nlm4_notify_wrapper), 1400 .pc_argzero = 0, 1401 .pc_ressize = 0, 1402 .pc_xdrressize = XDR_void, 1403 .pc_name = "FREE_ALL", 1404 }, 1405 }; 1406 1407 /* 1408 * Storage requirements for XDR arguments and results 1409 */ 1410 union nlm4svc_xdrstore { 1411 struct nlm4_testargs_wrapper testargs; 1412 struct nlm4_lockargs_wrapper lockargs; 1413 struct nlm4_cancargs_wrapper cancargs; 1414 struct nlm4_unlockargs_wrapper unlockargs; 1415 struct nlm4_notifyargs_wrapper notifyargs; 1416 struct nlm4_shareargs_wrapper shareargs; 1417 struct nlm4_notify_wrapper notify; 1418 struct nlm4_testres_wrapper testres; 1419 struct nlm4_res_wrapper res; 1420 struct nlm4_shareres_wrapper shareres; 1421 }; 1422 1423 static DEFINE_PER_CPU_ALIGNED(unsigned long, 1424 nlm4svc_call_counters[ARRAY_SIZE(nlm4svc_procedures)]); 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_count = nlm4svc_call_counters, 1431 .vs_dispatch = nlmsvc_dispatch, 1432 .vs_xdrsize = sizeof(union nlm4svc_xdrstore), 1433 }; 1434