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 return 0; 350 } 351 352 /* 353 * Write arguments. Splice the buffer to be written into the iovec. 354 */ 355 static int 356 nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) 357 { 358 struct xdr_buf *sndbuf = &req->rq_snd_buf; 359 u32 count = args->count; 360 361 p = xdr_encode_fhandle(p, args->fh); 362 p = xdr_encode_hyper(p, args->offset); 363 *p++ = htonl(count); 364 *p++ = htonl(args->stable); 365 *p++ = htonl(count); 366 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p); 367 368 /* Copy the page array */ 369 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count); 370 return 0; 371 } 372 373 /* 374 * Encode CREATE arguments 375 */ 376 static int 377 nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args) 378 { 379 p = xdr_encode_fhandle(p, args->fh); 380 p = xdr_encode_array(p, args->name, args->len); 381 382 *p++ = htonl(args->createmode); 383 if (args->createmode == NFS3_CREATE_EXCLUSIVE) { 384 *p++ = args->verifier[0]; 385 *p++ = args->verifier[1]; 386 } else 387 p = xdr_encode_sattr(p, args->sattr); 388 389 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 390 return 0; 391 } 392 393 /* 394 * Encode MKDIR arguments 395 */ 396 static int 397 nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args) 398 { 399 p = xdr_encode_fhandle(p, args->fh); 400 p = xdr_encode_array(p, args->name, args->len); 401 p = xdr_encode_sattr(p, args->sattr); 402 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 403 return 0; 404 } 405 406 /* 407 * Encode SYMLINK arguments 408 */ 409 static int 410 nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args) 411 { 412 p = xdr_encode_fhandle(p, args->fromfh); 413 p = xdr_encode_array(p, args->fromname, args->fromlen); 414 p = xdr_encode_sattr(p, args->sattr); 415 *p++ = htonl(args->pathlen); 416 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 417 418 /* Copy the page */ 419 xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen); 420 return 0; 421 } 422 423 /* 424 * Encode MKNOD arguments 425 */ 426 static int 427 nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args) 428 { 429 p = xdr_encode_fhandle(p, args->fh); 430 p = xdr_encode_array(p, args->name, args->len); 431 *p++ = htonl(args->type); 432 p = xdr_encode_sattr(p, args->sattr); 433 if (args->type == NF3CHR || args->type == NF3BLK) { 434 *p++ = htonl(MAJOR(args->rdev)); 435 *p++ = htonl(MINOR(args->rdev)); 436 } 437 438 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 439 return 0; 440 } 441 442 /* 443 * Encode RENAME arguments 444 */ 445 static int 446 nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args) 447 { 448 p = xdr_encode_fhandle(p, args->fromfh); 449 p = xdr_encode_array(p, args->fromname, args->fromlen); 450 p = xdr_encode_fhandle(p, args->tofh); 451 p = xdr_encode_array(p, args->toname, args->tolen); 452 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 453 return 0; 454 } 455 456 /* 457 * Encode LINK arguments 458 */ 459 static int 460 nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args) 461 { 462 p = xdr_encode_fhandle(p, args->fromfh); 463 p = xdr_encode_fhandle(p, args->tofh); 464 p = xdr_encode_array(p, args->toname, args->tolen); 465 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 466 return 0; 467 } 468 469 /* 470 * Encode arguments to readdir call 471 */ 472 static int 473 nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args) 474 { 475 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; 476 unsigned int replen; 477 u32 count = args->count; 478 479 p = xdr_encode_fhandle(p, args->fh); 480 p = xdr_encode_hyper(p, args->cookie); 481 *p++ = args->verf[0]; 482 *p++ = args->verf[1]; 483 if (args->plus) { 484 /* readdirplus: need dircount + buffer size. 485 * We just make sure we make dircount big enough */ 486 *p++ = htonl(count >> 3); 487 } 488 *p++ = htonl(count); 489 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 490 491 /* Inline the page array */ 492 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2; 493 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count); 494 return 0; 495 } 496 497 /* 498 * Decode the result of a readdir call. 499 * We just check for syntactical correctness. 500 */ 501 static int 502 nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res) 503 { 504 struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 505 struct kvec *iov = rcvbuf->head; 506 struct page **page; 507 int hdrlen, recvd; 508 int status, nr; 509 unsigned int len, pglen; 510 __be32 *entry, *end, *kaddr; 511 512 status = ntohl(*p++); 513 /* Decode post_op_attrs */ 514 p = xdr_decode_post_op_attr(p, res->dir_attr); 515 if (status) 516 return -nfs_stat_to_errno(status); 517 /* Decode verifier cookie */ 518 if (res->verf) { 519 res->verf[0] = *p++; 520 res->verf[1] = *p++; 521 } else { 522 p += 2; 523 } 524 525 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 526 if (iov->iov_len < hdrlen) { 527 printk(KERN_WARNING "NFS: READDIR reply header overflowed:" 528 "length %d > %Zu\n", hdrlen, iov->iov_len); 529 return -errno_NFSERR_IO; 530 } else if (iov->iov_len != hdrlen) { 531 dprintk("NFS: READDIR header is short. iovec will be shifted.\n"); 532 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); 533 } 534 535 pglen = rcvbuf->page_len; 536 recvd = rcvbuf->len - hdrlen; 537 if (pglen > recvd) 538 pglen = recvd; 539 page = rcvbuf->pages; 540 kaddr = p = kmap_atomic(*page, KM_USER0); 541 end = (__be32 *)((char *)p + pglen); 542 entry = p; 543 for (nr = 0; *p++; nr++) { 544 if (p + 3 > end) 545 goto short_pkt; 546 p += 2; /* inode # */ 547 len = ntohl(*p++); /* string length */ 548 p += XDR_QUADLEN(len) + 2; /* name + cookie */ 549 if (len > NFS3_MAXNAMLEN) { 550 printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n", 551 len); 552 goto err_unmap; 553 } 554 555 if (res->plus) { 556 /* post_op_attr */ 557 if (p + 2 > end) 558 goto short_pkt; 559 if (*p++) { 560 p += 21; 561 if (p + 1 > end) 562 goto short_pkt; 563 } 564 /* post_op_fh3 */ 565 if (*p++) { 566 if (p + 1 > end) 567 goto short_pkt; 568 len = ntohl(*p++); 569 if (len > NFS3_FHSIZE) { 570 printk(KERN_WARNING "NFS: giant filehandle in " 571 "readdir (len %x)!\n", len); 572 goto err_unmap; 573 } 574 p += XDR_QUADLEN(len); 575 } 576 } 577 578 if (p + 2 > end) 579 goto short_pkt; 580 entry = p; 581 } 582 if (!nr && (entry[0] != 0 || entry[1] == 0)) 583 goto short_pkt; 584 out: 585 kunmap_atomic(kaddr, KM_USER0); 586 return nr; 587 short_pkt: 588 entry[0] = entry[1] = 0; 589 /* truncate listing ? */ 590 if (!nr) { 591 printk(KERN_NOTICE "NFS: readdir reply truncated!\n"); 592 entry[1] = 1; 593 } 594 goto out; 595 err_unmap: 596 nr = -errno_NFSERR_IO; 597 goto out; 598 } 599 600 __be32 * 601 nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus) 602 { 603 struct nfs_entry old = *entry; 604 605 if (!*p++) { 606 if (!*p) 607 return ERR_PTR(-EAGAIN); 608 entry->eof = 1; 609 return ERR_PTR(-EBADCOOKIE); 610 } 611 612 p = xdr_decode_hyper(p, &entry->ino); 613 entry->len = ntohl(*p++); 614 entry->name = (const char *) p; 615 p += XDR_QUADLEN(entry->len); 616 entry->prev_cookie = entry->cookie; 617 p = xdr_decode_hyper(p, &entry->cookie); 618 619 if (plus) { 620 entry->fattr->valid = 0; 621 p = xdr_decode_post_op_attr(p, entry->fattr); 622 /* In fact, a post_op_fh3: */ 623 if (*p++) { 624 p = xdr_decode_fhandle(p, entry->fh); 625 /* Ugh -- server reply was truncated */ 626 if (p == NULL) { 627 dprintk("NFS: FH truncated\n"); 628 *entry = old; 629 return ERR_PTR(-EAGAIN); 630 } 631 } else 632 memset((u8*)(entry->fh), 0, sizeof(*entry->fh)); 633 } 634 635 entry->eof = !p[0] && p[1]; 636 return p; 637 } 638 639 /* 640 * Encode COMMIT arguments 641 */ 642 static int 643 nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args) 644 { 645 p = xdr_encode_fhandle(p, args->fh); 646 p = xdr_encode_hyper(p, args->offset); 647 *p++ = htonl(args->count); 648 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 649 return 0; 650 } 651 652 #ifdef CONFIG_NFS_V3_ACL 653 /* 654 * Encode GETACL arguments 655 */ 656 static int 657 nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p, 658 struct nfs3_getaclargs *args) 659 { 660 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; 661 unsigned int replen; 662 663 p = xdr_encode_fhandle(p, args->fh); 664 *p++ = htonl(args->mask); 665 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 666 667 if (args->mask & (NFS_ACL | NFS_DFACL)) { 668 /* Inline the page array */ 669 replen = (RPC_REPHDRSIZE + auth->au_rslack + 670 ACL3_getaclres_sz) << 2; 671 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, 672 NFSACL_MAXPAGES << PAGE_SHIFT); 673 } 674 return 0; 675 } 676 677 /* 678 * Encode SETACL arguments 679 */ 680 static int 681 nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p, 682 struct nfs3_setaclargs *args) 683 { 684 struct xdr_buf *buf = &req->rq_snd_buf; 685 unsigned int base, len_in_head, len = nfsacl_size( 686 (args->mask & NFS_ACL) ? args->acl_access : NULL, 687 (args->mask & NFS_DFACL) ? args->acl_default : NULL); 688 int count, err; 689 690 p = xdr_encode_fhandle(p, NFS_FH(args->inode)); 691 *p++ = htonl(args->mask); 692 base = (char *)p - (char *)buf->head->iov_base; 693 /* put as much of the acls into head as possible. */ 694 len_in_head = min_t(unsigned int, buf->head->iov_len - base, len); 695 len -= len_in_head; 696 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2)); 697 698 for (count = 0; (count << PAGE_SHIFT) < len; count++) { 699 args->pages[count] = alloc_page(GFP_KERNEL); 700 if (!args->pages[count]) { 701 while (count) 702 __free_page(args->pages[--count]); 703 return -ENOMEM; 704 } 705 } 706 xdr_encode_pages(buf, args->pages, 0, len); 707 708 err = nfsacl_encode(buf, base, args->inode, 709 (args->mask & NFS_ACL) ? 710 args->acl_access : NULL, 1, 0); 711 if (err > 0) 712 err = nfsacl_encode(buf, base + err, args->inode, 713 (args->mask & NFS_DFACL) ? 714 args->acl_default : NULL, 1, 715 NFS_ACL_DEFAULT); 716 return (err > 0) ? 0 : err; 717 } 718 #endif /* CONFIG_NFS_V3_ACL */ 719 720 /* 721 * NFS XDR decode functions 722 */ 723 724 /* 725 * Decode attrstat reply. 726 */ 727 static int 728 nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 729 { 730 int status; 731 732 if ((status = ntohl(*p++))) 733 return -nfs_stat_to_errno(status); 734 xdr_decode_fattr(p, fattr); 735 return 0; 736 } 737 738 /* 739 * Decode status+wcc_data reply 740 * SATTR, REMOVE, RMDIR 741 */ 742 static int 743 nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 744 { 745 int status; 746 747 if ((status = ntohl(*p++))) 748 status = -nfs_stat_to_errno(status); 749 xdr_decode_wcc_data(p, fattr); 750 return status; 751 } 752 753 static int 754 nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res) 755 { 756 return nfs3_xdr_wccstat(req, p, &res->dir_attr); 757 } 758 759 /* 760 * Decode LOOKUP reply 761 */ 762 static int 763 nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res) 764 { 765 int status; 766 767 if ((status = ntohl(*p++))) { 768 status = -nfs_stat_to_errno(status); 769 } else { 770 if (!(p = xdr_decode_fhandle(p, res->fh))) 771 return -errno_NFSERR_IO; 772 p = xdr_decode_post_op_attr(p, res->fattr); 773 } 774 xdr_decode_post_op_attr(p, res->dir_attr); 775 return status; 776 } 777 778 /* 779 * Decode ACCESS reply 780 */ 781 static int 782 nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res) 783 { 784 int status = ntohl(*p++); 785 786 p = xdr_decode_post_op_attr(p, res->fattr); 787 if (status) 788 return -nfs_stat_to_errno(status); 789 res->access = ntohl(*p++); 790 return 0; 791 } 792 793 static int 794 nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args) 795 { 796 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth; 797 unsigned int replen; 798 799 p = xdr_encode_fhandle(p, args->fh); 800 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p); 801 802 /* Inline the page array */ 803 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2; 804 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen); 805 return 0; 806 } 807 808 /* 809 * Decode READLINK reply 810 */ 811 static int 812 nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 813 { 814 struct xdr_buf *rcvbuf = &req->rq_rcv_buf; 815 struct kvec *iov = rcvbuf->head; 816 int hdrlen, len, recvd; 817 char *kaddr; 818 int status; 819 820 status = ntohl(*p++); 821 p = xdr_decode_post_op_attr(p, fattr); 822 823 if (status != 0) 824 return -nfs_stat_to_errno(status); 825 826 /* Convert length of symlink */ 827 len = ntohl(*p++); 828 if (len >= rcvbuf->page_len || len <= 0) { 829 dprintk(KERN_WARNING "nfs: server returned giant symlink!\n"); 830 return -ENAMETOOLONG; 831 } 832 833 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 834 if (iov->iov_len < hdrlen) { 835 printk(KERN_WARNING "NFS: READLINK reply header overflowed:" 836 "length %d > %Zu\n", hdrlen, iov->iov_len); 837 return -errno_NFSERR_IO; 838 } else if (iov->iov_len != hdrlen) { 839 dprintk("NFS: READLINK header is short. iovec will be shifted.\n"); 840 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen); 841 } 842 recvd = req->rq_rcv_buf.len - hdrlen; 843 if (recvd < len) { 844 printk(KERN_WARNING "NFS: server cheating in readlink reply: " 845 "count %u > recvd %u\n", len, recvd); 846 return -EIO; 847 } 848 849 /* NULL terminate the string we got */ 850 kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0); 851 kaddr[len+rcvbuf->page_base] = '\0'; 852 kunmap_atomic(kaddr, KM_USER0); 853 return 0; 854 } 855 856 /* 857 * Decode READ reply 858 */ 859 static int 860 nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res) 861 { 862 struct kvec *iov = req->rq_rcv_buf.head; 863 int status, count, ocount, recvd, hdrlen; 864 865 status = ntohl(*p++); 866 p = xdr_decode_post_op_attr(p, res->fattr); 867 868 if (status != 0) 869 return -nfs_stat_to_errno(status); 870 871 /* Decode reply could and EOF flag. NFSv3 is somewhat redundant 872 * in that it puts the count both in the res struct and in the 873 * opaque data count. */ 874 count = ntohl(*p++); 875 res->eof = ntohl(*p++); 876 ocount = ntohl(*p++); 877 878 if (ocount != count) { 879 printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n"); 880 return -errno_NFSERR_IO; 881 } 882 883 hdrlen = (u8 *) p - (u8 *) iov->iov_base; 884 if (iov->iov_len < hdrlen) { 885 printk(KERN_WARNING "NFS: READ reply header overflowed:" 886 "length %d > %Zu\n", hdrlen, iov->iov_len); 887 return -errno_NFSERR_IO; 888 } else if (iov->iov_len != hdrlen) { 889 dprintk("NFS: READ header is short. iovec will be shifted.\n"); 890 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen); 891 } 892 893 recvd = req->rq_rcv_buf.len - hdrlen; 894 if (count > recvd) { 895 printk(KERN_WARNING "NFS: server cheating in read reply: " 896 "count %d > recvd %d\n", count, recvd); 897 count = recvd; 898 res->eof = 0; 899 } 900 901 if (count < res->count) 902 res->count = count; 903 904 return count; 905 } 906 907 /* 908 * Decode WRITE response 909 */ 910 static int 911 nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) 912 { 913 int status; 914 915 status = ntohl(*p++); 916 p = xdr_decode_wcc_data(p, res->fattr); 917 918 if (status != 0) 919 return -nfs_stat_to_errno(status); 920 921 res->count = ntohl(*p++); 922 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++); 923 res->verf->verifier[0] = *p++; 924 res->verf->verifier[1] = *p++; 925 926 return res->count; 927 } 928 929 /* 930 * Decode a CREATE response 931 */ 932 static int 933 nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res) 934 { 935 int status; 936 937 status = ntohl(*p++); 938 if (status == 0) { 939 if (*p++) { 940 if (!(p = xdr_decode_fhandle(p, res->fh))) 941 return -errno_NFSERR_IO; 942 p = xdr_decode_post_op_attr(p, res->fattr); 943 } else { 944 memset(res->fh, 0, sizeof(*res->fh)); 945 /* Do decode post_op_attr but set it to NULL */ 946 p = xdr_decode_post_op_attr(p, res->fattr); 947 res->fattr->valid = 0; 948 } 949 } else { 950 status = -nfs_stat_to_errno(status); 951 } 952 p = xdr_decode_wcc_data(p, res->dir_attr); 953 return status; 954 } 955 956 /* 957 * Decode RENAME reply 958 */ 959 static int 960 nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res) 961 { 962 int status; 963 964 if ((status = ntohl(*p++)) != 0) 965 status = -nfs_stat_to_errno(status); 966 p = xdr_decode_wcc_data(p, res->fromattr); 967 p = xdr_decode_wcc_data(p, res->toattr); 968 return status; 969 } 970 971 /* 972 * Decode LINK reply 973 */ 974 static int 975 nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res) 976 { 977 int status; 978 979 if ((status = ntohl(*p++)) != 0) 980 status = -nfs_stat_to_errno(status); 981 p = xdr_decode_post_op_attr(p, res->fattr); 982 p = xdr_decode_wcc_data(p, res->dir_attr); 983 return status; 984 } 985 986 /* 987 * Decode FSSTAT reply 988 */ 989 static int 990 nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res) 991 { 992 int status; 993 994 status = ntohl(*p++); 995 996 p = xdr_decode_post_op_attr(p, res->fattr); 997 if (status != 0) 998 return -nfs_stat_to_errno(status); 999 1000 p = xdr_decode_hyper(p, &res->tbytes); 1001 p = xdr_decode_hyper(p, &res->fbytes); 1002 p = xdr_decode_hyper(p, &res->abytes); 1003 p = xdr_decode_hyper(p, &res->tfiles); 1004 p = xdr_decode_hyper(p, &res->ffiles); 1005 p = xdr_decode_hyper(p, &res->afiles); 1006 1007 /* ignore invarsec */ 1008 return 0; 1009 } 1010 1011 /* 1012 * Decode FSINFO reply 1013 */ 1014 static int 1015 nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res) 1016 { 1017 int status; 1018 1019 status = ntohl(*p++); 1020 1021 p = xdr_decode_post_op_attr(p, res->fattr); 1022 if (status != 0) 1023 return -nfs_stat_to_errno(status); 1024 1025 res->rtmax = ntohl(*p++); 1026 res->rtpref = ntohl(*p++); 1027 res->rtmult = ntohl(*p++); 1028 res->wtmax = ntohl(*p++); 1029 res->wtpref = ntohl(*p++); 1030 res->wtmult = ntohl(*p++); 1031 res->dtpref = ntohl(*p++); 1032 p = xdr_decode_hyper(p, &res->maxfilesize); 1033 1034 /* ignore time_delta and properties */ 1035 res->lease_time = 0; 1036 return 0; 1037 } 1038 1039 /* 1040 * Decode PATHCONF reply 1041 */ 1042 static int 1043 nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res) 1044 { 1045 int status; 1046 1047 status = ntohl(*p++); 1048 1049 p = xdr_decode_post_op_attr(p, res->fattr); 1050 if (status != 0) 1051 return -nfs_stat_to_errno(status); 1052 res->max_link = ntohl(*p++); 1053 res->max_namelen = ntohl(*p++); 1054 1055 /* ignore remaining fields */ 1056 return 0; 1057 } 1058 1059 /* 1060 * Decode COMMIT reply 1061 */ 1062 static int 1063 nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res) 1064 { 1065 int status; 1066 1067 status = ntohl(*p++); 1068 p = xdr_decode_wcc_data(p, res->fattr); 1069 if (status != 0) 1070 return -nfs_stat_to_errno(status); 1071 1072 res->verf->verifier[0] = *p++; 1073 res->verf->verifier[1] = *p++; 1074 return 0; 1075 } 1076 1077 #ifdef CONFIG_NFS_V3_ACL 1078 /* 1079 * Decode GETACL reply 1080 */ 1081 static int 1082 nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p, 1083 struct nfs3_getaclres *res) 1084 { 1085 struct xdr_buf *buf = &req->rq_rcv_buf; 1086 int status = ntohl(*p++); 1087 struct posix_acl **acl; 1088 unsigned int *aclcnt; 1089 int err, base; 1090 1091 if (status != 0) 1092 return -nfs_stat_to_errno(status); 1093 p = xdr_decode_post_op_attr(p, res->fattr); 1094 res->mask = ntohl(*p++); 1095 if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT)) 1096 return -EINVAL; 1097 base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base; 1098 1099 acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL; 1100 aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL; 1101 err = nfsacl_decode(buf, base, aclcnt, acl); 1102 1103 acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL; 1104 aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL; 1105 if (err > 0) 1106 err = nfsacl_decode(buf, base + err, aclcnt, acl); 1107 return (err > 0) ? 0 : err; 1108 } 1109 1110 /* 1111 * Decode setacl reply. 1112 */ 1113 static int 1114 nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr) 1115 { 1116 int status = ntohl(*p++); 1117 1118 if (status) 1119 return -nfs_stat_to_errno(status); 1120 xdr_decode_post_op_attr(p, fattr); 1121 return 0; 1122 } 1123 #endif /* CONFIG_NFS_V3_ACL */ 1124 1125 #define PROC(proc, argtype, restype, timer) \ 1126 [NFS3PROC_##proc] = { \ 1127 .p_proc = NFS3PROC_##proc, \ 1128 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \ 1129 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \ 1130 .p_arglen = NFS3_##argtype##_sz, \ 1131 .p_replen = NFS3_##restype##_sz, \ 1132 .p_timer = timer, \ 1133 .p_statidx = NFS3PROC_##proc, \ 1134 .p_name = #proc, \ 1135 } 1136 1137 struct rpc_procinfo nfs3_procedures[] = { 1138 PROC(GETATTR, fhandle, attrstat, 1), 1139 PROC(SETATTR, sattrargs, wccstat, 0), 1140 PROC(LOOKUP, diropargs, lookupres, 2), 1141 PROC(ACCESS, accessargs, accessres, 1), 1142 PROC(READLINK, readlinkargs, readlinkres, 3), 1143 PROC(READ, readargs, readres, 3), 1144 PROC(WRITE, writeargs, writeres, 4), 1145 PROC(CREATE, createargs, createres, 0), 1146 PROC(MKDIR, mkdirargs, createres, 0), 1147 PROC(SYMLINK, symlinkargs, createres, 0), 1148 PROC(MKNOD, mknodargs, createres, 0), 1149 PROC(REMOVE, removeargs, removeres, 0), 1150 PROC(RMDIR, diropargs, wccstat, 0), 1151 PROC(RENAME, renameargs, renameres, 0), 1152 PROC(LINK, linkargs, linkres, 0), 1153 PROC(READDIR, readdirargs, readdirres, 3), 1154 PROC(READDIRPLUS, readdirargs, readdirres, 3), 1155 PROC(FSSTAT, fhandle, fsstatres, 0), 1156 PROC(FSINFO, fhandle, fsinfores, 0), 1157 PROC(PATHCONF, fhandle, pathconfres, 0), 1158 PROC(COMMIT, commitargs, commitres, 5), 1159 }; 1160 1161 struct rpc_version nfs_version3 = { 1162 .number = 3, 1163 .nrprocs = ARRAY_SIZE(nfs3_procedures), 1164 .procs = nfs3_procedures 1165 }; 1166 1167 #ifdef CONFIG_NFS_V3_ACL 1168 static struct rpc_procinfo nfs3_acl_procedures[] = { 1169 [ACLPROC3_GETACL] = { 1170 .p_proc = ACLPROC3_GETACL, 1171 .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs, 1172 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres, 1173 .p_arglen = ACL3_getaclargs_sz, 1174 .p_replen = ACL3_getaclres_sz, 1175 .p_timer = 1, 1176 .p_name = "GETACL", 1177 }, 1178 [ACLPROC3_SETACL] = { 1179 .p_proc = ACLPROC3_SETACL, 1180 .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs, 1181 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres, 1182 .p_arglen = ACL3_setaclargs_sz, 1183 .p_replen = ACL3_setaclres_sz, 1184 .p_timer = 0, 1185 .p_name = "SETACL", 1186 }, 1187 }; 1188 1189 struct rpc_version nfsacl_version3 = { 1190 .number = 3, 1191 .nrprocs = sizeof(nfs3_acl_procedures)/ 1192 sizeof(nfs3_acl_procedures[0]), 1193 .procs = nfs3_acl_procedures, 1194 }; 1195 #endif /* CONFIG_NFS_V3_ACL */ 1196