Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * linux/fs/lockd/svcproc.c
0004  *
0005  * Lockd server procedures. We don't implement the NLM_*_RES 
0006  * procedures because we don't use the async procedures.
0007  *
0008  * Copyright (C) 1996, Olaf Kirch <okir@monad.swb.de>
0009  */
0010 
0011 #include <linux/types.h>
0012 #include <linux/time.h>
0013 #include <linux/lockd/lockd.h>
0014 #include <linux/lockd/share.h>
0015 #include <linux/sunrpc/svc_xprt.h>
0016 
0017 #define NLMDBG_FACILITY     NLMDBG_CLIENT
0018 
0019 #ifdef CONFIG_LOCKD_V4
0020 static __be32
0021 cast_to_nlm(__be32 status, u32 vers)
0022 {
0023     /* Note: status is assumed to be in network byte order !!! */
0024     if (vers != 4){
0025         switch (status) {
0026         case nlm_granted:
0027         case nlm_lck_denied:
0028         case nlm_lck_denied_nolocks:
0029         case nlm_lck_blocked:
0030         case nlm_lck_denied_grace_period:
0031         case nlm_drop_reply:
0032             break;
0033         case nlm4_deadlock:
0034             status = nlm_lck_denied;
0035             break;
0036         default:
0037             status = nlm_lck_denied_nolocks;
0038         }
0039     }
0040 
0041     return (status);
0042 }
0043 #define cast_status(status) (cast_to_nlm(status, rqstp->rq_vers))
0044 #else
0045 #define cast_status(status) (status)
0046 #endif
0047 
0048 /*
0049  * Obtain client and file from arguments
0050  */
0051 static __be32
0052 nlmsvc_retrieve_args(struct svc_rqst *rqstp, struct nlm_args *argp,
0053             struct nlm_host **hostp, struct nlm_file **filp)
0054 {
0055     struct nlm_host     *host = NULL;
0056     struct nlm_file     *file = NULL;
0057     struct nlm_lock     *lock = &argp->lock;
0058     int         mode;
0059     __be32          error = 0;
0060 
0061     /* nfsd callbacks must have been installed for this procedure */
0062     if (!nlmsvc_ops)
0063         return nlm_lck_denied_nolocks;
0064 
0065     /* Obtain host handle */
0066     if (!(host = nlmsvc_lookup_host(rqstp, lock->caller, lock->len))
0067      || (argp->monitor && nsm_monitor(host) < 0))
0068         goto no_locks;
0069     *hostp = host;
0070 
0071     /* Obtain file pointer. Not used by FREE_ALL call. */
0072     if (filp != NULL) {
0073         error = cast_status(nlm_lookup_file(rqstp, &file, lock));
0074         if (error != 0)
0075             goto no_locks;
0076         *filp = file;
0077 
0078         /* Set up the missing parts of the file_lock structure */
0079         mode = lock_to_openmode(&lock->fl);
0080         lock->fl.fl_file  = file->f_file[mode];
0081         lock->fl.fl_pid = current->tgid;
0082         lock->fl.fl_lmops = &nlmsvc_lock_operations;
0083         nlmsvc_locks_init_private(&lock->fl, host, (pid_t)lock->svid);
0084         if (!lock->fl.fl_owner) {
0085             /* lockowner allocation has failed */
0086             nlmsvc_release_host(host);
0087             return nlm_lck_denied_nolocks;
0088         }
0089     }
0090 
0091     return 0;
0092 
0093 no_locks:
0094     nlmsvc_release_host(host);
0095     if (error)
0096         return error;
0097     return nlm_lck_denied_nolocks;
0098 }
0099 
0100 /*
0101  * NULL: Test for presence of service
0102  */
0103 static __be32
0104 nlmsvc_proc_null(struct svc_rqst *rqstp)
0105 {
0106     dprintk("lockd: NULL          called\n");
0107     return rpc_success;
0108 }
0109 
0110 /*
0111  * TEST: Check for conflicting lock
0112  */
0113 static __be32
0114 __nlmsvc_proc_test(struct svc_rqst *rqstp, struct nlm_res *resp)
0115 {
0116     struct nlm_args *argp = rqstp->rq_argp;
0117     struct nlm_host *host;
0118     struct nlm_file *file;
0119     struct nlm_lockowner *test_owner;
0120     __be32 rc = rpc_success;
0121 
0122     dprintk("lockd: TEST          called\n");
0123     resp->cookie = argp->cookie;
0124 
0125     /* Obtain client and file */
0126     if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
0127         return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
0128 
0129     test_owner = argp->lock.fl.fl_owner;
0130 
0131     /* Now check for conflicting locks */
0132     resp->status = cast_status(nlmsvc_testlock(rqstp, file, host, &argp->lock, &resp->lock, &resp->cookie));
0133     if (resp->status == nlm_drop_reply)
0134         rc = rpc_drop_reply;
0135     else
0136         dprintk("lockd: TEST          status %d vers %d\n",
0137             ntohl(resp->status), rqstp->rq_vers);
0138 
0139     nlmsvc_put_lockowner(test_owner);
0140     nlmsvc_release_host(host);
0141     nlm_release_file(file);
0142     return rc;
0143 }
0144 
0145 static __be32
0146 nlmsvc_proc_test(struct svc_rqst *rqstp)
0147 {
0148     return __nlmsvc_proc_test(rqstp, rqstp->rq_resp);
0149 }
0150 
0151 static __be32
0152 __nlmsvc_proc_lock(struct svc_rqst *rqstp, struct nlm_res *resp)
0153 {
0154     struct nlm_args *argp = rqstp->rq_argp;
0155     struct nlm_host *host;
0156     struct nlm_file *file;
0157     __be32 rc = rpc_success;
0158 
0159     dprintk("lockd: LOCK          called\n");
0160 
0161     resp->cookie = argp->cookie;
0162 
0163     /* Obtain client and file */
0164     if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
0165         return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
0166 
0167 #if 0
0168     /* If supplied state doesn't match current state, we assume it's
0169      * an old request that time-warped somehow. Any error return would
0170      * do in this case because it's irrelevant anyway.
0171      *
0172      * NB: We don't retrieve the remote host's state yet.
0173      */
0174     if (host->h_nsmstate && host->h_nsmstate != argp->state) {
0175         resp->status = nlm_lck_denied_nolocks;
0176     } else
0177 #endif
0178 
0179     /* Now try to lock the file */
0180     resp->status = cast_status(nlmsvc_lock(rqstp, file, host, &argp->lock,
0181                            argp->block, &argp->cookie,
0182                            argp->reclaim));
0183     if (resp->status == nlm_drop_reply)
0184         rc = rpc_drop_reply;
0185     else
0186         dprintk("lockd: LOCK         status %d\n", ntohl(resp->status));
0187 
0188     nlmsvc_release_lockowner(&argp->lock);
0189     nlmsvc_release_host(host);
0190     nlm_release_file(file);
0191     return rc;
0192 }
0193 
0194 static __be32
0195 nlmsvc_proc_lock(struct svc_rqst *rqstp)
0196 {
0197     return __nlmsvc_proc_lock(rqstp, rqstp->rq_resp);
0198 }
0199 
0200 static __be32
0201 __nlmsvc_proc_cancel(struct svc_rqst *rqstp, struct nlm_res *resp)
0202 {
0203     struct nlm_args *argp = rqstp->rq_argp;
0204     struct nlm_host *host;
0205     struct nlm_file *file;
0206     struct net *net = SVC_NET(rqstp);
0207 
0208     dprintk("lockd: CANCEL        called\n");
0209 
0210     resp->cookie = argp->cookie;
0211 
0212     /* Don't accept requests during grace period */
0213     if (locks_in_grace(net)) {
0214         resp->status = nlm_lck_denied_grace_period;
0215         return rpc_success;
0216     }
0217 
0218     /* Obtain client and file */
0219     if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
0220         return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
0221 
0222     /* Try to cancel request. */
0223     resp->status = cast_status(nlmsvc_cancel_blocked(net, file, &argp->lock));
0224 
0225     dprintk("lockd: CANCEL        status %d\n", ntohl(resp->status));
0226     nlmsvc_release_lockowner(&argp->lock);
0227     nlmsvc_release_host(host);
0228     nlm_release_file(file);
0229     return rpc_success;
0230 }
0231 
0232 static __be32
0233 nlmsvc_proc_cancel(struct svc_rqst *rqstp)
0234 {
0235     return __nlmsvc_proc_cancel(rqstp, rqstp->rq_resp);
0236 }
0237 
0238 /*
0239  * UNLOCK: release a lock
0240  */
0241 static __be32
0242 __nlmsvc_proc_unlock(struct svc_rqst *rqstp, struct nlm_res *resp)
0243 {
0244     struct nlm_args *argp = rqstp->rq_argp;
0245     struct nlm_host *host;
0246     struct nlm_file *file;
0247     struct net *net = SVC_NET(rqstp);
0248 
0249     dprintk("lockd: UNLOCK        called\n");
0250 
0251     resp->cookie = argp->cookie;
0252 
0253     /* Don't accept new lock requests during grace period */
0254     if (locks_in_grace(net)) {
0255         resp->status = nlm_lck_denied_grace_period;
0256         return rpc_success;
0257     }
0258 
0259     /* Obtain client and file */
0260     if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
0261         return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
0262 
0263     /* Now try to remove the lock */
0264     resp->status = cast_status(nlmsvc_unlock(net, file, &argp->lock));
0265 
0266     dprintk("lockd: UNLOCK        status %d\n", ntohl(resp->status));
0267     nlmsvc_release_lockowner(&argp->lock);
0268     nlmsvc_release_host(host);
0269     nlm_release_file(file);
0270     return rpc_success;
0271 }
0272 
0273 static __be32
0274 nlmsvc_proc_unlock(struct svc_rqst *rqstp)
0275 {
0276     return __nlmsvc_proc_unlock(rqstp, rqstp->rq_resp);
0277 }
0278 
0279 /*
0280  * GRANTED: A server calls us to tell that a process' lock request
0281  * was granted
0282  */
0283 static __be32
0284 __nlmsvc_proc_granted(struct svc_rqst *rqstp, struct nlm_res *resp)
0285 {
0286     struct nlm_args *argp = rqstp->rq_argp;
0287 
0288     resp->cookie = argp->cookie;
0289 
0290     dprintk("lockd: GRANTED       called\n");
0291     resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
0292     dprintk("lockd: GRANTED       status %d\n", ntohl(resp->status));
0293     return rpc_success;
0294 }
0295 
0296 static __be32
0297 nlmsvc_proc_granted(struct svc_rqst *rqstp)
0298 {
0299     return __nlmsvc_proc_granted(rqstp, rqstp->rq_resp);
0300 }
0301 
0302 /*
0303  * This is the generic lockd callback for async RPC calls
0304  */
0305 static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
0306 {
0307 }
0308 
0309 void nlmsvc_release_call(struct nlm_rqst *call)
0310 {
0311     if (!refcount_dec_and_test(&call->a_count))
0312         return;
0313     nlmsvc_release_host(call->a_host);
0314     kfree(call);
0315 }
0316 
0317 static void nlmsvc_callback_release(void *data)
0318 {
0319     nlmsvc_release_call(data);
0320 }
0321 
0322 static const struct rpc_call_ops nlmsvc_callback_ops = {
0323     .rpc_call_done = nlmsvc_callback_exit,
0324     .rpc_release = nlmsvc_callback_release,
0325 };
0326 
0327 /*
0328  * `Async' versions of the above service routines. They aren't really,
0329  * because we send the callback before the reply proper. I hope this
0330  * doesn't break any clients.
0331  */
0332 static __be32 nlmsvc_callback(struct svc_rqst *rqstp, u32 proc,
0333         __be32 (*func)(struct svc_rqst *, struct nlm_res *))
0334 {
0335     struct nlm_args *argp = rqstp->rq_argp;
0336     struct nlm_host *host;
0337     struct nlm_rqst *call;
0338     __be32 stat;
0339 
0340     host = nlmsvc_lookup_host(rqstp,
0341                   argp->lock.caller,
0342                   argp->lock.len);
0343     if (host == NULL)
0344         return rpc_system_err;
0345 
0346     call = nlm_alloc_call(host);
0347     nlmsvc_release_host(host);
0348     if (call == NULL)
0349         return rpc_system_err;
0350 
0351     stat = func(rqstp, &call->a_res);
0352     if (stat != 0) {
0353         nlmsvc_release_call(call);
0354         return stat;
0355     }
0356 
0357     call->a_flags = RPC_TASK_ASYNC;
0358     if (nlm_async_reply(call, proc, &nlmsvc_callback_ops) < 0)
0359         return rpc_system_err;
0360     return rpc_success;
0361 }
0362 
0363 static __be32 nlmsvc_proc_test_msg(struct svc_rqst *rqstp)
0364 {
0365     dprintk("lockd: TEST_MSG      called\n");
0366     return nlmsvc_callback(rqstp, NLMPROC_TEST_RES, __nlmsvc_proc_test);
0367 }
0368 
0369 static __be32 nlmsvc_proc_lock_msg(struct svc_rqst *rqstp)
0370 {
0371     dprintk("lockd: LOCK_MSG      called\n");
0372     return nlmsvc_callback(rqstp, NLMPROC_LOCK_RES, __nlmsvc_proc_lock);
0373 }
0374 
0375 static __be32 nlmsvc_proc_cancel_msg(struct svc_rqst *rqstp)
0376 {
0377     dprintk("lockd: CANCEL_MSG    called\n");
0378     return nlmsvc_callback(rqstp, NLMPROC_CANCEL_RES, __nlmsvc_proc_cancel);
0379 }
0380 
0381 static __be32
0382 nlmsvc_proc_unlock_msg(struct svc_rqst *rqstp)
0383 {
0384     dprintk("lockd: UNLOCK_MSG    called\n");
0385     return nlmsvc_callback(rqstp, NLMPROC_UNLOCK_RES, __nlmsvc_proc_unlock);
0386 }
0387 
0388 static __be32
0389 nlmsvc_proc_granted_msg(struct svc_rqst *rqstp)
0390 {
0391     dprintk("lockd: GRANTED_MSG   called\n");
0392     return nlmsvc_callback(rqstp, NLMPROC_GRANTED_RES, __nlmsvc_proc_granted);
0393 }
0394 
0395 /*
0396  * SHARE: create a DOS share or alter existing share.
0397  */
0398 static __be32
0399 nlmsvc_proc_share(struct svc_rqst *rqstp)
0400 {
0401     struct nlm_args *argp = rqstp->rq_argp;
0402     struct nlm_res *resp = rqstp->rq_resp;
0403     struct nlm_host *host;
0404     struct nlm_file *file;
0405 
0406     dprintk("lockd: SHARE         called\n");
0407 
0408     resp->cookie = argp->cookie;
0409 
0410     /* Don't accept new lock requests during grace period */
0411     if (locks_in_grace(SVC_NET(rqstp)) && !argp->reclaim) {
0412         resp->status = nlm_lck_denied_grace_period;
0413         return rpc_success;
0414     }
0415 
0416     /* Obtain client and file */
0417     if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
0418         return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
0419 
0420     /* Now try to create the share */
0421     resp->status = cast_status(nlmsvc_share_file(host, file, argp));
0422 
0423     dprintk("lockd: SHARE         status %d\n", ntohl(resp->status));
0424     nlmsvc_release_lockowner(&argp->lock);
0425     nlmsvc_release_host(host);
0426     nlm_release_file(file);
0427     return rpc_success;
0428 }
0429 
0430 /*
0431  * UNSHARE: Release a DOS share.
0432  */
0433 static __be32
0434 nlmsvc_proc_unshare(struct svc_rqst *rqstp)
0435 {
0436     struct nlm_args *argp = rqstp->rq_argp;
0437     struct nlm_res *resp = rqstp->rq_resp;
0438     struct nlm_host *host;
0439     struct nlm_file *file;
0440 
0441     dprintk("lockd: UNSHARE       called\n");
0442 
0443     resp->cookie = argp->cookie;
0444 
0445     /* Don't accept requests during grace period */
0446     if (locks_in_grace(SVC_NET(rqstp))) {
0447         resp->status = nlm_lck_denied_grace_period;
0448         return rpc_success;
0449     }
0450 
0451     /* Obtain client and file */
0452     if ((resp->status = nlmsvc_retrieve_args(rqstp, argp, &host, &file)))
0453         return resp->status == nlm_drop_reply ? rpc_drop_reply :rpc_success;
0454 
0455     /* Now try to unshare the file */
0456     resp->status = cast_status(nlmsvc_unshare_file(host, file, argp));
0457 
0458     dprintk("lockd: UNSHARE       status %d\n", ntohl(resp->status));
0459     nlmsvc_release_lockowner(&argp->lock);
0460     nlmsvc_release_host(host);
0461     nlm_release_file(file);
0462     return rpc_success;
0463 }
0464 
0465 /*
0466  * NM_LOCK: Create an unmonitored lock
0467  */
0468 static __be32
0469 nlmsvc_proc_nm_lock(struct svc_rqst *rqstp)
0470 {
0471     struct nlm_args *argp = rqstp->rq_argp;
0472 
0473     dprintk("lockd: NM_LOCK       called\n");
0474 
0475     argp->monitor = 0;      /* just clean the monitor flag */
0476     return nlmsvc_proc_lock(rqstp);
0477 }
0478 
0479 /*
0480  * FREE_ALL: Release all locks and shares held by client
0481  */
0482 static __be32
0483 nlmsvc_proc_free_all(struct svc_rqst *rqstp)
0484 {
0485     struct nlm_args *argp = rqstp->rq_argp;
0486     struct nlm_host *host;
0487 
0488     /* Obtain client */
0489     if (nlmsvc_retrieve_args(rqstp, argp, &host, NULL))
0490         return rpc_success;
0491 
0492     nlmsvc_free_host_resources(host);
0493     nlmsvc_release_host(host);
0494     return rpc_success;
0495 }
0496 
0497 /*
0498  * SM_NOTIFY: private callback from statd (not part of official NLM proto)
0499  */
0500 static __be32
0501 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp)
0502 {
0503     struct nlm_reboot *argp = rqstp->rq_argp;
0504 
0505     dprintk("lockd: SM_NOTIFY     called\n");
0506 
0507     if (!nlm_privileged_requester(rqstp)) {
0508         char buf[RPC_MAX_ADDRBUFLEN];
0509         printk(KERN_WARNING "lockd: rejected NSM callback from %s\n",
0510                 svc_print_addr(rqstp, buf, sizeof(buf)));
0511         return rpc_system_err;
0512     }
0513 
0514     nlm_host_rebooted(SVC_NET(rqstp), argp);
0515     return rpc_success;
0516 }
0517 
0518 /*
0519  * client sent a GRANTED_RES, let's remove the associated block
0520  */
0521 static __be32
0522 nlmsvc_proc_granted_res(struct svc_rqst *rqstp)
0523 {
0524     struct nlm_res *argp = rqstp->rq_argp;
0525 
0526     if (!nlmsvc_ops)
0527         return rpc_success;
0528 
0529     dprintk("lockd: GRANTED_RES   called\n");
0530 
0531     nlmsvc_grant_reply(&argp->cookie, argp->status);
0532     return rpc_success;
0533 }
0534 
0535 static __be32
0536 nlmsvc_proc_unused(struct svc_rqst *rqstp)
0537 {
0538     return rpc_proc_unavail;
0539 }
0540 
0541 /*
0542  * NLM Server procedures.
0543  */
0544 
0545 struct nlm_void         { int dummy; };
0546 
0547 #define Ck  (1+XDR_QUADLEN(NLM_MAXCOOKIELEN))   /* cookie */
0548 #define St  1               /* status */
0549 #define No  (1+1024/4)          /* Net Obj */
0550 #define Rg  2               /* range - offset + size */
0551 
0552 const struct svc_procedure nlmsvc_procedures[24] = {
0553     [NLMPROC_NULL] = {
0554         .pc_func = nlmsvc_proc_null,
0555         .pc_decode = nlmsvc_decode_void,
0556         .pc_encode = nlmsvc_encode_void,
0557         .pc_argsize = sizeof(struct nlm_void),
0558         .pc_ressize = sizeof(struct nlm_void),
0559         .pc_xdrressize = St,
0560         .pc_name = "NULL",
0561     },
0562     [NLMPROC_TEST] = {
0563         .pc_func = nlmsvc_proc_test,
0564         .pc_decode = nlmsvc_decode_testargs,
0565         .pc_encode = nlmsvc_encode_testres,
0566         .pc_argsize = sizeof(struct nlm_args),
0567         .pc_ressize = sizeof(struct nlm_res),
0568         .pc_xdrressize = Ck+St+2+No+Rg,
0569         .pc_name = "TEST",
0570     },
0571     [NLMPROC_LOCK] = {
0572         .pc_func = nlmsvc_proc_lock,
0573         .pc_decode = nlmsvc_decode_lockargs,
0574         .pc_encode = nlmsvc_encode_res,
0575         .pc_argsize = sizeof(struct nlm_args),
0576         .pc_ressize = sizeof(struct nlm_res),
0577         .pc_xdrressize = Ck+St,
0578         .pc_name = "LOCK",
0579     },
0580     [NLMPROC_CANCEL] = {
0581         .pc_func = nlmsvc_proc_cancel,
0582         .pc_decode = nlmsvc_decode_cancargs,
0583         .pc_encode = nlmsvc_encode_res,
0584         .pc_argsize = sizeof(struct nlm_args),
0585         .pc_ressize = sizeof(struct nlm_res),
0586         .pc_xdrressize = Ck+St,
0587         .pc_name = "CANCEL",
0588     },
0589     [NLMPROC_UNLOCK] = {
0590         .pc_func = nlmsvc_proc_unlock,
0591         .pc_decode = nlmsvc_decode_unlockargs,
0592         .pc_encode = nlmsvc_encode_res,
0593         .pc_argsize = sizeof(struct nlm_args),
0594         .pc_ressize = sizeof(struct nlm_res),
0595         .pc_xdrressize = Ck+St,
0596         .pc_name = "UNLOCK",
0597     },
0598     [NLMPROC_GRANTED] = {
0599         .pc_func = nlmsvc_proc_granted,
0600         .pc_decode = nlmsvc_decode_testargs,
0601         .pc_encode = nlmsvc_encode_res,
0602         .pc_argsize = sizeof(struct nlm_args),
0603         .pc_ressize = sizeof(struct nlm_res),
0604         .pc_xdrressize = Ck+St,
0605         .pc_name = "GRANTED",
0606     },
0607     [NLMPROC_TEST_MSG] = {
0608         .pc_func = nlmsvc_proc_test_msg,
0609         .pc_decode = nlmsvc_decode_testargs,
0610         .pc_encode = nlmsvc_encode_void,
0611         .pc_argsize = sizeof(struct nlm_args),
0612         .pc_ressize = sizeof(struct nlm_void),
0613         .pc_xdrressize = St,
0614         .pc_name = "TEST_MSG",
0615     },
0616     [NLMPROC_LOCK_MSG] = {
0617         .pc_func = nlmsvc_proc_lock_msg,
0618         .pc_decode = nlmsvc_decode_lockargs,
0619         .pc_encode = nlmsvc_encode_void,
0620         .pc_argsize = sizeof(struct nlm_args),
0621         .pc_ressize = sizeof(struct nlm_void),
0622         .pc_xdrressize = St,
0623         .pc_name = "LOCK_MSG",
0624     },
0625     [NLMPROC_CANCEL_MSG] = {
0626         .pc_func = nlmsvc_proc_cancel_msg,
0627         .pc_decode = nlmsvc_decode_cancargs,
0628         .pc_encode = nlmsvc_encode_void,
0629         .pc_argsize = sizeof(struct nlm_args),
0630         .pc_ressize = sizeof(struct nlm_void),
0631         .pc_xdrressize = St,
0632         .pc_name = "CANCEL_MSG",
0633     },
0634     [NLMPROC_UNLOCK_MSG] = {
0635         .pc_func = nlmsvc_proc_unlock_msg,
0636         .pc_decode = nlmsvc_decode_unlockargs,
0637         .pc_encode = nlmsvc_encode_void,
0638         .pc_argsize = sizeof(struct nlm_args),
0639         .pc_ressize = sizeof(struct nlm_void),
0640         .pc_xdrressize = St,
0641         .pc_name = "UNLOCK_MSG",
0642     },
0643     [NLMPROC_GRANTED_MSG] = {
0644         .pc_func = nlmsvc_proc_granted_msg,
0645         .pc_decode = nlmsvc_decode_testargs,
0646         .pc_encode = nlmsvc_encode_void,
0647         .pc_argsize = sizeof(struct nlm_args),
0648         .pc_ressize = sizeof(struct nlm_void),
0649         .pc_xdrressize = St,
0650         .pc_name = "GRANTED_MSG",
0651     },
0652     [NLMPROC_TEST_RES] = {
0653         .pc_func = nlmsvc_proc_null,
0654         .pc_decode = nlmsvc_decode_void,
0655         .pc_encode = nlmsvc_encode_void,
0656         .pc_argsize = sizeof(struct nlm_res),
0657         .pc_ressize = sizeof(struct nlm_void),
0658         .pc_xdrressize = St,
0659         .pc_name = "TEST_RES",
0660     },
0661     [NLMPROC_LOCK_RES] = {
0662         .pc_func = nlmsvc_proc_null,
0663         .pc_decode = nlmsvc_decode_void,
0664         .pc_encode = nlmsvc_encode_void,
0665         .pc_argsize = sizeof(struct nlm_res),
0666         .pc_ressize = sizeof(struct nlm_void),
0667         .pc_xdrressize = St,
0668         .pc_name = "LOCK_RES",
0669     },
0670     [NLMPROC_CANCEL_RES] = {
0671         .pc_func = nlmsvc_proc_null,
0672         .pc_decode = nlmsvc_decode_void,
0673         .pc_encode = nlmsvc_encode_void,
0674         .pc_argsize = sizeof(struct nlm_res),
0675         .pc_ressize = sizeof(struct nlm_void),
0676         .pc_xdrressize = St,
0677         .pc_name = "CANCEL_RES",
0678     },
0679     [NLMPROC_UNLOCK_RES] = {
0680         .pc_func = nlmsvc_proc_null,
0681         .pc_decode = nlmsvc_decode_void,
0682         .pc_encode = nlmsvc_encode_void,
0683         .pc_argsize = sizeof(struct nlm_res),
0684         .pc_ressize = sizeof(struct nlm_void),
0685         .pc_xdrressize = St,
0686         .pc_name = "UNLOCK_RES",
0687     },
0688     [NLMPROC_GRANTED_RES] = {
0689         .pc_func = nlmsvc_proc_granted_res,
0690         .pc_decode = nlmsvc_decode_res,
0691         .pc_encode = nlmsvc_encode_void,
0692         .pc_argsize = sizeof(struct nlm_res),
0693         .pc_ressize = sizeof(struct nlm_void),
0694         .pc_xdrressize = St,
0695         .pc_name = "GRANTED_RES",
0696     },
0697     [NLMPROC_NSM_NOTIFY] = {
0698         .pc_func = nlmsvc_proc_sm_notify,
0699         .pc_decode = nlmsvc_decode_reboot,
0700         .pc_encode = nlmsvc_encode_void,
0701         .pc_argsize = sizeof(struct nlm_reboot),
0702         .pc_ressize = sizeof(struct nlm_void),
0703         .pc_xdrressize = St,
0704         .pc_name = "SM_NOTIFY",
0705     },
0706     [17] = {
0707         .pc_func = nlmsvc_proc_unused,
0708         .pc_decode = nlmsvc_decode_void,
0709         .pc_encode = nlmsvc_encode_void,
0710         .pc_argsize = sizeof(struct nlm_void),
0711         .pc_ressize = sizeof(struct nlm_void),
0712         .pc_xdrressize = St,
0713         .pc_name = "UNUSED",
0714     },
0715     [18] = {
0716         .pc_func = nlmsvc_proc_unused,
0717         .pc_decode = nlmsvc_decode_void,
0718         .pc_encode = nlmsvc_encode_void,
0719         .pc_argsize = sizeof(struct nlm_void),
0720         .pc_ressize = sizeof(struct nlm_void),
0721         .pc_xdrressize = St,
0722         .pc_name = "UNUSED",
0723     },
0724     [19] = {
0725         .pc_func = nlmsvc_proc_unused,
0726         .pc_decode = nlmsvc_decode_void,
0727         .pc_encode = nlmsvc_encode_void,
0728         .pc_argsize = sizeof(struct nlm_void),
0729         .pc_ressize = sizeof(struct nlm_void),
0730         .pc_xdrressize = St,
0731         .pc_name = "UNUSED",
0732     },
0733     [NLMPROC_SHARE] = {
0734         .pc_func = nlmsvc_proc_share,
0735         .pc_decode = nlmsvc_decode_shareargs,
0736         .pc_encode = nlmsvc_encode_shareres,
0737         .pc_argsize = sizeof(struct nlm_args),
0738         .pc_ressize = sizeof(struct nlm_res),
0739         .pc_xdrressize = Ck+St+1,
0740         .pc_name = "SHARE",
0741     },
0742     [NLMPROC_UNSHARE] = {
0743         .pc_func = nlmsvc_proc_unshare,
0744         .pc_decode = nlmsvc_decode_shareargs,
0745         .pc_encode = nlmsvc_encode_shareres,
0746         .pc_argsize = sizeof(struct nlm_args),
0747         .pc_ressize = sizeof(struct nlm_res),
0748         .pc_xdrressize = Ck+St+1,
0749         .pc_name = "UNSHARE",
0750     },
0751     [NLMPROC_NM_LOCK] = {
0752         .pc_func = nlmsvc_proc_nm_lock,
0753         .pc_decode = nlmsvc_decode_lockargs,
0754         .pc_encode = nlmsvc_encode_res,
0755         .pc_argsize = sizeof(struct nlm_args),
0756         .pc_ressize = sizeof(struct nlm_res),
0757         .pc_xdrressize = Ck+St,
0758         .pc_name = "NM_LOCK",
0759     },
0760     [NLMPROC_FREE_ALL] = {
0761         .pc_func = nlmsvc_proc_free_all,
0762         .pc_decode = nlmsvc_decode_notify,
0763         .pc_encode = nlmsvc_encode_void,
0764         .pc_argsize = sizeof(struct nlm_args),
0765         .pc_ressize = sizeof(struct nlm_void),
0766         .pc_xdrressize = 0,
0767         .pc_name = "FREE_ALL",
0768     },
0769 };