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