xref: /openbmc/linux/fs/nfs/nfs42xdr.c (revision abfbd895)
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 #define encode_clone_maxsz		(encode_stateid_maxsz + \
38 					encode_stateid_maxsz + \
39 					2 /* src offset */ + \
40 					2 /* dst offset */ + \
41 					2 /* count */)
42 #define decode_clone_maxsz		(op_decode_hdr_maxsz)
43 
44 #define NFS4_enc_allocate_sz		(compound_encode_hdr_maxsz + \
45 					 encode_putfh_maxsz + \
46 					 encode_allocate_maxsz + \
47 					 encode_getattr_maxsz)
48 #define NFS4_dec_allocate_sz		(compound_decode_hdr_maxsz + \
49 					 decode_putfh_maxsz + \
50 					 decode_allocate_maxsz + \
51 					 decode_getattr_maxsz)
52 #define NFS4_enc_deallocate_sz		(compound_encode_hdr_maxsz + \
53 					 encode_putfh_maxsz + \
54 					 encode_deallocate_maxsz + \
55 					 encode_getattr_maxsz)
56 #define NFS4_dec_deallocate_sz		(compound_decode_hdr_maxsz + \
57 					 decode_putfh_maxsz + \
58 					 decode_deallocate_maxsz + \
59 					 decode_getattr_maxsz)
60 #define NFS4_enc_seek_sz		(compound_encode_hdr_maxsz + \
61 					 encode_putfh_maxsz + \
62 					 encode_seek_maxsz)
63 #define NFS4_dec_seek_sz		(compound_decode_hdr_maxsz + \
64 					 decode_putfh_maxsz + \
65 					 decode_seek_maxsz)
66 #define NFS4_enc_layoutstats_sz		(compound_encode_hdr_maxsz + \
67 					 encode_sequence_maxsz + \
68 					 encode_putfh_maxsz + \
69 					 PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz)
70 #define NFS4_dec_layoutstats_sz		(compound_decode_hdr_maxsz + \
71 					 decode_sequence_maxsz + \
72 					 decode_putfh_maxsz + \
73 					 PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz)
74 #define NFS4_enc_clone_sz		(compound_encode_hdr_maxsz + \
75 					 encode_sequence_maxsz + \
76 					 encode_putfh_maxsz + \
77 					 encode_savefh_maxsz + \
78 					 encode_putfh_maxsz + \
79 					 encode_clone_maxsz + \
80 					 encode_getattr_maxsz)
81 #define NFS4_dec_clone_sz		(compound_decode_hdr_maxsz + \
82 					 decode_sequence_maxsz + \
83 					 decode_putfh_maxsz + \
84 					 decode_savefh_maxsz + \
85 					 decode_putfh_maxsz + \
86 					 decode_clone_maxsz + \
87 					 decode_getattr_maxsz)
88 
89 static void encode_fallocate(struct xdr_stream *xdr,
90 			     struct nfs42_falloc_args *args)
91 {
92 	encode_nfs4_stateid(xdr, &args->falloc_stateid);
93 	encode_uint64(xdr, args->falloc_offset);
94 	encode_uint64(xdr, args->falloc_length);
95 }
96 
97 static void encode_allocate(struct xdr_stream *xdr,
98 			    struct nfs42_falloc_args *args,
99 			    struct compound_hdr *hdr)
100 {
101 	encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
102 	encode_fallocate(xdr, args);
103 }
104 
105 static void encode_deallocate(struct xdr_stream *xdr,
106 			      struct nfs42_falloc_args *args,
107 			      struct compound_hdr *hdr)
108 {
109 	encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
110 	encode_fallocate(xdr, args);
111 }
112 
113 static void encode_seek(struct xdr_stream *xdr,
114 			struct nfs42_seek_args *args,
115 			struct compound_hdr *hdr)
116 {
117 	encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
118 	encode_nfs4_stateid(xdr, &args->sa_stateid);
119 	encode_uint64(xdr, args->sa_offset);
120 	encode_uint32(xdr, args->sa_what);
121 }
122 
123 static void encode_layoutstats(struct xdr_stream *xdr,
124 			       struct nfs42_layoutstat_args *args,
125 			       struct nfs42_layoutstat_devinfo *devinfo,
126 			       struct compound_hdr *hdr)
127 {
128 	__be32 *p;
129 
130 	encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
131 	p = reserve_space(xdr, 8 + 8);
132 	p = xdr_encode_hyper(p, devinfo->offset);
133 	p = xdr_encode_hyper(p, devinfo->length);
134 	encode_nfs4_stateid(xdr, &args->stateid);
135 	p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
136 	p = xdr_encode_hyper(p, devinfo->read_count);
137 	p = xdr_encode_hyper(p, devinfo->read_bytes);
138 	p = xdr_encode_hyper(p, devinfo->write_count);
139 	p = xdr_encode_hyper(p, devinfo->write_bytes);
140 	p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
141 			NFS4_DEVICEID4_SIZE);
142 	/* Encode layoutupdate4 */
143 	*p++ = cpu_to_be32(devinfo->layout_type);
144 	if (devinfo->layoutstats_encode != NULL)
145 		devinfo->layoutstats_encode(xdr, args, devinfo);
146 	else
147 		encode_uint32(xdr, 0);
148 }
149 
150 static void encode_clone(struct xdr_stream *xdr,
151 			 struct nfs42_clone_args *args,
152 			 struct compound_hdr *hdr)
153 {
154 	__be32 *p;
155 
156 	encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr);
157 	encode_nfs4_stateid(xdr, &args->src_stateid);
158 	encode_nfs4_stateid(xdr, &args->dst_stateid);
159 	p = reserve_space(xdr, 3*8);
160 	p = xdr_encode_hyper(p, args->src_offset);
161 	p = xdr_encode_hyper(p, args->dst_offset);
162 	xdr_encode_hyper(p, args->count);
163 }
164 
165 /*
166  * Encode ALLOCATE request
167  */
168 static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
169 				  struct xdr_stream *xdr,
170 				  struct nfs42_falloc_args *args)
171 {
172 	struct compound_hdr hdr = {
173 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
174 	};
175 
176 	encode_compound_hdr(xdr, req, &hdr);
177 	encode_sequence(xdr, &args->seq_args, &hdr);
178 	encode_putfh(xdr, args->falloc_fh, &hdr);
179 	encode_allocate(xdr, args, &hdr);
180 	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
181 	encode_nops(&hdr);
182 }
183 
184 /*
185  * Encode DEALLOCATE request
186  */
187 static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
188 				    struct xdr_stream *xdr,
189 				    struct nfs42_falloc_args *args)
190 {
191 	struct compound_hdr hdr = {
192 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
193 	};
194 
195 	encode_compound_hdr(xdr, req, &hdr);
196 	encode_sequence(xdr, &args->seq_args, &hdr);
197 	encode_putfh(xdr, args->falloc_fh, &hdr);
198 	encode_deallocate(xdr, args, &hdr);
199 	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
200 	encode_nops(&hdr);
201 }
202 
203 /*
204  * Encode SEEK request
205  */
206 static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
207 			      struct xdr_stream *xdr,
208 			      struct nfs42_seek_args *args)
209 {
210 	struct compound_hdr hdr = {
211 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
212 	};
213 
214 	encode_compound_hdr(xdr, req, &hdr);
215 	encode_sequence(xdr, &args->seq_args, &hdr);
216 	encode_putfh(xdr, args->sa_fh, &hdr);
217 	encode_seek(xdr, args, &hdr);
218 	encode_nops(&hdr);
219 }
220 
221 /*
222  * Encode LAYOUTSTATS request
223  */
224 static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
225 				     struct xdr_stream *xdr,
226 				     struct nfs42_layoutstat_args *args)
227 {
228 	int i;
229 
230 	struct compound_hdr hdr = {
231 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
232 	};
233 
234 	encode_compound_hdr(xdr, req, &hdr);
235 	encode_sequence(xdr, &args->seq_args, &hdr);
236 	encode_putfh(xdr, args->fh, &hdr);
237 	WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
238 	for (i = 0; i < args->num_dev; i++)
239 		encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
240 	encode_nops(&hdr);
241 }
242 
243 /*
244  * Encode CLONE request
245  */
246 static void nfs4_xdr_enc_clone(struct rpc_rqst *req,
247 			       struct xdr_stream *xdr,
248 			       struct nfs42_clone_args *args)
249 {
250 	struct compound_hdr hdr = {
251 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
252 	};
253 
254 	encode_compound_hdr(xdr, req, &hdr);
255 	encode_sequence(xdr, &args->seq_args, &hdr);
256 	encode_putfh(xdr, args->src_fh, &hdr);
257 	encode_savefh(xdr, &hdr);
258 	encode_putfh(xdr, args->dst_fh, &hdr);
259 	encode_clone(xdr, args, &hdr);
260 	encode_getfattr(xdr, args->dst_bitmask, &hdr);
261 	encode_nops(&hdr);
262 }
263 
264 static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
265 {
266 	return decode_op_hdr(xdr, OP_ALLOCATE);
267 }
268 
269 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
270 {
271 	return decode_op_hdr(xdr, OP_DEALLOCATE);
272 }
273 
274 static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
275 {
276 	int status;
277 	__be32 *p;
278 
279 	status = decode_op_hdr(xdr, OP_SEEK);
280 	if (status)
281 		return status;
282 
283 	p = xdr_inline_decode(xdr, 4 + 8);
284 	if (unlikely(!p))
285 		goto out_overflow;
286 
287 	res->sr_eof = be32_to_cpup(p++);
288 	p = xdr_decode_hyper(p, &res->sr_offset);
289 	return 0;
290 
291 out_overflow:
292 	print_overflow_msg(__func__, xdr);
293 	return -EIO;
294 }
295 
296 static int decode_layoutstats(struct xdr_stream *xdr)
297 {
298 	return decode_op_hdr(xdr, OP_LAYOUTSTATS);
299 }
300 
301 static int decode_clone(struct xdr_stream *xdr)
302 {
303 	return decode_op_hdr(xdr, OP_CLONE);
304 }
305 
306 /*
307  * Decode ALLOCATE request
308  */
309 static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
310 				 struct xdr_stream *xdr,
311 				 struct nfs42_falloc_res *res)
312 {
313 	struct compound_hdr hdr;
314 	int status;
315 
316 	status = decode_compound_hdr(xdr, &hdr);
317 	if (status)
318 		goto out;
319 	status = decode_sequence(xdr, &res->seq_res, rqstp);
320 	if (status)
321 		goto out;
322 	status = decode_putfh(xdr);
323 	if (status)
324 		goto out;
325 	status = decode_allocate(xdr, res);
326 	if (status)
327 		goto out;
328 	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
329 out:
330 	return status;
331 }
332 
333 /*
334  * Decode DEALLOCATE request
335  */
336 static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
337 				   struct xdr_stream *xdr,
338 				   struct nfs42_falloc_res *res)
339 {
340 	struct compound_hdr hdr;
341 	int status;
342 
343 	status = decode_compound_hdr(xdr, &hdr);
344 	if (status)
345 		goto out;
346 	status = decode_sequence(xdr, &res->seq_res, rqstp);
347 	if (status)
348 		goto out;
349 	status = decode_putfh(xdr);
350 	if (status)
351 		goto out;
352 	status = decode_deallocate(xdr, res);
353 	if (status)
354 		goto out;
355 	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
356 out:
357 	return status;
358 }
359 
360 /*
361  * Decode SEEK request
362  */
363 static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
364 			     struct xdr_stream *xdr,
365 			     struct nfs42_seek_res *res)
366 {
367 	struct compound_hdr hdr;
368 	int status;
369 
370 	status = decode_compound_hdr(xdr, &hdr);
371 	if (status)
372 		goto out;
373 	status = decode_sequence(xdr, &res->seq_res, rqstp);
374 	if (status)
375 		goto out;
376 	status = decode_putfh(xdr);
377 	if (status)
378 		goto out;
379 	status = decode_seek(xdr, res);
380 out:
381 	return status;
382 }
383 
384 /*
385  * Decode LAYOUTSTATS request
386  */
387 static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
388 				    struct xdr_stream *xdr,
389 				    struct nfs42_layoutstat_res *res)
390 {
391 	struct compound_hdr hdr;
392 	int status, i;
393 
394 	status = decode_compound_hdr(xdr, &hdr);
395 	if (status)
396 		goto out;
397 	status = decode_sequence(xdr, &res->seq_res, rqstp);
398 	if (status)
399 		goto out;
400 	status = decode_putfh(xdr);
401 	if (status)
402 		goto out;
403 	WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
404 	for (i = 0; i < res->num_dev; i++) {
405 		status = decode_layoutstats(xdr);
406 		if (status)
407 			goto out;
408 	}
409 out:
410 	res->rpc_status = status;
411 	return status;
412 }
413 
414 /*
415  * Decode CLONE request
416  */
417 static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp,
418 			      struct xdr_stream *xdr,
419 			      struct nfs42_clone_res *res)
420 {
421 	struct compound_hdr hdr;
422 	int status;
423 
424 	status = decode_compound_hdr(xdr, &hdr);
425 	if (status)
426 		goto out;
427 	status = decode_sequence(xdr, &res->seq_res, rqstp);
428 	if (status)
429 		goto out;
430 	status = decode_putfh(xdr);
431 	if (status)
432 		goto out;
433 	status = decode_savefh(xdr);
434 	if (status)
435 		goto out;
436 	status = decode_putfh(xdr);
437 	if (status)
438 		goto out;
439 	status = decode_clone(xdr);
440 	if (status)
441 		goto out;
442 	status = decode_getfattr(xdr, res->dst_fattr, res->server);
443 
444 out:
445 	res->rpc_status = status;
446 	return status;
447 }
448 
449 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */
450