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