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