1 /* 2 * linux/fs/nfs/nfs3xdr.c 3 * 4 * XDR functions to encode/decode NFSv3 RPC arguments and results. 5 * 6 * Copyright (C) 1996, 1997 Olaf Kirch 7 */ 8 9 #include <linux/param.h> 10 #include <linux/time.h> 11 #include <linux/mm.h> 12 #include <linux/slab.h> 13 #include <linux/utsname.h> 14 #include <linux/errno.h> 15 #include <linux/string.h> 16 #include <linux/in.h> 17 #include <linux/pagemap.h> 18 #include <linux/proc_fs.h> 19 #include <linux/kdev_t.h> 20 #include <linux/sunrpc/clnt.h> 21 #include <linux/nfs.h> 22 #include <linux/nfs3.h> 23 #include <linux/nfs_fs.h> 24 #include <linux/nfsacl.h> 25 #include "internal.h" 26 27 #define NFSDBG_FACILITY NFSDBG_XDR 28 29 /* Mapping from NFS error code to "errno" error code. */ 30 #define errno_NFSERR_IO EIO 31 32 /* 33 * Declare the space requirements for NFS arguments and replies as 34 * number of 32bit-words 35 */ 36 #define NFS3_fhandle_sz (1+16) 37 #define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */ 38 #define NFS3_sattr_sz (15) 39 #define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2)) 40 #define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2)) 41 #define NFS3_fattr_sz (21) 42 #define NFS3_wcc_attr_sz (6) 43 #define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz) 44 #define NFS3_post_op_attr_sz (1+NFS3_fattr_sz) 45 #define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz) 46 #define NFS3_fsstat_sz 47 #define NFS3_fsinfo_sz 48 #define NFS3_pathconf_sz 49 #define NFS3_entry_sz (NFS3_filename_sz+3) 50 51 #define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3) 52 #define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz) 53 #define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz) 54 #define NFS3_accessargs_sz (NFS3_fh_sz+1) 55 #define NFS3_readlinkargs_sz (NFS3_fh_sz) 56 #define NFS3_readargs_sz (NFS3_fh_sz+3) 57 #define NFS3_writeargs_sz (NFS3_fh_sz+5) 58 #define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz) 59 #define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz) 60 #define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz) 61 #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz) 62 #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz) 63 #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz) 64 #define NFS3_readdirargs_sz (NFS3_fh_sz+2) 65 #define NFS3_commitargs_sz (NFS3_fh_sz+3) 66 67 #define NFS3_attrstat_sz (1+NFS3_fattr_sz) 68 #define NFS3_wccstat_sz (1+NFS3_wcc_data_sz) 69 #define NFS3_removeres_sz (NFS3_wccstat_sz) 70 #define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz)) 71 #define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1) 72 #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1) 73 #define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3) 74 #define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4) 75 #define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) 76 #define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz)) 77 #define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz) 78 #define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2) 79 #define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13) 80 #define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12) 81 #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6) 82 #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2) 83 84 #define ACL3_getaclargs_sz (NFS3_fh_sz+1) 85 #define ACL3_setaclargs_sz (NFS3_fh_sz+1+2*(2+5*3)) 86 #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+2*(2+5*3)) 87 #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz) 88 89 /* 90 * Map file type to S_IFMT bits 91 */ 92 static struct { 93 unsigned int mode; 94 unsigned int nfs2type; 95 } nfs_type2fmt[] = { 96 { 0, NFNON }, 97 { S_IFREG, NFREG }, 98 { S_IFDIR, NFDIR }, 99 { S_IFBLK, NFBLK }, 100 { S_IFCHR, NFCHR }, 101 { S_IFLNK, NFLNK }, 102 { S_IFSOCK, NFSOCK }, 103 { S_IFIFO, NFFIFO }, 104 { 0, NFBAD } 105 }; 106 107 /* 108 * Common NFS XDR functions as inlines 109 */ 110 static inline __be32 * 111 xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fh) 112 { 113 return xdr_encode_array(p, fh->data, fh->size); 114 } 115 116 static inline __be32 * 117 xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh) 118 { 119 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) { 120 memcpy(fh->data, p, fh->size); 121 return p + XDR_QUADLEN(fh->size); 122 } 123 return NULL; 124 } 125 126 /* 127 * Encode/decode time. 128 */ 129 static inline __be32 * 130 xdr_encode_time3(__be32 *p, struct timespec *timep) 131 { 132 *p++ = htonl(timep->tv_sec); 133 *p++ = htonl(timep->tv_nsec); 134 return p; 135 } 136 137 static inline __be32 * 138 xdr_decode_time3(__be32 *p, struct timespec *timep) 139 { 140 timep->tv_sec = ntohl(*p++); 141 timep->tv_nsec = ntohl(*p++); 142 return p; 143 } 144 145 static __be32 * 146 xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr) 147 { 148 unsigned int type, major, minor; 149 int fmode; 150 151 type = ntohl(*p++); 152 if (type >= NF3BAD) 153 type = NF3BAD; 154 fmode = nfs_type2fmt[type].mode; 155 fattr->type = nfs_type2fmt[type].nfs2type; 156 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode; 157 fattr->nlink = ntohl(*p++); 158 fattr->uid = ntohl(*p++); 159 fattr->gid = ntohl(*p++); 160 p = xdr_decode_hyper(p, &fattr->size); 161 p = xdr_decode_hyper(p, &fattr->du.nfs3.used); 162 163 /* Turn remote device info into Linux-specific dev_t */ 164 major = ntohl(*p++); 165 minor = ntohl(*p++); 166 fattr->rdev = MKDEV(major, minor); 167 if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor) 168 fattr->rdev = 0; 169 170 p = xdr_decode_hyper(p, &fattr->fsid.major); 171 fattr->fsid.minor = 0; 172 p = xdr_decode_hyper(p, &fattr->fileid); 173 p = xdr_decode_time3(p, &fattr->atime); 174 p = xdr_decode_time3(p, &fattr->mtime); 175 p = xdr_decode_time3(p, &fattr->ctime); 176 177 /* Update the mode bits */ 178 fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3); 179 return p; 180 } 181 182 static inline __be32 * 183 xdr_encode_sattr(__be32 *p, struct iattr *attr) 184 { 185 if (attr->ia_valid & ATTR_MODE) { 186 *p++ = xdr_one; 187 *p++ = htonl(attr->ia_mode & S_IALLUGO); 188 } else { 189 *p++ = xdr_zero; 190 } 191 if (attr->ia_valid & ATTR_UID) { 192 *p++ = xdr_one; 193 *p++ = htonl(attr->ia_uid); 194 } else { 195 *p++ = xdr_zero; 196 } 197 if (attr->ia_valid & ATTR_GID) { 198 *p++ = xdr_one; 199 *p++ = htonl(attr->ia_gid); 200 } else { 201 *p++ = xdr_zero; 202 } 203 if (attr->ia_valid & ATTR_SIZE) { 204 *p++ = xdr_one; 205 p = xdr_encode_hyper(p, (__u64) attr->ia_size); 206 } else { 207 *p++ = xdr_zero; 208 } 209 if (attr->ia_valid & ATTR_ATIME_SET) { 210 *p++ = xdr_two; 211 p = xdr_encode_time3(p, &attr->ia_atime); 212 } else if (attr->ia_valid & ATTR_ATIME) { 213 *p++ = xdr_one; 214 } else { 215 *p++ = xdr_zero; 216 } 217 if (attr->ia_valid & ATTR_MTIME_SET) { 218 *p++ = xdr_two; 219 p = xdr_encode_time3(p, &attr->ia_mtime); 220 } else if (attr->ia_valid & ATTR_MTIME) { 221 *p++ = xdr_one; 222 } else { 223 *p++ = xdr_zero; 224 } 225 return p; 226 } 227 228 static inline __be32 * 229 xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr) 230 { 231 p = xdr_decode_hyper(p, &fattr->pre_size); 232 p = xdr_decode_time3(p, &fattr->pre_mtime); 233 p = xdr_decode_time3(p, &fattr->pre_ctime); 234 fattr->valid |= NFS_ATTR_WCC; 235 return p; 236 } 237 238 static inline __be32 * 239 xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr) 240 { 241 if (*p++) 242 p = xdr_decode_fattr(p, fattr); 243 return p; 244 } 245 246 static inline __be32 * 247 xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr) 248 { 249 if (*p++) 250 return xdr_decode_wcc_attr(p, fattr); 251 return p; 252 } 253 254 255 static inline __be32 * 256 xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr) 257 { 258 p = xdr_decode_pre_op_attr(p, fattr); 259 return xdr_decode_post_op_attr(p, fattr); 260 } 261 262 /* 263 * NFS encode functions 264 */ 265 266 /* 267 * Encode file handle argument 268 */ 269 static int 270 nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh) 271 { 272 p = xdr_encode_fhandle(p, fh); 273 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 274 return 0; 275 } 276 277 /* 278 * Encode SETATTR arguments 279 */ 280 static int 281 nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args) 282 { 283 p = xdr_encode_fhandle(p, args->fh); 284 p = xdr_encode_sattr(p, args->sattr); 285 *p++ = htonl(args->guard); 286 if (args->guard) 287 p = xdr_encode_time3(p, &args->guardtime); 288 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 289 return 0; 290 } 291 292 /* 293 * Encode directory ops argument 294 */ 295 static int 296 nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args) 297 { 298 p = xdr_encode_fhandle(p, args->fh); 299 p = xdr_encode_array(p, args->name, args->len); 300 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 301 return 0; 302 } 303 304 /* 305 * Encode REMOVE argument 306 */ 307 static int 308 nfs3_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args) 309 { 310 p = xdr_encode_fhandle(p, args->fh); 311 p = xdr_encode_array(p, args->name.name, args->name.len); 312 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 313 return 0; 314 } 315 316 /* 317 * Encode access() argument 318 */ 319 static int 320 nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args) 321 { 322 p = xdr_encode_fhandle(p, args->fh); 323 *p++ = htonl(args->access); 324 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 325 return 0; 326 } 327 328 /* 329 * Arguments to a READ call. Since we read data directly into the page 330 * cache, we also set up the reply iovec here so that iov[1] points 331 * exactly to the page we want to fetch. 332 */ 333 static int 334 nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args) 335 { 336 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; 337 unsigned int replen; 338 u32 count = args->count; 339 340 p = xdr_encode_fhandle(p, args->fh); 341 p = xdr_encode_hyper(p, args->offset); 342 *p++ = htonl(count); 343 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 344 345 /* Inline the page array */ 346 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2; 347 xdr_inline_pages(&req->rq_rcv_buf, replen, 348 args->pages, args->pgbase, count); 349 req->rq_rcv_buf.flags |= XDRBUF_READ; 350 return 0; 351 } 352 353 /* 354 * Write arguments. Splice the buffer to be written into the iovec. 355 */ 356 static int 357 nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) 358 { 359 struct xdr_buf *sndbuf = &req->rq_snd_buf; 360 u32 count = args->count; 361 362 p = xdr_encode_fhandle(p, args->fh); 363 p = xdr_encode_hyper(p, args->offset); 364 *p++ = htonl(count); 365 *p++ = htonl(args->stable); 366 *p++ = htonl(count); 367 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p); 368 369 /* Copy the page array */ 370 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count); 371 sndbuf->flags |= XDRBUF_WRITE; 372 return 0; 373 } 374 375 /* 376 * Encode CREATE arguments 377 */ 378 static int 379 nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args) 380 { 381 p = xdr_encode_fhandle(p, args->fh); 382 p = xdr_encode_array(p, args->name, args->len); 383 384 *p++ = htonl(args->createmode); 385 if (args->createmode == NFS3_CREATE_EXCLUSIVE) { 386 *p++ = args->verifier[0]; 387 *p++ = args->verifier[1]; 388 } else 389 p = xdr_encode_sattr(p, args->sattr); 390 391 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 392 return 0; 393 } 394 395 /* 396 * Encode MKDIR arguments 397 */ 398 static int 399 nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args) 400 { 401 p = xdr_encode_fhandle(p, args->fh); 402 p = xdr_encode_array(p, args->name, args->len); 403 p = xdr_encode_sattr(p, args->sattr); 404 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 405 return 0; 406 } 407 408 /* 409 * Encode SYMLINK arguments 410 */ 411 static int 412 nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args) 413 { 414 p = xdr_encode_fhandle(p, args->fromfh); 415 p = xdr_encode_array(p, args->fromname, args->fromlen); 416 p = xdr_encode_sattr(p, args->sattr); 417 *p++ = htonl(args->pathlen); 418 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 419 420 /* Copy the page */ 421 xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen); 422 return 0; 423 } 424 425 /* 426 * Encode MKNOD arguments 427 */ 428 static int 429 nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args) 430 { 431 p = xdr_encode_fhandle(p, args->fh); 432 p = xdr_encode_array(p, args->name, args->len); 433 *p++ = htonl(args->type); 434 p = xdr_encode_sattr(p, args->sattr); 435 if (args->type == NF3CHR || args->type == NF3BLK) { 436 *p++ = htonl(MAJOR(args->rdev)); 437 *p++ = htonl(MINOR(args->rdev)); 438 } 439 440 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 441 return 0; 442 } 443 444 /* 445 * Encode RENAME arguments 446 */ 447 static int 448 nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args) 449 { 450 p = xdr_encode_fhandle(p, args->fromfh); 451 p = xdr_encode_array(p, args->fromname, args->fromlen); 452 p = xdr_encode_fhandle(p, args->tofh); 453 p = xdr_encode_array(p, args->toname, args->tolen); 454 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 455 return 0; 456 } 457 458 /* 459 * Encode LINK arguments 460 */ 461 static int 462 nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args) 463 { 464 p = xdr_encode_fhandle(p, args->fromfh); 465 p = xdr_encode_fhandle(p, args->tofh); 466 p = xdr_encode_array(p, args->toname, args->tolen); 467 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 468 return 0; 469 } 470 471 /* 472 * Encode arguments to readdir call 473 */ 474 static int 475 nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args) 476 { 477 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; 478 unsigned int replen; 479 u32 count = args->count; 480 481 p = xdr_encode_fhandle(p, args->fh); 482 p = xdr_encode_hyper(p, args->cookie); 483 *p++ = args->verf[0]; 484 *p++ = args->verf[1]; 485 if (args->plus) { 486 /* readdirplus: need dircount + buffer size. 487 * We just make sure we make dircount big enough */ 488 *p++ = htonl(count >> 3); 489 } 490 *p++ = htonl(count); 491 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 492 493 /* Inline the page array */ 494 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2; 495 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count); 496 return 0; 497 } 498 499 /* 500 * Decode the result of a readdir call. 501 * We just check for syntactical correctness. 502 */ 503 static int 504 nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res) 505 { 506 struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 507 struct kvec *iov = rcvbuf->head; 508 struct page **page; 509 size_t hdrlen; 510 u32 len, recvd, pglen; 511 int status, nr; 512 __be32 *entry, *end, *kaddr; 513 514 status = ntohl(*p++); 515 /* Decode post_op_attrs */ 516 p = xdr_decode_post_op_attr(p, res->dir_attr); 517 if (status) 518 return -nfs_stat_to_errno(status); 519 /* Decode verifier cookie */ 520 if (res->verf) { 521 res->verf[0] = *p++; 522 res->verf[1] = *p++; 523 } else { 524 p += 2; 525 } 526 527 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 528 if (iov->iov_len < hdrlen) { 529 dprintk("NFS: READDIR reply header overflowed:" 530 "length %Zu > %Zu\n", hdrlen, iov->iov_len); 531 return -errno_NFSERR_IO; 532 } else if (iov->iov_len != hdrlen) { 533 dprintk("NFS: READDIR header is short. iovec will be shifted.\n"); 534 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); 535 } 536 537 pglen = rcvbuf->page_len; 538 recvd = rcvbuf->len - hdrlen; 539 if (pglen > recvd) 540 pglen = recvd; 541 page = rcvbuf->pages; 542 kaddr = p = kmap_atomic(*page, KM_USER0); 543 end = (__be32 *)((char *)p + pglen); 544 entry = p; 545 for (nr = 0; *p++; nr++) { 546 if (p + 3 > end) 547 goto short_pkt; 548 p += 2; /* inode # */ 549 len = ntohl(*p++); /* string length */ 550 p += XDR_QUADLEN(len) + 2; /* name + cookie */ 551 if (len > NFS3_MAXNAMLEN) { 552 dprintk("NFS: giant filename in readdir (len 0x%x)!\n", 553 len); 554 goto err_unmap; 555 } 556 557 if (res->plus) { 558 /* post_op_attr */ 559 if (p + 2 > end) 560 goto short_pkt; 561 if (*p++) { 562 p += 21; 563 if (p + 1 > end) 564 goto short_pkt; 565 } 566 /* post_op_fh3 */ 567 if (*p++) { 568 if (p + 1 > end) 569 goto short_pkt; 570 len = ntohl(*p++); 571 if (len > NFS3_FHSIZE) { 572 dprintk("NFS: giant filehandle in " 573 "readdir (len 0x%x)!\n", len); 574 goto err_unmap; 575 } 576 p += XDR_QUADLEN(len); 577 } 578 } 579 580 if (p + 2 > end) 581 goto short_pkt; 582 entry = p; 583 } 584 if (!nr && (entry[0] != 0 || entry[1] == 0)) 585 goto short_pkt; 586 out: 587 kunmap_atomic(kaddr, KM_USER0); 588 return nr; 589 short_pkt: 590 entry[0] = entry[1] = 0; 591 /* truncate listing ? */ 592 if (!nr) { 593 dprintk("NFS: readdir reply truncated!\n"); 594 entry[1] = 1; 595 } 596 goto out; 597 err_unmap: 598 nr = -errno_NFSERR_IO; 599 goto out; 600 } 601 602 __be32 * 603 nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) 604 { 605 struct nfs_entry old = *entry; 606 607 if (!*p++) { 608 if (!*p) 609 return ERR_PTR(-EAGAIN); 610 entry->eof = 1; 611 return ERR_PTR(-EBADCOOKIE); 612 } 613 614 p = xdr_decode_hyper(p, &entry->ino); 615 entry->len = ntohl(*p++); 616 entry->name = (const char *) p; 617 p += XDR_QUADLEN(entry->len); 618 entry->prev_cookie = entry->cookie; 619 p = xdr_decode_hyper(p, &entry->cookie); 620 621 if (plus) { 622 entry->fattr->valid = 0; 623 p = xdr_decode_post_op_attr(p, entry->fattr); 624 /* In fact, a post_op_fh3: */ 625 if (*p++) { 626 p = xdr_decode_fhandle(p, entry->fh); 627 /* Ugh -- server reply was truncated */ 628 if (p == NULL) { 629 dprintk("NFS: FH truncated\n"); 630 *entry = old; 631 return ERR_PTR(-EAGAIN); 632 } 633 } else 634 memset((u8*)(entry->fh), 0, sizeof(*entry->fh)); 635 } 636 637 entry->eof = !p[0] && p[1]; 638 return p; 639 } 640 641 /* 642 * Encode COMMIT arguments 643 */ 644 static int 645 nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) 646 { 647 p = xdr_encode_fhandle(p, args->fh); 648 p = xdr_encode_hyper(p, args->offset); 649 *p++ = htonl(args->count); 650 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 651 return 0; 652 } 653 654 #ifdef CONFIG_NFS_V3_ACL 655 /* 656 * Encode GETACL arguments 657 */ 658 static int 659 nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p, 660 struct nfs3_getaclargs *args) 661 { 662 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; 663 unsigned int replen; 664 665 p = xdr_encode_fhandle(p, args->fh); 666 *p++ = htonl(args->mask); 667 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 668 669 if (args->mask & (NFS_ACL | NFS_DFACL)) { 670 /* Inline the page array */ 671 replen = (RPC_REPHDRSIZE + auth->au_rslack + 672 ACL3_getaclres_sz) << 2; 673 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, 674 NFSACL_MAXPAGES << PAGE_SHIFT); 675 } 676 return 0; 677 } 678 679 /* 680 * Encode SETACL arguments 681 */ 682 static int 683 nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p, 684 struct nfs3_setaclargs *args) 685 { 686 struct xdr_buf *buf = &req->rq_snd_buf; 687 unsigned int base, len_in_head, len = nfsacl_size( 688 (args->mask & NFS_ACL) ? args->acl_access : NULL, 689 (args->mask & NFS_DFACL) ? args->acl_default : NULL); 690 int count, err; 691 692 p = xdr_encode_fhandle(p, NFS_FH(args->inode)); 693 *p++ = htonl(args->mask); 694 base = (char *)p - (char *)buf->head->iov_base; 695 /* put as much of the acls into head as possible. */ 696 len_in_head = min_t(unsigned int, buf->head->iov_len - base, len); 697 len -= len_in_head; 698 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2)); 699 700 for (count = 0; (count << PAGE_SHIFT) < len; count++) { 701 args->pages[count] = alloc_page(GFP_KERNEL); 702 if (!args->pages[count]) { 703 while (count) 704 __free_page(args->pages[--count]); 705 return -ENOMEM; 706 } 707 } 708 xdr_encode_pages(buf, args->pages, 0, len); 709 710 err = nfsacl_encode(buf, base, args->inode, 711 (args->mask & NFS_ACL) ? 712 args->acl_access : NULL, 1, 0); 713 if (err > 0) 714 err = nfsacl_encode(buf, base + err, args->inode, 715 (args->mask & NFS_DFACL) ? 716 args->acl_default : NULL, 1, 717 NFS_ACL_DEFAULT); 718 return (err > 0) ? 0 : err; 719 } 720 #endif /* CONFIG_NFS_V3_ACL */ 721 722 /* 723 * NFS XDR decode functions 724 */ 725 726 /* 727 * Decode attrstat reply. 728 */ 729 static int 730 nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 731 { 732 int status; 733 734 if ((status = ntohl(*p++))) 735 return -nfs_stat_to_errno(status); 736 xdr_decode_fattr(p, fattr); 737 return 0; 738 } 739 740 /* 741 * Decode status+wcc_data reply 742 * SATTR, REMOVE, RMDIR 743 */ 744 static int 745 nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 746 { 747 int status; 748 749 if ((status = ntohl(*p++))) 750 status = -nfs_stat_to_errno(status); 751 xdr_decode_wcc_data(p, fattr); 752 return status; 753 } 754 755 static int 756 nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res) 757 { 758 return nfs3_xdr_wccstat(req, p, &res->dir_attr); 759 } 760 761 /* 762 * Decode LOOKUP reply 763 */ 764 static int 765 nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res) 766 { 767 int status; 768 769 if ((status = ntohl(*p++))) { 770 status = -nfs_stat_to_errno(status); 771 } else { 772 if (!(p = xdr_decode_fhandle(p, res->fh))) 773 return -errno_NFSERR_IO; 774 p = xdr_decode_post_op_attr(p, res->fattr); 775 } 776 xdr_decode_post_op_attr(p, res->dir_attr); 777 return status; 778 } 779 780 /* 781 * Decode ACCESS reply 782 */ 783 static int 784 nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res) 785 { 786 int status = ntohl(*p++); 787 788 p = xdr_decode_post_op_attr(p, res->fattr); 789 if (status) 790 return -nfs_stat_to_errno(status); 791 res->access = ntohl(*p++); 792 return 0; 793 } 794 795 static int 796 nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args) 797 { 798 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; 799 unsigned int replen; 800 801 p = xdr_encode_fhandle(p, args->fh); 802 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 803 804 /* Inline the page array */ 805 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2; 806 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen); 807 return 0; 808 } 809 810 /* 811 * Decode READLINK reply 812 */ 813 static int 814 nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 815 { 816 struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 817 struct kvec *iov = rcvbuf->head; 818 size_t hdrlen; 819 u32 len, recvd; 820 char *kaddr; 821 int status; 822 823 status = ntohl(*p++); 824 p = xdr_decode_post_op_attr(p, fattr); 825 826 if (status != 0) 827 return -nfs_stat_to_errno(status); 828 829 /* Convert length of symlink */ 830 len = ntohl(*p++); 831 if (len >= rcvbuf->page_len) { 832 dprintk("nfs: server returned giant symlink!\n"); 833 return -ENAMETOOLONG; 834 } 835 836 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 837 if (iov->iov_len < hdrlen) { 838 dprintk("NFS: READLINK reply header overflowed:" 839 "length %Zu > %Zu\n", hdrlen, iov->iov_len); 840 return -errno_NFSERR_IO; 841 } else if (iov->iov_len != hdrlen) { 842 dprintk("NFS: READLINK header is short. " 843 "iovec will be shifted.\n"); 844 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); 845 } 846 recvd = req->rq_rcv_buf.len - hdrlen; 847 if (recvd < len) { 848 dprintk("NFS: server cheating in readlink reply: " 849 "count %u > recvd %u\n", len, recvd); 850 return -EIO; 851 } 852 853 /* NULL terminate the string we got */ 854 kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0); 855 kaddr[len+rcvbuf->page_base] = '\0'; 856 kunmap_atomic(kaddr, KM_USER0); 857 return 0; 858 } 859 860 /* 861 * Decode READ reply 862 */ 863 static int 864 nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) 865 { 866 struct kvec *iov = req->rq_rcv_buf.head; 867 size_t hdrlen; 868 u32 count, ocount, recvd; 869 int status; 870 871 status = ntohl(*p++); 872 p = xdr_decode_post_op_attr(p, res->fattr); 873 874 if (status != 0) 875 return -nfs_stat_to_errno(status); 876 877 /* Decode reply count and EOF flag. NFSv3 is somewhat redundant 878 * in that it puts the count both in the res struct and in the 879 * opaque data count. */ 880 count = ntohl(*p++); 881 res->eof = ntohl(*p++); 882 ocount = ntohl(*p++); 883 884 if (ocount != count) { 885 dprintk("NFS: READ count doesn't match RPC opaque count.\n"); 886 return -errno_NFSERR_IO; 887 } 888 889 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 890 if (iov->iov_len < hdrlen) { 891 dprintk("NFS: READ reply header overflowed:" 892 "length %Zu > %Zu\n", hdrlen, iov->iov_len); 893 return -errno_NFSERR_IO; 894 } else if (iov->iov_len != hdrlen) { 895 dprintk("NFS: READ header is short. iovec will be shifted.\n"); 896 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen); 897 } 898 899 recvd = req->rq_rcv_buf.len - hdrlen; 900 if (count > recvd) { 901 dprintk("NFS: server cheating in read reply: " 902 "count %u > recvd %u\n", count, recvd); 903 count = recvd; 904 res->eof = 0; 905 } 906 907 if (count < res->count) 908 res->count = count; 909 910 return count; 911 } 912 913 /* 914 * Decode WRITE response 915 */ 916 static int 917 nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) 918 { 919 int status; 920 921 status = ntohl(*p++); 922 p = xdr_decode_wcc_data(p, res->fattr); 923 924 if (status != 0) 925 return -nfs_stat_to_errno(status); 926 927 res->count = ntohl(*p++); 928 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++); 929 res->verf->verifier[0] = *p++; 930 res->verf->verifier[1] = *p++; 931 932 return res->count; 933 } 934 935 /* 936 * Decode a CREATE response 937 */ 938 static int 939 nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res) 940 { 941 int status; 942 943 status = ntohl(*p++); 944 if (status == 0) { 945 if (*p++) { 946 if (!(p = xdr_decode_fhandle(p, res->fh))) 947 return -errno_NFSERR_IO; 948 p = xdr_decode_post_op_attr(p, res->fattr); 949 } else { 950 memset(res->fh, 0, sizeof(*res->fh)); 951 /* Do decode post_op_attr but set it to NULL */ 952 p = xdr_decode_post_op_attr(p, res->fattr); 953 res->fattr->valid = 0; 954 } 955 } else { 956 status = -nfs_stat_to_errno(status); 957 } 958 p = xdr_decode_wcc_data(p, res->dir_attr); 959 return status; 960 } 961 962 /* 963 * Decode RENAME reply 964 */ 965 static int 966 nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res) 967 { 968 int status; 969 970 if ((status = ntohl(*p++)) != 0) 971 status = -nfs_stat_to_errno(status); 972 p = xdr_decode_wcc_data(p, res->fromattr); 973 p = xdr_decode_wcc_data(p, res->toattr); 974 return status; 975 } 976 977 /* 978 * Decode LINK reply 979 */ 980 static int 981 nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res) 982 { 983 int status; 984 985 if ((status = ntohl(*p++)) != 0) 986 status = -nfs_stat_to_errno(status); 987 p = xdr_decode_post_op_attr(p, res->fattr); 988 p = xdr_decode_wcc_data(p, res->dir_attr); 989 return status; 990 } 991 992 /* 993 * Decode FSSTAT reply 994 */ 995 static int 996 nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res) 997 { 998 int status; 999 1000 status = ntohl(*p++); 1001 1002 p = xdr_decode_post_op_attr(p, res->fattr); 1003 if (status != 0) 1004 return -nfs_stat_to_errno(status); 1005 1006 p = xdr_decode_hyper(p, &res->tbytes); 1007 p = xdr_decode_hyper(p, &res->fbytes); 1008 p = xdr_decode_hyper(p, &res->abytes); 1009 p = xdr_decode_hyper(p, &res->tfiles); 1010 p = xdr_decode_hyper(p, &res->ffiles); 1011 p = xdr_decode_hyper(p, &res->afiles); 1012 1013 /* ignore invarsec */ 1014 return 0; 1015 } 1016 1017 /* 1018 * Decode FSINFO reply 1019 */ 1020 static int 1021 nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res) 1022 { 1023 int status; 1024 1025 status = ntohl(*p++); 1026 1027 p = xdr_decode_post_op_attr(p, res->fattr); 1028 if (status != 0) 1029 return -nfs_stat_to_errno(status); 1030 1031 res->rtmax = ntohl(*p++); 1032 res->rtpref = ntohl(*p++); 1033 res->rtmult = ntohl(*p++); 1034 res->wtmax = ntohl(*p++); 1035 res->wtpref = ntohl(*p++); 1036 res->wtmult = ntohl(*p++); 1037 res->dtpref = ntohl(*p++); 1038 p = xdr_decode_hyper(p, &res->maxfilesize); 1039 1040 /* ignore time_delta and properties */ 1041 res->lease_time = 0; 1042 return 0; 1043 } 1044 1045 /* 1046 * Decode PATHCONF reply 1047 */ 1048 static int 1049 nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res) 1050 { 1051 int status; 1052 1053 status = ntohl(*p++); 1054 1055 p = xdr_decode_post_op_attr(p, res->fattr); 1056 if (status != 0) 1057 return -nfs_stat_to_errno(status); 1058 res->max_link = ntohl(*p++); 1059 res->max_namelen = ntohl(*p++); 1060 1061 /* ignore remaining fields */ 1062 return 0; 1063 } 1064 1065 /* 1066 * Decode COMMIT reply 1067 */ 1068 static int 1069 nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) 1070 { 1071 int status; 1072 1073 status = ntohl(*p++); 1074 p = xdr_decode_wcc_data(p, res->fattr); 1075 if (status != 0) 1076 return -nfs_stat_to_errno(status); 1077 1078 res->verf->verifier[0] = *p++; 1079 res->verf->verifier[1] = *p++; 1080 return 0; 1081 } 1082 1083 #ifdef CONFIG_NFS_V3_ACL 1084 /* 1085 * Decode GETACL reply 1086 */ 1087 static int 1088 nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p, 1089 struct nfs3_getaclres *res) 1090 { 1091 struct xdr_buf *buf = &req->rq_rcv_buf; 1092 int status = ntohl(*p++); 1093 struct posix_acl **acl; 1094 unsigned int *aclcnt; 1095 int err, base; 1096 1097 if (status != 0) 1098 return -nfs_stat_to_errno(status); 1099 p = xdr_decode_post_op_attr(p, res->fattr); 1100 res->mask = ntohl(*p++); 1101 if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) 1102 return -EINVAL; 1103 base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base; 1104 1105 acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL; 1106 aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL; 1107 err = nfsacl_decode(buf, base, aclcnt, acl); 1108 1109 acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL; 1110 aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL; 1111 if (err > 0) 1112 err = nfsacl_decode(buf, base + err, aclcnt, acl); 1113 return (err > 0) ? 0 : err; 1114 } 1115 1116 /* 1117 * Decode setacl reply. 1118 */ 1119 static int 1120 nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 1121 { 1122 int status = ntohl(*p++); 1123 1124 if (status) 1125 return -nfs_stat_to_errno(status); 1126 xdr_decode_post_op_attr(p, fattr); 1127 return 0; 1128 } 1129 #endif /* CONFIG_NFS_V3_ACL */ 1130 1131 #define PROC(proc, argtype, restype, timer) \ 1132 [NFS3PROC_##proc] = { \ 1133 .p_proc = NFS3PROC_##proc, \ 1134 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \ 1135 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \ 1136 .p_arglen = NFS3_##argtype##_sz, \ 1137 .p_replen = NFS3_##restype##_sz, \ 1138 .p_timer = timer, \ 1139 .p_statidx = NFS3PROC_##proc, \ 1140 .p_name = #proc, \ 1141 } 1142 1143 struct rpc_procinfo nfs3_procedures[] = { 1144 PROC(GETATTR, fhandle, attrstat, 1), 1145 PROC(SETATTR, sattrargs, wccstat, 0), 1146 PROC(LOOKUP, diropargs, lookupres, 2), 1147 PROC(ACCESS, accessargs, accessres, 1), 1148 PROC(READLINK, readlinkargs, readlinkres, 3), 1149 PROC(READ, readargs, readres, 3), 1150 PROC(WRITE, writeargs, writeres, 4), 1151 PROC(CREATE, createargs, createres, 0), 1152 PROC(MKDIR, mkdirargs, createres, 0), 1153 PROC(SYMLINK, symlinkargs, createres, 0), 1154 PROC(MKNOD, mknodargs, createres, 0), 1155 PROC(REMOVE, removeargs, removeres, 0), 1156 PROC(RMDIR, diropargs, wccstat, 0), 1157 PROC(RENAME, renameargs, renameres, 0), 1158 PROC(LINK, linkargs, linkres, 0), 1159 PROC(READDIR, readdirargs, readdirres, 3), 1160 PROC(READDIRPLUS, readdirargs, readdirres, 3), 1161 PROC(FSSTAT, fhandle, fsstatres, 0), 1162 PROC(FSINFO, fhandle, fsinfores, 0), 1163 PROC(PATHCONF, fhandle, pathconfres, 0), 1164 PROC(COMMIT, commitargs, commitres, 5), 1165 }; 1166 1167 struct rpc_version nfs_version3 = { 1168 .number = 3, 1169 .nrprocs = ARRAY_SIZE(nfs3_procedures), 1170 .procs = nfs3_procedures 1171 }; 1172 1173 #ifdef CONFIG_NFS_V3_ACL 1174 static struct rpc_procinfo nfs3_acl_procedures[] = { 1175 [ACLPROC3_GETACL] = { 1176 .p_proc = ACLPROC3_GETACL, 1177 .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs, 1178 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres, 1179 .p_arglen = ACL3_getaclargs_sz, 1180 .p_replen = ACL3_getaclres_sz, 1181 .p_timer = 1, 1182 .p_name = "GETACL", 1183 }, 1184 [ACLPROC3_SETACL] = { 1185 .p_proc = ACLPROC3_SETACL, 1186 .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs, 1187 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres, 1188 .p_arglen = ACL3_setaclargs_sz, 1189 .p_replen = ACL3_setaclres_sz, 1190 .p_timer = 0, 1191 .p_name = "SETACL", 1192 }, 1193 }; 1194 1195 struct rpc_version nfsacl_version3 = { 1196 .number = 3, 1197 .nrprocs = sizeof(nfs3_acl_procedures)/ 1198 sizeof(nfs3_acl_procedures[0]), 1199 .procs = nfs3_acl_procedures, 1200 }; 1201 #endif /* CONFIG_NFS_V3_ACL */ 1202