1 /* 2 * XDR support for nfsd/protocol version 3. 3 * 4 * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de> 5 * 6 * 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()! 7 */ 8 9 #include <linux/namei.h> 10 #include <linux/sunrpc/svc_xprt.h> 11 #include "xdr3.h" 12 #include "auth.h" 13 #include "netns.h" 14 #include "vfs.h" 15 16 #define NFSDDBG_FACILITY NFSDDBG_XDR 17 18 19 /* 20 * Mapping of S_IF* types to NFS file types 21 */ 22 static u32 nfs3_ftypes[] = { 23 NF3NON, NF3FIFO, NF3CHR, NF3BAD, 24 NF3DIR, NF3BAD, NF3BLK, NF3BAD, 25 NF3REG, NF3BAD, NF3LNK, NF3BAD, 26 NF3SOCK, NF3BAD, NF3LNK, NF3BAD, 27 }; 28 29 /* 30 * XDR functions for basic NFS types 31 */ 32 static __be32 * 33 encode_time3(__be32 *p, struct timespec *time) 34 { 35 *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec); 36 return p; 37 } 38 39 static __be32 * 40 decode_time3(__be32 *p, struct timespec *time) 41 { 42 time->tv_sec = ntohl(*p++); 43 time->tv_nsec = ntohl(*p++); 44 return p; 45 } 46 47 static __be32 * 48 decode_fh(__be32 *p, struct svc_fh *fhp) 49 { 50 unsigned int size; 51 fh_init(fhp, NFS3_FHSIZE); 52 size = ntohl(*p++); 53 if (size > NFS3_FHSIZE) 54 return NULL; 55 56 memcpy(&fhp->fh_handle.fh_base, p, size); 57 fhp->fh_handle.fh_size = size; 58 return p + XDR_QUADLEN(size); 59 } 60 61 /* Helper function for NFSv3 ACL code */ 62 __be32 *nfs3svc_decode_fh(__be32 *p, struct svc_fh *fhp) 63 { 64 return decode_fh(p, fhp); 65 } 66 67 static __be32 * 68 encode_fh(__be32 *p, struct svc_fh *fhp) 69 { 70 unsigned int size = fhp->fh_handle.fh_size; 71 *p++ = htonl(size); 72 if (size) p[XDR_QUADLEN(size)-1]=0; 73 memcpy(p, &fhp->fh_handle.fh_base, size); 74 return p + XDR_QUADLEN(size); 75 } 76 77 /* 78 * Decode a file name and make sure that the path contains 79 * no slashes or null bytes. 80 */ 81 static __be32 * 82 decode_filename(__be32 *p, char **namp, unsigned int *lenp) 83 { 84 char *name; 85 unsigned int i; 86 87 if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXNAMLEN)) != NULL) { 88 for (i = 0, name = *namp; i < *lenp; i++, name++) { 89 if (*name == '\0' || *name == '/') 90 return NULL; 91 } 92 } 93 94 return p; 95 } 96 97 static __be32 * 98 decode_sattr3(__be32 *p, struct iattr *iap) 99 { 100 u32 tmp; 101 102 iap->ia_valid = 0; 103 104 if (*p++) { 105 iap->ia_valid |= ATTR_MODE; 106 iap->ia_mode = ntohl(*p++); 107 } 108 if (*p++) { 109 iap->ia_uid = make_kuid(&init_user_ns, ntohl(*p++)); 110 if (uid_valid(iap->ia_uid)) 111 iap->ia_valid |= ATTR_UID; 112 } 113 if (*p++) { 114 iap->ia_gid = make_kgid(&init_user_ns, ntohl(*p++)); 115 if (gid_valid(iap->ia_gid)) 116 iap->ia_valid |= ATTR_GID; 117 } 118 if (*p++) { 119 u64 newsize; 120 121 iap->ia_valid |= ATTR_SIZE; 122 p = xdr_decode_hyper(p, &newsize); 123 iap->ia_size = min_t(u64, newsize, NFS_OFFSET_MAX); 124 } 125 if ((tmp = ntohl(*p++)) == 1) { /* set to server time */ 126 iap->ia_valid |= ATTR_ATIME; 127 } else if (tmp == 2) { /* set to client time */ 128 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET; 129 iap->ia_atime.tv_sec = ntohl(*p++); 130 iap->ia_atime.tv_nsec = ntohl(*p++); 131 } 132 if ((tmp = ntohl(*p++)) == 1) { /* set to server time */ 133 iap->ia_valid |= ATTR_MTIME; 134 } else if (tmp == 2) { /* set to client time */ 135 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET; 136 iap->ia_mtime.tv_sec = ntohl(*p++); 137 iap->ia_mtime.tv_nsec = ntohl(*p++); 138 } 139 return p; 140 } 141 142 static __be32 *encode_fsid(__be32 *p, struct svc_fh *fhp) 143 { 144 u64 f; 145 switch(fsid_source(fhp)) { 146 default: 147 case FSIDSOURCE_DEV: 148 p = xdr_encode_hyper(p, (u64)huge_encode_dev 149 (fhp->fh_dentry->d_sb->s_dev)); 150 break; 151 case FSIDSOURCE_FSID: 152 p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid); 153 break; 154 case FSIDSOURCE_UUID: 155 f = ((u64*)fhp->fh_export->ex_uuid)[0]; 156 f ^= ((u64*)fhp->fh_export->ex_uuid)[1]; 157 p = xdr_encode_hyper(p, f); 158 break; 159 } 160 return p; 161 } 162 163 static __be32 * 164 encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, 165 struct kstat *stat) 166 { 167 *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); 168 *p++ = htonl((u32) (stat->mode & S_IALLUGO)); 169 *p++ = htonl((u32) stat->nlink); 170 *p++ = htonl((u32) from_kuid(&init_user_ns, stat->uid)); 171 *p++ = htonl((u32) from_kgid(&init_user_ns, stat->gid)); 172 if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) { 173 p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN); 174 } else { 175 p = xdr_encode_hyper(p, (u64) stat->size); 176 } 177 p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9); 178 *p++ = htonl((u32) MAJOR(stat->rdev)); 179 *p++ = htonl((u32) MINOR(stat->rdev)); 180 p = encode_fsid(p, fhp); 181 p = xdr_encode_hyper(p, stat->ino); 182 p = encode_time3(p, &stat->atime); 183 p = encode_time3(p, &stat->mtime); 184 p = encode_time3(p, &stat->ctime); 185 186 return p; 187 } 188 189 static __be32 * 190 encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 191 { 192 /* Attributes to follow */ 193 *p++ = xdr_one; 194 return encode_fattr3(rqstp, p, fhp, &fhp->fh_post_attr); 195 } 196 197 /* 198 * Encode post-operation attributes. 199 * The inode may be NULL if the call failed because of a stale file 200 * handle. In this case, no attributes are returned. 201 */ 202 static __be32 * 203 encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 204 { 205 struct dentry *dentry = fhp->fh_dentry; 206 if (dentry && d_really_is_positive(dentry)) { 207 __be32 err; 208 struct kstat stat; 209 210 err = fh_getattr(fhp, &stat); 211 if (!err) { 212 *p++ = xdr_one; /* attributes follow */ 213 lease_get_mtime(d_inode(dentry), &stat.mtime); 214 return encode_fattr3(rqstp, p, fhp, &stat); 215 } 216 } 217 *p++ = xdr_zero; 218 return p; 219 } 220 221 /* Helper for NFSv3 ACLs */ 222 __be32 * 223 nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 224 { 225 return encode_post_op_attr(rqstp, p, fhp); 226 } 227 228 /* 229 * Enocde weak cache consistency data 230 */ 231 static __be32 * 232 encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) 233 { 234 struct dentry *dentry = fhp->fh_dentry; 235 236 if (dentry && d_really_is_positive(dentry) && fhp->fh_post_saved) { 237 if (fhp->fh_pre_saved) { 238 *p++ = xdr_one; 239 p = xdr_encode_hyper(p, (u64) fhp->fh_pre_size); 240 p = encode_time3(p, &fhp->fh_pre_mtime); 241 p = encode_time3(p, &fhp->fh_pre_ctime); 242 } else { 243 *p++ = xdr_zero; 244 } 245 return encode_saved_post_attr(rqstp, p, fhp); 246 } 247 /* no pre- or post-attrs */ 248 *p++ = xdr_zero; 249 return encode_post_op_attr(rqstp, p, fhp); 250 } 251 252 /* 253 * Fill in the post_op attr for the wcc data 254 */ 255 void fill_post_wcc(struct svc_fh *fhp) 256 { 257 __be32 err; 258 259 if (fhp->fh_post_saved) 260 printk("nfsd: inode locked twice during operation.\n"); 261 262 err = fh_getattr(fhp, &fhp->fh_post_attr); 263 fhp->fh_post_change = d_inode(fhp->fh_dentry)->i_version; 264 if (err) { 265 fhp->fh_post_saved = false; 266 /* Grab the ctime anyway - set_change_info might use it */ 267 fhp->fh_post_attr.ctime = d_inode(fhp->fh_dentry)->i_ctime; 268 } else 269 fhp->fh_post_saved = true; 270 } 271 272 /* 273 * XDR decode functions 274 */ 275 int 276 nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *args) 277 { 278 p = decode_fh(p, &args->fh); 279 if (!p) 280 return 0; 281 return xdr_argsize_check(rqstp, p); 282 } 283 284 int 285 nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p, 286 struct nfsd3_sattrargs *args) 287 { 288 p = decode_fh(p, &args->fh); 289 if (!p) 290 return 0; 291 p = decode_sattr3(p, &args->attrs); 292 293 if ((args->check_guard = ntohl(*p++)) != 0) { 294 struct timespec time; 295 p = decode_time3(p, &time); 296 args->guardtime = time.tv_sec; 297 } 298 299 return xdr_argsize_check(rqstp, p); 300 } 301 302 int 303 nfs3svc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p, 304 struct nfsd3_diropargs *args) 305 { 306 if (!(p = decode_fh(p, &args->fh)) 307 || !(p = decode_filename(p, &args->name, &args->len))) 308 return 0; 309 310 return xdr_argsize_check(rqstp, p); 311 } 312 313 int 314 nfs3svc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p, 315 struct nfsd3_accessargs *args) 316 { 317 p = decode_fh(p, &args->fh); 318 if (!p) 319 return 0; 320 args->access = ntohl(*p++); 321 322 return xdr_argsize_check(rqstp, p); 323 } 324 325 int 326 nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p, 327 struct nfsd3_readargs *args) 328 { 329 unsigned int len; 330 int v; 331 u32 max_blocksize = svc_max_payload(rqstp); 332 333 p = decode_fh(p, &args->fh); 334 if (!p) 335 return 0; 336 p = xdr_decode_hyper(p, &args->offset); 337 338 args->count = ntohl(*p++); 339 len = min(args->count, max_blocksize); 340 341 /* set up the kvec */ 342 v=0; 343 while (len > 0) { 344 struct page *p = *(rqstp->rq_next_page++); 345 346 rqstp->rq_vec[v].iov_base = page_address(p); 347 rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE); 348 len -= rqstp->rq_vec[v].iov_len; 349 v++; 350 } 351 args->vlen = v; 352 return xdr_argsize_check(rqstp, p); 353 } 354 355 int 356 nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p, 357 struct nfsd3_writeargs *args) 358 { 359 unsigned int len, v, hdr, dlen; 360 u32 max_blocksize = svc_max_payload(rqstp); 361 struct kvec *head = rqstp->rq_arg.head; 362 struct kvec *tail = rqstp->rq_arg.tail; 363 364 p = decode_fh(p, &args->fh); 365 if (!p) 366 return 0; 367 p = xdr_decode_hyper(p, &args->offset); 368 369 args->count = ntohl(*p++); 370 args->stable = ntohl(*p++); 371 len = args->len = ntohl(*p++); 372 if ((void *)p > head->iov_base + head->iov_len) 373 return 0; 374 /* 375 * The count must equal the amount of data passed. 376 */ 377 if (args->count != args->len) 378 return 0; 379 380 /* 381 * Check to make sure that we got the right number of 382 * bytes. 383 */ 384 hdr = (void*)p - head->iov_base; 385 dlen = head->iov_len + rqstp->rq_arg.page_len + tail->iov_len - hdr; 386 /* 387 * Round the length of the data which was specified up to 388 * the next multiple of XDR units and then compare that 389 * against the length which was actually received. 390 * Note that when RPCSEC/GSS (for example) is used, the 391 * data buffer can be padded so dlen might be larger 392 * than required. It must never be smaller. 393 */ 394 if (dlen < XDR_QUADLEN(len)*4) 395 return 0; 396 397 if (args->count > max_blocksize) { 398 args->count = max_blocksize; 399 len = args->len = max_blocksize; 400 } 401 rqstp->rq_vec[0].iov_base = (void*)p; 402 rqstp->rq_vec[0].iov_len = head->iov_len - hdr; 403 v = 0; 404 while (len > rqstp->rq_vec[v].iov_len) { 405 len -= rqstp->rq_vec[v].iov_len; 406 v++; 407 rqstp->rq_vec[v].iov_base = page_address(rqstp->rq_pages[v]); 408 rqstp->rq_vec[v].iov_len = PAGE_SIZE; 409 } 410 rqstp->rq_vec[v].iov_len = len; 411 args->vlen = v + 1; 412 return 1; 413 } 414 415 int 416 nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p, 417 struct nfsd3_createargs *args) 418 { 419 if (!(p = decode_fh(p, &args->fh)) 420 || !(p = decode_filename(p, &args->name, &args->len))) 421 return 0; 422 423 switch (args->createmode = ntohl(*p++)) { 424 case NFS3_CREATE_UNCHECKED: 425 case NFS3_CREATE_GUARDED: 426 p = decode_sattr3(p, &args->attrs); 427 break; 428 case NFS3_CREATE_EXCLUSIVE: 429 args->verf = p; 430 p += 2; 431 break; 432 default: 433 return 0; 434 } 435 436 return xdr_argsize_check(rqstp, p); 437 } 438 int 439 nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p, 440 struct nfsd3_createargs *args) 441 { 442 if (!(p = decode_fh(p, &args->fh)) || 443 !(p = decode_filename(p, &args->name, &args->len))) 444 return 0; 445 p = decode_sattr3(p, &args->attrs); 446 447 return xdr_argsize_check(rqstp, p); 448 } 449 450 int 451 nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p, 452 struct nfsd3_symlinkargs *args) 453 { 454 unsigned int len, avail; 455 char *old, *new; 456 struct kvec *vec; 457 458 if (!(p = decode_fh(p, &args->ffh)) || 459 !(p = decode_filename(p, &args->fname, &args->flen)) 460 ) 461 return 0; 462 p = decode_sattr3(p, &args->attrs); 463 464 /* now decode the pathname, which might be larger than the first page. 465 * As we have to check for nul's anyway, we copy it into a new page 466 * This page appears in the rq_res.pages list, but as pages_len is always 467 * 0, it won't get in the way 468 */ 469 len = ntohl(*p++); 470 if (len == 0 || len > NFS3_MAXPATHLEN || len >= PAGE_SIZE) 471 return 0; 472 args->tname = new = page_address(*(rqstp->rq_next_page++)); 473 args->tlen = len; 474 /* first copy and check from the first page */ 475 old = (char*)p; 476 vec = &rqstp->rq_arg.head[0]; 477 if ((void *)old > vec->iov_base + vec->iov_len) 478 return 0; 479 avail = vec->iov_len - (old - (char*)vec->iov_base); 480 while (len && avail && *old) { 481 *new++ = *old++; 482 len--; 483 avail--; 484 } 485 /* now copy next page if there is one */ 486 if (len && !avail && rqstp->rq_arg.page_len) { 487 avail = min_t(unsigned int, rqstp->rq_arg.page_len, PAGE_SIZE); 488 old = page_address(rqstp->rq_arg.pages[0]); 489 } 490 while (len && avail && *old) { 491 *new++ = *old++; 492 len--; 493 avail--; 494 } 495 *new = '\0'; 496 if (len) 497 return 0; 498 499 return 1; 500 } 501 502 int 503 nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p, 504 struct nfsd3_mknodargs *args) 505 { 506 if (!(p = decode_fh(p, &args->fh)) 507 || !(p = decode_filename(p, &args->name, &args->len))) 508 return 0; 509 510 args->ftype = ntohl(*p++); 511 512 if (args->ftype == NF3BLK || args->ftype == NF3CHR 513 || args->ftype == NF3SOCK || args->ftype == NF3FIFO) 514 p = decode_sattr3(p, &args->attrs); 515 516 if (args->ftype == NF3BLK || args->ftype == NF3CHR) { 517 args->major = ntohl(*p++); 518 args->minor = ntohl(*p++); 519 } 520 521 return xdr_argsize_check(rqstp, p); 522 } 523 524 int 525 nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p, 526 struct nfsd3_renameargs *args) 527 { 528 if (!(p = decode_fh(p, &args->ffh)) 529 || !(p = decode_filename(p, &args->fname, &args->flen)) 530 || !(p = decode_fh(p, &args->tfh)) 531 || !(p = decode_filename(p, &args->tname, &args->tlen))) 532 return 0; 533 534 return xdr_argsize_check(rqstp, p); 535 } 536 537 int 538 nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, 539 struct nfsd3_readlinkargs *args) 540 { 541 p = decode_fh(p, &args->fh); 542 if (!p) 543 return 0; 544 args->buffer = page_address(*(rqstp->rq_next_page++)); 545 546 return xdr_argsize_check(rqstp, p); 547 } 548 549 int 550 nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p, 551 struct nfsd3_linkargs *args) 552 { 553 if (!(p = decode_fh(p, &args->ffh)) 554 || !(p = decode_fh(p, &args->tfh)) 555 || !(p = decode_filename(p, &args->tname, &args->tlen))) 556 return 0; 557 558 return xdr_argsize_check(rqstp, p); 559 } 560 561 int 562 nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p, 563 struct nfsd3_readdirargs *args) 564 { 565 p = decode_fh(p, &args->fh); 566 if (!p) 567 return 0; 568 p = xdr_decode_hyper(p, &args->cookie); 569 args->verf = p; p += 2; 570 args->dircount = ~0; 571 args->count = ntohl(*p++); 572 args->count = min_t(u32, args->count, PAGE_SIZE); 573 args->buffer = page_address(*(rqstp->rq_next_page++)); 574 575 return xdr_argsize_check(rqstp, p); 576 } 577 578 int 579 nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p, 580 struct nfsd3_readdirargs *args) 581 { 582 int len; 583 u32 max_blocksize = svc_max_payload(rqstp); 584 585 p = decode_fh(p, &args->fh); 586 if (!p) 587 return 0; 588 p = xdr_decode_hyper(p, &args->cookie); 589 args->verf = p; p += 2; 590 args->dircount = ntohl(*p++); 591 args->count = ntohl(*p++); 592 593 len = args->count = min(args->count, max_blocksize); 594 while (len > 0) { 595 struct page *p = *(rqstp->rq_next_page++); 596 if (!args->buffer) 597 args->buffer = page_address(p); 598 len -= PAGE_SIZE; 599 } 600 601 return xdr_argsize_check(rqstp, p); 602 } 603 604 int 605 nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p, 606 struct nfsd3_commitargs *args) 607 { 608 p = decode_fh(p, &args->fh); 609 if (!p) 610 return 0; 611 p = xdr_decode_hyper(p, &args->offset); 612 args->count = ntohl(*p++); 613 614 return xdr_argsize_check(rqstp, p); 615 } 616 617 /* 618 * XDR encode functions 619 */ 620 /* 621 * There must be an encoding function for void results so svc_process 622 * will work properly. 623 */ 624 int 625 nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) 626 { 627 return xdr_ressize_check(rqstp, p); 628 } 629 630 /* GETATTR */ 631 int 632 nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p, 633 struct nfsd3_attrstat *resp) 634 { 635 if (resp->status == 0) { 636 lease_get_mtime(d_inode(resp->fh.fh_dentry), 637 &resp->stat.mtime); 638 p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat); 639 } 640 return xdr_ressize_check(rqstp, p); 641 } 642 643 /* SETATTR, REMOVE, RMDIR */ 644 int 645 nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p, 646 struct nfsd3_attrstat *resp) 647 { 648 p = encode_wcc_data(rqstp, p, &resp->fh); 649 return xdr_ressize_check(rqstp, p); 650 } 651 652 /* LOOKUP */ 653 int 654 nfs3svc_encode_diropres(struct svc_rqst *rqstp, __be32 *p, 655 struct nfsd3_diropres *resp) 656 { 657 if (resp->status == 0) { 658 p = encode_fh(p, &resp->fh); 659 p = encode_post_op_attr(rqstp, p, &resp->fh); 660 } 661 p = encode_post_op_attr(rqstp, p, &resp->dirfh); 662 return xdr_ressize_check(rqstp, p); 663 } 664 665 /* ACCESS */ 666 int 667 nfs3svc_encode_accessres(struct svc_rqst *rqstp, __be32 *p, 668 struct nfsd3_accessres *resp) 669 { 670 p = encode_post_op_attr(rqstp, p, &resp->fh); 671 if (resp->status == 0) 672 *p++ = htonl(resp->access); 673 return xdr_ressize_check(rqstp, p); 674 } 675 676 /* READLINK */ 677 int 678 nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p, 679 struct nfsd3_readlinkres *resp) 680 { 681 p = encode_post_op_attr(rqstp, p, &resp->fh); 682 if (resp->status == 0) { 683 *p++ = htonl(resp->len); 684 xdr_ressize_check(rqstp, p); 685 rqstp->rq_res.page_len = resp->len; 686 if (resp->len & 3) { 687 /* need to pad the tail */ 688 rqstp->rq_res.tail[0].iov_base = p; 689 *p = 0; 690 rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3); 691 } 692 return 1; 693 } else 694 return xdr_ressize_check(rqstp, p); 695 } 696 697 /* READ */ 698 int 699 nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p, 700 struct nfsd3_readres *resp) 701 { 702 p = encode_post_op_attr(rqstp, p, &resp->fh); 703 if (resp->status == 0) { 704 *p++ = htonl(resp->count); 705 *p++ = htonl(resp->eof); 706 *p++ = htonl(resp->count); /* xdr opaque count */ 707 xdr_ressize_check(rqstp, p); 708 /* now update rqstp->rq_res to reflect data as well */ 709 rqstp->rq_res.page_len = resp->count; 710 if (resp->count & 3) { 711 /* need to pad the tail */ 712 rqstp->rq_res.tail[0].iov_base = p; 713 *p = 0; 714 rqstp->rq_res.tail[0].iov_len = 4 - (resp->count & 3); 715 } 716 return 1; 717 } else 718 return xdr_ressize_check(rqstp, p); 719 } 720 721 /* WRITE */ 722 int 723 nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p, 724 struct nfsd3_writeres *resp) 725 { 726 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 727 728 p = encode_wcc_data(rqstp, p, &resp->fh); 729 if (resp->status == 0) { 730 *p++ = htonl(resp->count); 731 *p++ = htonl(resp->committed); 732 *p++ = htonl(nn->nfssvc_boot.tv_sec); 733 *p++ = htonl(nn->nfssvc_boot.tv_usec); 734 } 735 return xdr_ressize_check(rqstp, p); 736 } 737 738 /* CREATE, MKDIR, SYMLINK, MKNOD */ 739 int 740 nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p, 741 struct nfsd3_diropres *resp) 742 { 743 if (resp->status == 0) { 744 *p++ = xdr_one; 745 p = encode_fh(p, &resp->fh); 746 p = encode_post_op_attr(rqstp, p, &resp->fh); 747 } 748 p = encode_wcc_data(rqstp, p, &resp->dirfh); 749 return xdr_ressize_check(rqstp, p); 750 } 751 752 /* RENAME */ 753 int 754 nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p, 755 struct nfsd3_renameres *resp) 756 { 757 p = encode_wcc_data(rqstp, p, &resp->ffh); 758 p = encode_wcc_data(rqstp, p, &resp->tfh); 759 return xdr_ressize_check(rqstp, p); 760 } 761 762 /* LINK */ 763 int 764 nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p, 765 struct nfsd3_linkres *resp) 766 { 767 p = encode_post_op_attr(rqstp, p, &resp->fh); 768 p = encode_wcc_data(rqstp, p, &resp->tfh); 769 return xdr_ressize_check(rqstp, p); 770 } 771 772 /* READDIR */ 773 int 774 nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p, 775 struct nfsd3_readdirres *resp) 776 { 777 p = encode_post_op_attr(rqstp, p, &resp->fh); 778 779 if (resp->status == 0) { 780 /* stupid readdir cookie */ 781 memcpy(p, resp->verf, 8); p += 2; 782 xdr_ressize_check(rqstp, p); 783 if (rqstp->rq_res.head[0].iov_len + (2<<2) > PAGE_SIZE) 784 return 1; /*No room for trailer */ 785 rqstp->rq_res.page_len = (resp->count) << 2; 786 787 /* add the 'tail' to the end of the 'head' page - page 0. */ 788 rqstp->rq_res.tail[0].iov_base = p; 789 *p++ = 0; /* no more entries */ 790 *p++ = htonl(resp->common.err == nfserr_eof); 791 rqstp->rq_res.tail[0].iov_len = 2<<2; 792 return 1; 793 } else 794 return xdr_ressize_check(rqstp, p); 795 } 796 797 static __be32 * 798 encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, 799 int namlen, u64 ino) 800 { 801 *p++ = xdr_one; /* mark entry present */ 802 p = xdr_encode_hyper(p, ino); /* file id */ 803 p = xdr_encode_array(p, name, namlen);/* name length & name */ 804 805 cd->offset = p; /* remember pointer */ 806 p = xdr_encode_hyper(p, NFS_OFFSET_MAX);/* offset of next entry */ 807 808 return p; 809 } 810 811 static __be32 812 compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, 813 const char *name, int namlen, u64 ino) 814 { 815 struct svc_export *exp; 816 struct dentry *dparent, *dchild; 817 __be32 rv = nfserr_noent; 818 819 dparent = cd->fh.fh_dentry; 820 exp = cd->fh.fh_export; 821 822 if (isdotent(name, namlen)) { 823 if (namlen == 2) { 824 dchild = dget_parent(dparent); 825 /* filesystem root - cannot return filehandle for ".." */ 826 if (dchild == dparent) 827 goto out; 828 } else 829 dchild = dget(dparent); 830 } else 831 dchild = lookup_one_len_unlocked(name, dparent, namlen); 832 if (IS_ERR(dchild)) 833 return rv; 834 if (d_mountpoint(dchild)) 835 goto out; 836 if (d_really_is_negative(dchild)) 837 goto out; 838 if (dchild->d_inode->i_ino != ino) 839 goto out; 840 rv = fh_compose(fhp, exp, dchild, &cd->fh); 841 out: 842 dput(dchild); 843 return rv; 844 } 845 846 static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen, u64 ino) 847 { 848 struct svc_fh *fh = &cd->scratch; 849 __be32 err; 850 851 fh_init(fh, NFS3_FHSIZE); 852 err = compose_entry_fh(cd, fh, name, namlen, ino); 853 if (err) { 854 *p++ = 0; 855 *p++ = 0; 856 goto out; 857 } 858 p = encode_post_op_attr(cd->rqstp, p, fh); 859 *p++ = xdr_one; /* yes, a file handle follows */ 860 p = encode_fh(p, fh); 861 out: 862 fh_put(fh); 863 return p; 864 } 865 866 /* 867 * Encode a directory entry. This one works for both normal readdir 868 * and readdirplus. 869 * The normal readdir reply requires 2 (fileid) + 1 (stringlen) 870 * + string + 2 (cookie) + 1 (next) words, i.e. 6 + strlen. 871 * 872 * The readdirplus baggage is 1+21 words for post_op_attr, plus the 873 * file handle. 874 */ 875 876 #define NFS3_ENTRY_BAGGAGE (2 + 1 + 2 + 1) 877 #define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2)) 878 static int 879 encode_entry(struct readdir_cd *ccd, const char *name, int namlen, 880 loff_t offset, u64 ino, unsigned int d_type, int plus) 881 { 882 struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres, 883 common); 884 __be32 *p = cd->buffer; 885 caddr_t curr_page_addr = NULL; 886 struct page ** page; 887 int slen; /* string (name) length */ 888 int elen; /* estimated entry length in words */ 889 int num_entry_words = 0; /* actual number of words */ 890 891 if (cd->offset) { 892 u64 offset64 = offset; 893 894 if (unlikely(cd->offset1)) { 895 /* we ended up with offset on a page boundary */ 896 *cd->offset = htonl(offset64 >> 32); 897 *cd->offset1 = htonl(offset64 & 0xffffffff); 898 cd->offset1 = NULL; 899 } else { 900 xdr_encode_hyper(cd->offset, offset64); 901 } 902 } 903 904 /* 905 dprintk("encode_entry(%.*s @%ld%s)\n", 906 namlen, name, (long) offset, plus? " plus" : ""); 907 */ 908 909 /* truncate filename if too long */ 910 namlen = min(namlen, NFS3_MAXNAMLEN); 911 912 slen = XDR_QUADLEN(namlen); 913 elen = slen + NFS3_ENTRY_BAGGAGE 914 + (plus? NFS3_ENTRYPLUS_BAGGAGE : 0); 915 916 if (cd->buflen < elen) { 917 cd->common.err = nfserr_toosmall; 918 return -EINVAL; 919 } 920 921 /* determine which page in rq_respages[] we are currently filling */ 922 for (page = cd->rqstp->rq_respages + 1; 923 page < cd->rqstp->rq_next_page; page++) { 924 curr_page_addr = page_address(*page); 925 926 if (((caddr_t)cd->buffer >= curr_page_addr) && 927 ((caddr_t)cd->buffer < curr_page_addr + PAGE_SIZE)) 928 break; 929 } 930 931 if ((caddr_t)(cd->buffer + elen) < (curr_page_addr + PAGE_SIZE)) { 932 /* encode entry in current page */ 933 934 p = encode_entry_baggage(cd, p, name, namlen, ino); 935 936 if (plus) 937 p = encode_entryplus_baggage(cd, p, name, namlen, ino); 938 num_entry_words = p - cd->buffer; 939 } else if (*(page+1) != NULL) { 940 /* temporarily encode entry into next page, then move back to 941 * current and next page in rq_respages[] */ 942 __be32 *p1, *tmp; 943 int len1, len2; 944 945 /* grab next page for temporary storage of entry */ 946 p1 = tmp = page_address(*(page+1)); 947 948 p1 = encode_entry_baggage(cd, p1, name, namlen, ino); 949 950 if (plus) 951 p1 = encode_entryplus_baggage(cd, p1, name, namlen, ino); 952 953 /* determine entry word length and lengths to go in pages */ 954 num_entry_words = p1 - tmp; 955 len1 = curr_page_addr + PAGE_SIZE - (caddr_t)cd->buffer; 956 if ((num_entry_words << 2) < len1) { 957 /* the actual number of words in the entry is less 958 * than elen and can still fit in the current page 959 */ 960 memmove(p, tmp, num_entry_words << 2); 961 p += num_entry_words; 962 963 /* update offset */ 964 cd->offset = cd->buffer + (cd->offset - tmp); 965 } else { 966 unsigned int offset_r = (cd->offset - tmp) << 2; 967 968 /* update pointer to offset location. 969 * This is a 64bit quantity, so we need to 970 * deal with 3 cases: 971 * - entirely in first page 972 * - entirely in second page 973 * - 4 bytes in each page 974 */ 975 if (offset_r + 8 <= len1) { 976 cd->offset = p + (cd->offset - tmp); 977 } else if (offset_r >= len1) { 978 cd->offset -= len1 >> 2; 979 } else { 980 /* sitting on the fence */ 981 BUG_ON(offset_r != len1 - 4); 982 cd->offset = p + (cd->offset - tmp); 983 cd->offset1 = tmp; 984 } 985 986 len2 = (num_entry_words << 2) - len1; 987 988 /* move from temp page to current and next pages */ 989 memmove(p, tmp, len1); 990 memmove(tmp, (caddr_t)tmp+len1, len2); 991 992 p = tmp + (len2 >> 2); 993 } 994 } 995 else { 996 cd->common.err = nfserr_toosmall; 997 return -EINVAL; 998 } 999 1000 cd->buflen -= num_entry_words; 1001 cd->buffer = p; 1002 cd->common.err = nfs_ok; 1003 return 0; 1004 1005 } 1006 1007 int 1008 nfs3svc_encode_entry(void *cd, const char *name, 1009 int namlen, loff_t offset, u64 ino, unsigned int d_type) 1010 { 1011 return encode_entry(cd, name, namlen, offset, ino, d_type, 0); 1012 } 1013 1014 int 1015 nfs3svc_encode_entry_plus(void *cd, const char *name, 1016 int namlen, loff_t offset, u64 ino, 1017 unsigned int d_type) 1018 { 1019 return encode_entry(cd, name, namlen, offset, ino, d_type, 1); 1020 } 1021 1022 /* FSSTAT */ 1023 int 1024 nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p, 1025 struct nfsd3_fsstatres *resp) 1026 { 1027 struct kstatfs *s = &resp->stats; 1028 u64 bs = s->f_bsize; 1029 1030 *p++ = xdr_zero; /* no post_op_attr */ 1031 1032 if (resp->status == 0) { 1033 p = xdr_encode_hyper(p, bs * s->f_blocks); /* total bytes */ 1034 p = xdr_encode_hyper(p, bs * s->f_bfree); /* free bytes */ 1035 p = xdr_encode_hyper(p, bs * s->f_bavail); /* user available bytes */ 1036 p = xdr_encode_hyper(p, s->f_files); /* total inodes */ 1037 p = xdr_encode_hyper(p, s->f_ffree); /* free inodes */ 1038 p = xdr_encode_hyper(p, s->f_ffree); /* user available inodes */ 1039 *p++ = htonl(resp->invarsec); /* mean unchanged time */ 1040 } 1041 return xdr_ressize_check(rqstp, p); 1042 } 1043 1044 /* FSINFO */ 1045 int 1046 nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p, 1047 struct nfsd3_fsinfores *resp) 1048 { 1049 *p++ = xdr_zero; /* no post_op_attr */ 1050 1051 if (resp->status == 0) { 1052 *p++ = htonl(resp->f_rtmax); 1053 *p++ = htonl(resp->f_rtpref); 1054 *p++ = htonl(resp->f_rtmult); 1055 *p++ = htonl(resp->f_wtmax); 1056 *p++ = htonl(resp->f_wtpref); 1057 *p++ = htonl(resp->f_wtmult); 1058 *p++ = htonl(resp->f_dtpref); 1059 p = xdr_encode_hyper(p, resp->f_maxfilesize); 1060 *p++ = xdr_one; 1061 *p++ = xdr_zero; 1062 *p++ = htonl(resp->f_properties); 1063 } 1064 1065 return xdr_ressize_check(rqstp, p); 1066 } 1067 1068 /* PATHCONF */ 1069 int 1070 nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, __be32 *p, 1071 struct nfsd3_pathconfres *resp) 1072 { 1073 *p++ = xdr_zero; /* no post_op_attr */ 1074 1075 if (resp->status == 0) { 1076 *p++ = htonl(resp->p_link_max); 1077 *p++ = htonl(resp->p_name_max); 1078 *p++ = htonl(resp->p_no_trunc); 1079 *p++ = htonl(resp->p_chown_restricted); 1080 *p++ = htonl(resp->p_case_insensitive); 1081 *p++ = htonl(resp->p_case_preserving); 1082 } 1083 1084 return xdr_ressize_check(rqstp, p); 1085 } 1086 1087 /* COMMIT */ 1088 int 1089 nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p, 1090 struct nfsd3_commitres *resp) 1091 { 1092 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 1093 1094 p = encode_wcc_data(rqstp, p, &resp->fh); 1095 /* Write verifier */ 1096 if (resp->status == 0) { 1097 *p++ = htonl(nn->nfssvc_boot.tv_sec); 1098 *p++ = htonl(nn->nfssvc_boot.tv_usec); 1099 } 1100 return xdr_ressize_check(rqstp, p); 1101 } 1102 1103 /* 1104 * XDR release functions 1105 */ 1106 int 1107 nfs3svc_release_fhandle(struct svc_rqst *rqstp, __be32 *p, 1108 struct nfsd3_attrstat *resp) 1109 { 1110 fh_put(&resp->fh); 1111 return 1; 1112 } 1113 1114 int 1115 nfs3svc_release_fhandle2(struct svc_rqst *rqstp, __be32 *p, 1116 struct nfsd3_fhandle_pair *resp) 1117 { 1118 fh_put(&resp->fh1); 1119 fh_put(&resp->fh2); 1120 return 1; 1121 } 1122