File Index
Files and directories
Sign in
FILE

svcproc.c

File preview with syntax highlighting.

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