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