cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

svcproc.c (19911B)


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