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 */ 22static 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 */ 32static __be32 * 33encode_time3(__be32 *p, struct timespec *time) 34{ 35 *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec); 36 return p; 37} 38 39static __be32 * 40decode_time3(__be32 *p, struct timespec *time) 41{ 42 time->tv_sec = ntohl(*p++); 43 time->tv_nsec = ntohl(*p++); 44 return p; 45} 46 47static __be32 * 48decode_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 67static __be32 * 68encode_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 */ 81static __be32 * 82decode_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 97static __be32 * 98decode_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 142static __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 (d_inode(fhp->fh_dentry)->i_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 163static __be32 * 164encode_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 189static __be32 * 190encode_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 */ 202static __be32 * 203encode_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 * 223nfs3svc_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 */ 231static __be32 * 232encode_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 */ 255void 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 = 0; 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 = 1; 270} 271 272/* 273 * XDR decode functions 274 */ 275int 276nfs3svc_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 284int 285nfs3svc_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 302int 303nfs3svc_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 313int 314nfs3svc_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 325int 326nfs3svc_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 355int 356nfs3svc_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 362 p = decode_fh(p, &args->fh); 363 if (!p) 364 return 0; 365 p = xdr_decode_hyper(p, &args->offset); 366 367 args->count = ntohl(*p++); 368 args->stable = ntohl(*p++); 369 len = args->len = ntohl(*p++); 370 /* 371 * The count must equal the amount of data passed. 372 */ 373 if (args->count != args->len) 374 return 0; 375 376 /* 377 * Check to make sure that we got the right number of 378 * bytes. 379 */ 380 hdr = (void*)p - rqstp->rq_arg.head[0].iov_base; 381 dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len 382 - hdr; 383 /* 384 * Round the length of the data which was specified up to 385 * the next multiple of XDR units and then compare that 386 * against the length which was actually received. 387 * Note that when RPCSEC/GSS (for example) is used, the 388 * data buffer can be padded so dlen might be larger 389 * than required. It must never be smaller. 390 */ 391 if (dlen < XDR_QUADLEN(len)*4) 392 return 0; 393 394 if (args->count > max_blocksize) { 395 args->count = max_blocksize; 396 len = args->len = max_blocksize; 397 } 398 rqstp->rq_vec[0].iov_base = (void*)p; 399 rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr; 400 v = 0; 401 while (len > rqstp->rq_vec[v].iov_len) { 402 len -= rqstp->rq_vec[v].iov_len; 403 v++; 404 rqstp->rq_vec[v].iov_base = page_address(rqstp->rq_pages[v]); 405 rqstp->rq_vec[v].iov_len = PAGE_SIZE; 406 } 407 rqstp->rq_vec[v].iov_len = len; 408 args->vlen = v + 1; 409 return 1; 410} 411 412int 413nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p, 414 struct nfsd3_createargs *args) 415{ 416 if (!(p = decode_fh(p, &args->fh)) 417 || !(p = decode_filename(p, &args->name, &args->len))) 418 return 0; 419 420 switch (args->createmode = ntohl(*p++)) { 421 case NFS3_CREATE_UNCHECKED: 422 case NFS3_CREATE_GUARDED: 423 p = decode_sattr3(p, &args->attrs); 424 break; 425 case NFS3_CREATE_EXCLUSIVE: 426 args->verf = p; 427 p += 2; 428 break; 429 default: 430 return 0; 431 } 432 433 return xdr_argsize_check(rqstp, p); 434} 435int 436nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p, 437 struct nfsd3_createargs *args) 438{ 439 if (!(p = decode_fh(p, &args->fh)) || 440 !(p = decode_filename(p, &args->name, &args->len))) 441 return 0; 442 p = decode_sattr3(p, &args->attrs); 443 444 return xdr_argsize_check(rqstp, p); 445} 446 447int 448nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p, 449 struct nfsd3_symlinkargs *args) 450{ 451 unsigned int len, avail; 452 char *old, *new; 453 struct kvec *vec; 454 455 if (!(p = decode_fh(p, &args->ffh)) || 456 !(p = decode_filename(p, &args->fname, &args->flen)) 457 ) 458 return 0; 459 p = decode_sattr3(p, &args->attrs); 460 461 /* now decode the pathname, which might be larger than the first page. 462 * As we have to check for nul's anyway, we copy it into a new page 463 * This page appears in the rq_res.pages list, but as pages_len is always 464 * 0, it won't get in the way 465 */ 466 len = ntohl(*p++); 467 if (len == 0 || len > NFS3_MAXPATHLEN || len >= PAGE_SIZE) 468 return 0; 469 args->tname = new = page_address(*(rqstp->rq_next_page++)); 470 args->tlen = len; 471 /* first copy and check from the first page */ 472 old = (char*)p; 473 vec = &rqstp->rq_arg.head[0]; 474 avail = vec->iov_len - (old - (char*)vec->iov_base); 475 while (len && avail && *old) { 476 *new++ = *old++; 477 len--; 478 avail--; 479 } 480 /* now copy next page if there is one */ 481 if (len && !avail && rqstp->rq_arg.page_len) { 482 avail = min_t(unsigned int, rqstp->rq_arg.page_len, PAGE_SIZE); 483 old = page_address(rqstp->rq_arg.pages[0]); 484 } 485 while (len && avail && *old) { 486 *new++ = *old++; 487 len--; 488 avail--; 489 } 490 *new = '\0'; 491 if (len) 492 return 0; 493 494 return 1; 495} 496 497int 498nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p, 499 struct nfsd3_mknodargs *args) 500{ 501 if (!(p = decode_fh(p, &args->fh)) 502 || !(p = decode_filename(p, &args->name, &args->len))) 503 return 0; 504 505 args->ftype = ntohl(*p++); 506 507 if (args->ftype == NF3BLK || args->ftype == NF3CHR 508 || args->ftype == NF3SOCK || args->ftype == NF3FIFO) 509 p = decode_sattr3(p, &args->attrs); 510 511 if (args->ftype == NF3BLK || args->ftype == NF3CHR) { 512 args->major = ntohl(*p++); 513 args->minor = ntohl(*p++); 514 } 515 516 return xdr_argsize_check(rqstp, p); 517} 518 519int 520nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p, 521 struct nfsd3_renameargs *args) 522{ 523 if (!(p = decode_fh(p, &args->ffh)) 524 || !(p = decode_filename(p, &args->fname, &args->flen)) 525 || !(p = decode_fh(p, &args->tfh)) 526 || !(p = decode_filename(p, &args->tname, &args->tlen))) 527 return 0; 528 529 return xdr_argsize_check(rqstp, p); 530} 531 532int 533nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, 534 struct nfsd3_readlinkargs *args) 535{ 536 p = decode_fh(p, &args->fh); 537 if (!p) 538 return 0; 539 args->buffer = page_address(*(rqstp->rq_next_page++)); 540 541 return xdr_argsize_check(rqstp, p); 542} 543 544int 545nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p, 546 struct nfsd3_linkargs *args) 547{ 548 if (!(p = decode_fh(p, &args->ffh)) 549 || !(p = decode_fh(p, &args->tfh)) 550 || !(p = decode_filename(p, &args->tname, &args->tlen))) 551 return 0; 552 553 return xdr_argsize_check(rqstp, p); 554} 555 556int 557nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p, 558 struct nfsd3_readdirargs *args) 559{ 560 p = decode_fh(p, &args->fh); 561 if (!p) 562 return 0; 563 p = xdr_decode_hyper(p, &args->cookie); 564 args->verf = p; p += 2; 565 args->dircount = ~0; 566 args->count = ntohl(*p++); 567 args->count = min_t(u32, args->count, PAGE_SIZE); 568 args->buffer = page_address(*(rqstp->rq_next_page++)); 569 570 return xdr_argsize_check(rqstp, p); 571} 572 573int 574nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p, 575 struct nfsd3_readdirargs *args) 576{ 577 int len; 578 u32 max_blocksize = svc_max_payload(rqstp); 579 580 p = decode_fh(p, &args->fh); 581 if (!p) 582 return 0; 583 p = xdr_decode_hyper(p, &args->cookie); 584 args->verf = p; p += 2; 585 args->dircount = ntohl(*p++); 586 args->count = ntohl(*p++); 587 588 len = args->count = min(args->count, max_blocksize); 589 while (len > 0) { 590 struct page *p = *(rqstp->rq_next_page++); 591 if (!args->buffer) 592 args->buffer = page_address(p); 593 len -= PAGE_SIZE; 594 } 595 596 return xdr_argsize_check(rqstp, p); 597} 598 599int 600nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p, 601 struct nfsd3_commitargs *args) 602{ 603 p = decode_fh(p, &args->fh); 604 if (!p) 605 return 0; 606 p = xdr_decode_hyper(p, &args->offset); 607 args->count = ntohl(*p++); 608 609 return xdr_argsize_check(rqstp, p); 610} 611 612/* 613 * XDR encode functions 614 */ 615/* 616 * There must be an encoding function for void results so svc_process 617 * will work properly. 618 */ 619int 620nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) 621{ 622 return xdr_ressize_check(rqstp, p); 623} 624 625/* GETATTR */ 626int 627nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p, 628 struct nfsd3_attrstat *resp) 629{ 630 if (resp->status == 0) { 631 lease_get_mtime(d_inode(resp->fh.fh_dentry), 632 &resp->stat.mtime); 633 p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat); 634 } 635 return xdr_ressize_check(rqstp, p); 636} 637 638/* SETATTR, REMOVE, RMDIR */ 639int 640nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p, 641 struct nfsd3_attrstat *resp) 642{ 643 p = encode_wcc_data(rqstp, p, &resp->fh); 644 return xdr_ressize_check(rqstp, p); 645} 646 647/* LOOKUP */ 648int 649nfs3svc_encode_diropres(struct svc_rqst *rqstp, __be32 *p, 650 struct nfsd3_diropres *resp) 651{ 652 if (resp->status == 0) { 653 p = encode_fh(p, &resp->fh); 654 p = encode_post_op_attr(rqstp, p, &resp->fh); 655 } 656 p = encode_post_op_attr(rqstp, p, &resp->dirfh); 657 return xdr_ressize_check(rqstp, p); 658} 659 660/* ACCESS */ 661int 662nfs3svc_encode_accessres(struct svc_rqst *rqstp, __be32 *p, 663 struct nfsd3_accessres *resp) 664{ 665 p = encode_post_op_attr(rqstp, p, &resp->fh); 666 if (resp->status == 0) 667 *p++ = htonl(resp->access); 668 return xdr_ressize_check(rqstp, p); 669} 670 671/* READLINK */ 672int 673nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p, 674 struct nfsd3_readlinkres *resp) 675{ 676 p = encode_post_op_attr(rqstp, p, &resp->fh); 677 if (resp->status == 0) { 678 *p++ = htonl(resp->len); 679 xdr_ressize_check(rqstp, p); 680 rqstp->rq_res.page_len = resp->len; 681 if (resp->len & 3) { 682 /* need to pad the tail */ 683 rqstp->rq_res.tail[0].iov_base = p; 684 *p = 0; 685 rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3); 686 } 687 return 1; 688 } else 689 return xdr_ressize_check(rqstp, p); 690} 691 692/* READ */ 693int 694nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p, 695 struct nfsd3_readres *resp) 696{ 697 p = encode_post_op_attr(rqstp, p, &resp->fh); 698 if (resp->status == 0) { 699 *p++ = htonl(resp->count); 700 *p++ = htonl(resp->eof); 701 *p++ = htonl(resp->count); /* xdr opaque count */ 702 xdr_ressize_check(rqstp, p); 703 /* now update rqstp->rq_res to reflect data as well */ 704 rqstp->rq_res.page_len = resp->count; 705 if (resp->count & 3) { 706 /* need to pad the tail */ 707 rqstp->rq_res.tail[0].iov_base = p; 708 *p = 0; 709 rqstp->rq_res.tail[0].iov_len = 4 - (resp->count & 3); 710 } 711 return 1; 712 } else 713 return xdr_ressize_check(rqstp, p); 714} 715 716/* WRITE */ 717int 718nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p, 719 struct nfsd3_writeres *resp) 720{ 721 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 722 723 p = encode_wcc_data(rqstp, p, &resp->fh); 724 if (resp->status == 0) { 725 *p++ = htonl(resp->count); 726 *p++ = htonl(resp->committed); 727 *p++ = htonl(nn->nfssvc_boot.tv_sec); 728 *p++ = htonl(nn->nfssvc_boot.tv_usec); 729 } 730 return xdr_ressize_check(rqstp, p); 731} 732 733/* CREATE, MKDIR, SYMLINK, MKNOD */ 734int 735nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p, 736 struct nfsd3_diropres *resp) 737{ 738 if (resp->status == 0) { 739 *p++ = xdr_one; 740 p = encode_fh(p, &resp->fh); 741 p = encode_post_op_attr(rqstp, p, &resp->fh); 742 } 743 p = encode_wcc_data(rqstp, p, &resp->dirfh); 744 return xdr_ressize_check(rqstp, p); 745} 746 747/* RENAME */ 748int 749nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p, 750 struct nfsd3_renameres *resp) 751{ 752 p = encode_wcc_data(rqstp, p, &resp->ffh); 753 p = encode_wcc_data(rqstp, p, &resp->tfh); 754 return xdr_ressize_check(rqstp, p); 755} 756 757/* LINK */ 758int 759nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p, 760 struct nfsd3_linkres *resp) 761{ 762 p = encode_post_op_attr(rqstp, p, &resp->fh); 763 p = encode_wcc_data(rqstp, p, &resp->tfh); 764 return xdr_ressize_check(rqstp, p); 765} 766 767/* READDIR */ 768int 769nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p, 770 struct nfsd3_readdirres *resp) 771{ 772 p = encode_post_op_attr(rqstp, p, &resp->fh); 773 774 if (resp->status == 0) { 775 /* stupid readdir cookie */ 776 memcpy(p, resp->verf, 8); p += 2; 777 xdr_ressize_check(rqstp, p); 778 if (rqstp->rq_res.head[0].iov_len + (2<<2) > PAGE_SIZE) 779 return 1; /*No room for trailer */ 780 rqstp->rq_res.page_len = (resp->count) << 2; 781 782 /* add the 'tail' to the end of the 'head' page - page 0. */ 783 rqstp->rq_res.tail[0].iov_base = p; 784 *p++ = 0; /* no more entries */ 785 *p++ = htonl(resp->common.err == nfserr_eof); 786 rqstp->rq_res.tail[0].iov_len = 2<<2; 787 return 1; 788 } else 789 return xdr_ressize_check(rqstp, p); 790} 791 792static __be32 * 793encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, 794 int namlen, u64 ino) 795{ 796 *p++ = xdr_one; /* mark entry present */ 797 p = xdr_encode_hyper(p, ino); /* file id */ 798 p = xdr_encode_array(p, name, namlen);/* name length & name */ 799 800 cd->offset = p; /* remember pointer */ 801 p = xdr_encode_hyper(p, NFS_OFFSET_MAX);/* offset of next entry */ 802 803 return p; 804} 805 806static __be32 807compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, 808 const char *name, int namlen) 809{ 810 struct svc_export *exp; 811 struct dentry *dparent, *dchild; 812 __be32 rv = nfserr_noent; 813 814 dparent = cd->fh.fh_dentry; 815 exp = cd->fh.fh_export; 816 817 if (isdotent(name, namlen)) { 818 if (namlen == 2) { 819 dchild = dget_parent(dparent); 820 /* filesystem root - cannot return filehandle for ".." */ 821 if (dchild == dparent) 822 goto out; 823 } else 824 dchild = dget(dparent); 825 } else 826 dchild = lookup_one_len(name, dparent, namlen); 827 if (IS_ERR(dchild)) 828 return rv; 829 if (d_mountpoint(dchild)) 830 goto out; 831 if (d_really_is_negative(dchild)) 832 goto out; 833 rv = fh_compose(fhp, exp, dchild, &cd->fh); 834out: 835 dput(dchild); 836 return rv; 837} 838 839static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen) 840{ 841 struct svc_fh *fh = &cd->scratch; 842 __be32 err; 843 844 fh_init(fh, NFS3_FHSIZE); 845 err = compose_entry_fh(cd, fh, name, namlen); 846 if (err) { 847 *p++ = 0; 848 *p++ = 0; 849 goto out; 850 } 851 p = encode_post_op_attr(cd->rqstp, p, fh); 852 *p++ = xdr_one; /* yes, a file handle follows */ 853 p = encode_fh(p, fh); 854out: 855 fh_put(fh); 856 return p; 857} 858 859/* 860 * Encode a directory entry. This one works for both normal readdir 861 * and readdirplus. 862 * The normal readdir reply requires 2 (fileid) + 1 (stringlen) 863 * + string + 2 (cookie) + 1 (next) words, i.e. 6 + strlen. 864 * 865 * The readdirplus baggage is 1+21 words for post_op_attr, plus the 866 * file handle. 867 */ 868 869#define NFS3_ENTRY_BAGGAGE (2 + 1 + 2 + 1) 870#define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2)) 871static int 872encode_entry(struct readdir_cd *ccd, const char *name, int namlen, 873 loff_t offset, u64 ino, unsigned int d_type, int plus) 874{ 875 struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres, 876 common); 877 __be32 *p = cd->buffer; 878 caddr_t curr_page_addr = NULL; 879 struct page ** page; 880 int slen; /* string (name) length */ 881 int elen; /* estimated entry length in words */ 882 int num_entry_words = 0; /* actual number of words */ 883 884 if (cd->offset) { 885 u64 offset64 = offset; 886 887 if (unlikely(cd->offset1)) { 888 /* we ended up with offset on a page boundary */ 889 *cd->offset = htonl(offset64 >> 32); 890 *cd->offset1 = htonl(offset64 & 0xffffffff); 891 cd->offset1 = NULL; 892 } else { 893 xdr_encode_hyper(cd->offset, offset64); 894 } 895 } 896 897 /* 898 dprintk("encode_entry(%.*s @%ld%s)\n", 899 namlen, name, (long) offset, plus? " plus" : ""); 900 */ 901 902 /* truncate filename if too long */ 903 namlen = min(namlen, NFS3_MAXNAMLEN); 904 905 slen = XDR_QUADLEN(namlen); 906 elen = slen + NFS3_ENTRY_BAGGAGE 907 + (plus? NFS3_ENTRYPLUS_BAGGAGE : 0); 908 909 if (cd->buflen < elen) { 910 cd->common.err = nfserr_toosmall; 911 return -EINVAL; 912 } 913 914 /* determine which page in rq_respages[] we are currently filling */ 915 for (page = cd->rqstp->rq_respages + 1; 916 page < cd->rqstp->rq_next_page; page++) { 917 curr_page_addr = page_address(*page); 918 919 if (((caddr_t)cd->buffer >= curr_page_addr) && 920 ((caddr_t)cd->buffer < curr_page_addr + PAGE_SIZE)) 921 break; 922 } 923 924 if ((caddr_t)(cd->buffer + elen) < (curr_page_addr + PAGE_SIZE)) { 925 /* encode entry in current page */ 926 927 p = encode_entry_baggage(cd, p, name, namlen, ino); 928 929 if (plus) 930 p = encode_entryplus_baggage(cd, p, name, namlen); 931 num_entry_words = p - cd->buffer; 932 } else if (*(page+1) != NULL) { 933 /* temporarily encode entry into next page, then move back to 934 * current and next page in rq_respages[] */ 935 __be32 *p1, *tmp; 936 int len1, len2; 937 938 /* grab next page for temporary storage of entry */ 939 p1 = tmp = page_address(*(page+1)); 940 941 p1 = encode_entry_baggage(cd, p1, name, namlen, ino); 942 943 if (plus) 944 p1 = encode_entryplus_baggage(cd, p1, name, namlen); 945 946 /* determine entry word length and lengths to go in pages */ 947 num_entry_words = p1 - tmp; 948 len1 = curr_page_addr + PAGE_SIZE - (caddr_t)cd->buffer; 949 if ((num_entry_words << 2) < len1) { 950 /* the actual number of words in the entry is less 951 * than elen and can still fit in the current page 952 */ 953 memmove(p, tmp, num_entry_words << 2); 954 p += num_entry_words; 955 956 /* update offset */ 957 cd->offset = cd->buffer + (cd->offset - tmp); 958 } else { 959 unsigned int offset_r = (cd->offset - tmp) << 2; 960 961 /* update pointer to offset location. 962 * This is a 64bit quantity, so we need to 963 * deal with 3 cases: 964 * - entirely in first page 965 * - entirely in second page 966 * - 4 bytes in each page 967 */ 968 if (offset_r + 8 <= len1) { 969 cd->offset = p + (cd->offset - tmp); 970 } else if (offset_r >= len1) { 971 cd->offset -= len1 >> 2; 972 } else { 973 /* sitting on the fence */ 974 BUG_ON(offset_r != len1 - 4); 975 cd->offset = p + (cd->offset - tmp); 976 cd->offset1 = tmp; 977 } 978 979 len2 = (num_entry_words << 2) - len1; 980 981 /* move from temp page to current and next pages */ 982 memmove(p, tmp, len1); 983 memmove(tmp, (caddr_t)tmp+len1, len2); 984 985 p = tmp + (len2 >> 2); 986 } 987 } 988 else { 989 cd->common.err = nfserr_toosmall; 990 return -EINVAL; 991 } 992 993 cd->buflen -= num_entry_words; 994 cd->buffer = p; 995 cd->common.err = nfs_ok; 996 return 0; 997 998} 999 1000int 1001nfs3svc_encode_entry(void *cd, const char *name, 1002 int namlen, loff_t offset, u64 ino, unsigned int d_type) 1003{ 1004 return encode_entry(cd, name, namlen, offset, ino, d_type, 0); 1005} 1006 1007int 1008nfs3svc_encode_entry_plus(void *cd, const char *name, 1009 int namlen, loff_t offset, u64 ino, 1010 unsigned int d_type) 1011{ 1012 return encode_entry(cd, name, namlen, offset, ino, d_type, 1); 1013} 1014 1015/* FSSTAT */ 1016int 1017nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p, 1018 struct nfsd3_fsstatres *resp) 1019{ 1020 struct kstatfs *s = &resp->stats; 1021 u64 bs = s->f_bsize; 1022 1023 *p++ = xdr_zero; /* no post_op_attr */ 1024 1025 if (resp->status == 0) { 1026 p = xdr_encode_hyper(p, bs * s->f_blocks); /* total bytes */ 1027 p = xdr_encode_hyper(p, bs * s->f_bfree); /* free bytes */ 1028 p = xdr_encode_hyper(p, bs * s->f_bavail); /* user available bytes */ 1029 p = xdr_encode_hyper(p, s->f_files); /* total inodes */ 1030 p = xdr_encode_hyper(p, s->f_ffree); /* free inodes */ 1031 p = xdr_encode_hyper(p, s->f_ffree); /* user available inodes */ 1032 *p++ = htonl(resp->invarsec); /* mean unchanged time */ 1033 } 1034 return xdr_ressize_check(rqstp, p); 1035} 1036 1037/* FSINFO */ 1038int 1039nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p, 1040 struct nfsd3_fsinfores *resp) 1041{ 1042 *p++ = xdr_zero; /* no post_op_attr */ 1043 1044 if (resp->status == 0) { 1045 *p++ = htonl(resp->f_rtmax); 1046 *p++ = htonl(resp->f_rtpref); 1047 *p++ = htonl(resp->f_rtmult); 1048 *p++ = htonl(resp->f_wtmax); 1049 *p++ = htonl(resp->f_wtpref); 1050 *p++ = htonl(resp->f_wtmult); 1051 *p++ = htonl(resp->f_dtpref); 1052 p = xdr_encode_hyper(p, resp->f_maxfilesize); 1053 *p++ = xdr_one; 1054 *p++ = xdr_zero; 1055 *p++ = htonl(resp->f_properties); 1056 } 1057 1058 return xdr_ressize_check(rqstp, p); 1059} 1060 1061/* PATHCONF */ 1062int 1063nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, __be32 *p, 1064 struct nfsd3_pathconfres *resp) 1065{ 1066 *p++ = xdr_zero; /* no post_op_attr */ 1067 1068 if (resp->status == 0) { 1069 *p++ = htonl(resp->p_link_max); 1070 *p++ = htonl(resp->p_name_max); 1071 *p++ = htonl(resp->p_no_trunc); 1072 *p++ = htonl(resp->p_chown_restricted); 1073 *p++ = htonl(resp->p_case_insensitive); 1074 *p++ = htonl(resp->p_case_preserving); 1075 } 1076 1077 return xdr_ressize_check(rqstp, p); 1078} 1079 1080/* COMMIT */ 1081int 1082nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p, 1083 struct nfsd3_commitres *resp) 1084{ 1085 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 1086 1087 p = encode_wcc_data(rqstp, p, &resp->fh); 1088 /* Write verifier */ 1089 if (resp->status == 0) { 1090 *p++ = htonl(nn->nfssvc_boot.tv_sec); 1091 *p++ = htonl(nn->nfssvc_boot.tv_usec); 1092 } 1093 return xdr_ressize_check(rqstp, p); 1094} 1095 1096/* 1097 * XDR release functions 1098 */ 1099int 1100nfs3svc_release_fhandle(struct svc_rqst *rqstp, __be32 *p, 1101 struct nfsd3_attrstat *resp) 1102{ 1103 fh_put(&resp->fh); 1104 return 1; 1105} 1106 1107int 1108nfs3svc_release_fhandle2(struct svc_rqst *rqstp, __be32 *p, 1109 struct nfsd3_fhandle_pair *resp) 1110{ 1111 fh_put(&resp->fh1); 1112 fh_put(&resp->fh2); 1113 return 1; 1114} 1115