linux/fs/lockd/svcproc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * linux/fs/lockd/svcproc.c
   4 *
   5 * Lockd server procedures. We don't implement the NLM_*_RES 
   6 * procedures because we don't use the async procedures.
   7 *
   8 * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
   9 */
  10
  11#include <linux/types.h>
  12#include <linux/time.h>
  13#include <linux/lockd/lockd.h>
  14#include <linux/lockd/share.h>
  15#include <linux/sunrpc/svc_xprt.h>
  16
  17#define NLMDBG_FACILITY         NLMDBG_CLIENT
  18
  19#ifdef CONFIG_LOCKD_V4
  20static __be32
  21cast_to_nlm(__be32 status, u32 vers)
  22{
  23        /* Note: status is assumed to be in network byte order !!! */
  24        if (vers != 4){
  25                switch (status) {
  26                case nlm_granted:
  27                case nlm_lck_denied:
  28                case nlm_lck_denied_nolocks:
  29                case nlm_lck_blocked:
  30                case nlm_lck_denied_grace_period:
  31                case nlm_drop_reply:
  32                        break;
  33                case nlm4_deadlock:
  34                        status = nlm_lck_denied;
  35                        break;
  36                default:
  37                        status = nlm_lck_denied_nolocks;
  38                }
  39        }
  40
  41        return (status);
  42}
  43#define cast_status(status) (cast_to_nlm(status, rqstp->rq_vers))
  44#else
  45#define cast_status(status) (status)
  46#endif
  47
  48/*
  49 * Obtain client and file from arguments
  50 */
  51static __be32
  52nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
  53                        struct nlm_host **hostp, struct nlm_file **filp)
  54{
  55        struct nlm_host         *host = NULL;
  56        struct nlm_file         *file = NULL;
  57        struct nlm_lock         *lock = &argp->lock;
  58        int                     mode;
  59        __be32                  error = 0;
  60
  61        /* nfsd callbacks must have been installed for this procedure */
  62        if (!nlmsvc_ops)
  63                return nlm_lck_denied_nolocks;
  64
  65        /* Obtain host handle */
  66        if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
  67         || (argp->monitor && nsm_monitor(host) < 0))
  68                goto no_locks;
  69        *hostp = host;
  70
  71        /* Obtain file pointer. Not used by FREE_ALL call. */
  72        if (filp != NULL) {
  73                error = cast_status(nlm_lookup_file(rqstp, &file, lock));
  74                if (error != 0)
  75                        goto no_locks;
  76                *filp = file;
  77
  78                /* Set up the missing parts of the file_lock structure */
  79                mode = lock_to_openmode(&lock->fl);
  80                lock->fl.fl_file  = file->f_file[mode];
  81                lock->fl.fl_pid = current->tgid;
  82                lock->fl.fl_lmops = &nlmsvc_lock_operations;
  83                nlmsvc_locks_init_private(&lock->fl, host, (pid_t)lock->svid);
  84                if (!lock->fl.fl_owner) {
  85                        /* lockowner allocation has failed */
  86                        nlmsvc_release_host(host);
  87                        return nlm_lck_denied_nolocks;
  88                }
  89        }
  90
  91        return 0;
  92
  93no_locks:
  94        nlmsvc_release_host(host);
  95        if (error)
  96                return error;
  97        return nlm_lck_denied_nolocks;
  98}
  99
 100/*
 101 * NULL: Test for presence of service
 102 */
 103static __be32
 104nlmsvc_proc_null(struct svc_rqst *rqstp)
 105{
 106        dprintk("lockd: NULL          called\n");
 107        return rpc_success;
 108}
 109
 110/*
 111 * TEST: Check for conflicting lock
 112 */
 113static __be32
 114__nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
 115{
 116        struct nlm_args *argp = rqstp->rq_argp;
 117        struct nlm_host *host;
 118        struct nlm_file *file;
 119        __be32 rc = rpc_success;
 120
 121        dprintk("lockd: TEST          called\n");
 122        resp->cookie = argp->cookie;
 123
 124        /* Obtain client and file */
 125        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
 126                return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 127
 128        /* Now check for conflicting locks */
 129        resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
 130        if (resp->status == nlm_drop_reply)
 131                rc = rpc_drop_reply;
 132        else
 133                dprintk("lockd: TEST          status %d vers %d\n",
 134                        ntohl(resp->status), rqstp->rq_vers);
 135
 136        nlmsvc_release_lockowner(&argp->lock);
 137        nlmsvc_release_host(host);
 138        nlm_release_file(file);
 139        return rc;
 140}
 141
 142static __be32
 143nlmsvc_proc_test(struct svc_rqst *rqstp)
 144{
 145        return __nlmsvc_proc_test(rqstp, rqstp->rq_resp);
 146}
 147
 148static __be32
 149__nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp)
 150{
 151        struct nlm_args *argp = rqstp->rq_argp;
 152        struct nlm_host *host;
 153        struct nlm_file *file;
 154        __be32 rc = rpc_success;
 155
 156        dprintk("lockd: LOCK          called\n");
 157
 158        resp->cookie = argp->cookie;
 159
 160        /* Obtain client and file */
 161        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
 162                return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 163
 164#if 0
 165        /* If supplied state doesn't match current state, we assume it's
 166         * an old request that time-warped somehow. Any error return would
 167         * do in this case because it's irrelevant anyway.
 168         *
 169         * NB: We don't retrieve the remote host's state yet.
 170         */
 171        if (host->h_nsmstate && host->h_nsmstate != argp->state) {
 172                resp->status = nlm_lck_denied_nolocks;
 173        } else
 174#endif
 175
 176        /* Now try to lock the file */
 177        resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock,
 178                                               argp->block, &argp->cookie,
 179                                               argp->reclaim));
 180        if (resp->status == nlm_drop_reply)
 181                rc = rpc_drop_reply;
 182        else
 183                dprintk("lockd: LOCK         status %d\n", ntohl(resp->status));
 184
 185        nlmsvc_release_lockowner(&argp->lock);
 186        nlmsvc_release_host(host);
 187        nlm_release_file(file);
 188        return rc;
 189}
 190
 191static __be32
 192nlmsvc_proc_lock(struct svc_rqst *rqstp)
 193{
 194        return __nlmsvc_proc_lock(rqstp, rqstp->rq_resp);
 195}
 196
 197static __be32
 198__nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_res *resp)
 199{
 200        struct nlm_args *argp = rqstp->rq_argp;
 201        struct nlm_host *host;
 202        struct nlm_file *file;
 203        struct net *net = SVC_NET(rqstp);
 204
 205        dprintk("lockd: CANCEL        called\n");
 206
 207        resp->cookie = argp->cookie;
 208
 209        /* Don't accept requests during grace period */
 210        if (locks_in_grace(net)) {
 211                resp->status = nlm_lck_denied_grace_period;
 212                return rpc_success;
 213        }
 214
 215        /* Obtain client and file */
 216        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
 217                return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 218
 219        /* Try to cancel request. */
 220        resp->status = cast_status(nlmsvc_cancel_blocked(net, file, &argp->lock));
 221
 222        dprintk("lockd: CANCEL        status %d\n", ntohl(resp->status));
 223        nlmsvc_release_lockowner(&argp->lock);
 224        nlmsvc_release_host(host);
 225        nlm_release_file(file);
 226        return rpc_success;
 227}
 228
 229static __be32
 230nlmsvc_proc_cancel(struct svc_rqst *rqstp)
 231{
 232        return __nlmsvc_proc_cancel(rqstp, rqstp->rq_resp);
 233}
 234
 235/*
 236 * UNLOCK: release a lock
 237 */
 238static __be32
 239__nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_res *resp)
 240{
 241        struct nlm_args *argp = rqstp->rq_argp;
 242        struct nlm_host *host;
 243        struct nlm_file *file;
 244        struct net *net = SVC_NET(rqstp);
 245
 246        dprintk("lockd: UNLOCK        called\n");
 247
 248        resp->cookie = argp->cookie;
 249
 250        /* Don't accept new lock requests during grace period */
 251        if (locks_in_grace(net)) {
 252                resp->status = nlm_lck_denied_grace_period;
 253                return rpc_success;
 254        }
 255
 256        /* Obtain client and file */
 257        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
 258                return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 259
 260        /* Now try to remove the lock */
 261        resp->status = cast_status(nlmsvc_unlock(net, file, &argp->lock));
 262
 263        dprintk("lockd: UNLOCK        status %d\n", ntohl(resp->status));
 264        nlmsvc_release_lockowner(&argp->lock);
 265        nlmsvc_release_host(host);
 266        nlm_release_file(file);
 267        return rpc_success;
 268}
 269
 270static __be32
 271nlmsvc_proc_unlock(struct svc_rqst *rqstp)
 272{
 273        return __nlmsvc_proc_unlock(rqstp, rqstp->rq_resp);
 274}
 275
 276/*
 277 * GRANTED: A server calls us to tell that a process' lock request
 278 * was granted
 279 */
 280static __be32
 281__nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_res *resp)
 282{
 283        struct nlm_args *argp = rqstp->rq_argp;
 284
 285        resp->cookie = argp->cookie;
 286
 287        dprintk("lockd: GRANTED       called\n");
 288        resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
 289        dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
 290        return rpc_success;
 291}
 292
 293static __be32
 294nlmsvc_proc_granted(struct svc_rqst *rqstp)
 295{
 296        return __nlmsvc_proc_granted(rqstp, rqstp->rq_resp);
 297}
 298
 299/*
 300 * This is the generic lockd callback for async RPC calls
 301 */
 302static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
 303{
 304        dprintk("lockd: %5u callback returned %d\n", task->tk_pid,
 305                        -task->tk_status);
 306}
 307
 308void nlmsvc_release_call(struct nlm_rqst *call)
 309{
 310        if (!refcount_dec_and_test(&call->a_count))
 311                return;
 312        nlmsvc_release_host(call->a_host);
 313        kfree(call);
 314}
 315
 316static void nlmsvc_callback_release(void *data)
 317{
 318        nlmsvc_release_call(data);
 319}
 320
 321static const struct rpc_call_ops nlmsvc_callback_ops = {
 322        .rpc_call_done = nlmsvc_callback_exit,
 323        .rpc_release = nlmsvc_callback_release,
 324};
 325
 326/*
 327 * `Async' versions of the above service routines. They aren't really,
 328 * because we send the callback before the reply proper. I hope this
 329 * doesn't break any clients.
 330 */
 331static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc,
 332                __be32 (*func)(struct svc_rqst *, struct nlm_res *))
 333{
 334        struct nlm_args *argp = rqstp->rq_argp;
 335        struct nlm_host *host;
 336        struct nlm_rqst *call;
 337        __be32 stat;
 338
 339        host = nlmsvc_lookup_host(rqstp,
 340                                  argp->lock.caller,
 341                                  argp->lock.len);
 342        if (host == NULL)
 343                return rpc_system_err;
 344
 345        call = nlm_alloc_call(host);
 346        nlmsvc_release_host(host);
 347        if (call == NULL)
 348                return rpc_system_err;
 349
 350        stat = func(rqstp, &call->a_res);
 351        if (stat != 0) {
 352                nlmsvc_release_call(call);
 353                return stat;
 354        }
 355
 356        call->a_flags = RPC_TASK_ASYNC;
 357        if (nlm_async_reply(call, proc, &nlmsvc_callback_ops) < 0)
 358                return rpc_system_err;
 359        return rpc_success;
 360}
 361
 362static __be32 nlmsvc_proc_test_msg(struct svc_rqst *rqstp)
 363{
 364        dprintk("lockd: TEST_MSG      called\n");
 365        return nlmsvc_callback(rqstp, NLMPROC_TEST_RES, __nlmsvc_proc_test);
 366}
 367
 368static __be32 nlmsvc_proc_lock_msg(struct svc_rqst *rqstp)
 369{
 370        dprintk("lockd: LOCK_MSG      called\n");
 371        return nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, __nlmsvc_proc_lock);
 372}
 373
 374static __be32 nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp)
 375{
 376        dprintk("lockd: CANCEL_MSG    called\n");
 377        return nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, __nlmsvc_proc_cancel);
 378}
 379
 380static __be32
 381nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp)
 382{
 383        dprintk("lockd: UNLOCK_MSG    called\n");
 384        return nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, __nlmsvc_proc_unlock);
 385}
 386
 387static __be32
 388nlmsvc_proc_granted_msg(struct svc_rqst *rqstp)
 389{
 390        dprintk("lockd: GRANTED_MSG   called\n");
 391        return nlmsvc_callback(rqstp, NLMPROC_GRANTED_RES, __nlmsvc_proc_granted);
 392}
 393
 394/*
 395 * SHARE: create a DOS share or alter existing share.
 396 */
 397static __be32
 398nlmsvc_proc_share(struct svc_rqst *rqstp)
 399{
 400        struct nlm_args *argp = rqstp->rq_argp;
 401        struct nlm_res *resp = rqstp->rq_resp;
 402        struct nlm_host *host;
 403        struct nlm_file *file;
 404
 405        dprintk("lockd: SHARE         called\n");
 406
 407        resp->cookie = argp->cookie;
 408
 409        /* Don't accept new lock requests during grace period */
 410        if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) {
 411                resp->status = nlm_lck_denied_grace_period;
 412                return rpc_success;
 413        }
 414
 415        /* Obtain client and file */
 416        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
 417                return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 418
 419        /* Now try to create the share */
 420        resp->status = cast_status(nlmsvc_share_file(host, file, argp));
 421
 422        dprintk("lockd: SHARE         status %d\n", ntohl(resp->status));
 423        nlmsvc_release_lockowner(&argp->lock);
 424        nlmsvc_release_host(host);
 425        nlm_release_file(file);
 426        return rpc_success;
 427}
 428
 429/*
 430 * UNSHARE: Release a DOS share.
 431 */
 432static __be32
 433nlmsvc_proc_unshare(struct svc_rqst *rqstp)
 434{
 435        struct nlm_args *argp = rqstp->rq_argp;
 436        struct nlm_res *resp = rqstp->rq_resp;
 437        struct nlm_host *host;
 438        struct nlm_file *file;
 439
 440        dprintk("lockd: UNSHARE       called\n");
 441
 442        resp->cookie = argp->cookie;
 443
 444        /* Don't accept requests during grace period */
 445        if (locks_in_grace(SVC_NET(rqstp))) {
 446                resp->status = nlm_lck_denied_grace_period;
 447                return rpc_success;
 448        }
 449
 450        /* Obtain client and file */
 451        if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
 452                return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
 453
 454        /* Now try to unshare the file */
 455        resp->status = cast_status(nlmsvc_unshare_file(host, file, argp));
 456
 457        dprintk("lockd: UNSHARE       status %d\n", ntohl(resp->status));
 458        nlmsvc_release_lockowner(&argp->lock);
 459        nlmsvc_release_host(host);
 460        nlm_release_file(file);
 461        return rpc_success;
 462}
 463
 464/*
 465 * NM_LOCK: Create an unmonitored lock
 466 */
 467static __be32
 468nlmsvc_proc_nm_lock(struct svc_rqst *rqstp)
 469{
 470        struct nlm_args *argp = rqstp->rq_argp;
 471
 472        dprintk("lockd: NM_LOCK       called\n");
 473
 474        argp->monitor = 0;              /* just clean the monitor flag */
 475        return nlmsvc_proc_lock(rqstp);
 476}
 477
 478/*
 479 * FREE_ALL: Release all locks and shares held by client
 480 */
 481static __be32
 482nlmsvc_proc_free_all(struct svc_rqst *rqstp)
 483{
 484        struct nlm_args *argp = rqstp->rq_argp;
 485        struct nlm_host *host;
 486
 487        /* Obtain client */
 488        if (nlmsvc_retrieve_args(rqstp, argp, &host, NULL))
 489                return rpc_success;
 490
 491        nlmsvc_free_host_resources(host);
 492        nlmsvc_release_host(host);
 493        return rpc_success;
 494}
 495
 496/*
 497 * SM_NOTIFY: private callback from statd (not part of official NLM proto)
 498 */
 499static __be32
 500nlmsvc_proc_sm_notify(struct svc_rqst *rqstp)
 501{
 502        struct nlm_reboot *argp = rqstp->rq_argp;
 503
 504        dprintk("lockd: SM_NOTIFY     called\n");
 505
 506        if (!nlm_privileged_requester(rqstp)) {
 507                char buf[RPC_MAX_ADDRBUFLEN];
 508                printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
 509                                svc_print_addr(rqstp, buf, sizeof(buf)));
 510                return rpc_system_err;
 511        }
 512
 513        nlm_host_rebooted(SVC_NET(rqstp), argp);
 514        return rpc_success;
 515}
 516
 517/*
 518 * client sent a GRANTED_RES, let's remove the associated block
 519 */
 520static __be32
 521nlmsvc_proc_granted_res(struct svc_rqst *rqstp)
 522{
 523        struct nlm_res *argp = rqstp->rq_argp;
 524
 525        if (!nlmsvc_ops)
 526                return rpc_success;
 527
 528        dprintk("lockd: GRANTED_RES   called\n");
 529
 530        nlmsvc_grant_reply(&argp->cookie, argp->status);
 531        return rpc_success;
 532}
 533
 534static __be32
 535nlmsvc_proc_unused(struct svc_rqst *rqstp)
 536{
 537        return rpc_proc_unavail;
 538}
 539
 540/*
 541 * NLM Server procedures.
 542 */
 543
 544struct nlm_void                 { int dummy; };
 545
 546#define Ck      (1+XDR_QUADLEN(NLM_MAXCOOKIELEN))       /* cookie */
 547#define St      1                               /* status */
 548#define No      (1+1024/4)                      /* Net Obj */
 549#define Rg      2                               /* range - offset + size */
 550
 551const struct svc_procedure nlmsvc_procedures[24] = {
 552        [NLMPROC_NULL] = {
 553                .pc_func = nlmsvc_proc_null,
 554                .pc_decode = nlmsvc_decode_void,
 555                .pc_encode = nlmsvc_encode_void,
 556                .pc_argsize = sizeof(struct nlm_void),
 557                .pc_ressize = sizeof(struct nlm_void),
 558                .pc_xdrressize = St,
 559                .pc_name = "NULL",
 560        },
 561        [NLMPROC_TEST] = {
 562                .pc_func = nlmsvc_proc_test,
 563                .pc_decode = nlmsvc_decode_testargs,
 564                .pc_encode = nlmsvc_encode_testres,
 565                .pc_argsize = sizeof(struct nlm_args),
 566                .pc_ressize = sizeof(struct nlm_res),
 567                .pc_xdrressize = Ck+St+2+No+Rg,
 568                .pc_name = "TEST",
 569        },
 570        [NLMPROC_LOCK] = {
 571                .pc_func = nlmsvc_proc_lock,
 572                .pc_decode = nlmsvc_decode_lockargs,
 573                .pc_encode = nlmsvc_encode_res,
 574                .pc_argsize = sizeof(struct nlm_args),
 575                .pc_ressize = sizeof(struct nlm_res),
 576                .pc_xdrressize = Ck+St,
 577                .pc_name = "LOCK",
 578        },
 579        [NLMPROC_CANCEL] = {
 580                .pc_func = nlmsvc_proc_cancel,
 581                .pc_decode = nlmsvc_decode_cancargs,
 582                .pc_encode = nlmsvc_encode_res,
 583                .pc_argsize = sizeof(struct nlm_args),
 584                .pc_ressize = sizeof(struct nlm_res),
 585                .pc_xdrressize = Ck+St,
 586                .pc_name = "CANCEL",
 587        },
 588        [NLMPROC_UNLOCK] = {
 589                .pc_func = nlmsvc_proc_unlock,
 590                .pc_decode = nlmsvc_decode_unlockargs,
 591                .pc_encode = nlmsvc_encode_res,
 592                .pc_argsize = sizeof(struct nlm_args),
 593                .pc_ressize = sizeof(struct nlm_res),
 594                .pc_xdrressize = Ck+St,
 595                .pc_name = "UNLOCK",
 596        },
 597        [NLMPROC_GRANTED] = {
 598                .pc_func = nlmsvc_proc_granted,
 599                .pc_decode = nlmsvc_decode_testargs,
 600                .pc_encode = nlmsvc_encode_res,
 601                .pc_argsize = sizeof(struct nlm_args),
 602                .pc_ressize = sizeof(struct nlm_res),
 603                .pc_xdrressize = Ck+St,
 604                .pc_name = "GRANTED",
 605        },
 606        [NLMPROC_TEST_MSG] = {
 607                .pc_func = nlmsvc_proc_test_msg,
 608                .pc_decode = nlmsvc_decode_testargs,
 609                .pc_encode = nlmsvc_encode_void,
 610                .pc_argsize = sizeof(struct nlm_args),
 611                .pc_ressize = sizeof(struct nlm_void),
 612                .pc_xdrressize = St,
 613                .pc_name = "TEST_MSG",
 614        },
 615        [NLMPROC_LOCK_MSG] = {
 616                .pc_func = nlmsvc_proc_lock_msg,
 617                .pc_decode = nlmsvc_decode_lockargs,
 618                .pc_encode = nlmsvc_encode_void,
 619                .pc_argsize = sizeof(struct nlm_args),
 620                .pc_ressize = sizeof(struct nlm_void),
 621                .pc_xdrressize = St,
 622                .pc_name = "LOCK_MSG",
 623        },
 624        [NLMPROC_CANCEL_MSG] = {
 625                .pc_func = nlmsvc_proc_cancel_msg,
 626                .pc_decode = nlmsvc_decode_cancargs,
 627                .pc_encode = nlmsvc_encode_void,
 628                .pc_argsize = sizeof(struct nlm_args),
 629                .pc_ressize = sizeof(struct nlm_void),
 630                .pc_xdrressize = St,
 631                .pc_name = "CANCEL_MSG",
 632        },
 633        [NLMPROC_UNLOCK_MSG] = {
 634                .pc_func = nlmsvc_proc_unlock_msg,
 635                .pc_decode = nlmsvc_decode_unlockargs,
 636                .pc_encode = nlmsvc_encode_void,
 637                .pc_argsize = sizeof(struct nlm_args),
 638                .pc_ressize = sizeof(struct nlm_void),
 639                .pc_xdrressize = St,
 640                .pc_name = "UNLOCK_MSG",
 641        },
 642        [NLMPROC_GRANTED_MSG] = {
 643                .pc_func = nlmsvc_proc_granted_msg,
 644                .pc_decode = nlmsvc_decode_testargs,
 645                .pc_encode = nlmsvc_encode_void,
 646                .pc_argsize = sizeof(struct nlm_args),
 647                .pc_ressize = sizeof(struct nlm_void),
 648                .pc_xdrressize = St,
 649                .pc_name = "GRANTED_MSG",
 650        },
 651        [NLMPROC_TEST_RES] = {
 652                .pc_func = nlmsvc_proc_null,
 653                .pc_decode = nlmsvc_decode_void,
 654                .pc_encode = nlmsvc_encode_void,
 655                .pc_argsize = sizeof(struct nlm_res),
 656                .pc_ressize = sizeof(struct nlm_void),
 657                .pc_xdrressize = St,
 658                .pc_name = "TEST_RES",
 659        },
 660        [NLMPROC_LOCK_RES] = {
 661                .pc_func = nlmsvc_proc_null,
 662                .pc_decode = nlmsvc_decode_void,
 663                .pc_encode = nlmsvc_encode_void,
 664                .pc_argsize = sizeof(struct nlm_res),
 665                .pc_ressize = sizeof(struct nlm_void),
 666                .pc_xdrressize = St,
 667                .pc_name = "LOCK_RES",
 668        },
 669        [NLMPROC_CANCEL_RES] = {
 670                .pc_func = nlmsvc_proc_null,
 671                .pc_decode = nlmsvc_decode_void,
 672                .pc_encode = nlmsvc_encode_void,
 673                .pc_argsize = sizeof(struct nlm_res),
 674                .pc_ressize = sizeof(struct nlm_void),
 675                .pc_xdrressize = St,
 676                .pc_name = "CANCEL_RES",
 677        },
 678        [NLMPROC_UNLOCK_RES] = {
 679                .pc_func = nlmsvc_proc_null,
 680                .pc_decode = nlmsvc_decode_void,
 681                .pc_encode = nlmsvc_encode_void,
 682                .pc_argsize = sizeof(struct nlm_res),
 683                .pc_ressize = sizeof(struct nlm_void),
 684                .pc_xdrressize = St,
 685                .pc_name = "UNLOCK_RES",
 686        },
 687        [NLMPROC_GRANTED_RES] = {
 688                .pc_func = nlmsvc_proc_granted_res,
 689                .pc_decode = nlmsvc_decode_res,
 690                .pc_encode = nlmsvc_encode_void,
 691                .pc_argsize = sizeof(struct nlm_res),
 692                .pc_ressize = sizeof(struct nlm_void),
 693                .pc_xdrressize = St,
 694                .pc_name = "GRANTED_RES",
 695        },
 696        [NLMPROC_NSM_NOTIFY] = {
 697                .pc_func = nlmsvc_proc_sm_notify,
 698                .pc_decode = nlmsvc_decode_reboot,
 699                .pc_encode = nlmsvc_encode_void,
 700                .pc_argsize = sizeof(struct nlm_reboot),
 701                .pc_ressize = sizeof(struct nlm_void),
 702                .pc_xdrressize = St,
 703                .pc_name = "SM_NOTIFY",
 704        },
 705        [17] = {
 706                .pc_func = nlmsvc_proc_unused,
 707                .pc_decode = nlmsvc_decode_void,
 708                .pc_encode = nlmsvc_encode_void,
 709                .pc_argsize = sizeof(struct nlm_void),
 710                .pc_ressize = sizeof(struct nlm_void),
 711                .pc_xdrressize = St,
 712                .pc_name = "UNUSED",
 713        },
 714        [18] = {
 715                .pc_func = nlmsvc_proc_unused,
 716                .pc_decode = nlmsvc_decode_void,
 717                .pc_encode = nlmsvc_encode_void,
 718                .pc_argsize = sizeof(struct nlm_void),
 719                .pc_ressize = sizeof(struct nlm_void),
 720                .pc_xdrressize = St,
 721                .pc_name = "UNUSED",
 722        },
 723        [19] = {
 724                .pc_func = nlmsvc_proc_unused,
 725                .pc_decode = nlmsvc_decode_void,
 726                .pc_encode = nlmsvc_encode_void,
 727                .pc_argsize = sizeof(struct nlm_void),
 728                .pc_ressize = sizeof(struct nlm_void),
 729                .pc_xdrressize = St,
 730                .pc_name = "UNUSED",
 731        },
 732        [NLMPROC_SHARE] = {
 733                .pc_func = nlmsvc_proc_share,
 734                .pc_decode = nlmsvc_decode_shareargs,
 735                .pc_encode = nlmsvc_encode_shareres,
 736                .pc_argsize = sizeof(struct nlm_args),
 737                .pc_ressize = sizeof(struct nlm_res),
 738                .pc_xdrressize = Ck+St+1,
 739                .pc_name = "SHARE",
 740        },
 741        [NLMPROC_UNSHARE] = {
 742                .pc_func = nlmsvc_proc_unshare,
 743                .pc_decode = nlmsvc_decode_shareargs,
 744                .pc_encode = nlmsvc_encode_shareres,
 745                .pc_argsize = sizeof(struct nlm_args),
 746                .pc_ressize = sizeof(struct nlm_res),
 747                .pc_xdrressize = Ck+St+1,
 748                .pc_name = "UNSHARE",
 749        },
 750        [NLMPROC_NM_LOCK] = {
 751                .pc_func = nlmsvc_proc_nm_lock,
 752                .pc_decode = nlmsvc_decode_lockargs,
 753                .pc_encode = nlmsvc_encode_res,
 754                .pc_argsize = sizeof(struct nlm_args),
 755                .pc_ressize = sizeof(struct nlm_res),
 756                .pc_xdrressize = Ck+St,
 757                .pc_name = "NM_LOCK",
 758        },
 759        [NLMPROC_FREE_ALL] = {
 760                .pc_func = nlmsvc_proc_free_all,
 761                .pc_decode = nlmsvc_decode_notify,
 762                .pc_encode = nlmsvc_encode_void,
 763                .pc_argsize = sizeof(struct nlm_args),
 764                .pc_ressize = sizeof(struct nlm_void),
 765                .pc_xdrressize = 0,
 766                .pc_name = "FREE_ALL",
 767        },
 768};
 769