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