]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - fs/nfs/nfs42xdr.c
NFS: Fix a tracepoint NULL-pointer dereference
[karo-tx-linux.git] / fs / nfs / nfs42xdr.c
1 /*
2  * Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com>
3  */
4 #ifndef __LINUX_FS_NFS_NFS4_2XDR_H
5 #define __LINUX_FS_NFS_NFS4_2XDR_H
6
7 #include "nfs42.h"
8
9 #define encode_fallocate_maxsz          (encode_stateid_maxsz + \
10                                          2 /* offset */ + \
11                                          2 /* length */)
12 #define encode_allocate_maxsz           (op_encode_hdr_maxsz + \
13                                          encode_fallocate_maxsz)
14 #define decode_allocate_maxsz           (op_decode_hdr_maxsz)
15 #define encode_deallocate_maxsz         (op_encode_hdr_maxsz + \
16                                          encode_fallocate_maxsz)
17 #define decode_deallocate_maxsz         (op_decode_hdr_maxsz)
18 #define encode_seek_maxsz               (op_encode_hdr_maxsz + \
19                                          encode_stateid_maxsz + \
20                                          2 /* offset */ + \
21                                          1 /* whence */)
22 #define decode_seek_maxsz               (op_decode_hdr_maxsz + \
23                                          1 /* eof */ + \
24                                          1 /* whence */ + \
25                                          2 /* offset */ + \
26                                          2 /* length */)
27 #define encode_io_info_maxsz            4
28 #define encode_layoutstats_maxsz        (op_decode_hdr_maxsz + \
29                                         2 /* offset */ + \
30                                         2 /* length */ + \
31                                         encode_stateid_maxsz + \
32                                         encode_io_info_maxsz + \
33                                         encode_io_info_maxsz + \
34                                         1 /* opaque devaddr4 length */ + \
35                                         XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE))
36 #define decode_layoutstats_maxsz        (op_decode_hdr_maxsz)
37
38 #define NFS4_enc_allocate_sz            (compound_encode_hdr_maxsz + \
39                                          encode_putfh_maxsz + \
40                                          encode_allocate_maxsz + \
41                                          encode_getattr_maxsz)
42 #define NFS4_dec_allocate_sz            (compound_decode_hdr_maxsz + \
43                                          decode_putfh_maxsz + \
44                                          decode_allocate_maxsz + \
45                                          decode_getattr_maxsz)
46 #define NFS4_enc_deallocate_sz          (compound_encode_hdr_maxsz + \
47                                          encode_putfh_maxsz + \
48                                          encode_deallocate_maxsz + \
49                                          encode_getattr_maxsz)
50 #define NFS4_dec_deallocate_sz          (compound_decode_hdr_maxsz + \
51                                          decode_putfh_maxsz + \
52                                          decode_deallocate_maxsz + \
53                                          decode_getattr_maxsz)
54 #define NFS4_enc_seek_sz                (compound_encode_hdr_maxsz + \
55                                          encode_putfh_maxsz + \
56                                          encode_seek_maxsz)
57 #define NFS4_dec_seek_sz                (compound_decode_hdr_maxsz + \
58                                          decode_putfh_maxsz + \
59                                          decode_seek_maxsz)
60 #define NFS4_enc_layoutstats_sz         (compound_encode_hdr_maxsz + \
61                                          encode_sequence_maxsz + \
62                                          encode_putfh_maxsz + \
63                                          PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz)
64 #define NFS4_dec_layoutstats_sz         (compound_decode_hdr_maxsz + \
65                                          decode_sequence_maxsz + \
66                                          decode_putfh_maxsz + \
67                                          PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz)
68
69
70 static void encode_fallocate(struct xdr_stream *xdr,
71                              struct nfs42_falloc_args *args)
72 {
73         encode_nfs4_stateid(xdr, &args->falloc_stateid);
74         encode_uint64(xdr, args->falloc_offset);
75         encode_uint64(xdr, args->falloc_length);
76 }
77
78 static void encode_allocate(struct xdr_stream *xdr,
79                             struct nfs42_falloc_args *args,
80                             struct compound_hdr *hdr)
81 {
82         encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
83         encode_fallocate(xdr, args);
84 }
85
86 static void encode_deallocate(struct xdr_stream *xdr,
87                               struct nfs42_falloc_args *args,
88                               struct compound_hdr *hdr)
89 {
90         encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
91         encode_fallocate(xdr, args);
92 }
93
94 static void encode_seek(struct xdr_stream *xdr,
95                         struct nfs42_seek_args *args,
96                         struct compound_hdr *hdr)
97 {
98         encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
99         encode_nfs4_stateid(xdr, &args->sa_stateid);
100         encode_uint64(xdr, args->sa_offset);
101         encode_uint32(xdr, args->sa_what);
102 }
103
104 static void encode_layoutstats(struct xdr_stream *xdr,
105                                struct nfs42_layoutstat_args *args,
106                                struct nfs42_layoutstat_devinfo *devinfo,
107                                struct compound_hdr *hdr)
108 {
109         __be32 *p;
110
111         encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
112         p = reserve_space(xdr, 8 + 8);
113         p = xdr_encode_hyper(p, devinfo->offset);
114         p = xdr_encode_hyper(p, devinfo->length);
115         encode_nfs4_stateid(xdr, &args->stateid);
116         p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
117         p = xdr_encode_hyper(p, devinfo->read_count);
118         p = xdr_encode_hyper(p, devinfo->read_bytes);
119         p = xdr_encode_hyper(p, devinfo->write_count);
120         p = xdr_encode_hyper(p, devinfo->write_bytes);
121         p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
122                         NFS4_DEVICEID4_SIZE);
123         /* Encode layoutupdate4 */
124         *p++ = cpu_to_be32(devinfo->layout_type);
125         if (devinfo->layoutstats_encode != NULL)
126                 devinfo->layoutstats_encode(xdr, args, devinfo);
127         else
128                 encode_uint32(xdr, 0);
129 }
130
131 /*
132  * Encode ALLOCATE request
133  */
134 static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
135                                   struct xdr_stream *xdr,
136                                   struct nfs42_falloc_args *args)
137 {
138         struct compound_hdr hdr = {
139                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
140         };
141
142         encode_compound_hdr(xdr, req, &hdr);
143         encode_sequence(xdr, &args->seq_args, &hdr);
144         encode_putfh(xdr, args->falloc_fh, &hdr);
145         encode_allocate(xdr, args, &hdr);
146         encode_getfattr(xdr, args->falloc_bitmask, &hdr);
147         encode_nops(&hdr);
148 }
149
150 /*
151  * Encode DEALLOCATE request
152  */
153 static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
154                                     struct xdr_stream *xdr,
155                                     struct nfs42_falloc_args *args)
156 {
157         struct compound_hdr hdr = {
158                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
159         };
160
161         encode_compound_hdr(xdr, req, &hdr);
162         encode_sequence(xdr, &args->seq_args, &hdr);
163         encode_putfh(xdr, args->falloc_fh, &hdr);
164         encode_deallocate(xdr, args, &hdr);
165         encode_getfattr(xdr, args->falloc_bitmask, &hdr);
166         encode_nops(&hdr);
167 }
168
169 /*
170  * Encode SEEK request
171  */
172 static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
173                               struct xdr_stream *xdr,
174                               struct nfs42_seek_args *args)
175 {
176         struct compound_hdr hdr = {
177                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
178         };
179
180         encode_compound_hdr(xdr, req, &hdr);
181         encode_sequence(xdr, &args->seq_args, &hdr);
182         encode_putfh(xdr, args->sa_fh, &hdr);
183         encode_seek(xdr, args, &hdr);
184         encode_nops(&hdr);
185 }
186
187 /*
188  * Encode LAYOUTSTATS request
189  */
190 static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
191                                      struct xdr_stream *xdr,
192                                      struct nfs42_layoutstat_args *args)
193 {
194         int i;
195
196         struct compound_hdr hdr = {
197                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
198         };
199
200         encode_compound_hdr(xdr, req, &hdr);
201         encode_sequence(xdr, &args->seq_args, &hdr);
202         encode_putfh(xdr, args->fh, &hdr);
203         WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
204         for (i = 0; i < args->num_dev; i++)
205                 encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
206         encode_nops(&hdr);
207 }
208
209 static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
210 {
211         return decode_op_hdr(xdr, OP_ALLOCATE);
212 }
213
214 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
215 {
216         return decode_op_hdr(xdr, OP_DEALLOCATE);
217 }
218
219 static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
220 {
221         int status;
222         __be32 *p;
223
224         status = decode_op_hdr(xdr, OP_SEEK);
225         if (status)
226                 return status;
227
228         p = xdr_inline_decode(xdr, 4 + 8);
229         if (unlikely(!p))
230                 goto out_overflow;
231
232         res->sr_eof = be32_to_cpup(p++);
233         p = xdr_decode_hyper(p, &res->sr_offset);
234         return 0;
235
236 out_overflow:
237         print_overflow_msg(__func__, xdr);
238         return -EIO;
239 }
240
241 static int decode_layoutstats(struct xdr_stream *xdr)
242 {
243         return decode_op_hdr(xdr, OP_LAYOUTSTATS);
244 }
245
246 /*
247  * Decode ALLOCATE request
248  */
249 static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
250                                  struct xdr_stream *xdr,
251                                  struct nfs42_falloc_res *res)
252 {
253         struct compound_hdr hdr;
254         int status;
255
256         status = decode_compound_hdr(xdr, &hdr);
257         if (status)
258                 goto out;
259         status = decode_sequence(xdr, &res->seq_res, rqstp);
260         if (status)
261                 goto out;
262         status = decode_putfh(xdr);
263         if (status)
264                 goto out;
265         status = decode_allocate(xdr, res);
266         if (status)
267                 goto out;
268         decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
269 out:
270         return status;
271 }
272
273 /*
274  * Decode DEALLOCATE request
275  */
276 static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
277                                    struct xdr_stream *xdr,
278                                    struct nfs42_falloc_res *res)
279 {
280         struct compound_hdr hdr;
281         int status;
282
283         status = decode_compound_hdr(xdr, &hdr);
284         if (status)
285                 goto out;
286         status = decode_sequence(xdr, &res->seq_res, rqstp);
287         if (status)
288                 goto out;
289         status = decode_putfh(xdr);
290         if (status)
291                 goto out;
292         status = decode_deallocate(xdr, res);
293         if (status)
294                 goto out;
295         decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
296 out:
297         return status;
298 }
299
300 /*
301  * Decode SEEK request
302  */
303 static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
304                              struct xdr_stream *xdr,
305                              struct nfs42_seek_res *res)
306 {
307         struct compound_hdr hdr;
308         int status;
309
310         status = decode_compound_hdr(xdr, &hdr);
311         if (status)
312                 goto out;
313         status = decode_sequence(xdr, &res->seq_res, rqstp);
314         if (status)
315                 goto out;
316         status = decode_putfh(xdr);
317         if (status)
318                 goto out;
319         status = decode_seek(xdr, res);
320 out:
321         return status;
322 }
323
324 /*
325  * Decode LAYOUTSTATS request
326  */
327 static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
328                                     struct xdr_stream *xdr,
329                                     struct nfs42_layoutstat_res *res)
330 {
331         struct compound_hdr hdr;
332         int status, i;
333
334         status = decode_compound_hdr(xdr, &hdr);
335         if (status)
336                 goto out;
337         status = decode_sequence(xdr, &res->seq_res, rqstp);
338         if (status)
339                 goto out;
340         status = decode_putfh(xdr);
341         if (status)
342                 goto out;
343         WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
344         for (i = 0; i < res->num_dev; i++) {
345                 status = decode_layoutstats(xdr);
346                 if (status)
347                         goto out;
348         }
349 out:
350         res->rpc_status = status;
351         return status;
352 }
353
354 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */