1/*
2 * Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com>
3 */
4#ifndef __LINUX_FS_NFS_NFS4_2XDR_H
5#define __LINUX_FS_NFS_NFS4_2XDR_H
6
7#define encode_fallocate_maxsz		(encode_stateid_maxsz + \
8					 2 /* offset */ + \
9					 2 /* length */)
10#define encode_allocate_maxsz		(op_encode_hdr_maxsz + \
11					 encode_fallocate_maxsz)
12#define decode_allocate_maxsz		(op_decode_hdr_maxsz)
13#define encode_deallocate_maxsz		(op_encode_hdr_maxsz + \
14					 encode_fallocate_maxsz)
15#define decode_deallocate_maxsz		(op_decode_hdr_maxsz)
16#define encode_seek_maxsz		(op_encode_hdr_maxsz + \
17					 encode_stateid_maxsz + \
18					 2 /* offset */ + \
19					 1 /* whence */)
20#define decode_seek_maxsz		(op_decode_hdr_maxsz + \
21					 1 /* eof */ + \
22					 1 /* whence */ + \
23					 2 /* offset */ + \
24					 2 /* length */)
25
26#define NFS4_enc_allocate_sz		(compound_encode_hdr_maxsz + \
27					 encode_putfh_maxsz + \
28					 encode_allocate_maxsz + \
29					 encode_getattr_maxsz)
30#define NFS4_dec_allocate_sz		(compound_decode_hdr_maxsz + \
31					 decode_putfh_maxsz + \
32					 decode_allocate_maxsz + \
33					 decode_getattr_maxsz)
34#define NFS4_enc_deallocate_sz		(compound_encode_hdr_maxsz + \
35					 encode_putfh_maxsz + \
36					 encode_deallocate_maxsz + \
37					 encode_getattr_maxsz)
38#define NFS4_dec_deallocate_sz		(compound_decode_hdr_maxsz + \
39					 decode_putfh_maxsz + \
40					 decode_deallocate_maxsz + \
41					 decode_getattr_maxsz)
42#define NFS4_enc_seek_sz		(compound_encode_hdr_maxsz + \
43					 encode_putfh_maxsz + \
44					 encode_seek_maxsz)
45#define NFS4_dec_seek_sz		(compound_decode_hdr_maxsz + \
46					 decode_putfh_maxsz + \
47					 decode_seek_maxsz)
48
49
50static void encode_fallocate(struct xdr_stream *xdr,
51			     struct nfs42_falloc_args *args)
52{
53	encode_nfs4_stateid(xdr, &args->falloc_stateid);
54	encode_uint64(xdr, args->falloc_offset);
55	encode_uint64(xdr, args->falloc_length);
56}
57
58static void encode_allocate(struct xdr_stream *xdr,
59			    struct nfs42_falloc_args *args,
60			    struct compound_hdr *hdr)
61{
62	encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
63	encode_fallocate(xdr, args);
64}
65
66static void encode_deallocate(struct xdr_stream *xdr,
67			      struct nfs42_falloc_args *args,
68			      struct compound_hdr *hdr)
69{
70	encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
71	encode_fallocate(xdr, args);
72}
73
74static void encode_seek(struct xdr_stream *xdr,
75			struct nfs42_seek_args *args,
76			struct compound_hdr *hdr)
77{
78	encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
79	encode_nfs4_stateid(xdr, &args->sa_stateid);
80	encode_uint64(xdr, args->sa_offset);
81	encode_uint32(xdr, args->sa_what);
82}
83
84/*
85 * Encode ALLOCATE request
86 */
87static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
88				  struct xdr_stream *xdr,
89				  struct nfs42_falloc_args *args)
90{
91	struct compound_hdr hdr = {
92		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
93	};
94
95	encode_compound_hdr(xdr, req, &hdr);
96	encode_sequence(xdr, &args->seq_args, &hdr);
97	encode_putfh(xdr, args->falloc_fh, &hdr);
98	encode_allocate(xdr, args, &hdr);
99	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
100	encode_nops(&hdr);
101}
102
103/*
104 * Encode DEALLOCATE request
105 */
106static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
107				    struct xdr_stream *xdr,
108				    struct nfs42_falloc_args *args)
109{
110	struct compound_hdr hdr = {
111		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
112	};
113
114	encode_compound_hdr(xdr, req, &hdr);
115	encode_sequence(xdr, &args->seq_args, &hdr);
116	encode_putfh(xdr, args->falloc_fh, &hdr);
117	encode_deallocate(xdr, args, &hdr);
118	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
119	encode_nops(&hdr);
120}
121
122/*
123 * Encode SEEK request
124 */
125static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
126			      struct xdr_stream *xdr,
127			      struct nfs42_seek_args *args)
128{
129	struct compound_hdr hdr = {
130		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
131	};
132
133	encode_compound_hdr(xdr, req, &hdr);
134	encode_sequence(xdr, &args->seq_args, &hdr);
135	encode_putfh(xdr, args->sa_fh, &hdr);
136	encode_seek(xdr, args, &hdr);
137	encode_nops(&hdr);
138}
139
140static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
141{
142	return decode_op_hdr(xdr, OP_ALLOCATE);
143}
144
145static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
146{
147	return decode_op_hdr(xdr, OP_DEALLOCATE);
148}
149
150static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
151{
152	int status;
153	__be32 *p;
154
155	status = decode_op_hdr(xdr, OP_SEEK);
156	if (status)
157		return status;
158
159	p = xdr_inline_decode(xdr, 4 + 8);
160	if (unlikely(!p))
161		goto out_overflow;
162
163	res->sr_eof = be32_to_cpup(p++);
164	p = xdr_decode_hyper(p, &res->sr_offset);
165	return 0;
166
167out_overflow:
168	print_overflow_msg(__func__, xdr);
169	return -EIO;
170}
171
172/*
173 * Decode ALLOCATE request
174 */
175static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
176				 struct xdr_stream *xdr,
177				 struct nfs42_falloc_res *res)
178{
179	struct compound_hdr hdr;
180	int status;
181
182	status = decode_compound_hdr(xdr, &hdr);
183	if (status)
184		goto out;
185	status = decode_sequence(xdr, &res->seq_res, rqstp);
186	if (status)
187		goto out;
188	status = decode_putfh(xdr);
189	if (status)
190		goto out;
191	status = decode_allocate(xdr, res);
192	if (status)
193		goto out;
194	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
195out:
196	return status;
197}
198
199/*
200 * Decode DEALLOCATE request
201 */
202static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
203				   struct xdr_stream *xdr,
204				   struct nfs42_falloc_res *res)
205{
206	struct compound_hdr hdr;
207	int status;
208
209	status = decode_compound_hdr(xdr, &hdr);
210	if (status)
211		goto out;
212	status = decode_sequence(xdr, &res->seq_res, rqstp);
213	if (status)
214		goto out;
215	status = decode_putfh(xdr);
216	if (status)
217		goto out;
218	status = decode_deallocate(xdr, res);
219	if (status)
220		goto out;
221	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
222out:
223	return status;
224}
225
226/*
227 * Decode SEEK request
228 */
229static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
230			     struct xdr_stream *xdr,
231			     struct nfs42_seek_res *res)
232{
233	struct compound_hdr hdr;
234	int status;
235
236	status = decode_compound_hdr(xdr, &hdr);
237	if (status)
238		goto out;
239	status = decode_sequence(xdr, &res->seq_res, rqstp);
240	if (status)
241		goto out;
242	status = decode_putfh(xdr);
243	if (status)
244		goto out;
245	status = decode_seek(xdr, res);
246out:
247	return status;
248}
249#endif /* __LINUX_FS_NFS_NFS4_2XDR_H */
250