xref: /linux/fs/lockd/svcproc.c (revision d141ec2825b4d3ec52f27c43bdd864090159273a)
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
nlm_netobj_to_cookie(struct lockd_cookie * cookie,netobj * object)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
nlm_lock_to_lockd_lock(struct lockd_lock * lock,struct nlm_lock * alock)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 *
nlm3svc_lookup_host(struct svc_rqst * rqstp,string caller,bool monitored)132 nlm3svc_lookup_host(struct svc_rqst *rqstp, string caller, bool monitored)
133 {
134 	struct nlm_host *host;
135 
136 	if (!rcu_access_pointer(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
nlm3svc_lookup_file(struct svc_rqst * rqstp,struct nlm_host * host,struct lockd_lock * lock,struct nlm_file ** filp,struct nlm_lock * xdr_lock,unsigned char type)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 
cast_status(__be32 status)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  */
nlmsvc_proc_null(struct svc_rqst * rqstp)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  */
nlmsvc_proc_test(struct svc_rqst * rqstp)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
nlmsvc_do_lock(struct svc_rqst * rqstp,bool monitored)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
nlmsvc_proc_lock(struct svc_rqst * rqstp)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
nlmsvc_proc_cancel(struct svc_rqst * rqstp)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
nlmsvc_proc_unlock(struct svc_rqst * rqstp)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
nlmsvc_proc_granted(struct svc_rqst * rqstp)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  */
nlmsvc_callback_exit(struct rpc_task * task,void * data)549 static void nlmsvc_callback_exit(struct rpc_task *task, void *data)
550 {
551 }
552 
nlmsvc_release_call(struct nlm_rqst * call)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 
nlmsvc_callback_release(void * data)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
nlmsvc_callback(struct svc_rqst * rqstp,struct nlm_host * host,u32 proc,__be32 (* func)(struct svc_rqst *,struct lockd_res *))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
__nlmsvc_proc_test_msg(struct svc_rqst * rqstp,struct lockd_res * resp)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  */
nlmsvc_proc_test_msg(struct svc_rqst * rqstp)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
__nlmsvc_proc_lock_msg(struct svc_rqst * rqstp,struct lockd_res * resp)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  */
nlmsvc_proc_lock_msg(struct svc_rqst * rqstp)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
__nlmsvc_proc_cancel_msg(struct svc_rqst * rqstp,struct lockd_res * resp)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  */
nlmsvc_proc_cancel_msg(struct svc_rqst * rqstp)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
__nlmsvc_proc_unlock_msg(struct svc_rqst * rqstp,struct lockd_res * resp)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  */
nlmsvc_proc_unlock_msg(struct svc_rqst * rqstp)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
__nlmsvc_proc_granted_msg(struct svc_rqst * rqstp,struct lockd_res * resp)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  */
nlmsvc_proc_granted_msg(struct svc_rqst * rqstp)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 = nlmsvc_lookup_host(rqstp, argp->xdrgen.alock.caller_name.data,
905 				  argp->xdrgen.alock.caller_name.len);
906 	if (!host)
907 		return rpc_system_err;
908 
909 	return nlmsvc_callback(rqstp, host, NLMPROC_GRANTED_RES,
910 			       __nlmsvc_proc_granted_msg);
911 }
912 
913 /**
914  * nlmsvc_proc_granted_res - GRANTED_RES: Lock Granted result
915  * @rqstp: RPC transaction context
916  *
917  * Returns:
918  *   %rpc_success:		RPC executed successfully.
919  *
920  * RPC synopsis:
921  *   void NLMPROC_GRANTED_RES(nlm_res) = 15;
922  */
nlmsvc_proc_granted_res(struct svc_rqst * rqstp)923 static __be32 nlmsvc_proc_granted_res(struct svc_rqst *rqstp)
924 {
925 	struct nlm_res_wrapper *argp = rqstp->rq_argp;
926 
927 	if (!rcu_access_pointer(nlmsvc_ops))
928 		return rpc_success;
929 
930 	if (nlm_netobj_to_cookie(&argp->cookie, &argp->xdrgen.cookie))
931 		return rpc_success;
932 	nlmsvc_grant_reply(&argp->cookie, argp->xdrgen.stat.stat);
933 
934 	return rpc_success;
935 }
936 
937 /**
938  * nlmsvc_proc_sm_notify - SM_NOTIFY: Peer has rebooted
939  * @rqstp: RPC transaction context
940  *
941  * Returns:
942  *   %rpc_success:		RPC executed successfully.
943  *   %rpc_system_err:		RPC execution failed.
944  *
945  * The SM_NOTIFY procedure is a private callback from Linux statd and is
946  * not part of the official NLM protocol.
947  *
948  * RPC synopsis:
949  *   void NLM_SM_NOTIFY(nlm_notifyargs) = 16;
950  */
nlmsvc_proc_sm_notify(struct svc_rqst * rqstp)951 static __be32 nlmsvc_proc_sm_notify(struct svc_rqst *rqstp)
952 {
953 	struct nlm_notifyargs_wrapper *argp = rqstp->rq_argp;
954 	struct lockd_reboot *reboot = &argp->reboot;
955 
956 	if (!nlm_privileged_requester(rqstp)) {
957 		char buf[RPC_MAX_ADDRBUFLEN];
958 
959 		pr_warn("lockd: rejected NSM callback from %s\n",
960 			svc_print_addr(rqstp, buf, sizeof(buf)));
961 		return rpc_system_err;
962 	}
963 
964 	reboot->len = argp->xdrgen.notify.name.len;
965 	reboot->mon = (char *)argp->xdrgen.notify.name.data;
966 	reboot->state = argp->xdrgen.notify.state;
967 	memcpy(&reboot->priv.data, argp->xdrgen.private,
968 	       sizeof(reboot->priv.data));
969 
970 	nlm_host_rebooted(SVC_NET(rqstp), reboot);
971 
972 	return rpc_success;
973 }
974 
975 /**
976  * nlmsvc_proc_unused - stub for unused procedures
977  * @rqstp: RPC transaction context
978  *
979  * Returns:
980  *   %rpc_proc_unavail:	Program can't support procedure.
981  */
nlmsvc_proc_unused(struct svc_rqst * rqstp)982 static __be32 nlmsvc_proc_unused(struct svc_rqst *rqstp)
983 {
984 	return rpc_proc_unavail;
985 }
986 
987 /**
988  * nlmsvc_proc_share - SHARE: Open a file using DOS file-sharing modes
989  * @rqstp: RPC transaction context
990  *
991  * Returns:
992  *   %rpc_success:		RPC executed successfully.
993  *   %rpc_drop_reply:		Do not send an RPC reply.
994  *
995  * RPC synopsis:
996  *   nlm_shareres NLM_SHARE(nlm_shareargs) = 20;
997  *
998  * Permissible procedure status codes:
999  *   %LCK_GRANTED:		The requested share lock was granted.
1000  *   %LCK_DENIED:		The requested lock conflicted with existing
1001  *				lock reservations for the file.
1002  *   %LCK_DENIED_GRACE_PERIOD:	The server has recently restarted and is
1003  *				re-establishing existing locks, and is not
1004  *				yet ready to accept normal service requests.
1005  *
1006  * The Linux NLM server implementation also returns:
1007  *   %LCK_DENIED_NOLOCKS:	A needed resource could not be allocated.
1008  */
nlmsvc_proc_share(struct svc_rqst * rqstp)1009 static __be32 nlmsvc_proc_share(struct svc_rqst *rqstp)
1010 {
1011 	struct nlm_shareargs_wrapper *argp = rqstp->rq_argp;
1012 	struct nlm_shareres_wrapper *resp = rqstp->rq_resp;
1013 	struct lockd_lock *lock = &argp->lock;
1014 	struct nlm_host	*host = NULL;
1015 	struct nlm_file	*file = NULL;
1016 	struct nlm_lock xdr_lock = {
1017 		.fh		= argp->xdrgen.share.fh,
1018 		.oh		= argp->xdrgen.share.oh,
1019 		.uppid		= LOCKD_SHARE_SVID,
1020 	};
1021 
1022 	resp->xdrgen.cookie = argp->xdrgen.cookie;
1023 
1024 	resp->xdrgen.stat = nlm_lck_denied_grace_period;
1025 	if (locks_in_grace(SVC_NET(rqstp)) && !argp->xdrgen.reclaim)
1026 		goto out;
1027 
1028 	resp->xdrgen.stat = nlm_lck_denied_nolocks;
1029 	host = nlm3svc_lookup_host(rqstp, argp->xdrgen.share.caller_name, false);
1030 	if (!host)
1031 		goto out;
1032 
1033 	resp->xdrgen.stat = nlm3svc_lookup_file(rqstp, host, lock, &file,
1034 						&xdr_lock, F_RDLCK);
1035 	if (resp->xdrgen.stat)
1036 		goto out;
1037 
1038 	resp->xdrgen.stat = nlmsvc_share_file(host, file, &lock->oh,
1039 					      argp->xdrgen.share.access,
1040 					      argp->xdrgen.share.mode);
1041 
1042 	nlmsvc_release_lockowner(lock);
1043 
1044 out:
1045 	if (file)
1046 		nlm_release_file(file);
1047 	nlmsvc_release_host(host);
1048 	return resp->xdrgen.stat == nlm__int__drop_reply ?
1049 		rpc_drop_reply : rpc_success;
1050 }
1051 
1052 /**
1053  * nlmsvc_proc_unshare - UNSHARE: Release a share reservation
1054  * @rqstp: RPC transaction context
1055  *
1056  * Returns:
1057  *   %rpc_success:		RPC executed successfully.
1058  *   %rpc_drop_reply:		Do not send an RPC reply.
1059  *
1060  * RPC synopsis:
1061  *   nlm_shareres NLM_UNSHARE(nlm_shareargs) = 21;
1062  *
1063  * Permissible procedure status codes:
1064  *   %LCK_GRANTED:		The share reservation was released.
1065  *   %LCK_DENIED_GRACE_PERIOD:	The server has recently restarted and is
1066  *				re-establishing existing locks, and is not
1067  *				yet ready to accept normal service requests.
1068  *
1069  * The Linux NLM server implementation also returns:
1070  *   %LCK_DENIED_NOLOCKS:	A needed resource could not be allocated.
1071  */
nlmsvc_proc_unshare(struct svc_rqst * rqstp)1072 static __be32 nlmsvc_proc_unshare(struct svc_rqst *rqstp)
1073 {
1074 	struct nlm_shareargs_wrapper *argp = rqstp->rq_argp;
1075 	struct nlm_shareres_wrapper *resp = rqstp->rq_resp;
1076 	struct lockd_lock *lock = &argp->lock;
1077 	struct nlm_lock xdr_lock = {
1078 		.fh		= argp->xdrgen.share.fh,
1079 		.oh		= argp->xdrgen.share.oh,
1080 		.uppid		= LOCKD_SHARE_SVID,
1081 	};
1082 	struct nlm_host	*host = NULL;
1083 	struct nlm_file	*file = NULL;
1084 
1085 	resp->xdrgen.cookie = argp->xdrgen.cookie;
1086 
1087 	resp->xdrgen.stat = nlm_lck_denied_grace_period;
1088 	if (locks_in_grace(SVC_NET(rqstp)))
1089 		goto out;
1090 
1091 	resp->xdrgen.stat = nlm_lck_denied_nolocks;
1092 	host = nlm3svc_lookup_host(rqstp, argp->xdrgen.share.caller_name, false);
1093 	if (!host)
1094 		goto out;
1095 
1096 	resp->xdrgen.stat = nlm3svc_lookup_file(rqstp, host, lock, &file,
1097 						&xdr_lock, F_RDLCK);
1098 	if (resp->xdrgen.stat)
1099 		goto out;
1100 
1101 	resp->xdrgen.stat = nlmsvc_unshare_file(host, file, &lock->oh,
1102 						argp->xdrgen.share.access,
1103 						argp->xdrgen.share.mode);
1104 
1105 	nlmsvc_release_lockowner(lock);
1106 
1107 out:
1108 	if (file)
1109 		nlm_release_file(file);
1110 	nlmsvc_release_host(host);
1111 	return resp->xdrgen.stat == nlm__int__drop_reply ?
1112 		rpc_drop_reply : rpc_success;
1113 }
1114 
1115 /**
1116  * nlmsvc_proc_nm_lock - NM_LOCK: Establish a non-monitored lock
1117  * @rqstp: RPC transaction context
1118  *
1119  * Returns:
1120  *   %rpc_success:		RPC executed successfully.
1121  *   %rpc_drop_reply:		Do not send an RPC reply.
1122  *
1123  * RPC synopsis:
1124  *   nlm_res NLM_NM_LOCK(nlm_lockargs) = 22;
1125  *
1126  * Permissible procedure status codes:
1127  *   %LCK_GRANTED:		The requested lock was granted.
1128  *   %LCK_DENIED:		The requested lock conflicted with existing
1129  *				lock reservations for the file.
1130  *   %LCK_DENIED_NOLOCKS:	The server could not allocate the resources
1131  *				needed to process the request.
1132  *   %LCK_BLOCKED:		The blocking request cannot be granted
1133  *				immediately. The server will send an
1134  *				NLM_GRANTED callback to the client when
1135  *				the lock can be granted.
1136  *   %LCK_DENIED_GRACE_PERIOD:	The server has recently restarted and is
1137  *				re-establishing existing locks, and is not
1138  *				yet ready to accept normal service requests.
1139  */
nlmsvc_proc_nm_lock(struct svc_rqst * rqstp)1140 static __be32 nlmsvc_proc_nm_lock(struct svc_rqst *rqstp)
1141 {
1142 	return nlmsvc_do_lock(rqstp, false);
1143 }
1144 
1145 /**
1146  * nlmsvc_proc_free_all - FREE_ALL: Discard client's lock and share state
1147  * @rqstp: RPC transaction context
1148  *
1149  * Returns:
1150  *   %rpc_success:		RPC executed successfully.
1151  *
1152  * RPC synopsis:
1153  *   void NLMPROC_FREE_ALL(nlm_notify) = 23;
1154  */
nlmsvc_proc_free_all(struct svc_rqst * rqstp)1155 static __be32 nlmsvc_proc_free_all(struct svc_rqst *rqstp)
1156 {
1157 	struct nlm_notify_wrapper *argp = rqstp->rq_argp;
1158 	struct nlm_host	*host;
1159 
1160 	host = nlm3svc_lookup_host(rqstp, argp->xdrgen.name, false);
1161 	if (!host)
1162 		goto out;
1163 
1164 	nlmsvc_free_host_resources(host);
1165 
1166 	nlmsvc_release_host(host);
1167 
1168 out:
1169 	return rpc_success;
1170 }
1171 
1172 /*
1173  * NLMv3 Server procedures.
1174  */
1175 
1176 static const struct svc_procedure nlmsvc_procedures[24] = {
1177 	[NLM_NULL] = {
1178 		.pc_func	= nlmsvc_proc_null,
1179 		.pc_decode	= xdrgen_svc_decode_void,
1180 		.pc_encode	= xdrgen_svc_encode_void,
1181 		.pc_argsize	= XDR_void,
1182 		.pc_argzero	= 0,
1183 		.pc_ressize	= 0,
1184 		.pc_xdrressize	= XDR_void,
1185 		.pc_name	= "NULL",
1186 	},
1187 	[NLM_TEST] = {
1188 		.pc_func	= nlmsvc_proc_test,
1189 		.pc_decode	= nlm_svc_decode_nlm_testargs,
1190 		.pc_encode	= nlm_svc_encode_nlm_testres,
1191 		.pc_argsize	= sizeof(struct nlm_testargs_wrapper),
1192 		.pc_argzero	= 0,
1193 		.pc_ressize	= sizeof(struct nlm_testres_wrapper),
1194 		.pc_xdrressize	= NLM3_nlm_testres_sz,
1195 		.pc_name	= "TEST",
1196 	},
1197 	[NLM_LOCK] = {
1198 		.pc_func	= nlmsvc_proc_lock,
1199 		.pc_decode	= nlm_svc_decode_nlm_lockargs,
1200 		.pc_encode	= nlm_svc_encode_nlm_res,
1201 		.pc_argsize	= sizeof(struct nlm_lockargs_wrapper),
1202 		.pc_argzero	= 0,
1203 		.pc_ressize	= sizeof(struct nlm_res_wrapper),
1204 		.pc_xdrressize	= NLM3_nlm_res_sz,
1205 		.pc_name	= "LOCK",
1206 	},
1207 	[NLM_CANCEL] = {
1208 		.pc_func	= nlmsvc_proc_cancel,
1209 		.pc_decode	= nlm_svc_decode_nlm_cancargs,
1210 		.pc_encode	= nlm_svc_encode_nlm_res,
1211 		.pc_argsize	= sizeof(struct nlm_cancargs_wrapper),
1212 		.pc_argzero	= 0,
1213 		.pc_ressize	= sizeof(struct nlm_res_wrapper),
1214 		.pc_xdrressize	= NLM3_nlm_res_sz,
1215 		.pc_name	= "CANCEL",
1216 	},
1217 	[NLM_UNLOCK] = {
1218 		.pc_func	= nlmsvc_proc_unlock,
1219 		.pc_decode	= nlm_svc_decode_nlm_unlockargs,
1220 		.pc_encode	= nlm_svc_encode_nlm_res,
1221 		.pc_argsize	= sizeof(struct nlm_unlockargs_wrapper),
1222 		.pc_argzero	= 0,
1223 		.pc_ressize	= sizeof(struct nlm_res_wrapper),
1224 		.pc_xdrressize	= NLM3_nlm_res_sz,
1225 		.pc_name	= "UNLOCK",
1226 	},
1227 	[NLM_GRANTED] = {
1228 		.pc_func	= nlmsvc_proc_granted,
1229 		.pc_decode	= nlm_svc_decode_nlm_testargs,
1230 		.pc_encode	= nlm_svc_encode_nlm_res,
1231 		.pc_argsize	= sizeof(struct nlm_testargs_wrapper),
1232 		.pc_argzero	= 0,
1233 		.pc_ressize	= sizeof(struct nlm_res_wrapper),
1234 		.pc_xdrressize	= NLM3_nlm_res_sz,
1235 		.pc_name	= "GRANTED",
1236 	},
1237 	[NLM_TEST_MSG] = {
1238 		.pc_func	= nlmsvc_proc_test_msg,
1239 		.pc_decode	= nlm_svc_decode_nlm_testargs,
1240 		.pc_encode	= xdrgen_svc_encode_void,
1241 		.pc_argsize	= sizeof(struct nlm_testargs_wrapper),
1242 		.pc_argzero	= 0,
1243 		.pc_ressize	= 0,
1244 		.pc_xdrressize	= XDR_void,
1245 		.pc_name	= "TEST_MSG",
1246 	},
1247 	[NLM_LOCK_MSG] = {
1248 		.pc_func	= nlmsvc_proc_lock_msg,
1249 		.pc_decode	= nlm_svc_decode_nlm_lockargs,
1250 		.pc_encode	= xdrgen_svc_encode_void,
1251 		.pc_argsize	= sizeof(struct nlm_lockargs_wrapper),
1252 		.pc_argzero	= 0,
1253 		.pc_ressize	= 0,
1254 		.pc_xdrressize	= XDR_void,
1255 		.pc_name	= "LOCK_MSG",
1256 	},
1257 	[NLM_CANCEL_MSG] = {
1258 		.pc_func	= nlmsvc_proc_cancel_msg,
1259 		.pc_decode	= nlm_svc_decode_nlm_cancargs,
1260 		.pc_encode	= xdrgen_svc_encode_void,
1261 		.pc_argsize	= sizeof(struct nlm_cancargs_wrapper),
1262 		.pc_argzero	= 0,
1263 		.pc_ressize	= 0,
1264 		.pc_xdrressize	= XDR_void,
1265 		.pc_name	= "CANCEL_MSG",
1266 	},
1267 	[NLM_UNLOCK_MSG] = {
1268 		.pc_func	= nlmsvc_proc_unlock_msg,
1269 		.pc_decode	= nlm_svc_decode_nlm_unlockargs,
1270 		.pc_encode	= xdrgen_svc_encode_void,
1271 		.pc_argsize	= sizeof(struct nlm_unlockargs_wrapper),
1272 		.pc_argzero	= 0,
1273 		.pc_ressize	= 0,
1274 		.pc_xdrressize	= XDR_void,
1275 		.pc_name	= "UNLOCK_MSG",
1276 	},
1277 	[NLM_GRANTED_MSG] = {
1278 		.pc_func	= nlmsvc_proc_granted_msg,
1279 		.pc_decode	= nlm_svc_decode_nlm_testargs,
1280 		.pc_encode	= xdrgen_svc_encode_void,
1281 		.pc_argsize	= sizeof(struct nlm_testargs_wrapper),
1282 		.pc_argzero	= 0,
1283 		.pc_ressize	= 0,
1284 		.pc_xdrressize	= XDR_void,
1285 		.pc_name	= "GRANTED_MSG",
1286 	},
1287 	[NLM_TEST_RES] = {
1288 		.pc_func	= nlmsvc_proc_null,
1289 		.pc_decode	= nlm_svc_decode_nlm_testres,
1290 		.pc_encode	= xdrgen_svc_encode_void,
1291 		.pc_argsize	= sizeof(struct nlm_testres),
1292 		.pc_argzero	= 0,
1293 		.pc_ressize	= 0,
1294 		.pc_xdrressize	= XDR_void,
1295 		.pc_name	= "TEST_RES",
1296 	},
1297 	[NLM_LOCK_RES] = {
1298 		.pc_func	= nlmsvc_proc_null,
1299 		.pc_decode	= nlm_svc_decode_nlm_res,
1300 		.pc_encode	= xdrgen_svc_encode_void,
1301 		.pc_argsize	= sizeof(struct nlm_res),
1302 		.pc_argzero	= 0,
1303 		.pc_ressize	= 0,
1304 		.pc_xdrressize	= XDR_void,
1305 		.pc_name	= "LOCK_RES",
1306 	},
1307 	[NLM_CANCEL_RES] = {
1308 		.pc_func	= nlmsvc_proc_null,
1309 		.pc_decode	= nlm_svc_decode_nlm_res,
1310 		.pc_encode	= xdrgen_svc_encode_void,
1311 		.pc_argsize	= sizeof(struct nlm_res),
1312 		.pc_argzero	= 0,
1313 		.pc_ressize	= 0,
1314 		.pc_xdrressize	= XDR_void,
1315 		.pc_name	= "CANCEL_RES",
1316 	},
1317 	[NLM_UNLOCK_RES] = {
1318 		.pc_func	= nlmsvc_proc_null,
1319 		.pc_decode	= nlm_svc_decode_nlm_res,
1320 		.pc_encode	= xdrgen_svc_encode_void,
1321 		.pc_argsize	= sizeof(struct nlm_res),
1322 		.pc_argzero	= 0,
1323 		.pc_ressize	= 0,
1324 		.pc_xdrressize	= XDR_void,
1325 		.pc_name	= "UNLOCK_RES",
1326 	},
1327 	[NLM_GRANTED_RES] = {
1328 		.pc_func	= nlmsvc_proc_granted_res,
1329 		.pc_decode	= nlm_svc_decode_nlm_res,
1330 		.pc_encode	= xdrgen_svc_encode_void,
1331 		.pc_argsize	= sizeof(struct nlm_res_wrapper),
1332 		.pc_argzero	= 0,
1333 		.pc_ressize	= 0,
1334 		.pc_xdrressize	= XDR_void,
1335 		.pc_name	= "GRANTED_RES",
1336 	},
1337 	[NLM_SM_NOTIFY] = {
1338 		.pc_func	= nlmsvc_proc_sm_notify,
1339 		.pc_decode	= nlm_svc_decode_nlm_notifyargs,
1340 		.pc_encode	= xdrgen_svc_encode_void,
1341 		.pc_argsize	= sizeof(struct nlm_notifyargs_wrapper),
1342 		.pc_argzero	= 0,
1343 		.pc_ressize	= 0,
1344 		.pc_xdrressize	= XDR_void,
1345 		.pc_name	= "SM_NOTIFY",
1346 	},
1347 	[17] = {
1348 		.pc_func	= nlmsvc_proc_unused,
1349 		.pc_decode	= xdrgen_svc_decode_void,
1350 		.pc_encode	= xdrgen_svc_encode_void,
1351 		.pc_argsize	= 0,
1352 		.pc_argzero	= 0,
1353 		.pc_ressize	= 0,
1354 		.pc_xdrressize	= XDR_void,
1355 		.pc_name	= "UNUSED",
1356 	},
1357 	[18] = {
1358 		.pc_func	= nlmsvc_proc_unused,
1359 		.pc_decode	= xdrgen_svc_decode_void,
1360 		.pc_encode	= xdrgen_svc_encode_void,
1361 		.pc_argsize	= 0,
1362 		.pc_argzero	= 0,
1363 		.pc_ressize	= 0,
1364 		.pc_xdrressize	= XDR_void,
1365 		.pc_name	= "UNUSED",
1366 	},
1367 	[19] = {
1368 		.pc_func	= nlmsvc_proc_unused,
1369 		.pc_decode	= xdrgen_svc_decode_void,
1370 		.pc_encode	= xdrgen_svc_encode_void,
1371 		.pc_argsize	= 0,
1372 		.pc_argzero	= 0,
1373 		.pc_ressize	= 0,
1374 		.pc_xdrressize	= XDR_void,
1375 		.pc_name	= "UNUSED",
1376 	},
1377 	[NLM_SHARE] = {
1378 		.pc_func	= nlmsvc_proc_share,
1379 		.pc_decode	= nlm_svc_decode_nlm_shareargs,
1380 		.pc_encode	= nlm_svc_encode_nlm_shareres,
1381 		.pc_argsize	= sizeof(struct nlm_shareargs_wrapper),
1382 		.pc_argzero	= 0,
1383 		.pc_ressize	= sizeof(struct nlm_shareres_wrapper),
1384 		.pc_xdrressize	= NLM3_nlm_shareres_sz,
1385 		.pc_name	= "SHARE",
1386 	},
1387 	[NLM_UNSHARE] = {
1388 		.pc_func	= nlmsvc_proc_unshare,
1389 		.pc_decode	= nlm_svc_decode_nlm_shareargs,
1390 		.pc_encode	= nlm_svc_encode_nlm_shareres,
1391 		.pc_argsize	= sizeof(struct nlm_shareargs_wrapper),
1392 		.pc_argzero	= 0,
1393 		.pc_ressize	= sizeof(struct nlm_shareres_wrapper),
1394 		.pc_xdrressize	= NLM3_nlm_shareres_sz,
1395 		.pc_name	= "UNSHARE",
1396 	},
1397 	[NLM_NM_LOCK] = {
1398 		.pc_func	= nlmsvc_proc_nm_lock,
1399 		.pc_decode	= nlm_svc_decode_nlm_lockargs,
1400 		.pc_encode	= nlm_svc_encode_nlm_res,
1401 		.pc_argsize	= sizeof(struct nlm_lockargs_wrapper),
1402 		.pc_argzero	= 0,
1403 		.pc_ressize	= sizeof(struct nlm_res_wrapper),
1404 		.pc_xdrressize	= NLM3_nlm_res_sz,
1405 		.pc_name	= "NM_LOCK",
1406 	},
1407 	[NLM_FREE_ALL] = {
1408 		.pc_func	= nlmsvc_proc_free_all,
1409 		.pc_decode	= nlm_svc_decode_nlm_notify,
1410 		.pc_encode	= xdrgen_svc_encode_void,
1411 		.pc_argsize	= sizeof(struct nlm_notify_wrapper),
1412 		.pc_argzero	= 0,
1413 		.pc_ressize	= 0,
1414 		.pc_xdrressize	= XDR_void,
1415 		.pc_name	= "FREE_ALL",
1416 	},
1417 };
1418 
1419 /*
1420  * Storage requirements for XDR arguments and results
1421  */
1422 union nlmsvc_xdrstore {
1423 	struct nlm_testargs_wrapper	testargs;
1424 	struct nlm_lockargs_wrapper	lockargs;
1425 	struct nlm_cancargs_wrapper	cancargs;
1426 	struct nlm_unlockargs_wrapper	unlockargs;
1427 	struct nlm_notifyargs_wrapper	notifyargs;
1428 	struct nlm_shareargs_wrapper	shareargs;
1429 	struct nlm_notify_wrapper	notify;
1430 	struct nlm_testres_wrapper	testres;
1431 	struct nlm_res_wrapper		res;
1432 	struct nlm_shareres_wrapper	shareres;
1433 };
1434 
1435 /*
1436  * NLMv1 defines only procedures 1 - 15. Linux lockd also implements
1437  * procedures 0 (NULL) and 16 (SM_NOTIFY).
1438  */
1439 const struct svc_version nlmsvc_version1 = {
1440 	.vs_vers	= 1,
1441 	.vs_nproc	= 17,
1442 	.vs_proc	= nlmsvc_procedures,
1443 	.vs_dispatch	= nlmsvc_dispatch,
1444 	.vs_xdrsize	= sizeof(union nlmsvc_xdrstore),
1445 };
1446 
1447 const struct svc_version nlmsvc_version3 = {
1448 	.vs_vers	= 3,
1449 	.vs_nproc	= ARRAY_SIZE(nlmsvc_procedures),
1450 	.vs_proc	= nlmsvc_procedures,
1451 	.vs_dispatch	= nlmsvc_dispatch,
1452 	.vs_xdrsize	= sizeof(union nlmsvc_xdrstore),
1453 };
1454