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