xref: /linux/fs/lockd/svc4proc.c (revision 5ea5880764cbb164afb17a62e76ca75dc371409d)
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/sunrpc/svc_xprt.h>
14 
15 #include "lockd.h"
16 
17 /*
18  * xdr.h defines SM_MAXSTRLEN and SM_PRIV_SIZE as macros.
19  * nlm4xdr_gen.h defines them as enum constants. Undefine the
20  * macros to allow the xdrgen enum definitions to be used.
21  */
22 #undef SM_MAXSTRLEN
23 #undef SM_PRIV_SIZE
24 
25 #include "share.h"
26 #include "nlm4xdr_gen.h"
27 
28 /*
29  * Wrapper structures combine xdrgen types with legacy nlm_lock.
30  * The xdrgen field must be first so the structure can be cast
31  * to its XDR type for the RPC dispatch layer.
32  */
33 struct nlm4_testargs_wrapper {
34 	struct nlm4_testargs		xdrgen;
35 	struct nlm_lock			lock;
36 };
37 
38 static_assert(offsetof(struct nlm4_testargs_wrapper, xdrgen) == 0);
39 
40 struct nlm4_lockargs_wrapper {
41 	struct nlm4_lockargs		xdrgen;
42 	struct nlm_cookie		cookie;
43 	struct nlm_lock			lock;
44 };
45 
46 static_assert(offsetof(struct nlm4_lockargs_wrapper, xdrgen) == 0);
47 
48 struct nlm4_cancargs_wrapper {
49 	struct nlm4_cancargs		xdrgen;
50 	struct nlm_lock			lock;
51 };
52 
53 static_assert(offsetof(struct nlm4_cancargs_wrapper, xdrgen) == 0);
54 
55 struct nlm4_unlockargs_wrapper {
56 	struct nlm4_unlockargs		xdrgen;
57 	struct nlm_lock			lock;
58 };
59 
60 static_assert(offsetof(struct nlm4_unlockargs_wrapper, xdrgen) == 0);
61 
62 struct nlm4_notifyargs_wrapper {
63 	struct nlm4_notifyargs		xdrgen;
64 	struct nlm_reboot		reboot;
65 };
66 
67 static_assert(offsetof(struct nlm4_notifyargs_wrapper, xdrgen) == 0);
68 
69 struct nlm4_notify_wrapper {
70 	struct nlm4_notify		xdrgen;
71 };
72 
73 static_assert(offsetof(struct nlm4_notify_wrapper, xdrgen) == 0);
74 
75 struct nlm4_testres_wrapper {
76 	struct nlm4_testres		xdrgen;
77 	struct nlm_lock			lock;
78 };
79 
80 struct nlm4_shareargs_wrapper {
81 	struct nlm4_shareargs		xdrgen;
82 	struct nlm_lock			lock;
83 };
84 
85 static_assert(offsetof(struct nlm4_shareargs_wrapper, xdrgen) == 0);
86 
87 static_assert(offsetof(struct nlm4_testres_wrapper, xdrgen) == 0);
88 
89 struct nlm4_res_wrapper {
90 	struct nlm4_res			xdrgen;
91 	struct nlm_cookie		cookie;
92 };
93 
94 static_assert(offsetof(struct nlm4_res_wrapper, xdrgen) == 0);
95 
96 struct nlm4_shareres_wrapper {
97 	struct nlm4_shareres		xdrgen;
98 };
99 
100 static_assert(offsetof(struct nlm4_shareres_wrapper, xdrgen) == 0);
101 
102 static __be32
103 nlm4_netobj_to_cookie(struct nlm_cookie *cookie, netobj *object)
104 {
105 	if (object->len > NLM_MAXCOOKIELEN)
106 		return nlm_lck_denied_nolocks;
107 	cookie->len = object->len;
108 	memcpy(cookie->data, object->data, object->len);
109 	return nlm_granted;
110 }
111 
112 static __be32
113 nlm4_lock_to_nlm_lock(struct nlm_lock *lock, struct nlm4_lock *alock)
114 {
115 	if (alock->fh.len > NFS_MAXFHSIZE)
116 		return nlm_lck_denied;
117 	lock->fh.size = alock->fh.len;
118 	memcpy(lock->fh.data, alock->fh.data, alock->fh.len);
119 	lock->oh.len = alock->oh.len;
120 	lock->oh.data = alock->oh.data;
121 	lock->svid = alock->svid;
122 	locks_init_lock(&lock->fl);
123 	lockd_set_file_lock_range4(&lock->fl, alock->l_offset, alock->l_len);
124 	return nlm_granted;
125 }
126 
127 static struct nlm_host *
128 nlm4svc_lookup_host(struct svc_rqst *rqstp, string caller, bool monitored)
129 {
130 	struct nlm_host *host;
131 
132 	if (!nlmsvc_ops)
133 		return NULL;
134 	host = nlmsvc_lookup_host(rqstp, caller.data, caller.len);
135 	if (!host)
136 		return NULL;
137 	if (monitored && nsm_monitor(host) < 0) {
138 		nlmsvc_release_host(host);
139 		return NULL;
140 	}
141 	return host;
142 }
143 
144 static __be32
145 nlm4svc_lookup_file(struct svc_rqst *rqstp, struct nlm_host *host,
146 		    struct nlm_lock *lock, struct nlm_file **filp,
147 		    struct nlm4_lock *xdr_lock, unsigned char type)
148 {
149 	struct file_lock *fl = &lock->fl;
150 	struct nlm_file *file = NULL;
151 	__be32 error;
152 
153 	if (xdr_lock->fh.len > NFS_MAXFHSIZE)
154 		return nlm_lck_denied_nolocks;
155 	lock->fh.size = xdr_lock->fh.len;
156 	memcpy(lock->fh.data, xdr_lock->fh.data, xdr_lock->fh.len);
157 
158 	lock->oh.len = xdr_lock->oh.len;
159 	lock->oh.data = xdr_lock->oh.data;
160 
161 	lock->svid = xdr_lock->svid;
162 	lock->lock_start = xdr_lock->l_offset;
163 	lock->lock_len = xdr_lock->l_len;
164 
165 	if (lock->lock_start > OFFSET_MAX ||
166 	    (lock->lock_len && ((lock->lock_len - 1) > (OFFSET_MAX - lock->lock_start))))
167 		return nlm4_fbig;
168 
169 	locks_init_lock(fl);
170 	fl->c.flc_type = type;
171 	lockd_set_file_lock_range4(fl, lock->lock_start, lock->lock_len);
172 
173 	error = nlm_lookup_file(rqstp, &file, lock);
174 	switch (error) {
175 	case nlm_granted:
176 		break;
177 	case nlm__int__stale_fh:
178 		return nlm4_stale_fh;
179 	case nlm__int__failed:
180 		return nlm4_failed;
181 	default:
182 		return error;
183 	}
184 	*filp = file;
185 
186 	fl->c.flc_flags = FL_POSIX;
187 	fl->c.flc_file = file->f_file[lock_to_openmode(fl)];
188 	fl->c.flc_pid = current->tgid;
189 	fl->fl_lmops = &nlmsvc_lock_operations;
190 	nlmsvc_locks_init_private(fl, host, (pid_t)lock->svid);
191 	if (!fl->c.flc_owner)
192 		return nlm_lck_denied_nolocks;
193 
194 	return nlm_granted;
195 }
196 
197 /**
198  * nlm4svc_proc_null - NULL: Test for presence of service
199  * @rqstp: RPC transaction context
200  *
201  * Returns:
202  *   %rpc_success:		RPC executed successfully
203  *
204  * RPC synopsis:
205  *   void NLMPROC4_NULL(void) = 0;
206  */
207 static __be32
208 nlm4svc_proc_null(struct svc_rqst *rqstp)
209 {
210 	return rpc_success;
211 }
212 
213 /**
214  * nlm4svc_proc_test - TEST: Check for conflicting lock
215  * @rqstp: RPC transaction context
216  *
217  * Returns:
218  *   %rpc_success:		RPC executed successfully.
219  *   %rpc_drop_reply:		Do not send an RPC reply.
220  *
221  * RPC synopsis:
222  *   nlm4_testres NLMPROC4_TEST(nlm4_testargs) = 1;
223  *
224  * Permissible procedure status codes:
225  *   %NLM4_GRANTED:		The server would be able to grant the
226  *				requested lock.
227  *   %NLM4_DENIED:		The requested lock conflicted with existing
228  *				lock reservations for the file.
229  *   %NLM4_DENIED_NOLOCKS:	The server could not allocate the resources
230  *				needed to process the request.
231  *   %NLM4_DENIED_GRACE_PERIOD:	The server has recently restarted and is
232  *				re-establishing existing locks, and is not
233  *				yet ready to accept normal service requests.
234  *
235  * The Linux NLM server implementation also returns:
236  *   %NLM4_STALE_FH:		The request specified an invalid file handle.
237  *   %NLM4_FBIG:		The request specified a length or offset
238  *				that exceeds the range supported by the
239  *				server.
240  *   %NLM4_FAILED:		The request failed for an unspecified reason.
241  */
242 static __be32 nlm4svc_proc_test(struct svc_rqst *rqstp)
243 {
244 	struct nlm4_testargs_wrapper *argp = rqstp->rq_argp;
245 	unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
246 	struct nlm4_testres_wrapper *resp = rqstp->rq_resp;
247 	struct nlm_file	*file = NULL;
248 	struct nlm_host	*host;
249 
250 	resp->xdrgen.cookie = argp->xdrgen.cookie;
251 
252 	resp->xdrgen.stat.stat = nlm_lck_denied_nolocks;
253 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
254 	if (!host)
255 		goto out;
256 
257 	resp->xdrgen.stat.stat = nlm4svc_lookup_file(rqstp, host, &argp->lock,
258 						     &file, &argp->xdrgen.alock,
259 						     type);
260 	if (resp->xdrgen.stat.stat)
261 		goto out;
262 
263 	resp->xdrgen.stat.stat = nlmsvc_testlock(rqstp, file, host,
264 						 &argp->lock, &resp->lock);
265 	nlmsvc_release_lockowner(&argp->lock);
266 
267 	if (resp->xdrgen.stat.stat == nlm_lck_denied) {
268 		struct nlm_lock *conf = &resp->lock;
269 		struct nlm4_holder *holder = &resp->xdrgen.stat.u.holder;
270 
271 		holder->exclusive = (conf->fl.c.flc_type != F_RDLCK);
272 		holder->svid = conf->svid;
273 		holder->oh.len = conf->oh.len;
274 		holder->oh.data = conf->oh.data;
275 		holder->l_offset = conf->fl.fl_start;
276 		if (conf->fl.fl_end == OFFSET_MAX)
277 			holder->l_len = 0;
278 		else
279 			holder->l_len = conf->fl.fl_end - conf->fl.fl_start + 1;
280 	}
281 
282 out:
283 	if (file)
284 		nlm_release_file(file);
285 	nlmsvc_release_host(host);
286 	return resp->xdrgen.stat.stat == nlm__int__drop_reply ?
287 		rpc_drop_reply : rpc_success;
288 }
289 
290 static __be32
291 nlm4svc_do_lock(struct svc_rqst *rqstp, bool monitored)
292 {
293 	struct nlm4_lockargs_wrapper *argp = rqstp->rq_argp;
294 	unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
295 	struct nlm4_res_wrapper *resp = rqstp->rq_resp;
296 	struct nlm_file	*file = NULL;
297 	struct nlm_host	*host = NULL;
298 
299 	resp->xdrgen.cookie = argp->xdrgen.cookie;
300 
301 	resp->xdrgen.stat.stat = nlm4_netobj_to_cookie(&argp->cookie,
302 						       &argp->xdrgen.cookie);
303 	if (resp->xdrgen.stat.stat)
304 		goto out;
305 
306 	resp->xdrgen.stat.stat = nlm_lck_denied_nolocks;
307 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name,
308 				   monitored);
309 	if (!host)
310 		goto out;
311 
312 	resp->xdrgen.stat.stat = nlm4svc_lookup_file(rqstp, host, &argp->lock,
313 						     &file, &argp->xdrgen.alock,
314 						     type);
315 	if (resp->xdrgen.stat.stat)
316 		goto out;
317 
318 	resp->xdrgen.stat.stat = nlmsvc_lock(rqstp, file, host, &argp->lock,
319 					     argp->xdrgen.block, &argp->cookie,
320 					     argp->xdrgen.reclaim);
321 	if (resp->xdrgen.stat.stat == nlm__int__deadlock)
322 		resp->xdrgen.stat.stat = nlm4_deadlock;
323 
324 	nlmsvc_release_lockowner(&argp->lock);
325 
326 out:
327 	if (file)
328 		nlm_release_file(file);
329 	nlmsvc_release_host(host);
330 	return resp->xdrgen.stat.stat == nlm__int__drop_reply ?
331 		rpc_drop_reply : rpc_success;
332 }
333 
334 /**
335  * nlm4svc_proc_lock - LOCK: Establish a monitored lock
336  * @rqstp: RPC transaction context
337  *
338  * Returns:
339  *   %rpc_success:		RPC executed successfully.
340  *   %rpc_drop_reply:		Do not send an RPC reply.
341  *
342  * RPC synopsis:
343  *   nlm4_res NLMPROC4_LOCK(nlm4_lockargs) = 2;
344  *
345  * Permissible procedure status codes:
346  *   %NLM4_GRANTED:		The requested lock was granted.
347  *   %NLM4_DENIED:		The requested lock conflicted with existing
348  *				lock reservations for the file.
349  *   %NLM4_DENIED_NOLOCKS:	The server could not allocate the resources
350  *				needed to process the request.
351  *   %NLM4_BLOCKED:		The blocking request cannot be granted
352  *				immediately. The server will send an
353  *				NLMPROC4_GRANTED callback to the client when
354  *				the lock can be granted.
355  *   %NLM4_DENIED_GRACE_PERIOD:	The server has recently restarted and is
356  *				re-establishing existing locks, and is not
357  *				yet ready to accept normal service requests.
358  *
359  * The Linux NLM server implementation also returns:
360  *   %NLM4_DEADLCK:		The request could not be granted and
361  *				blocking would cause a deadlock.
362  *   %NLM4_STALE_FH:		The request specified an invalid file handle.
363  *   %NLM4_FBIG:		The request specified a length or offset
364  *				that exceeds the range supported by the
365  *				server.
366  *   %NLM4_FAILED:		The request failed for an unspecified reason.
367  */
368 static __be32
369 nlm4svc_proc_lock(struct svc_rqst *rqstp)
370 {
371 	return nlm4svc_do_lock(rqstp, true);
372 }
373 
374 /**
375  * nlm4svc_proc_cancel - CANCEL: Cancel an outstanding blocked lock request
376  * @rqstp: RPC transaction context
377  *
378  * Returns:
379  *   %rpc_success:		RPC executed successfully
380  *   %rpc_drop_reply:		Do not send an RPC reply
381  *
382  * RPC synopsis:
383  *   nlm4_res NLMPROC4_CANCEL(nlm4_cancargs) = 3;
384  *
385  * Permissible procedure status codes:
386  *   %NLM4_LCK_GRANTED:		The requested lock was canceled.
387  *   %NLM4_LCK_DENIED:		There was no lock to cancel.
388  *   %NLM4_DENIED_GRACE_PERIOD:	The server has recently restarted and is
389  *				re-establishing existing locks, and is not
390  *				yet ready to accept normal service requests.
391  *
392  * The Linux NLM server implementation also returns:
393  *   %NLM4_DENIED_NOLOCKS:	A needed resource could not be allocated.
394  *   %NLM4_STALE_FH:		The request specified an invalid file handle.
395  *   %NLM4_FBIG:		The request specified a length or offset
396  *				that exceeds the range supported by the
397  *				server.
398  *   %NLM4_FAILED:		The request failed for an unspecified reason.
399  */
400 static __be32
401 nlm4svc_proc_cancel(struct svc_rqst *rqstp)
402 {
403 	struct nlm4_cancargs_wrapper *argp = rqstp->rq_argp;
404 	unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
405 	struct nlm4_res_wrapper *resp = rqstp->rq_resp;
406 	struct net *net = SVC_NET(rqstp);
407 	struct nlm_host	*host = NULL;
408 	struct nlm_file	*file = NULL;
409 
410 	resp->xdrgen.cookie = argp->xdrgen.cookie;
411 
412 	resp->xdrgen.stat.stat = nlm_lck_denied_grace_period;
413 	if (locks_in_grace(net))
414 		goto out;
415 
416 	resp->xdrgen.stat.stat = nlm_lck_denied_nolocks;
417 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
418 	if (!host)
419 		goto out;
420 
421 	resp->xdrgen.stat.stat = nlm4svc_lookup_file(rqstp, host, &argp->lock,
422 						     &file, &argp->xdrgen.alock,
423 						     type);
424 	if (resp->xdrgen.stat.stat)
425 		goto out;
426 
427 	resp->xdrgen.stat.stat = nlmsvc_cancel_blocked(net, file, &argp->lock);
428 	nlmsvc_release_lockowner(&argp->lock);
429 
430 out:
431 	if (file)
432 		nlm_release_file(file);
433 	nlmsvc_release_host(host);
434 	return resp->xdrgen.stat.stat == nlm__int__drop_reply ?
435 		rpc_drop_reply : rpc_success;
436 }
437 
438 /**
439  * nlm4svc_proc_unlock - UNLOCK: Remove a lock
440  * @rqstp: RPC transaction context
441  *
442  * Returns:
443  *   %rpc_success:		RPC executed successfully.
444  *   %rpc_drop_reply:		Do not send an RPC reply.
445  *
446  * RPC synopsis:
447  *   nlm4_res NLMPROC4_UNLOCK(nlm4_unlockargs) = 4;
448  *
449  * Permissible procedure status codes:
450  *   %NLM4_GRANTED:		The requested lock was released.
451  *   %NLM4_DENIED_GRACE_PERIOD:	The server has recently restarted and is
452  *				re-establishing existing locks, and is not
453  *				yet ready to accept normal service requests.
454  *
455  * The Linux NLM server implementation also returns:
456  *   %NLM4_DENIED_NOLOCKS:	A needed resource could not be allocated.
457  *   %NLM4_STALE_FH:		The request specified an invalid file handle.
458  *   %NLM4_FBIG:		The request specified a length or offset
459  *				that exceeds the range supported by the
460  *				server.
461  *   %NLM4_FAILED:		The request failed for an unspecified reason.
462  */
463 static __be32
464 nlm4svc_proc_unlock(struct svc_rqst *rqstp)
465 {
466 	struct nlm4_unlockargs_wrapper *argp = rqstp->rq_argp;
467 	struct nlm4_res_wrapper *resp = rqstp->rq_resp;
468 	struct net *net = SVC_NET(rqstp);
469 	struct nlm_host	*host = NULL;
470 	struct nlm_file	*file = NULL;
471 
472 	resp->xdrgen.cookie = argp->xdrgen.cookie;
473 
474 	resp->xdrgen.stat.stat = nlm_lck_denied_grace_period;
475 	if (locks_in_grace(net))
476 		goto out;
477 
478 	resp->xdrgen.stat.stat = nlm_lck_denied_nolocks;
479 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
480 	if (!host)
481 		goto out;
482 
483 	resp->xdrgen.stat.stat = nlm4svc_lookup_file(rqstp, host, &argp->lock,
484 						     &file, &argp->xdrgen.alock,
485 						     F_UNLCK);
486 	if (resp->xdrgen.stat.stat)
487 		goto out;
488 
489 	resp->xdrgen.stat.stat = nlmsvc_unlock(net, file, &argp->lock);
490 	nlmsvc_release_lockowner(&argp->lock);
491 
492 out:
493 	if (file)
494 		nlm_release_file(file);
495 	nlmsvc_release_host(host);
496 	return resp->xdrgen.stat.stat == nlm__int__drop_reply ?
497 		rpc_drop_reply : rpc_success;
498 }
499 
500 /**
501  * nlm4svc_proc_granted - GRANTED: Server grants a previously blocked lock
502  * @rqstp: RPC transaction context
503  *
504  * Returns:
505  *   %rpc_success:		RPC executed successfully.
506  *
507  * RPC synopsis:
508  *   nlm4_res NLMPROC4_GRANTED(nlm4_testargs) = 5;
509  *
510  * Permissible procedure status codes:
511  *   %NLM4_GRANTED:		The requested lock was granted.
512  *   %NLM4_DENIED:		The server could not allocate the resources
513  *				needed to process the request.
514  *   %NLM4_DENIED_GRACE_PERIOD:	The server has recently restarted and is
515  *				re-establishing existing locks, and is not
516  *				yet ready to accept normal service requests.
517  */
518 static __be32
519 nlm4svc_proc_granted(struct svc_rqst *rqstp)
520 {
521 	struct nlm4_testargs_wrapper *argp = rqstp->rq_argp;
522 	struct nlm4_res_wrapper *resp = rqstp->rq_resp;
523 
524 	resp->xdrgen.cookie = argp->xdrgen.cookie;
525 
526 	resp->xdrgen.stat.stat = nlm4_lock_to_nlm_lock(&argp->lock,
527 						       &argp->xdrgen.alock);
528 	if (resp->xdrgen.stat.stat)
529 		goto out;
530 
531 	resp->xdrgen.stat.stat = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
532 
533 out:
534 	return rpc_success;
535 }
536 
537 /*
538  * This is the generic lockd callback for async RPC calls
539  */
540 static void nlm4svc_callback_exit(struct rpc_task *task, void *data)
541 {
542 }
543 
544 static void nlm4svc_callback_release(void *data)
545 {
546 	nlmsvc_release_call(data);
547 }
548 
549 static const struct rpc_call_ops nlm4svc_callback_ops = {
550 	.rpc_call_done = nlm4svc_callback_exit,
551 	.rpc_release = nlm4svc_callback_release,
552 };
553 
554 /*
555  * Dispatch an async callback RPC to a client with a pre-resolved host.
556  * Caller provides a reference to @host; this function takes ownership
557  * and releases it via nlmsvc_release_host() before returning.
558  */
559 static __be32
560 nlm4svc_callback(struct svc_rqst *rqstp, struct nlm_host *host, u32 proc,
561 		 __be32 (*func)(struct svc_rqst *,  struct nlm_res *))
562 {
563 	struct nlm_rqst	*call;
564 	__be32 stat;
565 
566 	call = nlm_alloc_call(host);
567 	nlmsvc_release_host(host);
568 	if (call == NULL)
569 		return rpc_system_err;
570 
571 	stat = func(rqstp, &call->a_res);
572 	if (stat != 0) {
573 		nlmsvc_release_call(call);
574 		return stat;
575 	}
576 
577 	call->a_flags = RPC_TASK_ASYNC;
578 	if (nlm_async_reply(call, proc, &nlm4svc_callback_ops) < 0)
579 		return rpc_system_err;
580 	return rpc_success;
581 }
582 
583 static __be32
584 __nlm4svc_proc_test_msg(struct svc_rqst *rqstp, struct nlm_res *resp)
585 {
586 	struct nlm4_testargs_wrapper *argp = rqstp->rq_argp;
587 	unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
588 	struct nlm_lockowner *owner;
589 	struct nlm_file	*file = NULL;
590 	struct nlm_host	*host = NULL;
591 
592 	resp->status = nlm_lck_denied_nolocks;
593 	if (nlm4_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie))
594 		goto out;
595 
596 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
597 	if (!host)
598 		goto out;
599 
600 	resp->status = nlm4svc_lookup_file(rqstp, host, &argp->lock,
601 					   &file, &argp->xdrgen.alock, type);
602 	if (resp->status)
603 		goto out;
604 
605 	owner = argp->lock.fl.c.flc_owner;
606 	resp->status = nlmsvc_testlock(rqstp, file, host, &argp->lock,
607 				       &resp->lock);
608 	nlmsvc_put_lockowner(owner);
609 
610 out:
611 	if (file)
612 		nlm_release_file(file);
613 	nlmsvc_release_host(host);
614 	return resp->status == nlm__int__drop_reply ? rpc_drop_reply : rpc_success;
615 }
616 
617 /**
618  * nlm4svc_proc_test_msg - TEST_MSG: Check for conflicting lock
619  * @rqstp: RPC transaction context
620  *
621  * Returns:
622  *   %rpc_success:		RPC executed successfully.
623  *   %rpc_system_err:		RPC execution failed.
624  *
625  * RPC synopsis:
626  *   void NLMPROC4_TEST_MSG(nlm4_testargs) = 6;
627  *
628  * The response to this request is delivered via the TEST_RES procedure.
629  */
630 static __be32 nlm4svc_proc_test_msg(struct svc_rqst *rqstp)
631 {
632 	struct nlm4_testargs_wrapper *argp = rqstp->rq_argp;
633 	struct nlm_host *host;
634 
635 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
636 	if (!host)
637 		return rpc_system_err;
638 
639 	return nlm4svc_callback(rqstp, host, NLMPROC4_TEST_RES,
640 				__nlm4svc_proc_test_msg);
641 }
642 
643 static __be32
644 __nlm4svc_proc_lock_msg(struct svc_rqst *rqstp, struct nlm_res *resp)
645 {
646 	struct nlm4_lockargs_wrapper *argp = rqstp->rq_argp;
647 	unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
648 	struct nlm_file	*file = NULL;
649 	struct nlm_host	*host = NULL;
650 
651 	resp->status = nlm_lck_denied_nolocks;
652 	if (nlm4_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie))
653 		goto out;
654 
655 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, true);
656 	if (!host)
657 		goto out;
658 
659 	resp->status = nlm4svc_lookup_file(rqstp, host, &argp->lock,
660 					   &file, &argp->xdrgen.alock, type);
661 	if (resp->status)
662 		goto out;
663 
664 	resp->status = nlmsvc_lock(rqstp, file, host, &argp->lock,
665 				   argp->xdrgen.block, &resp->cookie,
666 				   argp->xdrgen.reclaim);
667 	nlmsvc_release_lockowner(&argp->lock);
668 
669 out:
670 	if (file)
671 		nlm_release_file(file);
672 	nlmsvc_release_host(host);
673 	return resp->status == nlm__int__drop_reply ?
674 		rpc_drop_reply : rpc_success;
675 }
676 
677 /**
678  * nlm4svc_proc_lock_msg - LOCK_MSG: Establish a monitored lock
679  * @rqstp: RPC transaction context
680  *
681  * Returns:
682  *   %rpc_success:		RPC executed successfully.
683  *   %rpc_system_err:		RPC execution failed.
684  *
685  * RPC synopsis:
686  *   void NLMPROC4_LOCK_MSG(nlm4_lockargs) = 7;
687  *
688  * The response to this request is delivered via the LOCK_RES procedure.
689  */
690 static __be32 nlm4svc_proc_lock_msg(struct svc_rqst *rqstp)
691 {
692 	struct nlm4_lockargs_wrapper *argp = rqstp->rq_argp;
693 	struct nlm_host *host;
694 
695 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, true);
696 	if (!host)
697 		return rpc_system_err;
698 
699 	return nlm4svc_callback(rqstp, host, NLMPROC4_LOCK_RES,
700 				__nlm4svc_proc_lock_msg);
701 }
702 
703 static __be32
704 __nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp, struct nlm_res *resp)
705 {
706 	struct nlm4_cancargs_wrapper *argp = rqstp->rq_argp;
707 	unsigned char type = argp->xdrgen.exclusive ? F_WRLCK : F_RDLCK;
708 	struct net *net = SVC_NET(rqstp);
709 	struct nlm_file	*file = NULL;
710 	struct nlm_host	*host = NULL;
711 
712 	resp->status = nlm_lck_denied_nolocks;
713 	if (nlm4_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie))
714 		goto out;
715 
716 	resp->status = nlm_lck_denied_grace_period;
717 	if (locks_in_grace(net))
718 		goto out;
719 
720 	resp->status = nlm_lck_denied_nolocks;
721 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
722 	if (!host)
723 		goto out;
724 
725 	resp->status = nlm4svc_lookup_file(rqstp, host, &argp->lock,
726 					   &file, &argp->xdrgen.alock, type);
727 	if (resp->status)
728 		goto out;
729 
730 	resp->status = nlmsvc_cancel_blocked(net, file, &argp->lock);
731 	nlmsvc_release_lockowner(&argp->lock);
732 
733 out:
734 	if (file)
735 		nlm_release_file(file);
736 	nlmsvc_release_host(host);
737 	return resp->status == nlm__int__drop_reply ?
738 		rpc_drop_reply : rpc_success;
739 }
740 
741 /**
742  * nlm4svc_proc_cancel_msg - CANCEL_MSG: Cancel an outstanding lock request
743  * @rqstp: RPC transaction context
744  *
745  * Returns:
746  *   %rpc_success:		RPC executed successfully.
747  *   %rpc_system_err:		RPC execution failed.
748  *
749  * RPC synopsis:
750  *   void NLMPROC4_CANCEL_MSG(nlm4_cancargs) = 8;
751  *
752  * The response to this request is delivered via the CANCEL_RES procedure.
753  */
754 static __be32 nlm4svc_proc_cancel_msg(struct svc_rqst *rqstp)
755 {
756 	struct nlm4_cancargs_wrapper *argp = rqstp->rq_argp;
757 	struct nlm_host *host;
758 
759 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
760 	if (!host)
761 		return rpc_system_err;
762 
763 	return nlm4svc_callback(rqstp, host, NLMPROC4_CANCEL_RES,
764 				__nlm4svc_proc_cancel_msg);
765 }
766 
767 static __be32
768 __nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp, struct nlm_res *resp)
769 {
770 	struct nlm4_unlockargs_wrapper *argp = rqstp->rq_argp;
771 	struct net *net = SVC_NET(rqstp);
772 	struct nlm_file	*file = NULL;
773 	struct nlm_host	*host = NULL;
774 
775 	resp->status = nlm_lck_denied_nolocks;
776 	if (nlm4_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie))
777 		goto out;
778 
779 	resp->status = nlm_lck_denied_grace_period;
780 	if (locks_in_grace(net))
781 		goto out;
782 
783 	resp->status = nlm_lck_denied_nolocks;
784 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
785 	if (!host)
786 		goto out;
787 
788 	resp->status = nlm4svc_lookup_file(rqstp, host, &argp->lock,
789 					   &file, &argp->xdrgen.alock, F_UNLCK);
790 	if (resp->status)
791 		goto out;
792 
793 	resp->status = nlmsvc_unlock(net, file, &argp->lock);
794 	nlmsvc_release_lockowner(&argp->lock);
795 
796 out:
797 	if (file)
798 		nlm_release_file(file);
799 	nlmsvc_release_host(host);
800 	return resp->status == nlm__int__drop_reply ?
801 		rpc_drop_reply : rpc_success;
802 }
803 
804 /**
805  * nlm4svc_proc_unlock_msg - UNLOCK_MSG: Remove an existing lock
806  * @rqstp: RPC transaction context
807  *
808  * Returns:
809  *   %rpc_success:		RPC executed successfully.
810  *   %rpc_system_err:		RPC execution failed.
811  *
812  * RPC synopsis:
813  *   void NLMPROC4_UNLOCK_MSG(nlm4_unlockargs) = 9;
814  *
815  * The response to this request is delivered via the UNLOCK_RES procedure.
816  */
817 static __be32 nlm4svc_proc_unlock_msg(struct svc_rqst *rqstp)
818 {
819 	struct nlm4_unlockargs_wrapper *argp = rqstp->rq_argp;
820 	struct nlm_host *host;
821 
822 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
823 	if (!host)
824 		return rpc_system_err;
825 
826 	return nlm4svc_callback(rqstp, host, NLMPROC4_UNLOCK_RES,
827 				__nlm4svc_proc_unlock_msg);
828 }
829 
830 static __be32
831 __nlm4svc_proc_granted_msg(struct svc_rqst *rqstp, struct nlm_res *resp)
832 {
833 	struct nlm4_testargs_wrapper *argp = rqstp->rq_argp;
834 
835 	resp->status = nlm_lck_denied;
836 	if (nlm4_netobj_to_cookie(&resp->cookie, &argp->xdrgen.cookie))
837 		goto out;
838 
839 	if (nlm4_lock_to_nlm_lock(&argp->lock, &argp->xdrgen.alock))
840 		goto out;
841 
842 	resp->status = nlmclnt_grant(svc_addr(rqstp), &argp->lock);
843 
844 out:
845 	return rpc_success;
846 }
847 
848 /**
849  * nlm4svc_proc_granted_msg - GRANTED_MSG: Blocked lock has been granted
850  * @rqstp: RPC transaction context
851  *
852  * Returns:
853  *   %rpc_success:		RPC executed successfully.
854  *   %rpc_system_err:		RPC execution failed.
855  *
856  * RPC synopsis:
857  *   void NLMPROC4_GRANTED_MSG(nlm4_testargs) = 10;
858  *
859  * The response to this request is delivered via the GRANTED_RES procedure.
860  */
861 static __be32 nlm4svc_proc_granted_msg(struct svc_rqst *rqstp)
862 {
863 	struct nlm4_testargs_wrapper *argp = rqstp->rq_argp;
864 	struct nlm_host *host;
865 
866 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.alock.caller_name, false);
867 	if (!host)
868 		return rpc_system_err;
869 
870 	return nlm4svc_callback(rqstp, host, NLMPROC4_GRANTED_RES,
871 				__nlm4svc_proc_granted_msg);
872 }
873 
874 /**
875  * nlm4svc_proc_granted_res - GRANTED_RES: Lock Granted result
876  * @rqstp: RPC transaction context
877  *
878  * Returns:
879  *   %rpc_success:		RPC executed successfully.
880  *
881  * RPC synopsis:
882  *   void NLMPROC4_GRANTED_RES(nlm4_res) = 15;
883  */
884 static __be32 nlm4svc_proc_granted_res(struct svc_rqst *rqstp)
885 {
886 	struct nlm4_res_wrapper *argp = rqstp->rq_argp;
887 
888 	if (!nlmsvc_ops)
889 		return rpc_success;
890 
891 	if (nlm4_netobj_to_cookie(&argp->cookie, &argp->xdrgen.cookie))
892 		return rpc_success;
893 	nlmsvc_grant_reply(&argp->cookie, argp->xdrgen.stat.stat);
894 
895 	return rpc_success;
896 }
897 
898 /**
899  * nlm4svc_proc_sm_notify - SM_NOTIFY: Peer has rebooted
900  * @rqstp: RPC transaction context
901  *
902  * Returns:
903  *   %rpc_success:		RPC executed successfully.
904  *   %rpc_system_err:		RPC execution failed.
905  *
906  * The SM_NOTIFY procedure is a private callback from Linux statd and is
907  * not part of the official NLM protocol.
908  *
909  * RPC synopsis:
910  *   void NLMPROC4_SM_NOTIFY(nlm4_notifyargs) = 16;
911  */
912 static __be32 nlm4svc_proc_sm_notify(struct svc_rqst *rqstp)
913 {
914 	struct nlm4_notifyargs_wrapper *argp = rqstp->rq_argp;
915 	struct nlm_reboot *reboot = &argp->reboot;
916 
917 	if (!nlm_privileged_requester(rqstp)) {
918 		char buf[RPC_MAX_ADDRBUFLEN];
919 
920 		pr_warn("lockd: rejected NSM callback from %s\n",
921 			svc_print_addr(rqstp, buf, sizeof(buf)));
922 		return rpc_system_err;
923 	}
924 
925 	reboot->len = argp->xdrgen.notify.name.len;
926 	reboot->mon = (char *)argp->xdrgen.notify.name.data;
927 	reboot->state = argp->xdrgen.notify.state;
928 	memcpy(&reboot->priv.data, argp->xdrgen.private,
929 	       sizeof(reboot->priv.data));
930 
931 	nlm_host_rebooted(SVC_NET(rqstp), reboot);
932 
933 	return rpc_success;
934 }
935 
936 /**
937  * nlm4svc_proc_unused - stub for unused procedures
938  * @rqstp: RPC transaction context
939  *
940  * Returns:
941  *   %rpc_proc_unavail:	Program can't support procedure.
942  */
943 static __be32 nlm4svc_proc_unused(struct svc_rqst *rqstp)
944 {
945 	return rpc_proc_unavail;
946 }
947 
948 /**
949  * nlm4svc_proc_share - SHARE: Open a file using DOS file-sharing modes
950  * @rqstp: RPC transaction context
951  *
952  * Returns:
953  *   %rpc_success:		RPC executed successfully.
954  *   %rpc_drop_reply:		Do not send an RPC reply.
955  *
956  * RPC synopsis:
957  *   nlm4_shareres NLMPROC4_SHARE(nlm4_shareargs) = 20;
958  *
959  * Permissible procedure status codes:
960  *   %NLM4_GRANTED:		The requested share lock was granted.
961  *   %NLM4_DENIED:		The requested lock conflicted with existing
962  *				lock reservations for the file.
963  *   %NLM4_DENIED_GRACE_PERIOD:	The server has recently restarted and is
964  *				re-establishing existing locks, and is not
965  *				yet ready to accept normal service requests.
966  *
967  * The Linux NLM server implementation also returns:
968  *   %NLM4_DENIED_NOLOCKS:	A needed resource could not be allocated.
969  *   %NLM4_STALE_FH:		The request specified an invalid file handle.
970  *   %NLM4_FBIG:		The request specified a length or offset
971  *				that exceeds the range supported by the
972  *				server.
973  *   %NLM4_FAILED:		The request failed for an unspecified reason.
974  */
975 static __be32 nlm4svc_proc_share(struct svc_rqst *rqstp)
976 {
977 	struct nlm4_shareargs_wrapper *argp = rqstp->rq_argp;
978 	struct nlm4_shareres_wrapper *resp = rqstp->rq_resp;
979 	struct nlm_lock	*lock = &argp->lock;
980 	struct nlm_host	*host = NULL;
981 	struct nlm_file	*file = NULL;
982 	struct nlm4_lock xdr_lock = {
983 		.fh		= argp->xdrgen.share.fh,
984 		.oh		= argp->xdrgen.share.oh,
985 		.svid		= LOCKD_SHARE_SVID,
986 	};
987 
988 	resp->xdrgen.cookie = argp->xdrgen.cookie;
989 
990 	resp->xdrgen.stat = nlm_lck_denied_grace_period;
991 	if (locks_in_grace(SVC_NET(rqstp)) && !argp->xdrgen.reclaim)
992 		goto out;
993 
994 	resp->xdrgen.stat = nlm_lck_denied_nolocks;
995 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.share.caller_name, true);
996 	if (!host)
997 		goto out;
998 
999 	resp->xdrgen.stat = nlm4svc_lookup_file(rqstp, host, lock, &file,
1000 						&xdr_lock, F_RDLCK);
1001 	if (resp->xdrgen.stat)
1002 		goto out;
1003 
1004 	resp->xdrgen.stat = nlmsvc_share_file(host, file, &lock->oh,
1005 					      argp->xdrgen.share.access,
1006 					      argp->xdrgen.share.mode);
1007 
1008 	nlmsvc_release_lockowner(lock);
1009 
1010 out:
1011 	if (file)
1012 		nlm_release_file(file);
1013 	nlmsvc_release_host(host);
1014 	return resp->xdrgen.stat == nlm__int__drop_reply ?
1015 		rpc_drop_reply : rpc_success;
1016 }
1017 
1018 /**
1019  * nlm4svc_proc_unshare - UNSHARE: Release a share reservation
1020  * @rqstp: RPC transaction context
1021  *
1022  * Returns:
1023  *   %rpc_success:		RPC executed successfully.
1024  *   %rpc_drop_reply:		Do not send an RPC reply.
1025  *
1026  * RPC synopsis:
1027  *   nlm4_shareres NLMPROC4_UNSHARE(nlm4_shareargs) = 21;
1028  *
1029  * Permissible procedure status codes:
1030  *   %NLM4_GRANTED:		The share reservation was released.
1031  *   %NLM4_DENIED_GRACE_PERIOD:	The server has recently restarted and is
1032  *				re-establishing existing locks, and is not
1033  *				yet ready to accept normal service requests.
1034  *
1035  * The Linux NLM server implementation also returns:
1036  *   %NLM4_DENIED_NOLOCKS:	A needed resource could not be allocated.
1037  *   %NLM4_STALE_FH:		The request specified an invalid file handle.
1038  *   %NLM4_FBIG:		The request specified a length or offset
1039  *				that exceeds the range supported by the
1040  *				server.
1041  *   %NLM4_FAILED:		The request failed for an unspecified reason.
1042  */
1043 static __be32 nlm4svc_proc_unshare(struct svc_rqst *rqstp)
1044 {
1045 	struct nlm4_shareargs_wrapper *argp = rqstp->rq_argp;
1046 	struct nlm4_shareres_wrapper *resp = rqstp->rq_resp;
1047 	struct nlm_lock	*lock = &argp->lock;
1048 	struct nlm4_lock xdr_lock = {
1049 		.fh		= argp->xdrgen.share.fh,
1050 		.oh		= argp->xdrgen.share.oh,
1051 		.svid		= LOCKD_SHARE_SVID,
1052 	};
1053 	struct nlm_host	*host = NULL;
1054 	struct nlm_file	*file = NULL;
1055 
1056 	resp->xdrgen.cookie = argp->xdrgen.cookie;
1057 
1058 	resp->xdrgen.stat = nlm_lck_denied_grace_period;
1059 	if (locks_in_grace(SVC_NET(rqstp)))
1060 		goto out;
1061 
1062 	resp->xdrgen.stat = nlm_lck_denied_nolocks;
1063 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.share.caller_name, true);
1064 	if (!host)
1065 		goto out;
1066 
1067 	resp->xdrgen.stat = nlm4svc_lookup_file(rqstp, host, lock, &file,
1068 						&xdr_lock, F_RDLCK);
1069 	if (resp->xdrgen.stat)
1070 		goto out;
1071 
1072 	resp->xdrgen.stat = nlmsvc_unshare_file(host, file, &lock->oh);
1073 
1074 	nlmsvc_release_lockowner(lock);
1075 
1076 out:
1077 	if (file)
1078 		nlm_release_file(file);
1079 	nlmsvc_release_host(host);
1080 	return resp->xdrgen.stat == nlm__int__drop_reply ?
1081 		rpc_drop_reply : rpc_success;
1082 }
1083 
1084 /**
1085  * nlm4svc_proc_nm_lock - NM_LOCK: Establish a non-monitored lock
1086  * @rqstp: RPC transaction context
1087  *
1088  * Returns:
1089  *   %rpc_success:		RPC executed successfully.
1090  *   %rpc_drop_reply:		Do not send an RPC reply.
1091  *
1092  * RPC synopsis:
1093  *   nlm4_res NLMPROC4_NM_LOCK(nlm4_lockargs) = 22;
1094  *
1095  * Permissible procedure status codes:
1096  *   %NLM4_GRANTED:		The requested lock was granted.
1097  *   %NLM4_DENIED:		The requested lock conflicted with existing
1098  *				lock reservations for the file.
1099  *   %NLM4_DENIED_NOLOCKS:	The server could not allocate the resources
1100  *				needed to process the request.
1101  *   %NLM4_BLOCKED:		The blocking request cannot be granted
1102  *				immediately. The server will send an
1103  *				NLMPROC4_GRANTED callback to the client when
1104  *				the lock can be granted.
1105  *   %NLM4_DENIED_GRACE_PERIOD:	The server has recently restarted and is
1106  *				re-establishing existing locks, and is not
1107  *				yet ready to accept normal service requests.
1108  *
1109  * The Linux NLM server implementation also returns:
1110  *   %NLM4_DEADLCK:		The request could not be granted and
1111  *				blocking would cause a deadlock.
1112  *   %NLM4_STALE_FH:		The request specified an invalid file handle.
1113  *   %NLM4_FBIG:		The request specified a length or offset
1114  *				that exceeds the range supported by the
1115  *				server.
1116  *   %NLM4_FAILED:		The request failed for an unspecified reason.
1117  */
1118 static __be32 nlm4svc_proc_nm_lock(struct svc_rqst *rqstp)
1119 {
1120 	return nlm4svc_do_lock(rqstp, false);
1121 }
1122 
1123 /**
1124  * nlm4svc_proc_free_all - FREE_ALL: Discard client's lock and share state
1125  * @rqstp: RPC transaction context
1126  *
1127  * Returns:
1128  *   %rpc_success:		RPC executed successfully.
1129  *
1130  * RPC synopsis:
1131  *   void NLMPROC4_FREE_ALL(nlm4_notify) = 23;
1132  */
1133 static __be32 nlm4svc_proc_free_all(struct svc_rqst *rqstp)
1134 {
1135 	struct nlm4_notify_wrapper *argp = rqstp->rq_argp;
1136 	struct nlm_host	*host;
1137 
1138 	host = nlm4svc_lookup_host(rqstp, argp->xdrgen.name, false);
1139 	if (!host)
1140 		goto out;
1141 
1142 	nlmsvc_free_host_resources(host);
1143 
1144 	nlmsvc_release_host(host);
1145 
1146 out:
1147 	return rpc_success;
1148 }
1149 
1150 
1151 /*
1152  * NLMv4 Server procedures.
1153  */
1154 
1155 static const struct svc_procedure nlm4svc_procedures[24] = {
1156 	[NLMPROC4_NULL] = {
1157 		.pc_func	= nlm4svc_proc_null,
1158 		.pc_decode	= nlm4_svc_decode_void,
1159 		.pc_encode	= nlm4_svc_encode_void,
1160 		.pc_argsize	= XDR_void,
1161 		.pc_argzero	= 0,
1162 		.pc_ressize	= 0,
1163 		.pc_xdrressize	= XDR_void,
1164 		.pc_name	= "NULL",
1165 	},
1166 	[NLMPROC4_TEST] = {
1167 		.pc_func	= nlm4svc_proc_test,
1168 		.pc_decode	= nlm4_svc_decode_nlm4_testargs,
1169 		.pc_encode	= nlm4_svc_encode_nlm4_testres,
1170 		.pc_argsize	= sizeof(struct nlm4_testargs_wrapper),
1171 		.pc_argzero	= 0,
1172 		.pc_ressize	= sizeof(struct nlm4_testres_wrapper),
1173 		.pc_xdrressize	= NLM4_nlm4_testres_sz,
1174 		.pc_name	= "TEST",
1175 	},
1176 	[NLMPROC4_LOCK] = {
1177 		.pc_func	= nlm4svc_proc_lock,
1178 		.pc_decode	= nlm4_svc_decode_nlm4_lockargs,
1179 		.pc_encode	= nlm4_svc_encode_nlm4_res,
1180 		.pc_argsize	= sizeof(struct nlm4_lockargs_wrapper),
1181 		.pc_argzero	= 0,
1182 		.pc_ressize	= sizeof(struct nlm4_res_wrapper),
1183 		.pc_xdrressize	= NLM4_nlm4_res_sz,
1184 		.pc_name	= "LOCK",
1185 	},
1186 	[NLMPROC4_CANCEL] = {
1187 		.pc_func	= nlm4svc_proc_cancel,
1188 		.pc_decode	= nlm4_svc_decode_nlm4_cancargs,
1189 		.pc_encode	= nlm4_svc_encode_nlm4_res,
1190 		.pc_argsize	= sizeof(struct nlm4_cancargs_wrapper),
1191 		.pc_argzero	= 0,
1192 		.pc_ressize	= sizeof(struct nlm4_res_wrapper),
1193 		.pc_xdrressize	= NLM4_nlm4_res_sz,
1194 		.pc_name	= "CANCEL",
1195 	},
1196 	[NLMPROC4_UNLOCK] = {
1197 		.pc_func	= nlm4svc_proc_unlock,
1198 		.pc_decode	= nlm4_svc_decode_nlm4_unlockargs,
1199 		.pc_encode	= nlm4_svc_encode_nlm4_res,
1200 		.pc_argsize	= sizeof(struct nlm4_unlockargs_wrapper),
1201 		.pc_argzero	= 0,
1202 		.pc_ressize	= sizeof(struct nlm4_res_wrapper),
1203 		.pc_xdrressize	= NLM4_nlm4_res_sz,
1204 		.pc_name	= "UNLOCK",
1205 	},
1206 	[NLMPROC4_GRANTED] = {
1207 		.pc_func	= nlm4svc_proc_granted,
1208 		.pc_decode	= nlm4_svc_decode_nlm4_testargs,
1209 		.pc_encode	= nlm4_svc_encode_nlm4_res,
1210 		.pc_argsize	= sizeof(struct nlm4_testargs_wrapper),
1211 		.pc_argzero	= 0,
1212 		.pc_ressize	= sizeof(struct nlm4_res_wrapper),
1213 		.pc_xdrressize	= NLM4_nlm4_res_sz,
1214 		.pc_name	= "GRANTED",
1215 	},
1216 	[NLMPROC4_TEST_MSG] = {
1217 		.pc_func	= nlm4svc_proc_test_msg,
1218 		.pc_decode	= nlm4_svc_decode_nlm4_testargs,
1219 		.pc_encode	= nlm4_svc_encode_void,
1220 		.pc_argsize	= sizeof(struct nlm4_testargs_wrapper),
1221 		.pc_argzero	= 0,
1222 		.pc_ressize	= 0,
1223 		.pc_xdrressize	= XDR_void,
1224 		.pc_name	= "TEST_MSG",
1225 	},
1226 	[NLMPROC4_LOCK_MSG] = {
1227 		.pc_func	= nlm4svc_proc_lock_msg,
1228 		.pc_decode	= nlm4_svc_decode_nlm4_lockargs,
1229 		.pc_encode	= nlm4_svc_encode_void,
1230 		.pc_argsize	= sizeof(struct nlm4_lockargs_wrapper),
1231 		.pc_argzero	= 0,
1232 		.pc_ressize	= 0,
1233 		.pc_xdrressize	= XDR_void,
1234 		.pc_name	= "LOCK_MSG",
1235 	},
1236 	[NLMPROC4_CANCEL_MSG] = {
1237 		.pc_func	= nlm4svc_proc_cancel_msg,
1238 		.pc_decode	= nlm4_svc_decode_nlm4_cancargs,
1239 		.pc_encode	= nlm4_svc_encode_void,
1240 		.pc_argsize	= sizeof(struct nlm4_cancargs_wrapper),
1241 		.pc_argzero	= 0,
1242 		.pc_ressize	= 0,
1243 		.pc_xdrressize	= XDR_void,
1244 		.pc_name	= "CANCEL_MSG",
1245 	},
1246 	[NLMPROC4_UNLOCK_MSG] = {
1247 		.pc_func	= nlm4svc_proc_unlock_msg,
1248 		.pc_decode	= nlm4_svc_decode_nlm4_unlockargs,
1249 		.pc_encode	= nlm4_svc_encode_void,
1250 		.pc_argsize	= sizeof(struct nlm4_unlockargs_wrapper),
1251 		.pc_argzero	= 0,
1252 		.pc_ressize	= 0,
1253 		.pc_xdrressize	= XDR_void,
1254 		.pc_name	= "UNLOCK_MSG",
1255 	},
1256 	[NLMPROC4_GRANTED_MSG] = {
1257 		.pc_func	= nlm4svc_proc_granted_msg,
1258 		.pc_decode	= nlm4_svc_decode_nlm4_testargs,
1259 		.pc_encode	= nlm4_svc_encode_void,
1260 		.pc_argsize	= sizeof(struct nlm4_testargs_wrapper),
1261 		.pc_argzero	= 0,
1262 		.pc_ressize	= 0,
1263 		.pc_xdrressize	= XDR_void,
1264 		.pc_name	= "GRANTED_MSG",
1265 	},
1266 	[NLMPROC4_TEST_RES] = {
1267 		.pc_func	= nlm4svc_proc_null,
1268 		.pc_decode	= nlm4_svc_decode_nlm4_testres,
1269 		.pc_encode	= nlm4_svc_encode_void,
1270 		.pc_argsize	= sizeof(struct nlm4_testres),
1271 		.pc_argzero	= 0,
1272 		.pc_ressize	= 0,
1273 		.pc_xdrressize	= XDR_void,
1274 		.pc_name	= "TEST_RES",
1275 	},
1276 	[NLMPROC4_LOCK_RES] = {
1277 		.pc_func	= nlm4svc_proc_null,
1278 		.pc_decode	= nlm4_svc_decode_nlm4_res,
1279 		.pc_encode	= nlm4_svc_encode_void,
1280 		.pc_argsize	= sizeof(struct nlm4_res),
1281 		.pc_argzero	= 0,
1282 		.pc_ressize	= 0,
1283 		.pc_xdrressize	= XDR_void,
1284 		.pc_name	= "LOCK_RES",
1285 	},
1286 	[NLMPROC4_CANCEL_RES] = {
1287 		.pc_func	= nlm4svc_proc_null,
1288 		.pc_decode	= nlm4_svc_decode_nlm4_res,
1289 		.pc_encode	= nlm4_svc_encode_void,
1290 		.pc_argsize	= sizeof(struct nlm4_res),
1291 		.pc_argzero	= 0,
1292 		.pc_ressize	= 0,
1293 		.pc_xdrressize	= XDR_void,
1294 		.pc_name	= "CANCEL_RES",
1295 	},
1296 	[NLMPROC4_UNLOCK_RES] = {
1297 		.pc_func	= nlm4svc_proc_null,
1298 		.pc_decode	= nlm4_svc_decode_nlm4_res,
1299 		.pc_encode	= nlm4_svc_encode_void,
1300 		.pc_argsize	= sizeof(struct nlm4_res),
1301 		.pc_argzero	= 0,
1302 		.pc_ressize	= 0,
1303 		.pc_xdrressize	= XDR_void,
1304 		.pc_name	= "UNLOCK_RES",
1305 	},
1306 	[NLMPROC4_GRANTED_RES] = {
1307 		.pc_func	= nlm4svc_proc_granted_res,
1308 		.pc_decode	= nlm4_svc_decode_nlm4_res,
1309 		.pc_encode	= nlm4_svc_encode_void,
1310 		.pc_argsize	= sizeof(struct nlm4_res_wrapper),
1311 		.pc_argzero	= 0,
1312 		.pc_ressize	= 0,
1313 		.pc_xdrressize	= XDR_void,
1314 		.pc_name	= "GRANTED_RES",
1315 	},
1316 	[NLMPROC4_SM_NOTIFY] = {
1317 		.pc_func	= nlm4svc_proc_sm_notify,
1318 		.pc_decode	= nlm4_svc_decode_nlm4_notifyargs,
1319 		.pc_encode	= nlm4_svc_encode_void,
1320 		.pc_argsize	= sizeof(struct nlm4_notifyargs_wrapper),
1321 		.pc_argzero	= 0,
1322 		.pc_ressize	= 0,
1323 		.pc_xdrressize	= XDR_void,
1324 		.pc_name	= "SM_NOTIFY",
1325 	},
1326 	[17] = {
1327 		.pc_func	= nlm4svc_proc_unused,
1328 		.pc_decode	= nlm4_svc_decode_void,
1329 		.pc_encode	= nlm4_svc_encode_void,
1330 		.pc_argsize	= 0,
1331 		.pc_argzero	= 0,
1332 		.pc_ressize	= 0,
1333 		.pc_xdrressize	= XDR_void,
1334 		.pc_name	= "UNUSED",
1335 	},
1336 	[18] = {
1337 		.pc_func	= nlm4svc_proc_unused,
1338 		.pc_decode	= nlm4_svc_decode_void,
1339 		.pc_encode	= nlm4_svc_encode_void,
1340 		.pc_argsize	= 0,
1341 		.pc_argzero	= 0,
1342 		.pc_ressize	= 0,
1343 		.pc_xdrressize	= XDR_void,
1344 		.pc_name	= "UNUSED",
1345 	},
1346 	[19] = {
1347 		.pc_func	= nlm4svc_proc_unused,
1348 		.pc_decode	= nlm4_svc_decode_void,
1349 		.pc_encode	= nlm4_svc_encode_void,
1350 		.pc_argsize	= 0,
1351 		.pc_argzero	= 0,
1352 		.pc_ressize	= 0,
1353 		.pc_xdrressize	= XDR_void,
1354 		.pc_name	= "UNUSED",
1355 	},
1356 	[NLMPROC4_SHARE] = {
1357 		.pc_func	= nlm4svc_proc_share,
1358 		.pc_decode	= nlm4_svc_decode_nlm4_shareargs,
1359 		.pc_encode	= nlm4_svc_encode_nlm4_shareres,
1360 		.pc_argsize	= sizeof(struct nlm4_shareargs_wrapper),
1361 		.pc_argzero	= 0,
1362 		.pc_ressize	= sizeof(struct nlm4_shareres_wrapper),
1363 		.pc_xdrressize	= NLM4_nlm4_shareres_sz,
1364 		.pc_name	= "SHARE",
1365 	},
1366 	[NLMPROC4_UNSHARE] = {
1367 		.pc_func	= nlm4svc_proc_unshare,
1368 		.pc_decode	= nlm4_svc_decode_nlm4_shareargs,
1369 		.pc_encode	= nlm4_svc_encode_nlm4_shareres,
1370 		.pc_argsize	= sizeof(struct nlm4_shareargs_wrapper),
1371 		.pc_argzero	= 0,
1372 		.pc_ressize	= sizeof(struct nlm4_shareres_wrapper),
1373 		.pc_xdrressize	= NLM4_nlm4_shareres_sz,
1374 		.pc_name	= "UNSHARE",
1375 	},
1376 	[NLMPROC4_NM_LOCK] = {
1377 		.pc_func	= nlm4svc_proc_nm_lock,
1378 		.pc_decode	= nlm4_svc_decode_nlm4_lockargs,
1379 		.pc_encode	= nlm4_svc_encode_nlm4_res,
1380 		.pc_argsize	= sizeof(struct nlm4_lockargs_wrapper),
1381 		.pc_argzero	= 0,
1382 		.pc_ressize	= sizeof(struct nlm4_res_wrapper),
1383 		.pc_xdrressize	= NLM4_nlm4_res_sz,
1384 		.pc_name	= "NM_LOCK",
1385 	},
1386 	[NLMPROC4_FREE_ALL] = {
1387 		.pc_func	= nlm4svc_proc_free_all,
1388 		.pc_decode	= nlm4_svc_decode_nlm4_notify,
1389 		.pc_encode	= nlm4_svc_encode_void,
1390 		.pc_argsize	= sizeof(struct nlm4_notify_wrapper),
1391 		.pc_argzero	= 0,
1392 		.pc_ressize	= 0,
1393 		.pc_xdrressize	= XDR_void,
1394 		.pc_name	= "FREE_ALL",
1395 	},
1396 };
1397 
1398 /*
1399  * Storage requirements for XDR arguments and results
1400  */
1401 union nlm4svc_xdrstore {
1402 	struct nlm4_testargs_wrapper	testargs;
1403 	struct nlm4_lockargs_wrapper	lockargs;
1404 	struct nlm4_cancargs_wrapper	cancargs;
1405 	struct nlm4_unlockargs_wrapper	unlockargs;
1406 	struct nlm4_notifyargs_wrapper	notifyargs;
1407 	struct nlm4_shareargs_wrapper	shareargs;
1408 	struct nlm4_notify_wrapper	notify;
1409 	struct nlm4_testres_wrapper	testres;
1410 	struct nlm4_res_wrapper		res;
1411 	struct nlm4_shareres_wrapper	shareres;
1412 };
1413 
1414 static DEFINE_PER_CPU_ALIGNED(unsigned long,
1415 			      nlm4svc_call_counters[ARRAY_SIZE(nlm4svc_procedures)]);
1416 
1417 const struct svc_version nlmsvc_version4 = {
1418 	.vs_vers	= 4,
1419 	.vs_nproc	= ARRAY_SIZE(nlm4svc_procedures),
1420 	.vs_proc	= nlm4svc_procedures,
1421 	.vs_count	= nlm4svc_call_counters,
1422 	.vs_dispatch	= nlmsvc_dispatch,
1423 	.vs_xdrsize	= sizeof(union nlm4svc_xdrstore),
1424 };
1425