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