Linux Audio

Check our new training course

Embedded Linux training

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