1 /* 2 * Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com> 3 */ 4 #ifndef __LINUX_FS_NFS_NFS4_2XDR_H 5 #define __LINUX_FS_NFS_NFS4_2XDR_H 6 7 #include "nfs42.h" 8 9 #define encode_fallocate_maxsz (encode_stateid_maxsz + \ 10 2 /* offset */ + \ 11 2 /* length */) 12 #define encode_allocate_maxsz (op_encode_hdr_maxsz + \ 13 encode_fallocate_maxsz) 14 #define decode_allocate_maxsz (op_decode_hdr_maxsz) 15 #define encode_deallocate_maxsz (op_encode_hdr_maxsz + \ 16 encode_fallocate_maxsz) 17 #define decode_deallocate_maxsz (op_decode_hdr_maxsz) 18 #define encode_seek_maxsz (op_encode_hdr_maxsz + \ 19 encode_stateid_maxsz + \ 20 2 /* offset */ + \ 21 1 /* whence */) 22 #define decode_seek_maxsz (op_decode_hdr_maxsz + \ 23 1 /* eof */ + \ 24 1 /* whence */ + \ 25 2 /* offset */ + \ 26 2 /* length */) 27 #define encode_io_info_maxsz 4 28 #define encode_layoutstats_maxsz (op_decode_hdr_maxsz + \ 29 2 /* offset */ + \ 30 2 /* length */ + \ 31 encode_stateid_maxsz + \ 32 encode_io_info_maxsz + \ 33 encode_io_info_maxsz + \ 34 1 /* opaque devaddr4 length */ + \ 35 XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE)) 36 #define decode_layoutstats_maxsz (op_decode_hdr_maxsz) 37 #define encode_clone_maxsz (encode_stateid_maxsz + \ 38 encode_stateid_maxsz + \ 39 2 /* src offset */ + \ 40 2 /* dst offset */ + \ 41 2 /* count */) 42 #define decode_clone_maxsz (op_decode_hdr_maxsz) 43 44 #define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \ 45 encode_putfh_maxsz + \ 46 encode_allocate_maxsz + \ 47 encode_getattr_maxsz) 48 #define NFS4_dec_allocate_sz (compound_decode_hdr_maxsz + \ 49 decode_putfh_maxsz + \ 50 decode_allocate_maxsz + \ 51 decode_getattr_maxsz) 52 #define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \ 53 encode_putfh_maxsz + \ 54 encode_deallocate_maxsz + \ 55 encode_getattr_maxsz) 56 #define NFS4_dec_deallocate_sz (compound_decode_hdr_maxsz + \ 57 decode_putfh_maxsz + \ 58 decode_deallocate_maxsz + \ 59 decode_getattr_maxsz) 60 #define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \ 61 encode_putfh_maxsz + \ 62 encode_seek_maxsz) 63 #define NFS4_dec_seek_sz (compound_decode_hdr_maxsz + \ 64 decode_putfh_maxsz + \ 65 decode_seek_maxsz) 66 #define NFS4_enc_layoutstats_sz (compound_encode_hdr_maxsz + \ 67 encode_sequence_maxsz + \ 68 encode_putfh_maxsz + \ 69 PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz) 70 #define NFS4_dec_layoutstats_sz (compound_decode_hdr_maxsz + \ 71 decode_sequence_maxsz + \ 72 decode_putfh_maxsz + \ 73 PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz) 74 #define NFS4_enc_clone_sz (compound_encode_hdr_maxsz + \ 75 encode_sequence_maxsz + \ 76 encode_putfh_maxsz + \ 77 encode_savefh_maxsz + \ 78 encode_putfh_maxsz + \ 79 encode_clone_maxsz + \ 80 encode_getattr_maxsz) 81 #define NFS4_dec_clone_sz (compound_decode_hdr_maxsz + \ 82 decode_sequence_maxsz + \ 83 decode_putfh_maxsz + \ 84 decode_savefh_maxsz + \ 85 decode_putfh_maxsz + \ 86 decode_clone_maxsz + \ 87 decode_getattr_maxsz) 88 89 static void encode_fallocate(struct xdr_stream *xdr, 90 struct nfs42_falloc_args *args) 91 { 92 encode_nfs4_stateid(xdr, &args->falloc_stateid); 93 encode_uint64(xdr, args->falloc_offset); 94 encode_uint64(xdr, args->falloc_length); 95 } 96 97 static void encode_allocate(struct xdr_stream *xdr, 98 struct nfs42_falloc_args *args, 99 struct compound_hdr *hdr) 100 { 101 encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr); 102 encode_fallocate(xdr, args); 103 } 104 105 static void encode_deallocate(struct xdr_stream *xdr, 106 struct nfs42_falloc_args *args, 107 struct compound_hdr *hdr) 108 { 109 encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr); 110 encode_fallocate(xdr, args); 111 } 112 113 static void encode_seek(struct xdr_stream *xdr, 114 struct nfs42_seek_args *args, 115 struct compound_hdr *hdr) 116 { 117 encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr); 118 encode_nfs4_stateid(xdr, &args->sa_stateid); 119 encode_uint64(xdr, args->sa_offset); 120 encode_uint32(xdr, args->sa_what); 121 } 122 123 static void encode_layoutstats(struct xdr_stream *xdr, 124 struct nfs42_layoutstat_args *args, 125 struct nfs42_layoutstat_devinfo *devinfo, 126 struct compound_hdr *hdr) 127 { 128 __be32 *p; 129 130 encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr); 131 p = reserve_space(xdr, 8 + 8); 132 p = xdr_encode_hyper(p, devinfo->offset); 133 p = xdr_encode_hyper(p, devinfo->length); 134 encode_nfs4_stateid(xdr, &args->stateid); 135 p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4); 136 p = xdr_encode_hyper(p, devinfo->read_count); 137 p = xdr_encode_hyper(p, devinfo->read_bytes); 138 p = xdr_encode_hyper(p, devinfo->write_count); 139 p = xdr_encode_hyper(p, devinfo->write_bytes); 140 p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data, 141 NFS4_DEVICEID4_SIZE); 142 /* Encode layoutupdate4 */ 143 *p++ = cpu_to_be32(devinfo->layout_type); 144 if (devinfo->layoutstats_encode != NULL) 145 devinfo->layoutstats_encode(xdr, args, devinfo); 146 else 147 encode_uint32(xdr, 0); 148 } 149 150 static void encode_clone(struct xdr_stream *xdr, 151 struct nfs42_clone_args *args, 152 struct compound_hdr *hdr) 153 { 154 __be32 *p; 155 156 encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr); 157 encode_nfs4_stateid(xdr, &args->src_stateid); 158 encode_nfs4_stateid(xdr, &args->dst_stateid); 159 p = reserve_space(xdr, 3*8); 160 p = xdr_encode_hyper(p, args->src_offset); 161 p = xdr_encode_hyper(p, args->dst_offset); 162 xdr_encode_hyper(p, args->count); 163 } 164 165 /* 166 * Encode ALLOCATE request 167 */ 168 static void nfs4_xdr_enc_allocate(struct rpc_rqst *req, 169 struct xdr_stream *xdr, 170 struct nfs42_falloc_args *args) 171 { 172 struct compound_hdr hdr = { 173 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 174 }; 175 176 encode_compound_hdr(xdr, req, &hdr); 177 encode_sequence(xdr, &args->seq_args, &hdr); 178 encode_putfh(xdr, args->falloc_fh, &hdr); 179 encode_allocate(xdr, args, &hdr); 180 encode_getfattr(xdr, args->falloc_bitmask, &hdr); 181 encode_nops(&hdr); 182 } 183 184 /* 185 * Encode DEALLOCATE request 186 */ 187 static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req, 188 struct xdr_stream *xdr, 189 struct nfs42_falloc_args *args) 190 { 191 struct compound_hdr hdr = { 192 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 193 }; 194 195 encode_compound_hdr(xdr, req, &hdr); 196 encode_sequence(xdr, &args->seq_args, &hdr); 197 encode_putfh(xdr, args->falloc_fh, &hdr); 198 encode_deallocate(xdr, args, &hdr); 199 encode_getfattr(xdr, args->falloc_bitmask, &hdr); 200 encode_nops(&hdr); 201 } 202 203 /* 204 * Encode SEEK request 205 */ 206 static void nfs4_xdr_enc_seek(struct rpc_rqst *req, 207 struct xdr_stream *xdr, 208 struct nfs42_seek_args *args) 209 { 210 struct compound_hdr hdr = { 211 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 212 }; 213 214 encode_compound_hdr(xdr, req, &hdr); 215 encode_sequence(xdr, &args->seq_args, &hdr); 216 encode_putfh(xdr, args->sa_fh, &hdr); 217 encode_seek(xdr, args, &hdr); 218 encode_nops(&hdr); 219 } 220 221 /* 222 * Encode LAYOUTSTATS request 223 */ 224 static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req, 225 struct xdr_stream *xdr, 226 struct nfs42_layoutstat_args *args) 227 { 228 int i; 229 230 struct compound_hdr hdr = { 231 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 232 }; 233 234 encode_compound_hdr(xdr, req, &hdr); 235 encode_sequence(xdr, &args->seq_args, &hdr); 236 encode_putfh(xdr, args->fh, &hdr); 237 WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV); 238 for (i = 0; i < args->num_dev; i++) 239 encode_layoutstats(xdr, args, &args->devinfo[i], &hdr); 240 encode_nops(&hdr); 241 } 242 243 /* 244 * Encode CLONE request 245 */ 246 static void nfs4_xdr_enc_clone(struct rpc_rqst *req, 247 struct xdr_stream *xdr, 248 struct nfs42_clone_args *args) 249 { 250 struct compound_hdr hdr = { 251 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 252 }; 253 254 encode_compound_hdr(xdr, req, &hdr); 255 encode_sequence(xdr, &args->seq_args, &hdr); 256 encode_putfh(xdr, args->src_fh, &hdr); 257 encode_savefh(xdr, &hdr); 258 encode_putfh(xdr, args->dst_fh, &hdr); 259 encode_clone(xdr, args, &hdr); 260 encode_getfattr(xdr, args->dst_bitmask, &hdr); 261 encode_nops(&hdr); 262 } 263 264 static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) 265 { 266 return decode_op_hdr(xdr, OP_ALLOCATE); 267 } 268 269 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) 270 { 271 return decode_op_hdr(xdr, OP_DEALLOCATE); 272 } 273 274 static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res) 275 { 276 int status; 277 __be32 *p; 278 279 status = decode_op_hdr(xdr, OP_SEEK); 280 if (status) 281 return status; 282 283 p = xdr_inline_decode(xdr, 4 + 8); 284 if (unlikely(!p)) 285 goto out_overflow; 286 287 res->sr_eof = be32_to_cpup(p++); 288 p = xdr_decode_hyper(p, &res->sr_offset); 289 return 0; 290 291 out_overflow: 292 print_overflow_msg(__func__, xdr); 293 return -EIO; 294 } 295 296 static int decode_layoutstats(struct xdr_stream *xdr) 297 { 298 return decode_op_hdr(xdr, OP_LAYOUTSTATS); 299 } 300 301 static int decode_clone(struct xdr_stream *xdr) 302 { 303 return decode_op_hdr(xdr, OP_CLONE); 304 } 305 306 /* 307 * Decode ALLOCATE request 308 */ 309 static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp, 310 struct xdr_stream *xdr, 311 struct nfs42_falloc_res *res) 312 { 313 struct compound_hdr hdr; 314 int status; 315 316 status = decode_compound_hdr(xdr, &hdr); 317 if (status) 318 goto out; 319 status = decode_sequence(xdr, &res->seq_res, rqstp); 320 if (status) 321 goto out; 322 status = decode_putfh(xdr); 323 if (status) 324 goto out; 325 status = decode_allocate(xdr, res); 326 if (status) 327 goto out; 328 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); 329 out: 330 return status; 331 } 332 333 /* 334 * Decode DEALLOCATE request 335 */ 336 static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp, 337 struct xdr_stream *xdr, 338 struct nfs42_falloc_res *res) 339 { 340 struct compound_hdr hdr; 341 int status; 342 343 status = decode_compound_hdr(xdr, &hdr); 344 if (status) 345 goto out; 346 status = decode_sequence(xdr, &res->seq_res, rqstp); 347 if (status) 348 goto out; 349 status = decode_putfh(xdr); 350 if (status) 351 goto out; 352 status = decode_deallocate(xdr, res); 353 if (status) 354 goto out; 355 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); 356 out: 357 return status; 358 } 359 360 /* 361 * Decode SEEK request 362 */ 363 static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp, 364 struct xdr_stream *xdr, 365 struct nfs42_seek_res *res) 366 { 367 struct compound_hdr hdr; 368 int status; 369 370 status = decode_compound_hdr(xdr, &hdr); 371 if (status) 372 goto out; 373 status = decode_sequence(xdr, &res->seq_res, rqstp); 374 if (status) 375 goto out; 376 status = decode_putfh(xdr); 377 if (status) 378 goto out; 379 status = decode_seek(xdr, res); 380 out: 381 return status; 382 } 383 384 /* 385 * Decode LAYOUTSTATS request 386 */ 387 static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp, 388 struct xdr_stream *xdr, 389 struct nfs42_layoutstat_res *res) 390 { 391 struct compound_hdr hdr; 392 int status, i; 393 394 status = decode_compound_hdr(xdr, &hdr); 395 if (status) 396 goto out; 397 status = decode_sequence(xdr, &res->seq_res, rqstp); 398 if (status) 399 goto out; 400 status = decode_putfh(xdr); 401 if (status) 402 goto out; 403 WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV); 404 for (i = 0; i < res->num_dev; i++) { 405 status = decode_layoutstats(xdr); 406 if (status) 407 goto out; 408 } 409 out: 410 res->rpc_status = status; 411 return status; 412 } 413 414 /* 415 * Decode CLONE request 416 */ 417 static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp, 418 struct xdr_stream *xdr, 419 struct nfs42_clone_res *res) 420 { 421 struct compound_hdr hdr; 422 int status; 423 424 status = decode_compound_hdr(xdr, &hdr); 425 if (status) 426 goto out; 427 status = decode_sequence(xdr, &res->seq_res, rqstp); 428 if (status) 429 goto out; 430 status = decode_putfh(xdr); 431 if (status) 432 goto out; 433 status = decode_savefh(xdr); 434 if (status) 435 goto out; 436 status = decode_putfh(xdr); 437 if (status) 438 goto out; 439 status = decode_clone(xdr); 440 if (status) 441 goto out; 442 status = decode_getfattr(xdr, res->dst_fattr, res->server); 443 444 out: 445 res->rpc_status = status; 446 return status; 447 } 448 449 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */ 450