xref: /openbmc/linux/fs/nfs/nfs42xdr.c (revision 179dd8c0)
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 			      struct nfs42_layoutstat_res *res)
243 {
244 	return decode_op_hdr(xdr, OP_LAYOUTSTATS);
245 }
246 
247 /*
248  * Decode ALLOCATE request
249  */
250 static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
251 				 struct xdr_stream *xdr,
252 				 struct nfs42_falloc_res *res)
253 {
254 	struct compound_hdr hdr;
255 	int status;
256 
257 	status = decode_compound_hdr(xdr, &hdr);
258 	if (status)
259 		goto out;
260 	status = decode_sequence(xdr, &res->seq_res, rqstp);
261 	if (status)
262 		goto out;
263 	status = decode_putfh(xdr);
264 	if (status)
265 		goto out;
266 	status = decode_allocate(xdr, res);
267 	if (status)
268 		goto out;
269 	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
270 out:
271 	return status;
272 }
273 
274 /*
275  * Decode DEALLOCATE request
276  */
277 static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
278 				   struct xdr_stream *xdr,
279 				   struct nfs42_falloc_res *res)
280 {
281 	struct compound_hdr hdr;
282 	int status;
283 
284 	status = decode_compound_hdr(xdr, &hdr);
285 	if (status)
286 		goto out;
287 	status = decode_sequence(xdr, &res->seq_res, rqstp);
288 	if (status)
289 		goto out;
290 	status = decode_putfh(xdr);
291 	if (status)
292 		goto out;
293 	status = decode_deallocate(xdr, res);
294 	if (status)
295 		goto out;
296 	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
297 out:
298 	return status;
299 }
300 
301 /*
302  * Decode SEEK request
303  */
304 static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
305 			     struct xdr_stream *xdr,
306 			     struct nfs42_seek_res *res)
307 {
308 	struct compound_hdr hdr;
309 	int status;
310 
311 	status = decode_compound_hdr(xdr, &hdr);
312 	if (status)
313 		goto out;
314 	status = decode_sequence(xdr, &res->seq_res, rqstp);
315 	if (status)
316 		goto out;
317 	status = decode_putfh(xdr);
318 	if (status)
319 		goto out;
320 	status = decode_seek(xdr, res);
321 out:
322 	return status;
323 }
324 
325 /*
326  * Decode LAYOUTSTATS request
327  */
328 static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
329 				    struct xdr_stream *xdr,
330 				    struct nfs42_layoutstat_res *res)
331 {
332 	struct compound_hdr hdr;
333 	int status, i;
334 
335 	status = decode_compound_hdr(xdr, &hdr);
336 	if (status)
337 		goto out;
338 	status = decode_sequence(xdr, &res->seq_res, rqstp);
339 	if (status)
340 		goto out;
341 	status = decode_putfh(xdr);
342 	if (status)
343 		goto out;
344 	WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
345 	for (i = 0; i < res->num_dev; i++) {
346 		status = decode_layoutstats(xdr, res);
347 		if (status)
348 			goto out;
349 	}
350 out:
351 	res->rpc_status = status;
352 	return status;
353 }
354 
355 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */
356