~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/nfs/nfs42xdr.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php