Linux Audio

Check our new training course

Loading...
v4.17
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com>
  4 */
  5#ifndef __LINUX_FS_NFS_NFS4_2XDR_H
  6#define __LINUX_FS_NFS_NFS4_2XDR_H
  7
  8#include "nfs42.h"
  9
 
 
 
 10#define encode_fallocate_maxsz		(encode_stateid_maxsz + \
 11					 2 /* offset */ + \
 12					 2 /* length */)
 13#define NFS42_WRITE_RES_SIZE		(1 /* wr_callback_id size */ +\
 14					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
 15					 2 /* wr_count */ + \
 16					 1 /* wr_committed */ + \
 17					 XDR_QUADLEN(NFS4_VERIFIER_SIZE))
 18#define encode_allocate_maxsz		(op_encode_hdr_maxsz + \
 19					 encode_fallocate_maxsz)
 20#define decode_allocate_maxsz		(op_decode_hdr_maxsz)
 21#define encode_copy_maxsz		(op_encode_hdr_maxsz +          \
 22					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
 23					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
 24					 2 + 2 + 2 + 1 + 1 + 1)
 
 
 
 25#define decode_copy_maxsz		(op_decode_hdr_maxsz + \
 26					 NFS42_WRITE_RES_SIZE + \
 27					 1 /* cr_consecutive */ + \
 28					 1 /* cr_synchronous */)
 
 
 
 
 
 
 
 
 
 
 
 
 
 29#define encode_deallocate_maxsz		(op_encode_hdr_maxsz + \
 30					 encode_fallocate_maxsz)
 31#define decode_deallocate_maxsz		(op_decode_hdr_maxsz)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 32#define encode_seek_maxsz		(op_encode_hdr_maxsz + \
 33					 encode_stateid_maxsz + \
 34					 2 /* offset */ + \
 35					 1 /* whence */)
 36#define decode_seek_maxsz		(op_decode_hdr_maxsz + \
 37					 1 /* eof */ + \
 38					 1 /* whence */ + \
 39					 2 /* offset */ + \
 40					 2 /* length */)
 41#define encode_io_info_maxsz		4
 42#define encode_layoutstats_maxsz	(op_decode_hdr_maxsz + \
 43					2 /* offset */ + \
 44					2 /* length */ + \
 45					encode_stateid_maxsz + \
 46					encode_io_info_maxsz + \
 47					encode_io_info_maxsz + \
 48					1 /* opaque devaddr4 length */ + \
 49					XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE))
 50#define decode_layoutstats_maxsz	(op_decode_hdr_maxsz)
 
 
 
 
 
 
 
 
 
 51#define encode_clone_maxsz		(encode_stateid_maxsz + \
 52					encode_stateid_maxsz + \
 53					2 /* src offset */ + \
 54					2 /* dst offset */ + \
 55					2 /* count */)
 56#define decode_clone_maxsz		(op_decode_hdr_maxsz)
 
 
 
 
 
 
 
 
 
 
 
 
 57
 58#define NFS4_enc_allocate_sz		(compound_encode_hdr_maxsz + \
 
 59					 encode_putfh_maxsz + \
 60					 encode_allocate_maxsz + \
 61					 encode_getattr_maxsz)
 62#define NFS4_dec_allocate_sz		(compound_decode_hdr_maxsz + \
 
 63					 decode_putfh_maxsz + \
 64					 decode_allocate_maxsz + \
 65					 decode_getattr_maxsz)
 66#define NFS4_enc_copy_sz		(compound_encode_hdr_maxsz + \
 
 67					 encode_putfh_maxsz + \
 68					 encode_savefh_maxsz + \
 69					 encode_putfh_maxsz + \
 70					 encode_copy_maxsz + \
 71					 encode_commit_maxsz)
 72#define NFS4_dec_copy_sz		(compound_decode_hdr_maxsz + \
 
 73					 decode_putfh_maxsz + \
 74					 decode_savefh_maxsz + \
 75					 decode_putfh_maxsz + \
 76					 decode_copy_maxsz + \
 77					 decode_commit_maxsz)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 78#define NFS4_enc_deallocate_sz		(compound_encode_hdr_maxsz + \
 
 79					 encode_putfh_maxsz + \
 80					 encode_deallocate_maxsz + \
 81					 encode_getattr_maxsz)
 82#define NFS4_dec_deallocate_sz		(compound_decode_hdr_maxsz + \
 
 83					 decode_putfh_maxsz + \
 84					 decode_deallocate_maxsz + \
 85					 decode_getattr_maxsz)
 
 
 
 
 
 
 
 
 86#define NFS4_enc_seek_sz		(compound_encode_hdr_maxsz + \
 
 87					 encode_putfh_maxsz + \
 88					 encode_seek_maxsz)
 89#define NFS4_dec_seek_sz		(compound_decode_hdr_maxsz + \
 
 90					 decode_putfh_maxsz + \
 91					 decode_seek_maxsz)
 92#define NFS4_enc_layoutstats_sz		(compound_encode_hdr_maxsz + \
 93					 encode_sequence_maxsz + \
 94					 encode_putfh_maxsz + \
 95					 PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz)
 96#define NFS4_dec_layoutstats_sz		(compound_decode_hdr_maxsz + \
 97					 decode_sequence_maxsz + \
 98					 decode_putfh_maxsz + \
 99					 PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz)
 
 
 
 
 
 
 
 
 
 
100#define NFS4_enc_clone_sz		(compound_encode_hdr_maxsz + \
101					 encode_sequence_maxsz + \
102					 encode_putfh_maxsz + \
103					 encode_savefh_maxsz + \
104					 encode_putfh_maxsz + \
105					 encode_clone_maxsz + \
106					 encode_getattr_maxsz)
107#define NFS4_dec_clone_sz		(compound_decode_hdr_maxsz + \
108					 decode_sequence_maxsz + \
109					 decode_putfh_maxsz + \
110					 decode_savefh_maxsz + \
111					 decode_putfh_maxsz + \
112					 decode_clone_maxsz + \
113					 decode_getattr_maxsz)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
115static void encode_fallocate(struct xdr_stream *xdr,
116			     const struct nfs42_falloc_args *args)
117{
118	encode_nfs4_stateid(xdr, &args->falloc_stateid);
119	encode_uint64(xdr, args->falloc_offset);
120	encode_uint64(xdr, args->falloc_length);
121}
122
123static void encode_allocate(struct xdr_stream *xdr,
124			    const struct nfs42_falloc_args *args,
125			    struct compound_hdr *hdr)
126{
127	encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
128	encode_fallocate(xdr, args);
129}
130
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
131static void encode_copy(struct xdr_stream *xdr,
132			const struct nfs42_copy_args *args,
133			struct compound_hdr *hdr)
134{
135	encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr);
136	encode_nfs4_stateid(xdr, &args->src_stateid);
137	encode_nfs4_stateid(xdr, &args->dst_stateid);
138
139	encode_uint64(xdr, args->src_pos);
140	encode_uint64(xdr, args->dst_pos);
141	encode_uint64(xdr, args->count);
142
143	encode_uint32(xdr, 1); /* consecutive = true */
144	encode_uint32(xdr, 1); /* synchronous = true */
145	encode_uint32(xdr, 0); /* src server list */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146}
147
148static void encode_deallocate(struct xdr_stream *xdr,
149			      const struct nfs42_falloc_args *args,
150			      struct compound_hdr *hdr)
151{
152	encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
153	encode_fallocate(xdr, args);
154}
155
 
 
 
 
 
 
 
 
 
 
156static void encode_seek(struct xdr_stream *xdr,
157			const struct nfs42_seek_args *args,
158			struct compound_hdr *hdr)
159{
160	encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
161	encode_nfs4_stateid(xdr, &args->sa_stateid);
162	encode_uint64(xdr, args->sa_offset);
163	encode_uint32(xdr, args->sa_what);
164}
165
166static void encode_layoutstats(struct xdr_stream *xdr,
167			       const struct nfs42_layoutstat_args *args,
168			       struct nfs42_layoutstat_devinfo *devinfo,
169			       struct compound_hdr *hdr)
170{
171	__be32 *p;
172
173	encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
174	p = reserve_space(xdr, 8 + 8);
175	p = xdr_encode_hyper(p, devinfo->offset);
176	p = xdr_encode_hyper(p, devinfo->length);
177	encode_nfs4_stateid(xdr, &args->stateid);
178	p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
179	p = xdr_encode_hyper(p, devinfo->read_count);
180	p = xdr_encode_hyper(p, devinfo->read_bytes);
181	p = xdr_encode_hyper(p, devinfo->write_count);
182	p = xdr_encode_hyper(p, devinfo->write_bytes);
183	p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
184			NFS4_DEVICEID4_SIZE);
185	/* Encode layoutupdate4 */
186	*p++ = cpu_to_be32(devinfo->layout_type);
187	if (devinfo->ld_private.ops)
188		devinfo->ld_private.ops->encode(xdr, args,
189				&devinfo->ld_private);
190	else
191		encode_uint32(xdr, 0);
192}
193
194static void encode_clone(struct xdr_stream *xdr,
195			 const struct nfs42_clone_args *args,
196			 struct compound_hdr *hdr)
197{
198	__be32 *p;
199
200	encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr);
201	encode_nfs4_stateid(xdr, &args->src_stateid);
202	encode_nfs4_stateid(xdr, &args->dst_stateid);
203	p = reserve_space(xdr, 3*8);
204	p = xdr_encode_hyper(p, args->src_offset);
205	p = xdr_encode_hyper(p, args->dst_offset);
206	xdr_encode_hyper(p, args->count);
207}
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209/*
210 * Encode ALLOCATE request
211 */
212static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
213				  struct xdr_stream *xdr,
214				  const void *data)
215{
216	const struct nfs42_falloc_args *args = data;
217	struct compound_hdr hdr = {
218		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
219	};
220
221	encode_compound_hdr(xdr, req, &hdr);
222	encode_sequence(xdr, &args->seq_args, &hdr);
223	encode_putfh(xdr, args->falloc_fh, &hdr);
224	encode_allocate(xdr, args, &hdr);
225	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
226	encode_nops(&hdr);
227}
228
229static void encode_copy_commit(struct xdr_stream *xdr,
230			  const struct nfs42_copy_args *args,
231			  struct compound_hdr *hdr)
232{
233	__be32 *p;
234
235	encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
236	p = reserve_space(xdr, 12);
237	p = xdr_encode_hyper(p, args->dst_pos);
238	*p = cpu_to_be32(args->count);
239}
240
241/*
242 * Encode COPY request
243 */
244static void nfs4_xdr_enc_copy(struct rpc_rqst *req,
245			      struct xdr_stream *xdr,
246			      const void *data)
247{
248	const struct nfs42_copy_args *args = data;
249	struct compound_hdr hdr = {
250		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
251	};
252
253	encode_compound_hdr(xdr, req, &hdr);
254	encode_sequence(xdr, &args->seq_args, &hdr);
255	encode_putfh(xdr, args->src_fh, &hdr);
256	encode_savefh(xdr, &hdr);
257	encode_putfh(xdr, args->dst_fh, &hdr);
258	encode_copy(xdr, args, &hdr);
259	encode_copy_commit(xdr, args, &hdr);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260	encode_nops(&hdr);
261}
262
263/*
264 * Encode DEALLOCATE request
265 */
266static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
267				    struct xdr_stream *xdr,
268				    const void *data)
269{
270	const struct nfs42_falloc_args *args = data;
271	struct compound_hdr hdr = {
272		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
273	};
274
275	encode_compound_hdr(xdr, req, &hdr);
276	encode_sequence(xdr, &args->seq_args, &hdr);
277	encode_putfh(xdr, args->falloc_fh, &hdr);
278	encode_deallocate(xdr, args, &hdr);
279	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
280	encode_nops(&hdr);
281}
282
283/*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284 * Encode SEEK request
285 */
286static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
287			      struct xdr_stream *xdr,
288			      const void *data)
289{
290	const struct nfs42_seek_args *args = data;
291	struct compound_hdr hdr = {
292		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
293	};
294
295	encode_compound_hdr(xdr, req, &hdr);
296	encode_sequence(xdr, &args->seq_args, &hdr);
297	encode_putfh(xdr, args->sa_fh, &hdr);
298	encode_seek(xdr, args, &hdr);
299	encode_nops(&hdr);
300}
301
302/*
303 * Encode LAYOUTSTATS request
304 */
305static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
306				     struct xdr_stream *xdr,
307				     const void *data)
308{
309	const struct nfs42_layoutstat_args *args = data;
310	int i;
311
312	struct compound_hdr hdr = {
313		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
314	};
315
316	encode_compound_hdr(xdr, req, &hdr);
317	encode_sequence(xdr, &args->seq_args, &hdr);
318	encode_putfh(xdr, args->fh, &hdr);
319	WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
320	for (i = 0; i < args->num_dev; i++)
321		encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
322	encode_nops(&hdr);
323}
324
325/*
326 * Encode CLONE request
327 */
328static void nfs4_xdr_enc_clone(struct rpc_rqst *req,
329			       struct xdr_stream *xdr,
330			       const void *data)
331{
332	const struct nfs42_clone_args *args = data;
333	struct compound_hdr hdr = {
334		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
335	};
336
337	encode_compound_hdr(xdr, req, &hdr);
338	encode_sequence(xdr, &args->seq_args, &hdr);
339	encode_putfh(xdr, args->src_fh, &hdr);
340	encode_savefh(xdr, &hdr);
341	encode_putfh(xdr, args->dst_fh, &hdr);
342	encode_clone(xdr, args, &hdr);
343	encode_getfattr(xdr, args->dst_bitmask, &hdr);
344	encode_nops(&hdr);
345}
346
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
347static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
348{
349	return decode_op_hdr(xdr, OP_ALLOCATE);
350}
351
352static int decode_write_response(struct xdr_stream *xdr,
353				 struct nfs42_write_res *res)
354{
355	__be32 *p;
 
356
357	p = xdr_inline_decode(xdr, 4 + 8 + 4);
358	if (unlikely(!p))
359		goto out_overflow;
360
361	/*
362	 * We never use asynchronous mode, so warn if a server returns
363	 * a stateid.
364	 */
365	if (unlikely(*p != 0)) {
366		pr_err_once("%s: server has set unrequested "
367				"asynchronous mode\n", __func__);
368		return -EREMOTEIO;
 
 
 
 
 
369	}
370	p++;
 
 
371	p = xdr_decode_hyper(p, &res->count);
372	res->verifier.committed = be32_to_cpup(p);
373	return decode_verifier(xdr, &res->verifier.verifier);
 
 
 
 
 
 
 
 
 
374
375out_overflow:
376	print_overflow_msg(__func__, xdr);
377	return -EIO;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
378}
379
380static int decode_copy_requirements(struct xdr_stream *xdr,
381				    struct nfs42_copy_res *res) {
382	__be32 *p;
383
384	p = xdr_inline_decode(xdr, 4 + 4);
385	if (unlikely(!p))
386		goto out_overflow;
387
388	res->consecutive = be32_to_cpup(p++);
389	res->synchronous = be32_to_cpup(p++);
390	return 0;
391out_overflow:
392	print_overflow_msg(__func__, xdr);
393	return -EIO;
394}
395
396static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
397{
398	int status;
399
400	status = decode_op_hdr(xdr, OP_COPY);
401	if (status == NFS4ERR_OFFLOAD_NO_REQS) {
402		status = decode_copy_requirements(xdr, res);
403		if (status)
404			return status;
405		return NFS4ERR_OFFLOAD_NO_REQS;
406	} else if (status)
407		return status;
408
409	status = decode_write_response(xdr, &res->write_res);
410	if (status)
411		return status;
412
413	return decode_copy_requirements(xdr, res);
414}
415
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
416static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
417{
418	return decode_op_hdr(xdr, OP_DEALLOCATE);
419}
420
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
421static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
422{
423	int status;
424	__be32 *p;
425
426	status = decode_op_hdr(xdr, OP_SEEK);
427	if (status)
428		return status;
429
430	p = xdr_inline_decode(xdr, 4 + 8);
431	if (unlikely(!p))
432		goto out_overflow;
433
434	res->sr_eof = be32_to_cpup(p++);
435	p = xdr_decode_hyper(p, &res->sr_offset);
436	return 0;
437
438out_overflow:
439	print_overflow_msg(__func__, xdr);
440	return -EIO;
441}
442
443static int decode_layoutstats(struct xdr_stream *xdr)
444{
445	return decode_op_hdr(xdr, OP_LAYOUTSTATS);
446}
447
448static int decode_clone(struct xdr_stream *xdr)
449{
450	return decode_op_hdr(xdr, OP_CLONE);
451}
452
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
453/*
454 * Decode ALLOCATE request
455 */
456static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
457				 struct xdr_stream *xdr,
458				 void *data)
459{
460	struct nfs42_falloc_res *res = data;
461	struct compound_hdr hdr;
462	int status;
463
464	status = decode_compound_hdr(xdr, &hdr);
465	if (status)
466		goto out;
467	status = decode_sequence(xdr, &res->seq_res, rqstp);
468	if (status)
469		goto out;
470	status = decode_putfh(xdr);
471	if (status)
472		goto out;
473	status = decode_allocate(xdr, res);
474	if (status)
475		goto out;
476	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
477out:
478	return status;
479}
480
481/*
482 * Decode COPY response
483 */
484static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
485			     struct xdr_stream *xdr,
486			     void *data)
487{
488	struct nfs42_copy_res *res = data;
489	struct compound_hdr hdr;
490	int status;
491
492	status = decode_compound_hdr(xdr, &hdr);
493	if (status)
494		goto out;
495	status = decode_sequence(xdr, &res->seq_res, rqstp);
496	if (status)
497		goto out;
498	status = decode_putfh(xdr);
499	if (status)
500		goto out;
501	status = decode_savefh(xdr);
502	if (status)
503		goto out;
504	status = decode_putfh(xdr);
505	if (status)
506		goto out;
507	status = decode_copy(xdr, res);
508	if (status)
509		goto out;
510	status = decode_commit(xdr, &res->commit_res);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
511out:
512	return status;
513}
514
515/*
516 * Decode DEALLOCATE request
517 */
518static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
519				   struct xdr_stream *xdr,
520				   void *data)
521{
522	struct nfs42_falloc_res *res = data;
523	struct compound_hdr hdr;
524	int status;
525
526	status = decode_compound_hdr(xdr, &hdr);
527	if (status)
528		goto out;
529	status = decode_sequence(xdr, &res->seq_res, rqstp);
530	if (status)
531		goto out;
532	status = decode_putfh(xdr);
533	if (status)
534		goto out;
535	status = decode_deallocate(xdr, res);
536	if (status)
537		goto out;
538	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
539out:
540	return status;
541}
542
543/*
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
544 * Decode SEEK request
545 */
546static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
547			     struct xdr_stream *xdr,
548			     void *data)
549{
550	struct nfs42_seek_res *res = data;
551	struct compound_hdr hdr;
552	int status;
553
554	status = decode_compound_hdr(xdr, &hdr);
555	if (status)
556		goto out;
557	status = decode_sequence(xdr, &res->seq_res, rqstp);
558	if (status)
559		goto out;
560	status = decode_putfh(xdr);
561	if (status)
562		goto out;
563	status = decode_seek(xdr, res);
564out:
565	return status;
566}
567
568/*
569 * Decode LAYOUTSTATS request
570 */
571static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
572				    struct xdr_stream *xdr,
573				    void *data)
574{
575	struct nfs42_layoutstat_res *res = data;
576	struct compound_hdr hdr;
577	int status, i;
578
579	status = decode_compound_hdr(xdr, &hdr);
580	if (status)
581		goto out;
582	status = decode_sequence(xdr, &res->seq_res, rqstp);
583	if (status)
584		goto out;
585	status = decode_putfh(xdr);
586	if (status)
587		goto out;
588	WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
589	for (i = 0; i < res->num_dev; i++) {
590		status = decode_layoutstats(xdr);
591		if (status)
592			goto out;
593	}
594out:
595	res->rpc_status = status;
596	return status;
597}
598
599/*
600 * Decode CLONE request
601 */
602static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp,
603			      struct xdr_stream *xdr,
604			      void *data)
605{
606	struct nfs42_clone_res *res = data;
607	struct compound_hdr hdr;
608	int status;
609
610	status = decode_compound_hdr(xdr, &hdr);
611	if (status)
612		goto out;
613	status = decode_sequence(xdr, &res->seq_res, rqstp);
614	if (status)
615		goto out;
616	status = decode_putfh(xdr);
617	if (status)
618		goto out;
619	status = decode_savefh(xdr);
620	if (status)
621		goto out;
622	status = decode_putfh(xdr);
623	if (status)
624		goto out;
625	status = decode_clone(xdr);
626	if (status)
627		goto out;
628	status = decode_getfattr(xdr, res->dst_fattr, res->server);
 
 
 
 
629
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
630out:
631	res->rpc_status = status;
632	return status;
633}
634
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
635#endif /* __LINUX_FS_NFS_NFS4_2XDR_H */
v6.13.7
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com>
   4 */
   5#ifndef __LINUX_FS_NFS_NFS4_2XDR_H
   6#define __LINUX_FS_NFS_NFS4_2XDR_H
   7
   8#include "nfs42.h"
   9
  10/* Not limited by NFS itself, limited by the generic xattr code */
  11#define nfs4_xattr_name_maxsz   XDR_QUADLEN(XATTR_NAME_MAX)
  12
  13#define encode_fallocate_maxsz		(encode_stateid_maxsz + \
  14					 2 /* offset */ + \
  15					 2 /* length */)
  16#define NFS42_WRITE_RES_SIZE		(1 /* wr_callback_id size */ +\
  17					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
  18					 2 /* wr_count */ + \
  19					 1 /* wr_committed */ + \
  20					 XDR_QUADLEN(NFS4_VERIFIER_SIZE))
  21#define encode_allocate_maxsz		(op_encode_hdr_maxsz + \
  22					 encode_fallocate_maxsz)
  23#define decode_allocate_maxsz		(op_decode_hdr_maxsz)
  24#define encode_copy_maxsz		(op_encode_hdr_maxsz +          \
  25					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
  26					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
  27					 2 + 2 + 2 + 1 + 1 + 1 +\
  28					 1 + /* One cnr_source_server */\
  29					 1 + /* nl4_type */ \
  30					 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
  31#define decode_copy_maxsz		(op_decode_hdr_maxsz + \
  32					 NFS42_WRITE_RES_SIZE + \
  33					 1 /* cr_consecutive */ + \
  34					 1 /* cr_synchronous */)
  35#define encode_offload_cancel_maxsz	(op_encode_hdr_maxsz + \
  36					 XDR_QUADLEN(NFS4_STATEID_SIZE))
  37#define decode_offload_cancel_maxsz	(op_decode_hdr_maxsz)
  38#define encode_copy_notify_maxsz	(op_encode_hdr_maxsz + \
  39					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
  40					 1 + /* nl4_type */ \
  41					 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
  42#define decode_copy_notify_maxsz	(op_decode_hdr_maxsz + \
  43					 3 + /* cnr_lease_time */\
  44					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
  45					 1 + /* Support 1 cnr_source_server */\
  46					 1 + /* nl4_type */ \
  47					 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
  48#define encode_deallocate_maxsz		(op_encode_hdr_maxsz + \
  49					 encode_fallocate_maxsz)
  50#define decode_deallocate_maxsz		(op_decode_hdr_maxsz)
  51#define encode_read_plus_maxsz		(op_encode_hdr_maxsz + \
  52					 encode_stateid_maxsz + 3)
  53#define NFS42_READ_PLUS_DATA_SEGMENT_SIZE \
  54					(1 /* data_content4 */ + \
  55					 2 /* data_info4.di_offset */ + \
  56					 1 /* data_info4.di_length */)
  57#define NFS42_READ_PLUS_HOLE_SEGMENT_SIZE \
  58					(1 /* data_content4 */ + \
  59					 2 /* data_info4.di_offset */ + \
  60					 2 /* data_info4.di_length */)
  61#define READ_PLUS_SEGMENT_SIZE_DIFF	(NFS42_READ_PLUS_HOLE_SEGMENT_SIZE - \
  62					 NFS42_READ_PLUS_DATA_SEGMENT_SIZE)
  63#define decode_read_plus_maxsz		(op_decode_hdr_maxsz + \
  64					 1 /* rpr_eof */ + \
  65					 1 /* rpr_contents count */ + \
  66					 NFS42_READ_PLUS_HOLE_SEGMENT_SIZE)
  67#define encode_seek_maxsz		(op_encode_hdr_maxsz + \
  68					 encode_stateid_maxsz + \
  69					 2 /* offset */ + \
  70					 1 /* whence */)
  71#define decode_seek_maxsz		(op_decode_hdr_maxsz + \
  72					 1 /* eof */ + \
  73					 1 /* whence */ + \
  74					 2 /* offset */ + \
  75					 2 /* length */)
  76#define encode_io_info_maxsz		4
  77#define encode_layoutstats_maxsz	(op_decode_hdr_maxsz + \
  78					2 /* offset */ + \
  79					2 /* length */ + \
  80					encode_stateid_maxsz + \
  81					encode_io_info_maxsz + \
  82					encode_io_info_maxsz + \
  83					1 /* opaque devaddr4 length */ + \
  84					XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE))
  85#define decode_layoutstats_maxsz	(op_decode_hdr_maxsz)
  86#define encode_device_error_maxsz	(XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \
  87					1 /* status */ + 1 /* opnum */)
  88#define encode_layouterror_maxsz	(op_decode_hdr_maxsz + \
  89					2 /* offset */ + \
  90					2 /* length */ + \
  91					encode_stateid_maxsz + \
  92					1 /* Array size */ + \
  93					encode_device_error_maxsz)
  94#define decode_layouterror_maxsz	(op_decode_hdr_maxsz)
  95#define encode_clone_maxsz		(encode_stateid_maxsz + \
  96					encode_stateid_maxsz + \
  97					2 /* src offset */ + \
  98					2 /* dst offset */ + \
  99					2 /* count */)
 100#define decode_clone_maxsz		(op_decode_hdr_maxsz)
 101#define encode_getxattr_maxsz		(op_encode_hdr_maxsz + 1 + \
 102					 nfs4_xattr_name_maxsz)
 103#define decode_getxattr_maxsz		(op_decode_hdr_maxsz + 1 + pagepad_maxsz)
 104#define encode_setxattr_maxsz		(op_encode_hdr_maxsz + \
 105					 1 + nfs4_xattr_name_maxsz + 1)
 106#define decode_setxattr_maxsz		(op_decode_hdr_maxsz + decode_change_info_maxsz)
 107#define encode_listxattrs_maxsz		(op_encode_hdr_maxsz + 2 + 1)
 108#define decode_listxattrs_maxsz		(op_decode_hdr_maxsz + 2 + 1 + 1 + 1)
 109#define encode_removexattr_maxsz	(op_encode_hdr_maxsz + 1 + \
 110					 nfs4_xattr_name_maxsz)
 111#define decode_removexattr_maxsz	(op_decode_hdr_maxsz + \
 112					 decode_change_info_maxsz)
 113
 114#define NFS4_enc_allocate_sz		(compound_encode_hdr_maxsz + \
 115					 encode_sequence_maxsz + \
 116					 encode_putfh_maxsz + \
 117					 encode_allocate_maxsz + \
 118					 encode_getattr_maxsz)
 119#define NFS4_dec_allocate_sz		(compound_decode_hdr_maxsz + \
 120					 decode_sequence_maxsz + \
 121					 decode_putfh_maxsz + \
 122					 decode_allocate_maxsz + \
 123					 decode_getattr_maxsz)
 124#define NFS4_enc_copy_sz		(compound_encode_hdr_maxsz + \
 125					 encode_sequence_maxsz + \
 126					 encode_putfh_maxsz + \
 127					 encode_savefh_maxsz + \
 128					 encode_putfh_maxsz + \
 129					 encode_copy_maxsz + \
 130					 encode_commit_maxsz)
 131#define NFS4_dec_copy_sz		(compound_decode_hdr_maxsz + \
 132					 decode_sequence_maxsz + \
 133					 decode_putfh_maxsz + \
 134					 decode_savefh_maxsz + \
 135					 decode_putfh_maxsz + \
 136					 decode_copy_maxsz + \
 137					 decode_commit_maxsz)
 138#define NFS4_enc_offload_cancel_sz	(compound_encode_hdr_maxsz + \
 139					 encode_sequence_maxsz + \
 140					 encode_putfh_maxsz + \
 141					 encode_offload_cancel_maxsz)
 142#define NFS4_dec_offload_cancel_sz	(compound_decode_hdr_maxsz + \
 143					 decode_sequence_maxsz + \
 144					 decode_putfh_maxsz + \
 145					 decode_offload_cancel_maxsz)
 146#define NFS4_enc_copy_notify_sz		(compound_encode_hdr_maxsz + \
 147					 encode_sequence_maxsz + \
 148					 encode_putfh_maxsz + \
 149					 encode_copy_notify_maxsz)
 150#define NFS4_dec_copy_notify_sz		(compound_decode_hdr_maxsz + \
 151					 decode_sequence_maxsz + \
 152					 decode_putfh_maxsz + \
 153					 decode_copy_notify_maxsz)
 154#define NFS4_enc_deallocate_sz		(compound_encode_hdr_maxsz + \
 155					 encode_sequence_maxsz + \
 156					 encode_putfh_maxsz + \
 157					 encode_deallocate_maxsz + \
 158					 encode_getattr_maxsz)
 159#define NFS4_dec_deallocate_sz		(compound_decode_hdr_maxsz + \
 160					 decode_sequence_maxsz + \
 161					 decode_putfh_maxsz + \
 162					 decode_deallocate_maxsz + \
 163					 decode_getattr_maxsz)
 164#define NFS4_enc_read_plus_sz		(compound_encode_hdr_maxsz + \
 165					 encode_sequence_maxsz + \
 166					 encode_putfh_maxsz + \
 167					 encode_read_plus_maxsz)
 168#define NFS4_dec_read_plus_sz		(compound_decode_hdr_maxsz + \
 169					 decode_sequence_maxsz + \
 170					 decode_putfh_maxsz + \
 171					 decode_read_plus_maxsz)
 172#define NFS4_enc_seek_sz		(compound_encode_hdr_maxsz + \
 173					 encode_sequence_maxsz + \
 174					 encode_putfh_maxsz + \
 175					 encode_seek_maxsz)
 176#define NFS4_dec_seek_sz		(compound_decode_hdr_maxsz + \
 177					 decode_sequence_maxsz + \
 178					 decode_putfh_maxsz + \
 179					 decode_seek_maxsz)
 180#define NFS4_enc_layoutstats_sz		(compound_encode_hdr_maxsz + \
 181					 encode_sequence_maxsz + \
 182					 encode_putfh_maxsz + \
 183					 PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz)
 184#define NFS4_dec_layoutstats_sz		(compound_decode_hdr_maxsz + \
 185					 decode_sequence_maxsz + \
 186					 decode_putfh_maxsz + \
 187					 PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz)
 188#define NFS4_enc_layouterror_sz		(compound_encode_hdr_maxsz + \
 189					 encode_sequence_maxsz + \
 190					 encode_putfh_maxsz + \
 191					 NFS42_LAYOUTERROR_MAX * \
 192					 encode_layouterror_maxsz)
 193#define NFS4_dec_layouterror_sz		(compound_decode_hdr_maxsz + \
 194					 decode_sequence_maxsz + \
 195					 decode_putfh_maxsz + \
 196					 NFS42_LAYOUTERROR_MAX * \
 197					 decode_layouterror_maxsz)
 198#define NFS4_enc_clone_sz		(compound_encode_hdr_maxsz + \
 199					 encode_sequence_maxsz + \
 200					 encode_putfh_maxsz + \
 201					 encode_savefh_maxsz + \
 202					 encode_putfh_maxsz + \
 203					 encode_clone_maxsz + \
 204					 encode_getattr_maxsz)
 205#define NFS4_dec_clone_sz		(compound_decode_hdr_maxsz + \
 206					 decode_sequence_maxsz + \
 207					 decode_putfh_maxsz + \
 208					 decode_savefh_maxsz + \
 209					 decode_putfh_maxsz + \
 210					 decode_clone_maxsz + \
 211					 decode_getattr_maxsz)
 212#define NFS4_enc_getxattr_sz		(compound_encode_hdr_maxsz + \
 213					 encode_sequence_maxsz + \
 214					 encode_putfh_maxsz + \
 215					 encode_getxattr_maxsz)
 216#define NFS4_dec_getxattr_sz		(compound_decode_hdr_maxsz + \
 217					 decode_sequence_maxsz + \
 218					 decode_putfh_maxsz + \
 219					 decode_getxattr_maxsz)
 220#define NFS4_enc_setxattr_sz		(compound_encode_hdr_maxsz + \
 221					 encode_sequence_maxsz + \
 222					 encode_putfh_maxsz + \
 223					 encode_setxattr_maxsz + \
 224					 encode_getattr_maxsz)
 225#define NFS4_dec_setxattr_sz		(compound_decode_hdr_maxsz + \
 226					 decode_sequence_maxsz + \
 227					 decode_putfh_maxsz + \
 228					 decode_setxattr_maxsz + \
 229					 decode_getattr_maxsz)
 230#define NFS4_enc_listxattrs_sz		(compound_encode_hdr_maxsz + \
 231					 encode_sequence_maxsz + \
 232					 encode_putfh_maxsz + \
 233					 encode_listxattrs_maxsz)
 234#define NFS4_dec_listxattrs_sz		(compound_decode_hdr_maxsz + \
 235					 decode_sequence_maxsz + \
 236					 decode_putfh_maxsz + \
 237					 decode_listxattrs_maxsz)
 238#define NFS4_enc_removexattr_sz		(compound_encode_hdr_maxsz + \
 239					 encode_sequence_maxsz + \
 240					 encode_putfh_maxsz + \
 241					 encode_removexattr_maxsz)
 242#define NFS4_dec_removexattr_sz		(compound_decode_hdr_maxsz + \
 243					 decode_sequence_maxsz + \
 244					 decode_putfh_maxsz + \
 245					 decode_removexattr_maxsz)
 246
 247/*
 248 * These values specify the maximum amount of data that is not
 249 * associated with the extended attribute name or extended
 250 * attribute list in the SETXATTR, GETXATTR and LISTXATTR
 251 * respectively.
 252 */
 253const u32 nfs42_maxsetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
 254					compound_encode_hdr_maxsz +
 255					encode_sequence_maxsz +
 256					encode_putfh_maxsz + 1 +
 257					nfs4_xattr_name_maxsz)
 258					* XDR_UNIT);
 259
 260const u32 nfs42_maxgetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
 261					compound_decode_hdr_maxsz +
 262					decode_sequence_maxsz +
 263					decode_putfh_maxsz + 1) * XDR_UNIT);
 264
 265const u32 nfs42_maxlistxattrs_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
 266					compound_decode_hdr_maxsz +
 267					decode_sequence_maxsz +
 268					decode_putfh_maxsz + 3) * XDR_UNIT);
 269
 270static void encode_fallocate(struct xdr_stream *xdr,
 271			     const struct nfs42_falloc_args *args)
 272{
 273	encode_nfs4_stateid(xdr, &args->falloc_stateid);
 274	encode_uint64(xdr, args->falloc_offset);
 275	encode_uint64(xdr, args->falloc_length);
 276}
 277
 278static void encode_allocate(struct xdr_stream *xdr,
 279			    const struct nfs42_falloc_args *args,
 280			    struct compound_hdr *hdr)
 281{
 282	encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
 283	encode_fallocate(xdr, args);
 284}
 285
 286static void encode_nl4_server(struct xdr_stream *xdr,
 287			      const struct nl4_server *ns)
 288{
 289	encode_uint32(xdr, ns->nl4_type);
 290	switch (ns->nl4_type) {
 291	case NL4_NAME:
 292	case NL4_URL:
 293		encode_string(xdr, ns->u.nl4_str_sz, ns->u.nl4_str);
 294		break;
 295	case NL4_NETADDR:
 296		encode_string(xdr, ns->u.nl4_addr.netid_len,
 297			      ns->u.nl4_addr.netid);
 298		encode_string(xdr, ns->u.nl4_addr.addr_len,
 299			      ns->u.nl4_addr.addr);
 300		break;
 301	default:
 302		WARN_ON_ONCE(1);
 303	}
 304}
 305
 306static void encode_copy(struct xdr_stream *xdr,
 307			const struct nfs42_copy_args *args,
 308			struct compound_hdr *hdr)
 309{
 310	encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr);
 311	encode_nfs4_stateid(xdr, &args->src_stateid);
 312	encode_nfs4_stateid(xdr, &args->dst_stateid);
 313
 314	encode_uint64(xdr, args->src_pos);
 315	encode_uint64(xdr, args->dst_pos);
 316	encode_uint64(xdr, args->count);
 317
 318	encode_uint32(xdr, 1); /* consecutive = true */
 319	encode_uint32(xdr, args->sync);
 320	if (args->cp_src == NULL) { /* intra-ssc */
 321		encode_uint32(xdr, 0); /* no src server list */
 322		return;
 323	}
 324	encode_uint32(xdr, 1); /* supporting 1 server */
 325	encode_nl4_server(xdr, args->cp_src);
 326}
 327
 328static void encode_copy_commit(struct xdr_stream *xdr,
 329			  const struct nfs42_copy_args *args,
 330			  struct compound_hdr *hdr)
 331{
 332	__be32 *p;
 333
 334	encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
 335	p = reserve_space(xdr, 12);
 336	p = xdr_encode_hyper(p, args->dst_pos);
 337	*p = cpu_to_be32(args->count);
 338}
 339
 340static void encode_offload_cancel(struct xdr_stream *xdr,
 341				  const struct nfs42_offload_status_args *args,
 342				  struct compound_hdr *hdr)
 343{
 344	encode_op_hdr(xdr, OP_OFFLOAD_CANCEL, decode_offload_cancel_maxsz, hdr);
 345	encode_nfs4_stateid(xdr, &args->osa_stateid);
 346}
 347
 348static void encode_copy_notify(struct xdr_stream *xdr,
 349			       const struct nfs42_copy_notify_args *args,
 350			       struct compound_hdr *hdr)
 351{
 352	encode_op_hdr(xdr, OP_COPY_NOTIFY, decode_copy_notify_maxsz, hdr);
 353	encode_nfs4_stateid(xdr, &args->cna_src_stateid);
 354	encode_nl4_server(xdr, &args->cna_dst);
 355}
 356
 357static void encode_deallocate(struct xdr_stream *xdr,
 358			      const struct nfs42_falloc_args *args,
 359			      struct compound_hdr *hdr)
 360{
 361	encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
 362	encode_fallocate(xdr, args);
 363}
 364
 365static void encode_read_plus(struct xdr_stream *xdr,
 366			     const struct nfs_pgio_args *args,
 367			     struct compound_hdr *hdr)
 368{
 369	encode_op_hdr(xdr, OP_READ_PLUS, decode_read_plus_maxsz, hdr);
 370	encode_nfs4_stateid(xdr, &args->stateid);
 371	encode_uint64(xdr, args->offset);
 372	encode_uint32(xdr, args->count);
 373}
 374
 375static void encode_seek(struct xdr_stream *xdr,
 376			const struct nfs42_seek_args *args,
 377			struct compound_hdr *hdr)
 378{
 379	encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
 380	encode_nfs4_stateid(xdr, &args->sa_stateid);
 381	encode_uint64(xdr, args->sa_offset);
 382	encode_uint32(xdr, args->sa_what);
 383}
 384
 385static void encode_layoutstats(struct xdr_stream *xdr,
 386			       const struct nfs42_layoutstat_args *args,
 387			       struct nfs42_layoutstat_devinfo *devinfo,
 388			       struct compound_hdr *hdr)
 389{
 390	__be32 *p;
 391
 392	encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
 393	p = reserve_space(xdr, 8 + 8);
 394	p = xdr_encode_hyper(p, devinfo->offset);
 395	p = xdr_encode_hyper(p, devinfo->length);
 396	encode_nfs4_stateid(xdr, &args->stateid);
 397	p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
 398	p = xdr_encode_hyper(p, devinfo->read_count);
 399	p = xdr_encode_hyper(p, devinfo->read_bytes);
 400	p = xdr_encode_hyper(p, devinfo->write_count);
 401	p = xdr_encode_hyper(p, devinfo->write_bytes);
 402	p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
 403			NFS4_DEVICEID4_SIZE);
 404	/* Encode layoutupdate4 */
 405	*p++ = cpu_to_be32(devinfo->layout_type);
 406	if (devinfo->ld_private.ops)
 407		devinfo->ld_private.ops->encode(xdr, args,
 408				&devinfo->ld_private);
 409	else
 410		encode_uint32(xdr, 0);
 411}
 412
 413static void encode_clone(struct xdr_stream *xdr,
 414			 const struct nfs42_clone_args *args,
 415			 struct compound_hdr *hdr)
 416{
 417	__be32 *p;
 418
 419	encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr);
 420	encode_nfs4_stateid(xdr, &args->src_stateid);
 421	encode_nfs4_stateid(xdr, &args->dst_stateid);
 422	p = reserve_space(xdr, 3*8);
 423	p = xdr_encode_hyper(p, args->src_offset);
 424	p = xdr_encode_hyper(p, args->dst_offset);
 425	xdr_encode_hyper(p, args->count);
 426}
 427
 428static void encode_device_error(struct xdr_stream *xdr,
 429				const struct nfs42_device_error *error)
 430{
 431	__be32 *p;
 432
 433	p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 2*4);
 434	p = xdr_encode_opaque_fixed(p, error->dev_id.data,
 435			NFS4_DEVICEID4_SIZE);
 436	*p++ = cpu_to_be32(error->status);
 437	*p = cpu_to_be32(error->opnum);
 438}
 439
 440static void encode_layouterror(struct xdr_stream *xdr,
 441			       const struct nfs42_layout_error *args,
 442			       struct compound_hdr *hdr)
 443{
 444	__be32 *p;
 445
 446	encode_op_hdr(xdr, OP_LAYOUTERROR, decode_layouterror_maxsz, hdr);
 447	p = reserve_space(xdr, 8 + 8);
 448	p = xdr_encode_hyper(p, args->offset);
 449	p = xdr_encode_hyper(p, args->length);
 450	encode_nfs4_stateid(xdr, &args->stateid);
 451	p = reserve_space(xdr, 4);
 452	*p = cpu_to_be32(1);
 453	encode_device_error(xdr, &args->errors[0]);
 454}
 455
 456static void encode_setxattr(struct xdr_stream *xdr,
 457			    const struct nfs42_setxattrargs *arg,
 458			    struct compound_hdr *hdr)
 459{
 460	__be32 *p;
 461
 462	BUILD_BUG_ON(XATTR_CREATE != SETXATTR4_CREATE);
 463	BUILD_BUG_ON(XATTR_REPLACE != SETXATTR4_REPLACE);
 464
 465	encode_op_hdr(xdr, OP_SETXATTR, decode_setxattr_maxsz, hdr);
 466	p = reserve_space(xdr, 4);
 467	*p = cpu_to_be32(arg->xattr_flags);
 468	encode_string(xdr, strlen(arg->xattr_name), arg->xattr_name);
 469	p = reserve_space(xdr, 4);
 470	*p = cpu_to_be32(arg->xattr_len);
 471	if (arg->xattr_len)
 472		xdr_write_pages(xdr, arg->xattr_pages, 0, arg->xattr_len);
 473}
 474
 475static void encode_getxattr(struct xdr_stream *xdr, const char *name,
 476			    struct compound_hdr *hdr)
 477{
 478	encode_op_hdr(xdr, OP_GETXATTR, decode_getxattr_maxsz, hdr);
 479	encode_string(xdr, strlen(name), name);
 480}
 481
 482static void encode_removexattr(struct xdr_stream *xdr, const char *name,
 483			       struct compound_hdr *hdr)
 484{
 485	encode_op_hdr(xdr, OP_REMOVEXATTR, decode_removexattr_maxsz, hdr);
 486	encode_string(xdr, strlen(name), name);
 487}
 488
 489static void encode_listxattrs(struct xdr_stream *xdr,
 490			     const struct nfs42_listxattrsargs *arg,
 491			     struct compound_hdr *hdr)
 492{
 493	__be32 *p;
 494
 495	encode_op_hdr(xdr, OP_LISTXATTRS, decode_listxattrs_maxsz, hdr);
 496
 497	p = reserve_space(xdr, 12);
 498	if (unlikely(!p))
 499		return;
 500
 501	p = xdr_encode_hyper(p, arg->cookie);
 502	/*
 503	 * RFC 8276 says to specify the full max length of the LISTXATTRS
 504	 * XDR reply. Count is set to the XDR length of the names array
 505	 * plus the EOF marker. So, add the cookie and the names count.
 506	 */
 507	*p = cpu_to_be32(arg->count + 8 + 4);
 508}
 509
 510/*
 511 * Encode ALLOCATE request
 512 */
 513static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
 514				  struct xdr_stream *xdr,
 515				  const void *data)
 516{
 517	const struct nfs42_falloc_args *args = data;
 518	struct compound_hdr hdr = {
 519		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 520	};
 521
 522	encode_compound_hdr(xdr, req, &hdr);
 523	encode_sequence(xdr, &args->seq_args, &hdr);
 524	encode_putfh(xdr, args->falloc_fh, &hdr);
 525	encode_allocate(xdr, args, &hdr);
 526	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
 527	encode_nops(&hdr);
 528}
 529
 
 
 
 
 
 
 
 
 
 
 
 
 530/*
 531 * Encode COPY request
 532 */
 533static void nfs4_xdr_enc_copy(struct rpc_rqst *req,
 534			      struct xdr_stream *xdr,
 535			      const void *data)
 536{
 537	const struct nfs42_copy_args *args = data;
 538	struct compound_hdr hdr = {
 539		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 540	};
 541
 542	encode_compound_hdr(xdr, req, &hdr);
 543	encode_sequence(xdr, &args->seq_args, &hdr);
 544	encode_putfh(xdr, args->src_fh, &hdr);
 545	encode_savefh(xdr, &hdr);
 546	encode_putfh(xdr, args->dst_fh, &hdr);
 547	encode_copy(xdr, args, &hdr);
 548	if (args->sync)
 549		encode_copy_commit(xdr, args, &hdr);
 550	encode_nops(&hdr);
 551}
 552
 553/*
 554 * Encode OFFLOAD_CANEL request
 555 */
 556static void nfs4_xdr_enc_offload_cancel(struct rpc_rqst *req,
 557					struct xdr_stream *xdr,
 558					const void *data)
 559{
 560	const struct nfs42_offload_status_args *args = data;
 561	struct compound_hdr hdr = {
 562		.minorversion = nfs4_xdr_minorversion(&args->osa_seq_args),
 563	};
 564
 565	encode_compound_hdr(xdr, req, &hdr);
 566	encode_sequence(xdr, &args->osa_seq_args, &hdr);
 567	encode_putfh(xdr, args->osa_src_fh, &hdr);
 568	encode_offload_cancel(xdr, args, &hdr);
 569	encode_nops(&hdr);
 570}
 571
 572/*
 573 * Encode COPY_NOTIFY request
 574 */
 575static void nfs4_xdr_enc_copy_notify(struct rpc_rqst *req,
 576				     struct xdr_stream *xdr,
 577				     const void *data)
 578{
 579	const struct nfs42_copy_notify_args *args = data;
 580	struct compound_hdr hdr = {
 581		.minorversion = nfs4_xdr_minorversion(&args->cna_seq_args),
 582	};
 583
 584	encode_compound_hdr(xdr, req, &hdr);
 585	encode_sequence(xdr, &args->cna_seq_args, &hdr);
 586	encode_putfh(xdr, args->cna_src_fh, &hdr);
 587	encode_copy_notify(xdr, args, &hdr);
 588	encode_nops(&hdr);
 589}
 590
 591/*
 592 * Encode DEALLOCATE request
 593 */
 594static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
 595				    struct xdr_stream *xdr,
 596				    const void *data)
 597{
 598	const struct nfs42_falloc_args *args = data;
 599	struct compound_hdr hdr = {
 600		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 601	};
 602
 603	encode_compound_hdr(xdr, req, &hdr);
 604	encode_sequence(xdr, &args->seq_args, &hdr);
 605	encode_putfh(xdr, args->falloc_fh, &hdr);
 606	encode_deallocate(xdr, args, &hdr);
 607	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
 608	encode_nops(&hdr);
 609}
 610
 611/*
 612 * Encode READ_PLUS request
 613 */
 614static void nfs4_xdr_enc_read_plus(struct rpc_rqst *req,
 615				   struct xdr_stream *xdr,
 616				   const void *data)
 617{
 618	const struct nfs_pgio_args *args = data;
 619	struct compound_hdr hdr = {
 620		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 621	};
 622
 623	encode_compound_hdr(xdr, req, &hdr);
 624	encode_sequence(xdr, &args->seq_args, &hdr);
 625	encode_putfh(xdr, args->fh, &hdr);
 626	encode_read_plus(xdr, args, &hdr);
 627
 628	rpc_prepare_reply_pages(req, args->pages, args->pgbase, args->count,
 629				hdr.replen - READ_PLUS_SEGMENT_SIZE_DIFF);
 630	encode_nops(&hdr);
 631}
 632
 633/*
 634 * Encode SEEK request
 635 */
 636static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
 637			      struct xdr_stream *xdr,
 638			      const void *data)
 639{
 640	const struct nfs42_seek_args *args = data;
 641	struct compound_hdr hdr = {
 642		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 643	};
 644
 645	encode_compound_hdr(xdr, req, &hdr);
 646	encode_sequence(xdr, &args->seq_args, &hdr);
 647	encode_putfh(xdr, args->sa_fh, &hdr);
 648	encode_seek(xdr, args, &hdr);
 649	encode_nops(&hdr);
 650}
 651
 652/*
 653 * Encode LAYOUTSTATS request
 654 */
 655static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
 656				     struct xdr_stream *xdr,
 657				     const void *data)
 658{
 659	const struct nfs42_layoutstat_args *args = data;
 660	int i;
 661
 662	struct compound_hdr hdr = {
 663		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 664	};
 665
 666	encode_compound_hdr(xdr, req, &hdr);
 667	encode_sequence(xdr, &args->seq_args, &hdr);
 668	encode_putfh(xdr, args->fh, &hdr);
 669	WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
 670	for (i = 0; i < args->num_dev; i++)
 671		encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
 672	encode_nops(&hdr);
 673}
 674
 675/*
 676 * Encode CLONE request
 677 */
 678static void nfs4_xdr_enc_clone(struct rpc_rqst *req,
 679			       struct xdr_stream *xdr,
 680			       const void *data)
 681{
 682	const struct nfs42_clone_args *args = data;
 683	struct compound_hdr hdr = {
 684		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 685	};
 686
 687	encode_compound_hdr(xdr, req, &hdr);
 688	encode_sequence(xdr, &args->seq_args, &hdr);
 689	encode_putfh(xdr, args->src_fh, &hdr);
 690	encode_savefh(xdr, &hdr);
 691	encode_putfh(xdr, args->dst_fh, &hdr);
 692	encode_clone(xdr, args, &hdr);
 693	encode_getfattr(xdr, args->dst_bitmask, &hdr);
 694	encode_nops(&hdr);
 695}
 696
 697/*
 698 * Encode LAYOUTERROR request
 699 */
 700static void nfs4_xdr_enc_layouterror(struct rpc_rqst *req,
 701				     struct xdr_stream *xdr,
 702				     const void *data)
 703{
 704	const struct nfs42_layouterror_args *args = data;
 705	struct compound_hdr hdr = {
 706		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 707	};
 708	int i;
 709
 710	encode_compound_hdr(xdr, req, &hdr);
 711	encode_sequence(xdr, &args->seq_args, &hdr);
 712	encode_putfh(xdr, NFS_FH(args->inode), &hdr);
 713	for (i = 0; i < args->num_errors; i++)
 714		encode_layouterror(xdr, &args->errors[i], &hdr);
 715	encode_nops(&hdr);
 716}
 717
 718/*
 719 * Encode SETXATTR request
 720 */
 721static void nfs4_xdr_enc_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
 722				  const void *data)
 723{
 724	const struct nfs42_setxattrargs *args = data;
 725	struct compound_hdr hdr = {
 726		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 727	};
 728
 729	encode_compound_hdr(xdr, req, &hdr);
 730	encode_sequence(xdr, &args->seq_args, &hdr);
 731	encode_putfh(xdr, args->fh, &hdr);
 732	encode_setxattr(xdr, args, &hdr);
 733	encode_getfattr(xdr, args->bitmask, &hdr);
 734	encode_nops(&hdr);
 735}
 736
 737/*
 738 * Encode GETXATTR request
 739 */
 740static void nfs4_xdr_enc_getxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
 741				  const void *data)
 742{
 743	const struct nfs42_getxattrargs *args = data;
 744	struct compound_hdr hdr = {
 745		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 746	};
 747	uint32_t replen;
 748
 749	encode_compound_hdr(xdr, req, &hdr);
 750	encode_sequence(xdr, &args->seq_args, &hdr);
 751	encode_putfh(xdr, args->fh, &hdr);
 752	replen = hdr.replen + op_decode_hdr_maxsz + 1;
 753	encode_getxattr(xdr, args->xattr_name, &hdr);
 754
 755	rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->xattr_len,
 756				replen);
 757
 758	encode_nops(&hdr);
 759}
 760
 761/*
 762 * Encode LISTXATTR request
 763 */
 764static void nfs4_xdr_enc_listxattrs(struct rpc_rqst *req,
 765				    struct xdr_stream *xdr, const void *data)
 766{
 767	const struct nfs42_listxattrsargs *args = data;
 768	struct compound_hdr hdr = {
 769		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 770	};
 771	uint32_t replen;
 772
 773	encode_compound_hdr(xdr, req, &hdr);
 774	encode_sequence(xdr, &args->seq_args, &hdr);
 775	encode_putfh(xdr, args->fh, &hdr);
 776	replen = hdr.replen + op_decode_hdr_maxsz + 2 + 1;
 777	encode_listxattrs(xdr, args, &hdr);
 778
 779	rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->count, replen);
 780
 781	encode_nops(&hdr);
 782}
 783
 784/*
 785 * Encode REMOVEXATTR request
 786 */
 787static void nfs4_xdr_enc_removexattr(struct rpc_rqst *req,
 788				     struct xdr_stream *xdr, const void *data)
 789{
 790	const struct nfs42_removexattrargs *args = data;
 791	struct compound_hdr hdr = {
 792		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
 793	};
 794
 795	encode_compound_hdr(xdr, req, &hdr);
 796	encode_sequence(xdr, &args->seq_args, &hdr);
 797	encode_putfh(xdr, args->fh, &hdr);
 798	encode_removexattr(xdr, args->xattr_name, &hdr);
 799	encode_nops(&hdr);
 800}
 801
 802static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
 803{
 804	return decode_op_hdr(xdr, OP_ALLOCATE);
 805}
 806
 807static int decode_write_response(struct xdr_stream *xdr,
 808				 struct nfs42_write_res *res)
 809{
 810	__be32 *p;
 811	int status, count;
 812
 813	p = xdr_inline_decode(xdr, 4);
 814	if (unlikely(!p))
 815		return -EIO;
 816	count = be32_to_cpup(p);
 817	if (count > 1)
 
 
 
 
 
 
 818		return -EREMOTEIO;
 819	else if (count == 1) {
 820		status = decode_opaque_fixed(xdr, &res->stateid,
 821				NFS4_STATEID_SIZE);
 822		if (unlikely(status))
 823			return -EIO;
 824	}
 825	p = xdr_inline_decode(xdr, 8 + 4);
 826	if (unlikely(!p))
 827		return -EIO;
 828	p = xdr_decode_hyper(p, &res->count);
 829	res->verifier.committed = be32_to_cpup(p);
 830	return decode_verifier(xdr, &res->verifier.verifier);
 831}
 832
 833static int decode_nl4_server(struct xdr_stream *xdr, struct nl4_server *ns)
 834{
 835	struct nfs42_netaddr *naddr;
 836	uint32_t dummy;
 837	char *dummy_str;
 838	__be32 *p;
 839	int status;
 840
 841	/* nl_type */
 842	p = xdr_inline_decode(xdr, 4);
 843	if (unlikely(!p))
 844		return -EIO;
 845	ns->nl4_type = be32_to_cpup(p);
 846	switch (ns->nl4_type) {
 847	case NL4_NAME:
 848	case NL4_URL:
 849		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
 850		if (unlikely(status))
 851			return status;
 852		if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
 853			return -EIO;
 854		memcpy(&ns->u.nl4_str, dummy_str, dummy);
 855		ns->u.nl4_str_sz = dummy;
 856		break;
 857	case NL4_NETADDR:
 858		naddr = &ns->u.nl4_addr;
 859
 860		/* netid string */
 861		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
 862		if (unlikely(status))
 863			return status;
 864		if (unlikely(dummy > RPCBIND_MAXNETIDLEN))
 865			return -EIO;
 866		naddr->netid_len = dummy;
 867		memcpy(naddr->netid, dummy_str, naddr->netid_len);
 868
 869		/* uaddr string */
 870		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
 871		if (unlikely(status))
 872			return status;
 873		if (unlikely(dummy > RPCBIND_MAXUADDRLEN))
 874			return -EIO;
 875		naddr->addr_len = dummy;
 876		memcpy(naddr->addr, dummy_str, naddr->addr_len);
 877		break;
 878	default:
 879		WARN_ON_ONCE(1);
 880		return -EIO;
 881	}
 882	return 0;
 883}
 884
 885static int decode_copy_requirements(struct xdr_stream *xdr,
 886				    struct nfs42_copy_res *res) {
 887	__be32 *p;
 888
 889	p = xdr_inline_decode(xdr, 4 + 4);
 890	if (unlikely(!p))
 891		return -EIO;
 892
 893	res->consecutive = be32_to_cpup(p++);
 894	res->synchronous = be32_to_cpup(p++);
 895	return 0;
 
 
 
 896}
 897
 898static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
 899{
 900	int status;
 901
 902	status = decode_op_hdr(xdr, OP_COPY);
 903	if (status == NFS4ERR_OFFLOAD_NO_REQS) {
 904		status = decode_copy_requirements(xdr, res);
 905		if (status)
 906			return status;
 907		return NFS4ERR_OFFLOAD_NO_REQS;
 908	} else if (status)
 909		return status;
 910
 911	status = decode_write_response(xdr, &res->write_res);
 912	if (status)
 913		return status;
 914
 915	return decode_copy_requirements(xdr, res);
 916}
 917
 918static int decode_offload_cancel(struct xdr_stream *xdr,
 919				 struct nfs42_offload_status_res *res)
 920{
 921	return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL);
 922}
 923
 924static int decode_copy_notify(struct xdr_stream *xdr,
 925			      struct nfs42_copy_notify_res *res)
 926{
 927	__be32 *p;
 928	int status, count;
 929
 930	status = decode_op_hdr(xdr, OP_COPY_NOTIFY);
 931	if (status)
 932		return status;
 933	/* cnr_lease_time */
 934	p = xdr_inline_decode(xdr, 12);
 935	if (unlikely(!p))
 936		return -EIO;
 937	p = xdr_decode_hyper(p, &res->cnr_lease_time.seconds);
 938	res->cnr_lease_time.nseconds = be32_to_cpup(p);
 939
 940	status = decode_opaque_fixed(xdr, &res->cnr_stateid, NFS4_STATEID_SIZE);
 941	if (unlikely(status))
 942		return -EIO;
 943
 944	/* number of source addresses */
 945	p = xdr_inline_decode(xdr, 4);
 946	if (unlikely(!p))
 947		return -EIO;
 948
 949	count = be32_to_cpup(p);
 950	if (count > 1)
 951		pr_warn("NFS: %s: nsvr %d > Supported. Use first servers\n",
 952			 __func__, count);
 953
 954	status = decode_nl4_server(xdr, &res->cnr_src);
 955	if (unlikely(status))
 956		return -EIO;
 957	return 0;
 958}
 959
 960static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
 961{
 962	return decode_op_hdr(xdr, OP_DEALLOCATE);
 963}
 964
 965struct read_plus_segment {
 966	enum data_content4 type;
 967	uint64_t offset;
 968	union {
 969		struct {
 970			uint64_t length;
 971		} hole;
 972
 973		struct {
 974			uint32_t length;
 975			unsigned int from;
 976		} data;
 977	};
 978};
 979
 980static inline uint64_t read_plus_segment_length(struct read_plus_segment *seg)
 981{
 982	return seg->type == NFS4_CONTENT_DATA ? seg->data.length : seg->hole.length;
 983}
 984
 985static int decode_read_plus_segment(struct xdr_stream *xdr,
 986				    struct read_plus_segment *seg)
 987{
 988	__be32 *p;
 989
 990	p = xdr_inline_decode(xdr, 4);
 991	if (!p)
 992		return -EIO;
 993	seg->type = be32_to_cpup(p++);
 994
 995	p = xdr_inline_decode(xdr, seg->type == NFS4_CONTENT_DATA ? 12 : 16);
 996	if (!p)
 997		return -EIO;
 998	p = xdr_decode_hyper(p, &seg->offset);
 999
1000	if (seg->type == NFS4_CONTENT_DATA) {
1001		struct xdr_buf buf;
1002		uint32_t len = be32_to_cpup(p);
1003
1004		seg->data.length = len;
1005		seg->data.from = xdr_stream_pos(xdr);
1006
1007		if (!xdr_stream_subsegment(xdr, &buf, xdr_align_size(len)))
1008			return -EIO;
1009	} else if (seg->type == NFS4_CONTENT_HOLE) {
1010		xdr_decode_hyper(p, &seg->hole.length);
1011	} else
1012		return -EINVAL;
1013	return 0;
1014}
1015
1016static int process_read_plus_segment(struct xdr_stream *xdr,
1017				     struct nfs_pgio_args *args,
1018				     struct nfs_pgio_res *res,
1019				     struct read_plus_segment *seg)
1020{
1021	unsigned long offset = seg->offset;
1022	unsigned long length = read_plus_segment_length(seg);
1023	unsigned int bufpos;
1024
1025	if (offset + length < args->offset)
1026		return 0;
1027	else if (offset > args->offset + args->count) {
1028		res->eof = 0;
1029		return 0;
1030	} else if (offset < args->offset) {
1031		length -= (args->offset - offset);
1032		offset = args->offset;
1033	} else if (offset + length > args->offset + args->count) {
1034		length = (args->offset + args->count) - offset;
1035		res->eof = 0;
1036	}
1037
1038	bufpos = xdr->buf->head[0].iov_len + (offset - args->offset);
1039	if (seg->type == NFS4_CONTENT_HOLE)
1040		return xdr_stream_zero(xdr, bufpos, length);
1041	else
1042		return xdr_stream_move_subsegment(xdr, seg->data.from, bufpos, length);
1043}
1044
1045static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
1046{
1047	struct nfs_pgio_header *hdr =
1048		container_of(res, struct nfs_pgio_header, res);
1049	struct nfs_pgio_args *args = &hdr->args;
1050	uint32_t segments;
1051	struct read_plus_segment *segs;
1052	int status, i;
1053	__be32 *p;
1054
1055	status = decode_op_hdr(xdr, OP_READ_PLUS);
1056	if (status)
1057		return status;
1058
1059	p = xdr_inline_decode(xdr, 4 + 4);
1060	if (unlikely(!p))
1061		return -EIO;
1062
1063	res->count = 0;
1064	res->eof = be32_to_cpup(p++);
1065	segments = be32_to_cpup(p++);
1066	if (segments == 0)
1067		return 0;
1068
1069	segs = kmalloc_array(segments, sizeof(*segs), GFP_KERNEL);
1070	if (!segs)
1071		return -ENOMEM;
1072
1073	for (i = 0; i < segments; i++) {
1074		status = decode_read_plus_segment(xdr, &segs[i]);
1075		if (status < 0)
1076			goto out;
1077	}
1078
1079	xdr_set_pagelen(xdr, xdr_align_size(args->count));
1080	for (i = segments; i > 0; i--)
1081		res->count += process_read_plus_segment(xdr, args, res, &segs[i-1]);
1082	status = 0;
1083
1084out:
1085	kfree(segs);
1086	return status;
1087}
1088
1089static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
1090{
1091	int status;
1092	__be32 *p;
1093
1094	status = decode_op_hdr(xdr, OP_SEEK);
1095	if (status)
1096		return status;
1097
1098	p = xdr_inline_decode(xdr, 4 + 8);
1099	if (unlikely(!p))
1100		return -EIO;
1101
1102	res->sr_eof = be32_to_cpup(p++);
1103	p = xdr_decode_hyper(p, &res->sr_offset);
1104	return 0;
 
 
 
 
1105}
1106
1107static int decode_layoutstats(struct xdr_stream *xdr)
1108{
1109	return decode_op_hdr(xdr, OP_LAYOUTSTATS);
1110}
1111
1112static int decode_clone(struct xdr_stream *xdr)
1113{
1114	return decode_op_hdr(xdr, OP_CLONE);
1115}
1116
1117static int decode_layouterror(struct xdr_stream *xdr)
1118{
1119	return decode_op_hdr(xdr, OP_LAYOUTERROR);
1120}
1121
1122static int decode_setxattr(struct xdr_stream *xdr,
1123			   struct nfs4_change_info *cinfo)
1124{
1125	int status;
1126
1127	status = decode_op_hdr(xdr, OP_SETXATTR);
1128	if (status)
1129		goto out;
1130	status = decode_change_info(xdr, cinfo);
1131out:
1132	return status;
1133}
1134
1135static int decode_getxattr(struct xdr_stream *xdr,
1136			   struct nfs42_getxattrres *res,
1137			   struct rpc_rqst *req)
1138{
1139	int status;
1140	__be32 *p;
1141	u32 len, rdlen;
1142
1143	status = decode_op_hdr(xdr, OP_GETXATTR);
1144	if (status)
1145		return status;
1146
1147	p = xdr_inline_decode(xdr, 4);
1148	if (unlikely(!p))
1149		return -EIO;
1150
1151	len = be32_to_cpup(p);
1152
1153	/*
1154	 * Only check against the page length here. The actual
1155	 * requested length may be smaller, but that is only
1156	 * checked against after possibly caching a valid reply.
1157	 */
1158	if (len > req->rq_rcv_buf.page_len)
1159		return -ERANGE;
1160
1161	res->xattr_len = len;
1162
1163	if (len > 0) {
1164		rdlen = xdr_read_pages(xdr, len);
1165		if (rdlen < len)
1166			return -EIO;
1167	}
1168
1169	return 0;
1170}
1171
1172static int decode_removexattr(struct xdr_stream *xdr,
1173			   struct nfs4_change_info *cinfo)
1174{
1175	int status;
1176
1177	status = decode_op_hdr(xdr, OP_REMOVEXATTR);
1178	if (status)
1179		goto out;
1180
1181	status = decode_change_info(xdr, cinfo);
1182out:
1183	return status;
1184}
1185
1186static int decode_listxattrs(struct xdr_stream *xdr,
1187			    struct nfs42_listxattrsres *res)
1188{
1189	int status;
1190	__be32 *p;
1191	u32 count, len, ulen;
1192	size_t left, copied;
1193	char *buf;
1194
1195	status = decode_op_hdr(xdr, OP_LISTXATTRS);
1196	if (status) {
1197		/*
1198		 * Special case: for LISTXATTRS, NFS4ERR_TOOSMALL
1199		 * should be translated to ERANGE.
1200		 */
1201		if (status == -ETOOSMALL)
1202			status = -ERANGE;
1203		/*
1204		 * Special case: for LISTXATTRS, NFS4ERR_NOXATTR
1205		 * should be translated to success with zero-length reply.
1206		 */
1207		if (status == -ENODATA) {
1208			res->eof = true;
1209			status = 0;
1210		}
1211		goto out;
1212	}
1213
1214	p = xdr_inline_decode(xdr, 8);
1215	if (unlikely(!p))
1216		return -EIO;
1217
1218	xdr_decode_hyper(p, &res->cookie);
1219
1220	p = xdr_inline_decode(xdr, 4);
1221	if (unlikely(!p))
1222		return -EIO;
1223
1224	left = res->xattr_len;
1225	buf = res->xattr_buf;
1226
1227	count = be32_to_cpup(p);
1228	copied = 0;
1229
1230	/*
1231	 * We have asked for enough room to encode the maximum number
1232	 * of possible attribute names, so everything should fit.
1233	 *
1234	 * But, don't rely on that assumption. Just decode entries
1235	 * until they don't fit anymore, just in case the server did
1236	 * something odd.
1237	 */
1238	while (count--) {
1239		p = xdr_inline_decode(xdr, 4);
1240		if (unlikely(!p))
1241			return -EIO;
1242
1243		len = be32_to_cpup(p);
1244		if (len > (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) {
1245			status = -ERANGE;
1246			goto out;
1247		}
1248
1249		p = xdr_inline_decode(xdr, len);
1250		if (unlikely(!p))
1251			return -EIO;
1252
1253		ulen = len + XATTR_USER_PREFIX_LEN + 1;
1254		if (buf) {
1255			if (ulen > left) {
1256				status = -ERANGE;
1257				goto out;
1258			}
1259
1260			memcpy(buf, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
1261			memcpy(buf + XATTR_USER_PREFIX_LEN, p, len);
1262
1263			buf[ulen - 1] = 0;
1264			buf += ulen;
1265			left -= ulen;
1266		}
1267		copied += ulen;
1268	}
1269
1270	p = xdr_inline_decode(xdr, 4);
1271	if (unlikely(!p))
1272		return -EIO;
1273
1274	res->eof = be32_to_cpup(p);
1275	res->copied = copied;
1276
1277out:
1278	if (status == -ERANGE && res->xattr_len == XATTR_LIST_MAX)
1279		status = -E2BIG;
1280
1281	return status;
1282}
1283
1284/*
1285 * Decode ALLOCATE request
1286 */
1287static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
1288				 struct xdr_stream *xdr,
1289				 void *data)
1290{
1291	struct nfs42_falloc_res *res = data;
1292	struct compound_hdr hdr;
1293	int status;
1294
1295	status = decode_compound_hdr(xdr, &hdr);
1296	if (status)
1297		goto out;
1298	status = decode_sequence(xdr, &res->seq_res, rqstp);
1299	if (status)
1300		goto out;
1301	status = decode_putfh(xdr);
1302	if (status)
1303		goto out;
1304	status = decode_allocate(xdr, res);
1305	if (status)
1306		goto out;
1307	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
1308out:
1309	return status;
1310}
1311
1312/*
1313 * Decode COPY response
1314 */
1315static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
1316			     struct xdr_stream *xdr,
1317			     void *data)
1318{
1319	struct nfs42_copy_res *res = data;
1320	struct compound_hdr hdr;
1321	int status;
1322
1323	status = decode_compound_hdr(xdr, &hdr);
1324	if (status)
1325		goto out;
1326	status = decode_sequence(xdr, &res->seq_res, rqstp);
1327	if (status)
1328		goto out;
1329	status = decode_putfh(xdr);
1330	if (status)
1331		goto out;
1332	status = decode_savefh(xdr);
1333	if (status)
1334		goto out;
1335	status = decode_putfh(xdr);
1336	if (status)
1337		goto out;
1338	status = decode_copy(xdr, res);
1339	if (status)
1340		goto out;
1341	if (res->commit_res.verf)
1342		status = decode_commit(xdr, &res->commit_res);
1343out:
1344	return status;
1345}
1346
1347/*
1348 * Decode OFFLOAD_CANCEL response
1349 */
1350static int nfs4_xdr_dec_offload_cancel(struct rpc_rqst *rqstp,
1351				       struct xdr_stream *xdr,
1352				       void *data)
1353{
1354	struct nfs42_offload_status_res *res = data;
1355	struct compound_hdr hdr;
1356	int status;
1357
1358	status = decode_compound_hdr(xdr, &hdr);
1359	if (status)
1360		goto out;
1361	status = decode_sequence(xdr, &res->osr_seq_res, rqstp);
1362	if (status)
1363		goto out;
1364	status = decode_putfh(xdr);
1365	if (status)
1366		goto out;
1367	status = decode_offload_cancel(xdr, res);
1368
1369out:
1370	return status;
1371}
1372
1373/*
1374 * Decode COPY_NOTIFY response
1375 */
1376static int nfs4_xdr_dec_copy_notify(struct rpc_rqst *rqstp,
1377				    struct xdr_stream *xdr,
1378				    void *data)
1379{
1380	struct nfs42_copy_notify_res *res = data;
1381	struct compound_hdr hdr;
1382	int status;
1383
1384	status = decode_compound_hdr(xdr, &hdr);
1385	if (status)
1386		goto out;
1387	status = decode_sequence(xdr, &res->cnr_seq_res, rqstp);
1388	if (status)
1389		goto out;
1390	status = decode_putfh(xdr);
1391	if (status)
1392		goto out;
1393	status = decode_copy_notify(xdr, res);
1394
1395out:
1396	return status;
1397}
1398
1399/*
1400 * Decode DEALLOCATE request
1401 */
1402static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
1403				   struct xdr_stream *xdr,
1404				   void *data)
1405{
1406	struct nfs42_falloc_res *res = data;
1407	struct compound_hdr hdr;
1408	int status;
1409
1410	status = decode_compound_hdr(xdr, &hdr);
1411	if (status)
1412		goto out;
1413	status = decode_sequence(xdr, &res->seq_res, rqstp);
1414	if (status)
1415		goto out;
1416	status = decode_putfh(xdr);
1417	if (status)
1418		goto out;
1419	status = decode_deallocate(xdr, res);
1420	if (status)
1421		goto out;
1422	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
1423out:
1424	return status;
1425}
1426
1427/*
1428 * Decode READ_PLUS request
1429 */
1430static int nfs4_xdr_dec_read_plus(struct rpc_rqst *rqstp,
1431				  struct xdr_stream *xdr,
1432				  void *data)
1433{
1434	struct nfs_pgio_res *res = data;
1435	struct compound_hdr hdr;
1436	int status;
1437
1438	xdr_set_scratch_buffer(xdr, res->scratch, READ_PLUS_SCRATCH_SIZE);
1439
1440	status = decode_compound_hdr(xdr, &hdr);
1441	if (status)
1442		goto out;
1443	status = decode_sequence(xdr, &res->seq_res, rqstp);
1444	if (status)
1445		goto out;
1446	status = decode_putfh(xdr);
1447	if (status)
1448		goto out;
1449	status = decode_read_plus(xdr, res);
1450	if (!status)
1451		status = res->count;
1452out:
1453	return status;
1454}
1455
1456/*
1457 * Decode SEEK request
1458 */
1459static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
1460			     struct xdr_stream *xdr,
1461			     void *data)
1462{
1463	struct nfs42_seek_res *res = data;
1464	struct compound_hdr hdr;
1465	int status;
1466
1467	status = decode_compound_hdr(xdr, &hdr);
1468	if (status)
1469		goto out;
1470	status = decode_sequence(xdr, &res->seq_res, rqstp);
1471	if (status)
1472		goto out;
1473	status = decode_putfh(xdr);
1474	if (status)
1475		goto out;
1476	status = decode_seek(xdr, res);
1477out:
1478	return status;
1479}
1480
1481/*
1482 * Decode LAYOUTSTATS request
1483 */
1484static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
1485				    struct xdr_stream *xdr,
1486				    void *data)
1487{
1488	struct nfs42_layoutstat_res *res = data;
1489	struct compound_hdr hdr;
1490	int status, i;
1491
1492	status = decode_compound_hdr(xdr, &hdr);
1493	if (status)
1494		goto out;
1495	status = decode_sequence(xdr, &res->seq_res, rqstp);
1496	if (status)
1497		goto out;
1498	status = decode_putfh(xdr);
1499	if (status)
1500		goto out;
1501	WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
1502	for (i = 0; i < res->num_dev; i++) {
1503		status = decode_layoutstats(xdr);
1504		if (status)
1505			goto out;
1506	}
1507out:
1508	res->rpc_status = status;
1509	return status;
1510}
1511
1512/*
1513 * Decode CLONE request
1514 */
1515static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp,
1516			      struct xdr_stream *xdr,
1517			      void *data)
1518{
1519	struct nfs42_clone_res *res = data;
1520	struct compound_hdr hdr;
1521	int status;
1522
1523	status = decode_compound_hdr(xdr, &hdr);
1524	if (status)
1525		goto out;
1526	status = decode_sequence(xdr, &res->seq_res, rqstp);
1527	if (status)
1528		goto out;
1529	status = decode_putfh(xdr);
1530	if (status)
1531		goto out;
1532	status = decode_savefh(xdr);
1533	if (status)
1534		goto out;
1535	status = decode_putfh(xdr);
1536	if (status)
1537		goto out;
1538	status = decode_clone(xdr);
1539	if (status)
1540		goto out;
1541	decode_getfattr(xdr, res->dst_fattr, res->server);
1542out:
1543	res->rpc_status = status;
1544	return status;
1545}
1546
1547/*
1548 * Decode LAYOUTERROR request
1549 */
1550static int nfs4_xdr_dec_layouterror(struct rpc_rqst *rqstp,
1551				    struct xdr_stream *xdr,
1552				    void *data)
1553{
1554	struct nfs42_layouterror_res *res = data;
1555	struct compound_hdr hdr;
1556	int status, i;
1557
1558	status = decode_compound_hdr(xdr, &hdr);
1559	if (status)
1560		goto out;
1561	status = decode_sequence(xdr, &res->seq_res, rqstp);
1562	if (status)
1563		goto out;
1564	status = decode_putfh(xdr);
1565
1566	for (i = 0; i < res->num_errors && status == 0; i++)
1567		status = decode_layouterror(xdr);
1568out:
1569	res->rpc_status = status;
1570	return status;
1571}
1572
1573/*
1574 * Decode SETXATTR request
1575 */
1576static int nfs4_xdr_dec_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1577				 void *data)
1578{
1579	struct nfs42_setxattrres *res = data;
1580	struct compound_hdr hdr;
1581	int status;
1582
1583	status = decode_compound_hdr(xdr, &hdr);
1584	if (status)
1585		goto out;
1586	status = decode_sequence(xdr, &res->seq_res, req);
1587	if (status)
1588		goto out;
1589	status = decode_putfh(xdr);
1590	if (status)
1591		goto out;
1592	status = decode_setxattr(xdr, &res->cinfo);
1593	if (status)
1594		goto out;
1595	status = decode_getfattr(xdr, res->fattr, res->server);
1596out:
1597	return status;
1598}
1599
1600/*
1601 * Decode GETXATTR request
1602 */
1603static int nfs4_xdr_dec_getxattr(struct rpc_rqst *rqstp,
1604				 struct xdr_stream *xdr, void *data)
1605{
1606	struct nfs42_getxattrres *res = data;
1607	struct compound_hdr hdr;
1608	int status;
1609
1610	status = decode_compound_hdr(xdr, &hdr);
1611	if (status)
1612		goto out;
1613	status = decode_sequence(xdr, &res->seq_res, rqstp);
1614	if (status)
1615		goto out;
1616	status = decode_putfh(xdr);
1617	if (status)
1618		goto out;
1619	status = decode_getxattr(xdr, res, rqstp);
1620out:
1621	return status;
1622}
1623
1624/*
1625 * Decode LISTXATTR request
1626 */
1627static int nfs4_xdr_dec_listxattrs(struct rpc_rqst *rqstp,
1628				   struct xdr_stream *xdr, void *data)
1629{
1630	struct nfs42_listxattrsres *res = data;
1631	struct compound_hdr hdr;
1632	int status;
1633
1634	xdr_set_scratch_page(xdr, res->scratch);
1635
1636	status = decode_compound_hdr(xdr, &hdr);
1637	if (status)
1638		goto out;
1639	status = decode_sequence(xdr, &res->seq_res, rqstp);
1640	if (status)
1641		goto out;
1642	status = decode_putfh(xdr);
1643	if (status)
1644		goto out;
1645	status = decode_listxattrs(xdr, res);
1646out:
1647	return status;
1648}
1649
1650/*
1651 * Decode REMOVEXATTR request
1652 */
1653static int nfs4_xdr_dec_removexattr(struct rpc_rqst *req,
1654				    struct xdr_stream *xdr, void *data)
1655{
1656	struct nfs42_removexattrres *res = data;
1657	struct compound_hdr hdr;
1658	int status;
1659
1660	status = decode_compound_hdr(xdr, &hdr);
1661	if (status)
1662		goto out;
1663	status = decode_sequence(xdr, &res->seq_res, req);
1664	if (status)
1665		goto out;
1666	status = decode_putfh(xdr);
1667	if (status)
1668		goto out;
1669
1670	status = decode_removexattr(xdr, &res->cinfo);
1671out:
1672	return status;
1673}
1674#endif /* __LINUX_FS_NFS_NFS4_2XDR_H */