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