perf stat aggregation: Add separate die member
[linux-2.6-microblaze.git] / fs / lockd / clntxdr.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * linux/fs/lockd/clntxdr.c
4  *
5  * XDR functions to encode/decode NLM version 3 RPC arguments and results.
6  * NLM version 3 is backwards compatible with NLM versions 1 and 2.
7  *
8  * NLM client-side only.
9  *
10  * Copyright (C) 2010, Oracle.  All rights reserved.
11  */
12
13 #include <linux/types.h>
14 #include <linux/sunrpc/xdr.h>
15 #include <linux/sunrpc/clnt.h>
16 #include <linux/sunrpc/stats.h>
17 #include <linux/lockd/lockd.h>
18
19 #include <uapi/linux/nfs2.h>
20
21 #define NLMDBG_FACILITY         NLMDBG_XDR
22
23 #if (NLMCLNT_OHSIZE > XDR_MAX_NETOBJ)
24 #  error "NLM host name cannot be larger than XDR_MAX_NETOBJ!"
25 #endif
26
27 /*
28  * Declare the space requirements for NLM arguments and replies as
29  * number of 32bit-words
30  */
31 #define NLM_cookie_sz           (1+(NLM_MAXCOOKIELEN>>2))
32 #define NLM_caller_sz           (1+(NLMCLNT_OHSIZE>>2))
33 #define NLM_owner_sz            (1+(NLMCLNT_OHSIZE>>2))
34 #define NLM_fhandle_sz          (1+(NFS2_FHSIZE>>2))
35 #define NLM_lock_sz             (3+NLM_caller_sz+NLM_owner_sz+NLM_fhandle_sz)
36 #define NLM_holder_sz           (4+NLM_owner_sz)
37
38 #define NLM_testargs_sz         (NLM_cookie_sz+1+NLM_lock_sz)
39 #define NLM_lockargs_sz         (NLM_cookie_sz+4+NLM_lock_sz)
40 #define NLM_cancargs_sz         (NLM_cookie_sz+2+NLM_lock_sz)
41 #define NLM_unlockargs_sz       (NLM_cookie_sz+NLM_lock_sz)
42
43 #define NLM_testres_sz          (NLM_cookie_sz+1+NLM_holder_sz)
44 #define NLM_res_sz              (NLM_cookie_sz+1)
45 #define NLM_norep_sz            (0)
46
47
48 static s32 loff_t_to_s32(loff_t offset)
49 {
50         s32 res;
51
52         if (offset >= NLM_OFFSET_MAX)
53                 res = NLM_OFFSET_MAX;
54         else if (offset <= -NLM_OFFSET_MAX)
55                 res = -NLM_OFFSET_MAX;
56         else
57                 res = offset;
58         return res;
59 }
60
61 static void nlm_compute_offsets(const struct nlm_lock *lock,
62                                 u32 *l_offset, u32 *l_len)
63 {
64         const struct file_lock *fl = &lock->fl;
65
66         *l_offset = loff_t_to_s32(fl->fl_start);
67         if (fl->fl_end == OFFSET_MAX)
68                 *l_len = 0;
69         else
70                 *l_len = loff_t_to_s32(fl->fl_end - fl->fl_start + 1);
71 }
72
73 /*
74  * Encode/decode NLMv3 basic data types
75  *
76  * Basic NLMv3 data types are not defined in an IETF standards
77  * document.  X/Open has a description of these data types that
78  * is useful.  See Chapter 10 of "Protocols for Interworking:
79  * XNFS, Version 3W".
80  *
81  * Not all basic data types have their own encoding and decoding
82  * functions.  For run-time efficiency, some data types are encoded
83  * or decoded inline.
84  */
85
86 static void encode_bool(struct xdr_stream *xdr, const int value)
87 {
88         __be32 *p;
89
90         p = xdr_reserve_space(xdr, 4);
91         *p = value ? xdr_one : xdr_zero;
92 }
93
94 static void encode_int32(struct xdr_stream *xdr, const s32 value)
95 {
96         __be32 *p;
97
98         p = xdr_reserve_space(xdr, 4);
99         *p = cpu_to_be32(value);
100 }
101
102 /*
103  *      typedef opaque netobj<MAXNETOBJ_SZ>
104  */
105 static void encode_netobj(struct xdr_stream *xdr,
106                           const u8 *data, const unsigned int length)
107 {
108         __be32 *p;
109
110         p = xdr_reserve_space(xdr, 4 + length);
111         xdr_encode_opaque(p, data, length);
112 }
113
114 static int decode_netobj(struct xdr_stream *xdr,
115                          struct xdr_netobj *obj)
116 {
117         ssize_t ret;
118
119         ret = xdr_stream_decode_opaque_inline(xdr, (void *)&obj->data,
120                         XDR_MAX_NETOBJ);
121         if (unlikely(ret < 0))
122                 return -EIO;
123         obj->len = ret;
124         return 0;
125 }
126
127 /*
128  *      netobj cookie;
129  */
130 static void encode_cookie(struct xdr_stream *xdr,
131                           const struct nlm_cookie *cookie)
132 {
133         encode_netobj(xdr, (u8 *)&cookie->data, cookie->len);
134 }
135
136 static int decode_cookie(struct xdr_stream *xdr,
137                          struct nlm_cookie *cookie)
138 {
139         u32 length;
140         __be32 *p;
141
142         p = xdr_inline_decode(xdr, 4);
143         if (unlikely(p == NULL))
144                 goto out_overflow;
145         length = be32_to_cpup(p++);
146         /* apparently HPUX can return empty cookies */
147         if (length == 0)
148                 goto out_hpux;
149         if (length > NLM_MAXCOOKIELEN)
150                 goto out_size;
151         p = xdr_inline_decode(xdr, length);
152         if (unlikely(p == NULL))
153                 goto out_overflow;
154         cookie->len = length;
155         memcpy(cookie->data, p, length);
156         return 0;
157 out_hpux:
158         cookie->len = 4;
159         memset(cookie->data, 0, 4);
160         return 0;
161 out_size:
162         dprintk("NFS: returned cookie was too long: %u\n", length);
163         return -EIO;
164 out_overflow:
165         return -EIO;
166 }
167
168 /*
169  *      netobj fh;
170  */
171 static void encode_fh(struct xdr_stream *xdr, const struct nfs_fh *fh)
172 {
173         encode_netobj(xdr, (u8 *)&fh->data, NFS2_FHSIZE);
174 }
175
176 /*
177  *      enum nlm_stats {
178  *              LCK_GRANTED = 0,
179  *              LCK_DENIED = 1,
180  *              LCK_DENIED_NOLOCKS = 2,
181  *              LCK_BLOCKED = 3,
182  *              LCK_DENIED_GRACE_PERIOD = 4
183  *      };
184  *
185  *
186  *      struct nlm_stat {
187  *              nlm_stats stat;
188  *      };
189  *
190  * NB: we don't swap bytes for the NLM status values.  The upper
191  * layers deal directly with the status value in network byte
192  * order.
193  */
194
195 static void encode_nlm_stat(struct xdr_stream *xdr,
196                             const __be32 stat)
197 {
198         __be32 *p;
199
200         WARN_ON_ONCE(be32_to_cpu(stat) > NLM_LCK_DENIED_GRACE_PERIOD);
201         p = xdr_reserve_space(xdr, 4);
202         *p = stat;
203 }
204
205 static int decode_nlm_stat(struct xdr_stream *xdr,
206                            __be32 *stat)
207 {
208         __be32 *p;
209
210         p = xdr_inline_decode(xdr, 4);
211         if (unlikely(p == NULL))
212                 goto out_overflow;
213         if (unlikely(ntohl(*p) > ntohl(nlm_lck_denied_grace_period)))
214                 goto out_enum;
215         *stat = *p;
216         return 0;
217 out_enum:
218         dprintk("%s: server returned invalid nlm_stats value: %u\n",
219                 __func__, be32_to_cpup(p));
220         return -EIO;
221 out_overflow:
222         return -EIO;
223 }
224
225 /*
226  *      struct nlm_holder {
227  *              bool exclusive;
228  *              int uppid;
229  *              netobj oh;
230  *              unsigned l_offset;
231  *              unsigned l_len;
232  *      };
233  */
234 static void encode_nlm_holder(struct xdr_stream *xdr,
235                               const struct nlm_res *result)
236 {
237         const struct nlm_lock *lock = &result->lock;
238         u32 l_offset, l_len;
239         __be32 *p;
240
241         encode_bool(xdr, lock->fl.fl_type == F_RDLCK);
242         encode_int32(xdr, lock->svid);
243         encode_netobj(xdr, lock->oh.data, lock->oh.len);
244
245         p = xdr_reserve_space(xdr, 4 + 4);
246         nlm_compute_offsets(lock, &l_offset, &l_len);
247         *p++ = cpu_to_be32(l_offset);
248         *p   = cpu_to_be32(l_len);
249 }
250
251 static int decode_nlm_holder(struct xdr_stream *xdr, struct nlm_res *result)
252 {
253         struct nlm_lock *lock = &result->lock;
254         struct file_lock *fl = &lock->fl;
255         u32 exclusive, l_offset, l_len;
256         int error;
257         __be32 *p;
258         s32 end;
259
260         memset(lock, 0, sizeof(*lock));
261         locks_init_lock(fl);
262
263         p = xdr_inline_decode(xdr, 4 + 4);
264         if (unlikely(p == NULL))
265                 goto out_overflow;
266         exclusive = be32_to_cpup(p++);
267         lock->svid = be32_to_cpup(p);
268         fl->fl_pid = (pid_t)lock->svid;
269
270         error = decode_netobj(xdr, &lock->oh);
271         if (unlikely(error))
272                 goto out;
273
274         p = xdr_inline_decode(xdr, 4 + 4);
275         if (unlikely(p == NULL))
276                 goto out_overflow;
277
278         fl->fl_flags = FL_POSIX;
279         fl->fl_type  = exclusive != 0 ? F_WRLCK : F_RDLCK;
280         l_offset = be32_to_cpup(p++);
281         l_len = be32_to_cpup(p);
282         end = l_offset + l_len - 1;
283
284         fl->fl_start = (loff_t)l_offset;
285         if (l_len == 0 || end < 0)
286                 fl->fl_end = OFFSET_MAX;
287         else
288                 fl->fl_end = (loff_t)end;
289         error = 0;
290 out:
291         return error;
292 out_overflow:
293         return -EIO;
294 }
295
296 /*
297  *      string caller_name<LM_MAXSTRLEN>;
298  */
299 static void encode_caller_name(struct xdr_stream *xdr, const char *name)
300 {
301         /* NB: client-side does not set lock->len */
302         u32 length = strlen(name);
303         __be32 *p;
304
305         p = xdr_reserve_space(xdr, 4 + length);
306         xdr_encode_opaque(p, name, length);
307 }
308
309 /*
310  *      struct nlm_lock {
311  *              string caller_name<LM_MAXSTRLEN>;
312  *              netobj fh;
313  *              netobj oh;
314  *              int uppid;
315  *              unsigned l_offset;
316  *              unsigned l_len;
317  *      };
318  */
319 static void encode_nlm_lock(struct xdr_stream *xdr,
320                             const struct nlm_lock *lock)
321 {
322         u32 l_offset, l_len;
323         __be32 *p;
324
325         encode_caller_name(xdr, lock->caller);
326         encode_fh(xdr, &lock->fh);
327         encode_netobj(xdr, lock->oh.data, lock->oh.len);
328
329         p = xdr_reserve_space(xdr, 4 + 4 + 4);
330         *p++ = cpu_to_be32(lock->svid);
331
332         nlm_compute_offsets(lock, &l_offset, &l_len);
333         *p++ = cpu_to_be32(l_offset);
334         *p   = cpu_to_be32(l_len);
335 }
336
337
338 /*
339  * NLMv3 XDR encode functions
340  *
341  * NLMv3 argument types are defined in Chapter 10 of The Open Group's
342  * "Protocols for Interworking: XNFS, Version 3W".
343  */
344
345 /*
346  *      struct nlm_testargs {
347  *              netobj cookie;
348  *              bool exclusive;
349  *              struct nlm_lock alock;
350  *      };
351  */
352 static void nlm_xdr_enc_testargs(struct rpc_rqst *req,
353                                  struct xdr_stream *xdr,
354                                  const void *data)
355 {
356         const struct nlm_args *args = data;
357         const struct nlm_lock *lock = &args->lock;
358
359         encode_cookie(xdr, &args->cookie);
360         encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
361         encode_nlm_lock(xdr, lock);
362 }
363
364 /*
365  *      struct nlm_lockargs {
366  *              netobj cookie;
367  *              bool block;
368  *              bool exclusive;
369  *              struct nlm_lock alock;
370  *              bool reclaim;
371  *              int state;
372  *      };
373  */
374 static void nlm_xdr_enc_lockargs(struct rpc_rqst *req,
375                                  struct xdr_stream *xdr,
376                                  const void *data)
377 {
378         const struct nlm_args *args = data;
379         const struct nlm_lock *lock = &args->lock;
380
381         encode_cookie(xdr, &args->cookie);
382         encode_bool(xdr, args->block);
383         encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
384         encode_nlm_lock(xdr, lock);
385         encode_bool(xdr, args->reclaim);
386         encode_int32(xdr, args->state);
387 }
388
389 /*
390  *      struct nlm_cancargs {
391  *              netobj cookie;
392  *              bool block;
393  *              bool exclusive;
394  *              struct nlm_lock alock;
395  *      };
396  */
397 static void nlm_xdr_enc_cancargs(struct rpc_rqst *req,
398                                  struct xdr_stream *xdr,
399                                  const void *data)
400 {
401         const struct nlm_args *args = data;
402         const struct nlm_lock *lock = &args->lock;
403
404         encode_cookie(xdr, &args->cookie);
405         encode_bool(xdr, args->block);
406         encode_bool(xdr, lock->fl.fl_type == F_WRLCK);
407         encode_nlm_lock(xdr, lock);
408 }
409
410 /*
411  *      struct nlm_unlockargs {
412  *              netobj cookie;
413  *              struct nlm_lock alock;
414  *      };
415  */
416 static void nlm_xdr_enc_unlockargs(struct rpc_rqst *req,
417                                    struct xdr_stream *xdr,
418                                    const void *data)
419 {
420         const struct nlm_args *args = data;
421         const struct nlm_lock *lock = &args->lock;
422
423         encode_cookie(xdr, &args->cookie);
424         encode_nlm_lock(xdr, lock);
425 }
426
427 /*
428  *      struct nlm_res {
429  *              netobj cookie;
430  *              nlm_stat stat;
431  *      };
432  */
433 static void nlm_xdr_enc_res(struct rpc_rqst *req,
434                             struct xdr_stream *xdr,
435                             const void *data)
436 {
437         const struct nlm_res *result = data;
438
439         encode_cookie(xdr, &result->cookie);
440         encode_nlm_stat(xdr, result->status);
441 }
442
443 /*
444  *      union nlm_testrply switch (nlm_stats stat) {
445  *      case LCK_DENIED:
446  *              struct nlm_holder holder;
447  *      default:
448  *              void;
449  *      };
450  *
451  *      struct nlm_testres {
452  *              netobj cookie;
453  *              nlm_testrply test_stat;
454  *      };
455  */
456 static void encode_nlm_testrply(struct xdr_stream *xdr,
457                                 const struct nlm_res *result)
458 {
459         if (result->status == nlm_lck_denied)
460                 encode_nlm_holder(xdr, result);
461 }
462
463 static void nlm_xdr_enc_testres(struct rpc_rqst *req,
464                                 struct xdr_stream *xdr,
465                                 const void *data)
466 {
467         const struct nlm_res *result = data;
468
469         encode_cookie(xdr, &result->cookie);
470         encode_nlm_stat(xdr, result->status);
471         encode_nlm_testrply(xdr, result);
472 }
473
474
475 /*
476  * NLMv3 XDR decode functions
477  *
478  * NLMv3 result types are defined in Chapter 10 of The Open Group's
479  * "Protocols for Interworking: XNFS, Version 3W".
480  */
481
482 /*
483  *      union nlm_testrply switch (nlm_stats stat) {
484  *      case LCK_DENIED:
485  *              struct nlm_holder holder;
486  *      default:
487  *              void;
488  *      };
489  *
490  *      struct nlm_testres {
491  *              netobj cookie;
492  *              nlm_testrply test_stat;
493  *      };
494  */
495 static int decode_nlm_testrply(struct xdr_stream *xdr,
496                                struct nlm_res *result)
497 {
498         int error;
499
500         error = decode_nlm_stat(xdr, &result->status);
501         if (unlikely(error))
502                 goto out;
503         if (result->status == nlm_lck_denied)
504                 error = decode_nlm_holder(xdr, result);
505 out:
506         return error;
507 }
508
509 static int nlm_xdr_dec_testres(struct rpc_rqst *req,
510                                struct xdr_stream *xdr,
511                                void *data)
512 {
513         struct nlm_res *result = data;
514         int error;
515
516         error = decode_cookie(xdr, &result->cookie);
517         if (unlikely(error))
518                 goto out;
519         error = decode_nlm_testrply(xdr, result);
520 out:
521         return error;
522 }
523
524 /*
525  *      struct nlm_res {
526  *              netobj cookie;
527  *              nlm_stat stat;
528  *      };
529  */
530 static int nlm_xdr_dec_res(struct rpc_rqst *req,
531                            struct xdr_stream *xdr,
532                            void *data)
533 {
534         struct nlm_res *result = data;
535         int error;
536
537         error = decode_cookie(xdr, &result->cookie);
538         if (unlikely(error))
539                 goto out;
540         error = decode_nlm_stat(xdr, &result->status);
541 out:
542         return error;
543 }
544
545
546 /*
547  * For NLM, a void procedure really returns nothing
548  */
549 #define nlm_xdr_dec_norep       NULL
550
551 #define PROC(proc, argtype, restype)    \
552 [NLMPROC_##proc] = {                                                    \
553         .p_proc      = NLMPROC_##proc,                                  \
554         .p_encode    = nlm_xdr_enc_##argtype,           \
555         .p_decode    = nlm_xdr_dec_##restype,                           \
556         .p_arglen    = NLM_##argtype##_sz,                              \
557         .p_replen    = NLM_##restype##_sz,                              \
558         .p_statidx   = NLMPROC_##proc,                                  \
559         .p_name      = #proc,                                           \
560         }
561
562 static const struct rpc_procinfo nlm_procedures[] = {
563         PROC(TEST,              testargs,       testres),
564         PROC(LOCK,              lockargs,       res),
565         PROC(CANCEL,            cancargs,       res),
566         PROC(UNLOCK,            unlockargs,     res),
567         PROC(GRANTED,           testargs,       res),
568         PROC(TEST_MSG,          testargs,       norep),
569         PROC(LOCK_MSG,          lockargs,       norep),
570         PROC(CANCEL_MSG,        cancargs,       norep),
571         PROC(UNLOCK_MSG,        unlockargs,     norep),
572         PROC(GRANTED_MSG,       testargs,       norep),
573         PROC(TEST_RES,          testres,        norep),
574         PROC(LOCK_RES,          res,            norep),
575         PROC(CANCEL_RES,        res,            norep),
576         PROC(UNLOCK_RES,        res,            norep),
577         PROC(GRANTED_RES,       res,            norep),
578 };
579
580 static unsigned int nlm_version1_counts[ARRAY_SIZE(nlm_procedures)];
581 static const struct rpc_version nlm_version1 = {
582         .number         = 1,
583         .nrprocs        = ARRAY_SIZE(nlm_procedures),
584         .procs          = nlm_procedures,
585         .counts         = nlm_version1_counts,
586 };
587
588 static unsigned int nlm_version3_counts[ARRAY_SIZE(nlm_procedures)];
589 static const struct rpc_version nlm_version3 = {
590         .number         = 3,
591         .nrprocs        = ARRAY_SIZE(nlm_procedures),
592         .procs          = nlm_procedures,
593         .counts         = nlm_version3_counts,
594 };
595
596 static const struct rpc_version *nlm_versions[] = {
597         [1] = &nlm_version1,
598         [3] = &nlm_version3,
599 #ifdef CONFIG_LOCKD_V4
600         [4] = &nlm_version4,
601 #endif
602 };
603
604 static struct rpc_stat          nlm_rpc_stats;
605
606 const struct rpc_program        nlm_program = {
607         .name           = "lockd",
608         .number         = NLM_PROGRAM,
609         .nrvers         = ARRAY_SIZE(nlm_versions),
610         .version        = nlm_versions,
611         .stats          = &nlm_rpc_stats,
612 };