1/* 2 * fs/nfs/nfs4xdr.c 3 * 4 * Server-side XDR for NFSv4 5 * 6 * Copyright (c) 2002 The Regents of the University of Michigan. 7 * All rights reserved. 8 * 9 * Kendrick Smith <kmsmith@umich.edu> 10 * Andy Adamson <andros@umich.edu> 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of the University nor the names of its 22 * contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED 26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 28 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 32 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * TODO: Neil Brown made the following observation: We currently 38 * initially reserve NFSD_BUFSIZE space on the transmit queue and 39 * never release any of that until the request is complete. 40 * It would be good to calculate a new maximum response size while 41 * decoding the COMPOUND, and call svc_reserve with this number 42 * at the end of nfs4svc_decode_compoundargs. 43 */ 44 45#include <linux/param.h> 46#include <linux/smp.h> 47#include <linux/fs.h> 48#include <linux/namei.h> 49#include <linux/vfs.h> 50#include <linux/sunrpc/xdr.h> 51#include <linux/sunrpc/svc.h> 52#include <linux/sunrpc/clnt.h> 53#include <linux/nfsd/nfsd.h> 54#include <linux/nfsd/state.h> 55#include <linux/nfsd/xdr4.h> 56#include <linux/nfsd_idmap.h> 57#include <linux/nfs4.h> 58#include <linux/nfs4_acl.h> 59 60#define NFSDDBG_FACILITY NFSDDBG_XDR 61 62/* 63 * As per referral draft, the fsid for a referral MUST be different from the fsid of the containing 64 * directory in order to indicate to the client that a filesystem boundary is present 65 * We use a fixed fsid for a referral 66 */ 67#define NFS4_REFERRAL_FSID_MAJOR 0x8000000ULL 68#define NFS4_REFERRAL_FSID_MINOR 0x8000000ULL 69 70static __be32 71check_filename(char *str, int len, __be32 err) 72{ 73 int i; 74 75 if (len == 0) 76 return nfserr_inval; 77 if (isdotent(str, len)) 78 return err; 79 for (i = 0; i < len; i++) 80 if (str[i] == '/') 81 return err; 82 return 0; 83} 84 85/* 86 * START OF "GENERIC" DECODE ROUTINES. 87 * These may look a little ugly since they are imported from a "generic" 88 * set of XDR encode/decode routines which are intended to be shared by 89 * all of our NFSv4 implementations (OpenBSD, MacOS X...). 90 * 91 * If the pain of reading these is too great, it should be a straightforward 92 * task to translate them into Linux-specific versions which are more 93 * consistent with the style used in NFSv2/v3... 94 */ 95#define DECODE_HEAD \ 96 __be32 *p; \ 97 __be32 status 98#define DECODE_TAIL \ 99 status = 0; \ 100out: \ 101 return status; \ 102xdr_error: \ 103 printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \ 104 status = nfserr_bad_xdr; \ 105 goto out 106 107#define READ32(x) (x) = ntohl(*p++) 108#define READ64(x) do { \ 109 (x) = (u64)ntohl(*p++) << 32; \ 110 (x) |= ntohl(*p++); \ 111} while (0) 112#define READTIME(x) do { \ 113 p++; \ 114 (x) = ntohl(*p++); \ 115 p++; \ 116} while (0) 117#define READMEM(x,nbytes) do { \ 118 x = (char *)p; \ 119 p += XDR_QUADLEN(nbytes); \ 120} while (0) 121#define SAVEMEM(x,nbytes) do { \ 122 if (!(x = (p==argp->tmp || p == argp->tmpp) ? \ 123 savemem(argp, p, nbytes) : \ 124 (char *)p)) { \ 125 printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \ 126 goto xdr_error; \ 127 } \ 128 p += XDR_QUADLEN(nbytes); \ 129} while (0) 130#define COPYMEM(x,nbytes) do { \ 131 memcpy((x), p, nbytes); \ 132 p += XDR_QUADLEN(nbytes); \ 133} while (0) 134 135/* READ_BUF, read_buf(): nbytes must be <= PAGE_SIZE */ 136#define READ_BUF(nbytes) do { \ 137 if (nbytes <= (u32)((char *)argp->end - (char *)argp->p)) { \ 138 p = argp->p; \ 139 argp->p += XDR_QUADLEN(nbytes); \ 140 } else if (!(p = read_buf(argp, nbytes))) { \ 141 printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); \ 142 goto xdr_error; \ 143 } \ 144} while (0) 145 146static __be32 *read_buf(struct nfsd4_compoundargs *argp, int nbytes) 147{ 148 /* We want more bytes than seem to be available. 149 * Maybe we need a new page, maybe we have just run out 150 */ 151 int avail = (char*)argp->end - (char*)argp->p; 152 __be32 *p; 153 if (avail + argp->pagelen < nbytes) 154 return NULL; 155 if (avail + PAGE_SIZE < nbytes) /* need more than a page !! */ 156 return NULL; 157 /* ok, we can do it with the current plus the next page */ 158 if (nbytes <= sizeof(argp->tmp)) 159 p = argp->tmp; 160 else { 161 kfree(argp->tmpp); 162 p = argp->tmpp = kmalloc(nbytes, GFP_KERNEL); 163 if (!p) 164 return NULL; 165 166 } 167 memcpy(p, argp->p, avail); 168 /* step to next page */ 169 argp->p = page_address(argp->pagelist[0]); 170 argp->pagelist++; 171 if (argp->pagelen < PAGE_SIZE) { 172 argp->end = p + (argp->pagelen>>2); 173 argp->pagelen = 0; 174 } else { 175 argp->end = p + (PAGE_SIZE>>2); 176 argp->pagelen -= PAGE_SIZE; 177 } 178 memcpy(((char*)p)+avail, argp->p, (nbytes - avail)); 179 argp->p += XDR_QUADLEN(nbytes - avail); 180 return p; 181} 182 183static int 184defer_free(struct nfsd4_compoundargs *argp, 185 void (*release)(const void *), void *p) 186{ 187 struct tmpbuf *tb; 188 189 tb = kmalloc(sizeof(*tb), GFP_KERNEL); 190 if (!tb) 191 return -ENOMEM; 192 tb->buf = p; 193 tb->release = release; 194 tb->next = argp->to_free; 195 argp->to_free = tb; 196 return 0; 197} 198 199static char *savemem(struct nfsd4_compoundargs *argp, __be32 *p, int nbytes) 200{ 201 if (p == argp->tmp) { 202 p = kmalloc(nbytes, GFP_KERNEL); 203 if (!p) 204 return NULL; 205 memcpy(p, argp->tmp, nbytes); 206 } else { 207 BUG_ON(p != argp->tmpp); 208 argp->tmpp = NULL; 209 } 210 if (defer_free(argp, kfree, p)) { 211 kfree(p); 212 return NULL; 213 } else 214 return (char *)p; 215} 216 217static __be32 218nfsd4_decode_bitmap(struct nfsd4_compoundargs *argp, u32 *bmval) 219{ 220 u32 bmlen; 221 DECODE_HEAD; 222 223 bmval[0] = 0; 224 bmval[1] = 0; 225 226 READ_BUF(4); 227 READ32(bmlen); 228 if (bmlen > 1000) 229 goto xdr_error; 230 231 READ_BUF(bmlen << 2); 232 if (bmlen > 0) 233 READ32(bmval[0]); 234 if (bmlen > 1) 235 READ32(bmval[1]); 236 237 DECODE_TAIL; 238} 239 240static __be32 241nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *iattr, 242 struct nfs4_acl **acl) 243{ 244 int expected_len, len = 0; 245 u32 dummy32; 246 char *buf; 247 int host_err; 248 249 DECODE_HEAD; 250 iattr->ia_valid = 0; 251 if ((status = nfsd4_decode_bitmap(argp, bmval))) 252 return status; 253 254 /* 255 * According to spec, unsupported attributes return ERR_ATTRNOTSUPP; 256 * read-only attributes return ERR_INVAL. 257 */ 258 if ((bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) || (bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1)) 259 return nfserr_attrnotsupp; 260 if ((bmval[0] & ~NFSD_WRITEABLE_ATTRS_WORD0) || (bmval[1] & ~NFSD_WRITEABLE_ATTRS_WORD1)) 261 return nfserr_inval; 262 263 READ_BUF(4); 264 READ32(expected_len); 265 266 if (bmval[0] & FATTR4_WORD0_SIZE) { 267 READ_BUF(8); 268 len += 8; 269 READ64(iattr->ia_size); 270 iattr->ia_valid |= ATTR_SIZE; 271 } 272 if (bmval[0] & FATTR4_WORD0_ACL) { 273 int nace; 274 struct nfs4_ace *ace; 275 276 READ_BUF(4); len += 4; 277 READ32(nace); 278 279 if (nace > NFS4_ACL_MAX) 280 return nfserr_resource; 281 282 *acl = nfs4_acl_new(nace); 283 if (*acl == NULL) { 284 host_err = -ENOMEM; 285 goto out_nfserr; 286 } 287 defer_free(argp, kfree, *acl); 288 289 (*acl)->naces = nace; 290 for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) { 291 READ_BUF(16); len += 16; 292 READ32(ace->type); 293 READ32(ace->flag); 294 READ32(ace->access_mask); 295 READ32(dummy32); 296 READ_BUF(dummy32); 297 len += XDR_QUADLEN(dummy32) << 2; 298 READMEM(buf, dummy32); 299 ace->whotype = nfs4_acl_get_whotype(buf, dummy32); 300 host_err = 0; 301 if (ace->whotype != NFS4_ACL_WHO_NAMED) 302 ace->who = 0; 303 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP) 304 host_err = nfsd_map_name_to_gid(argp->rqstp, 305 buf, dummy32, &ace->who); 306 else 307 host_err = nfsd_map_name_to_uid(argp->rqstp, 308 buf, dummy32, &ace->who); 309 if (host_err) 310 goto out_nfserr; 311 } 312 } else 313 *acl = NULL; 314 if (bmval[1] & FATTR4_WORD1_MODE) { 315 READ_BUF(4); 316 len += 4; 317 READ32(iattr->ia_mode); 318 iattr->ia_mode &= (S_IFMT | S_IALLUGO); 319 iattr->ia_valid |= ATTR_MODE; 320 } 321 if (bmval[1] & FATTR4_WORD1_OWNER) { 322 READ_BUF(4); 323 len += 4; 324 READ32(dummy32); 325 READ_BUF(dummy32); 326 len += (XDR_QUADLEN(dummy32) << 2); 327 READMEM(buf, dummy32); 328 if ((host_err = nfsd_map_name_to_uid(argp->rqstp, buf, dummy32, &iattr->ia_uid))) 329 goto out_nfserr; 330 iattr->ia_valid |= ATTR_UID; 331 } 332 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP) { 333 READ_BUF(4); 334 len += 4; 335 READ32(dummy32); 336 READ_BUF(dummy32); 337 len += (XDR_QUADLEN(dummy32) << 2); 338 READMEM(buf, dummy32); 339 if ((host_err = nfsd_map_name_to_gid(argp->rqstp, buf, dummy32, &iattr->ia_gid))) 340 goto out_nfserr; 341 iattr->ia_valid |= ATTR_GID; 342 } 343 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) { 344 READ_BUF(4); 345 len += 4; 346 READ32(dummy32); 347 switch (dummy32) { 348 case NFS4_SET_TO_CLIENT_TIME: 349 /* We require the high 32 bits of 'seconds' to be 0, and we ignore 350 all 32 bits of 'nseconds'. */ 351 READ_BUF(12); 352 len += 12; 353 READ32(dummy32); 354 if (dummy32) 355 return nfserr_inval; 356 READ32(iattr->ia_atime.tv_sec); 357 READ32(iattr->ia_atime.tv_nsec); 358 if (iattr->ia_atime.tv_nsec >= (u32)1000000000) 359 return nfserr_inval; 360 iattr->ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET); 361 break; 362 case NFS4_SET_TO_SERVER_TIME: 363 iattr->ia_valid |= ATTR_ATIME; 364 break; 365 default: 366 goto xdr_error; 367 } 368 } 369 if (bmval[1] & FATTR4_WORD1_TIME_METADATA) { 370 /* We require the high 32 bits of 'seconds' to be 0, and we ignore 371 all 32 bits of 'nseconds'. */ 372 READ_BUF(12); 373 len += 12; 374 READ32(dummy32); 375 if (dummy32) 376 return nfserr_inval; 377 READ32(iattr->ia_ctime.tv_sec); 378 READ32(iattr->ia_ctime.tv_nsec); 379 if (iattr->ia_ctime.tv_nsec >= (u32)1000000000) 380 return nfserr_inval; 381 iattr->ia_valid |= ATTR_CTIME; 382 } 383 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) { 384 READ_BUF(4); 385 len += 4; 386 READ32(dummy32); 387 switch (dummy32) { 388 case NFS4_SET_TO_CLIENT_TIME: 389 /* We require the high 32 bits of 'seconds' to be 0, and we ignore 390 all 32 bits of 'nseconds'. */ 391 READ_BUF(12); 392 len += 12; 393 READ32(dummy32); 394 if (dummy32) 395 return nfserr_inval; 396 READ32(iattr->ia_mtime.tv_sec); 397 READ32(iattr->ia_mtime.tv_nsec); 398 if (iattr->ia_mtime.tv_nsec >= (u32)1000000000) 399 return nfserr_inval; 400 iattr->ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET); 401 break; 402 case NFS4_SET_TO_SERVER_TIME: 403 iattr->ia_valid |= ATTR_MTIME; 404 break; 405 default: 406 goto xdr_error; 407 } 408 } 409 if (len != expected_len) 410 goto xdr_error; 411 412 DECODE_TAIL; 413 414out_nfserr: 415 status = nfserrno(host_err); 416 goto out; 417} 418 419static __be32 420nfsd4_decode_access(struct nfsd4_compoundargs *argp, struct nfsd4_access *access) 421{ 422 DECODE_HEAD; 423 424 READ_BUF(4); 425 READ32(access->ac_req_access); 426 427 DECODE_TAIL; 428} 429 430static __be32 431nfsd4_decode_close(struct nfsd4_compoundargs *argp, struct nfsd4_close *close) 432{ 433 DECODE_HEAD; 434 435 close->cl_stateowner = NULL; 436 READ_BUF(4 + sizeof(stateid_t)); 437 READ32(close->cl_seqid); 438 READ32(close->cl_stateid.si_generation); 439 COPYMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t)); 440 441 DECODE_TAIL; 442} 443 444 445static __be32 446nfsd4_decode_commit(struct nfsd4_compoundargs *argp, struct nfsd4_commit *commit) 447{ 448 DECODE_HEAD; 449 450 READ_BUF(12); 451 READ64(commit->co_offset); 452 READ32(commit->co_count); 453 454 DECODE_TAIL; 455} 456 457static __be32 458nfsd4_decode_create(struct nfsd4_compoundargs *argp, struct nfsd4_create *create) 459{ 460 DECODE_HEAD; 461 462 READ_BUF(4); 463 READ32(create->cr_type); 464 switch (create->cr_type) { 465 case NF4LNK: 466 READ_BUF(4); 467 READ32(create->cr_linklen); 468 READ_BUF(create->cr_linklen); 469 SAVEMEM(create->cr_linkname, create->cr_linklen); 470 break; 471 case NF4BLK: 472 case NF4CHR: 473 READ_BUF(8); 474 READ32(create->cr_specdata1); 475 READ32(create->cr_specdata2); 476 break; 477 case NF4SOCK: 478 case NF4FIFO: 479 case NF4DIR: 480 default: 481 break; 482 } 483 484 READ_BUF(4); 485 READ32(create->cr_namelen); 486 READ_BUF(create->cr_namelen); 487 SAVEMEM(create->cr_name, create->cr_namelen); 488 if ((status = check_filename(create->cr_name, create->cr_namelen, nfserr_inval))) 489 return status; 490 491 if ((status = nfsd4_decode_fattr(argp, create->cr_bmval, &create->cr_iattr, &create->cr_acl))) 492 goto out; 493 494 DECODE_TAIL; 495} 496 497static inline __be32 498nfsd4_decode_delegreturn(struct nfsd4_compoundargs *argp, struct nfsd4_delegreturn *dr) 499{ 500 DECODE_HEAD; 501 502 READ_BUF(sizeof(stateid_t)); 503 READ32(dr->dr_stateid.si_generation); 504 COPYMEM(&dr->dr_stateid.si_opaque, sizeof(stateid_opaque_t)); 505 506 DECODE_TAIL; 507} 508 509static inline __be32 510nfsd4_decode_getattr(struct nfsd4_compoundargs *argp, struct nfsd4_getattr *getattr) 511{ 512 return nfsd4_decode_bitmap(argp, getattr->ga_bmval); 513} 514 515static __be32 516nfsd4_decode_link(struct nfsd4_compoundargs *argp, struct nfsd4_link *link) 517{ 518 DECODE_HEAD; 519 520 READ_BUF(4); 521 READ32(link->li_namelen); 522 READ_BUF(link->li_namelen); 523 SAVEMEM(link->li_name, link->li_namelen); 524 if ((status = check_filename(link->li_name, link->li_namelen, nfserr_inval))) 525 return status; 526 527 DECODE_TAIL; 528} 529 530static __be32 531nfsd4_decode_lock(struct nfsd4_compoundargs *argp, struct nfsd4_lock *lock) 532{ 533 DECODE_HEAD; 534 535 lock->lk_replay_owner = NULL; 536 /* 537 * type, reclaim(boolean), offset, length, new_lock_owner(boolean) 538 */ 539 READ_BUF(28); 540 READ32(lock->lk_type); 541 if ((lock->lk_type < NFS4_READ_LT) || (lock->lk_type > NFS4_WRITEW_LT)) 542 goto xdr_error; 543 READ32(lock->lk_reclaim); 544 READ64(lock->lk_offset); 545 READ64(lock->lk_length); 546 READ32(lock->lk_is_new); 547 548 if (lock->lk_is_new) { 549 READ_BUF(36); 550 READ32(lock->lk_new_open_seqid); 551 READ32(lock->lk_new_open_stateid.si_generation); 552 553 COPYMEM(&lock->lk_new_open_stateid.si_opaque, sizeof(stateid_opaque_t)); 554 READ32(lock->lk_new_lock_seqid); 555 COPYMEM(&lock->lk_new_clientid, sizeof(clientid_t)); 556 READ32(lock->lk_new_owner.len); 557 READ_BUF(lock->lk_new_owner.len); 558 READMEM(lock->lk_new_owner.data, lock->lk_new_owner.len); 559 } else { 560 READ_BUF(20); 561 READ32(lock->lk_old_lock_stateid.si_generation); 562 COPYMEM(&lock->lk_old_lock_stateid.si_opaque, sizeof(stateid_opaque_t)); 563 READ32(lock->lk_old_lock_seqid); 564 } 565 566 DECODE_TAIL; 567} 568 569static __be32 570nfsd4_decode_lockt(struct nfsd4_compoundargs *argp, struct nfsd4_lockt *lockt) 571{ 572 DECODE_HEAD; 573 574 READ_BUF(32); 575 READ32(lockt->lt_type); 576 if((lockt->lt_type < NFS4_READ_LT) || (lockt->lt_type > NFS4_WRITEW_LT)) 577 goto xdr_error; 578 READ64(lockt->lt_offset); 579 READ64(lockt->lt_length); 580 COPYMEM(&lockt->lt_clientid, 8); 581 READ32(lockt->lt_owner.len); 582 READ_BUF(lockt->lt_owner.len); 583 READMEM(lockt->lt_owner.data, lockt->lt_owner.len); 584 585 DECODE_TAIL; 586} 587 588static __be32 589nfsd4_decode_locku(struct nfsd4_compoundargs *argp, struct nfsd4_locku *locku) 590{ 591 DECODE_HEAD; 592 593 locku->lu_stateowner = NULL; 594 READ_BUF(24 + sizeof(stateid_t)); 595 READ32(locku->lu_type); 596 if ((locku->lu_type < NFS4_READ_LT) || (locku->lu_type > NFS4_WRITEW_LT)) 597 goto xdr_error; 598 READ32(locku->lu_seqid); 599 READ32(locku->lu_stateid.si_generation); 600 COPYMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t)); 601 READ64(locku->lu_offset); 602 READ64(locku->lu_length); 603 604 DECODE_TAIL; 605} 606 607static __be32 608nfsd4_decode_lookup(struct nfsd4_compoundargs *argp, struct nfsd4_lookup *lookup) 609{ 610 DECODE_HEAD; 611 612 READ_BUF(4); 613 READ32(lookup->lo_len); 614 READ_BUF(lookup->lo_len); 615 SAVEMEM(lookup->lo_name, lookup->lo_len); 616 if ((status = check_filename(lookup->lo_name, lookup->lo_len, nfserr_noent))) 617 return status; 618 619 DECODE_TAIL; 620} 621 622static __be32 623nfsd4_decode_open(struct nfsd4_compoundargs *argp, struct nfsd4_open *open) 624{ 625 DECODE_HEAD; 626 627 memset(open->op_bmval, 0, sizeof(open->op_bmval)); 628 open->op_iattr.ia_valid = 0; 629 open->op_stateowner = NULL; 630 631 /* seqid, share_access, share_deny, clientid, ownerlen */ 632 READ_BUF(16 + sizeof(clientid_t)); 633 READ32(open->op_seqid); 634 READ32(open->op_share_access); 635 READ32(open->op_share_deny); 636 COPYMEM(&open->op_clientid, sizeof(clientid_t)); 637 READ32(open->op_owner.len); 638 639 /* owner, open_flag */ 640 READ_BUF(open->op_owner.len + 4); 641 SAVEMEM(open->op_owner.data, open->op_owner.len); 642 READ32(open->op_create); 643 switch (open->op_create) { 644 case NFS4_OPEN_NOCREATE: 645 break; 646 case NFS4_OPEN_CREATE: 647 READ_BUF(4); 648 READ32(open->op_createmode); 649 switch (open->op_createmode) { 650 case NFS4_CREATE_UNCHECKED: 651 case NFS4_CREATE_GUARDED: 652 if ((status = nfsd4_decode_fattr(argp, open->op_bmval, &open->op_iattr, &open->op_acl))) 653 goto out; 654 break; 655 case NFS4_CREATE_EXCLUSIVE: 656 READ_BUF(8); 657 COPYMEM(open->op_verf.data, 8); 658 break; 659 default: 660 goto xdr_error; 661 } 662 break; 663 default: 664 goto xdr_error; 665 } 666 667 /* open_claim */ 668 READ_BUF(4); 669 READ32(open->op_claim_type); 670 switch (open->op_claim_type) { 671 case NFS4_OPEN_CLAIM_NULL: 672 case NFS4_OPEN_CLAIM_DELEGATE_PREV: 673 READ_BUF(4); 674 READ32(open->op_fname.len); 675 READ_BUF(open->op_fname.len); 676 SAVEMEM(open->op_fname.data, open->op_fname.len); 677 if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval))) 678 return status; 679 break; 680 case NFS4_OPEN_CLAIM_PREVIOUS: 681 READ_BUF(4); 682 READ32(open->op_delegate_type); 683 break; 684 case NFS4_OPEN_CLAIM_DELEGATE_CUR: 685 READ_BUF(sizeof(stateid_t) + 4); 686 COPYMEM(&open->op_delegate_stateid, sizeof(stateid_t)); 687 READ32(open->op_fname.len); 688 READ_BUF(open->op_fname.len); 689 SAVEMEM(open->op_fname.data, open->op_fname.len); 690 if ((status = check_filename(open->op_fname.data, open->op_fname.len, nfserr_inval))) 691 return status; 692 break; 693 default: 694 goto xdr_error; 695 } 696 697 DECODE_TAIL; 698} 699 700static __be32 701nfsd4_decode_open_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_open_confirm *open_conf) 702{ 703 DECODE_HEAD; 704 705 open_conf->oc_stateowner = NULL; 706 READ_BUF(4 + sizeof(stateid_t)); 707 READ32(open_conf->oc_req_stateid.si_generation); 708 COPYMEM(&open_conf->oc_req_stateid.si_opaque, sizeof(stateid_opaque_t)); 709 READ32(open_conf->oc_seqid); 710 711 DECODE_TAIL; 712} 713 714static __be32 715nfsd4_decode_open_downgrade(struct nfsd4_compoundargs *argp, struct nfsd4_open_downgrade *open_down) 716{ 717 DECODE_HEAD; 718 719 open_down->od_stateowner = NULL; 720 READ_BUF(12 + sizeof(stateid_t)); 721 READ32(open_down->od_stateid.si_generation); 722 COPYMEM(&open_down->od_stateid.si_opaque, sizeof(stateid_opaque_t)); 723 READ32(open_down->od_seqid); 724 READ32(open_down->od_share_access); 725 READ32(open_down->od_share_deny); 726 727 DECODE_TAIL; 728} 729 730static __be32 731nfsd4_decode_putfh(struct nfsd4_compoundargs *argp, struct nfsd4_putfh *putfh) 732{ 733 DECODE_HEAD; 734 735 READ_BUF(4); 736 READ32(putfh->pf_fhlen); 737 if (putfh->pf_fhlen > NFS4_FHSIZE) 738 goto xdr_error; 739 READ_BUF(putfh->pf_fhlen); 740 SAVEMEM(putfh->pf_fhval, putfh->pf_fhlen); 741 742 DECODE_TAIL; 743} 744 745static __be32 746nfsd4_decode_read(struct nfsd4_compoundargs *argp, struct nfsd4_read *read) 747{ 748 DECODE_HEAD; 749 750 READ_BUF(sizeof(stateid_t) + 12); 751 READ32(read->rd_stateid.si_generation); 752 COPYMEM(&read->rd_stateid.si_opaque, sizeof(stateid_opaque_t)); 753 READ64(read->rd_offset); 754 READ32(read->rd_length); 755 756 DECODE_TAIL; 757} 758 759static __be32 760nfsd4_decode_readdir(struct nfsd4_compoundargs *argp, struct nfsd4_readdir *readdir) 761{ 762 DECODE_HEAD; 763 764 READ_BUF(24); 765 READ64(readdir->rd_cookie); 766 COPYMEM(readdir->rd_verf.data, sizeof(readdir->rd_verf.data)); 767 READ32(readdir->rd_dircount); /* just in case you needed a useless field... */ 768 READ32(readdir->rd_maxcount); 769 if ((status = nfsd4_decode_bitmap(argp, readdir->rd_bmval))) 770 goto out; 771 772 DECODE_TAIL; 773} 774 775static __be32 776nfsd4_decode_remove(struct nfsd4_compoundargs *argp, struct nfsd4_remove *remove) 777{ 778 DECODE_HEAD; 779 780 READ_BUF(4); 781 READ32(remove->rm_namelen); 782 READ_BUF(remove->rm_namelen); 783 SAVEMEM(remove->rm_name, remove->rm_namelen); 784 if ((status = check_filename(remove->rm_name, remove->rm_namelen, nfserr_noent))) 785 return status; 786 787 DECODE_TAIL; 788} 789 790static __be32 791nfsd4_decode_rename(struct nfsd4_compoundargs *argp, struct nfsd4_rename *rename) 792{ 793 DECODE_HEAD; 794 795 READ_BUF(4); 796 READ32(rename->rn_snamelen); 797 READ_BUF(rename->rn_snamelen + 4); 798 SAVEMEM(rename->rn_sname, rename->rn_snamelen); 799 READ32(rename->rn_tnamelen); 800 READ_BUF(rename->rn_tnamelen); 801 SAVEMEM(rename->rn_tname, rename->rn_tnamelen); 802 if ((status = check_filename(rename->rn_sname, rename->rn_snamelen, nfserr_noent))) 803 return status; 804 if ((status = check_filename(rename->rn_tname, rename->rn_tnamelen, nfserr_inval))) 805 return status; 806 807 DECODE_TAIL; 808} 809 810static __be32 811nfsd4_decode_renew(struct nfsd4_compoundargs *argp, clientid_t *clientid) 812{ 813 DECODE_HEAD; 814 815 READ_BUF(sizeof(clientid_t)); 816 COPYMEM(clientid, sizeof(clientid_t)); 817 818 DECODE_TAIL; 819} 820 821static __be32 822nfsd4_decode_setattr(struct nfsd4_compoundargs *argp, struct nfsd4_setattr *setattr) 823{ 824 DECODE_HEAD; 825 826 READ_BUF(sizeof(stateid_t)); 827 READ32(setattr->sa_stateid.si_generation); 828 COPYMEM(&setattr->sa_stateid.si_opaque, sizeof(stateid_opaque_t)); 829 if ((status = nfsd4_decode_fattr(argp, setattr->sa_bmval, &setattr->sa_iattr, &setattr->sa_acl))) 830 goto out; 831 832 DECODE_TAIL; 833} 834 835static __be32 836nfsd4_decode_setclientid(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid *setclientid) 837{ 838 DECODE_HEAD; 839 840 READ_BUF(12); 841 COPYMEM(setclientid->se_verf.data, 8); 842 READ32(setclientid->se_namelen); 843 844 READ_BUF(setclientid->se_namelen + 8); 845 SAVEMEM(setclientid->se_name, setclientid->se_namelen); 846 READ32(setclientid->se_callback_prog); 847 READ32(setclientid->se_callback_netid_len); 848 849 READ_BUF(setclientid->se_callback_netid_len + 4); 850 SAVEMEM(setclientid->se_callback_netid_val, setclientid->se_callback_netid_len); 851 READ32(setclientid->se_callback_addr_len); 852 853 READ_BUF(setclientid->se_callback_addr_len + 4); 854 SAVEMEM(setclientid->se_callback_addr_val, setclientid->se_callback_addr_len); 855 READ32(setclientid->se_callback_ident); 856 857 DECODE_TAIL; 858} 859 860static __be32 861nfsd4_decode_setclientid_confirm(struct nfsd4_compoundargs *argp, struct nfsd4_setclientid_confirm *scd_c) 862{ 863 DECODE_HEAD; 864 865 READ_BUF(8 + sizeof(nfs4_verifier)); 866 COPYMEM(&scd_c->sc_clientid, 8); 867 COPYMEM(&scd_c->sc_confirm, sizeof(nfs4_verifier)); 868 869 DECODE_TAIL; 870} 871 872/* Also used for NVERIFY */ 873static __be32 874nfsd4_decode_verify(struct nfsd4_compoundargs *argp, struct nfsd4_verify *verify) 875{ 876 DECODE_HEAD; 877 878 if ((status = nfsd4_decode_bitmap(argp, verify->ve_bmval))) 879 goto out; 880 881 /* For convenience's sake, we compare raw xdr'd attributes in 882 * nfsd4_proc_verify; however we still decode here just to return 883 * correct error in case of bad xdr. */ 884 READ_BUF(4); 885 READ32(verify->ve_attrlen); 886 READ_BUF(verify->ve_attrlen); 887 SAVEMEM(verify->ve_attrval, verify->ve_attrlen); 888 889 DECODE_TAIL; 890} 891 892static __be32 893nfsd4_decode_write(struct nfsd4_compoundargs *argp, struct nfsd4_write *write) 894{ 895 int avail; 896 int v; 897 int len; 898 DECODE_HEAD; 899 900 READ_BUF(sizeof(stateid_opaque_t) + 20); 901 READ32(write->wr_stateid.si_generation); 902 COPYMEM(&write->wr_stateid.si_opaque, sizeof(stateid_opaque_t)); 903 READ64(write->wr_offset); 904 READ32(write->wr_stable_how); 905 if (write->wr_stable_how > 2) 906 goto xdr_error; 907 READ32(write->wr_buflen); 908 909 /* Sorry .. no magic macros for this.. * 910 * READ_BUF(write->wr_buflen); 911 * SAVEMEM(write->wr_buf, write->wr_buflen); 912 */ 913 avail = (char*)argp->end - (char*)argp->p; 914 if (avail + argp->pagelen < write->wr_buflen) { 915 printk(KERN_NOTICE "xdr error! (%s:%d)\n", __FILE__, __LINE__); 916 goto xdr_error; 917 } 918 argp->rqstp->rq_vec[0].iov_base = p; 919 argp->rqstp->rq_vec[0].iov_len = avail; 920 v = 0; 921 len = write->wr_buflen; 922 while (len > argp->rqstp->rq_vec[v].iov_len) { 923 len -= argp->rqstp->rq_vec[v].iov_len; 924 v++; 925 argp->rqstp->rq_vec[v].iov_base = page_address(argp->pagelist[0]); 926 argp->pagelist++; 927 if (argp->pagelen >= PAGE_SIZE) { 928 argp->rqstp->rq_vec[v].iov_len = PAGE_SIZE; 929 argp->pagelen -= PAGE_SIZE; 930 } else { 931 argp->rqstp->rq_vec[v].iov_len = argp->pagelen; 932 argp->pagelen -= len; 933 } 934 } 935 argp->end = (__be32*) (argp->rqstp->rq_vec[v].iov_base + argp->rqstp->rq_vec[v].iov_len); 936 argp->p = (__be32*) (argp->rqstp->rq_vec[v].iov_base + (XDR_QUADLEN(len) << 2)); 937 argp->rqstp->rq_vec[v].iov_len = len; 938 write->wr_vlen = v+1; 939 940 DECODE_TAIL; 941} 942 943static __be32 944nfsd4_decode_release_lockowner(struct nfsd4_compoundargs *argp, struct nfsd4_release_lockowner *rlockowner) 945{ 946 DECODE_HEAD; 947 948 READ_BUF(12); 949 COPYMEM(&rlockowner->rl_clientid, sizeof(clientid_t)); 950 READ32(rlockowner->rl_owner.len); 951 READ_BUF(rlockowner->rl_owner.len); 952 READMEM(rlockowner->rl_owner.data, rlockowner->rl_owner.len); 953 954 DECODE_TAIL; 955} 956 957static __be32 958nfsd4_decode_compound(struct nfsd4_compoundargs *argp) 959{ 960 DECODE_HEAD; 961 struct nfsd4_op *op; 962 int i; 963 964 READ_BUF(4); 965 READ32(argp->taglen); 966 READ_BUF(argp->taglen + 8); 967 SAVEMEM(argp->tag, argp->taglen); 968 READ32(argp->minorversion); 969 READ32(argp->opcnt); 970 971 if (argp->taglen > NFSD4_MAX_TAGLEN) 972 goto xdr_error; 973 if (argp->opcnt > 100) 974 goto xdr_error; 975 976 if (argp->opcnt > ARRAY_SIZE(argp->iops)) { 977 argp->ops = kmalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL); 978 if (!argp->ops) { 979 argp->ops = argp->iops; 980 printk(KERN_INFO "nfsd: couldn't allocate room for COMPOUND\n"); 981 goto xdr_error; 982 } 983 } 984 985 for (i = 0; i < argp->opcnt; i++) { 986 op = &argp->ops[i]; 987 op->replay = NULL; 988 989 /* 990 * We can't use READ_BUF() here because we need to handle 991 * a missing opcode as an OP_WRITE + 1. So we need to check 992 * to see if we're truly at the end of our buffer or if there 993 * is another page we need to flip to. 994 */ 995 996 if (argp->p == argp->end) { 997 if (argp->pagelen < 4) { 998 /* There isn't an opcode still on the wire */ 999 op->opnum = OP_WRITE + 1; 1000 op->status = nfserr_bad_xdr; 1001 argp->opcnt = i+1; 1002 break; 1003 } 1004 1005 /* 1006 * False alarm. We just hit a page boundary, but there 1007 * is still data available. Move pointer across page 1008 * boundary. *snip from READ_BUF* 1009 */ 1010 argp->p = page_address(argp->pagelist[0]); 1011 argp->pagelist++; 1012 if (argp->pagelen < PAGE_SIZE) { 1013 argp->end = p + (argp->pagelen>>2); 1014 argp->pagelen = 0; 1015 } else { 1016 argp->end = p + (PAGE_SIZE>>2); 1017 argp->pagelen -= PAGE_SIZE; 1018 } 1019 } 1020 op->opnum = ntohl(*argp->p++); 1021 1022 switch (op->opnum) { 1023 case 2: /* Reserved operation */ 1024 op->opnum = OP_ILLEGAL; 1025 if (argp->minorversion == 0) 1026 op->status = nfserr_op_illegal; 1027 else 1028 op->status = nfserr_minor_vers_mismatch; 1029 break; 1030 case OP_ACCESS: 1031 op->status = nfsd4_decode_access(argp, &op->u.access); 1032 break; 1033 case OP_CLOSE: 1034 op->status = nfsd4_decode_close(argp, &op->u.close); 1035 break; 1036 case OP_COMMIT: 1037 op->status = nfsd4_decode_commit(argp, &op->u.commit); 1038 break; 1039 case OP_CREATE: 1040 op->status = nfsd4_decode_create(argp, &op->u.create); 1041 break; 1042 case OP_DELEGRETURN: 1043 op->status = nfsd4_decode_delegreturn(argp, &op->u.delegreturn); 1044 break; 1045 case OP_GETATTR: 1046 op->status = nfsd4_decode_getattr(argp, &op->u.getattr); 1047 break; 1048 case OP_GETFH: 1049 op->status = nfs_ok; 1050 break; 1051 case OP_LINK: 1052 op->status = nfsd4_decode_link(argp, &op->u.link); 1053 break; 1054 case OP_LOCK: 1055 op->status = nfsd4_decode_lock(argp, &op->u.lock); 1056 break; 1057 case OP_LOCKT: 1058 op->status = nfsd4_decode_lockt(argp, &op->u.lockt); 1059 break; 1060 case OP_LOCKU: 1061 op->status = nfsd4_decode_locku(argp, &op->u.locku); 1062 break; 1063 case OP_LOOKUP: 1064 op->status = nfsd4_decode_lookup(argp, &op->u.lookup); 1065 break; 1066 case OP_LOOKUPP: 1067 op->status = nfs_ok; 1068 break; 1069 case OP_NVERIFY: 1070 op->status = nfsd4_decode_verify(argp, &op->u.nverify); 1071 break; 1072 case OP_OPEN: 1073 op->status = nfsd4_decode_open(argp, &op->u.open); 1074 break; 1075 case OP_OPEN_CONFIRM: 1076 op->status = nfsd4_decode_open_confirm(argp, &op->u.open_confirm); 1077 break; 1078 case OP_OPEN_DOWNGRADE: 1079 op->status = nfsd4_decode_open_downgrade(argp, &op->u.open_downgrade); 1080 break; 1081 case OP_PUTFH: 1082 op->status = nfsd4_decode_putfh(argp, &op->u.putfh); 1083 break; 1084 case OP_PUTROOTFH: 1085 op->status = nfs_ok; 1086 break; 1087 case OP_READ: 1088 op->status = nfsd4_decode_read(argp, &op->u.read); 1089 break; 1090 case OP_READDIR: 1091 op->status = nfsd4_decode_readdir(argp, &op->u.readdir); 1092 break; 1093 case OP_READLINK: 1094 op->status = nfs_ok; 1095 break; 1096 case OP_REMOVE: 1097 op->status = nfsd4_decode_remove(argp, &op->u.remove); 1098 break; 1099 case OP_RENAME: 1100 op->status = nfsd4_decode_rename(argp, &op->u.rename); 1101 break; 1102 case OP_RESTOREFH: 1103 op->status = nfs_ok; 1104 break; 1105 case OP_RENEW: 1106 op->status = nfsd4_decode_renew(argp, &op->u.renew); 1107 break; 1108 case OP_SAVEFH: 1109 op->status = nfs_ok; 1110 break; 1111 case OP_SETATTR: 1112 op->status = nfsd4_decode_setattr(argp, &op->u.setattr); 1113 break; 1114 case OP_SETCLIENTID: 1115 op->status = nfsd4_decode_setclientid(argp, &op->u.setclientid); 1116 break; 1117 case OP_SETCLIENTID_CONFIRM: 1118 op->status = nfsd4_decode_setclientid_confirm(argp, &op->u.setclientid_confirm); 1119 break; 1120 case OP_VERIFY: 1121 op->status = nfsd4_decode_verify(argp, &op->u.verify); 1122 break; 1123 case OP_WRITE: 1124 op->status = nfsd4_decode_write(argp, &op->u.write); 1125 break; 1126 case OP_RELEASE_LOCKOWNER: 1127 op->status = nfsd4_decode_release_lockowner(argp, &op->u.release_lockowner); 1128 break; 1129 default: 1130 op->opnum = OP_ILLEGAL; 1131 op->status = nfserr_op_illegal; 1132 break; 1133 } 1134 1135 if (op->status) { 1136 argp->opcnt = i+1; 1137 break; 1138 } 1139 } 1140 1141 DECODE_TAIL; 1142} 1143/* 1144 * END OF "GENERIC" DECODE ROUTINES. 1145 */ 1146 1147/* 1148 * START OF "GENERIC" ENCODE ROUTINES. 1149 * These may look a little ugly since they are imported from a "generic" 1150 * set of XDR encode/decode routines which are intended to be shared by 1151 * all of our NFSv4 implementations (OpenBSD, MacOS X...). 1152 * 1153 * If the pain of reading these is too great, it should be a straightforward 1154 * task to translate them into Linux-specific versions which are more 1155 * consistent with the style used in NFSv2/v3... 1156 */ 1157#define ENCODE_HEAD __be32 *p 1158 1159#define WRITE32(n) *p++ = htonl(n) 1160#define WRITE64(n) do { \ 1161 *p++ = htonl((u32)((n) >> 32)); \ 1162 *p++ = htonl((u32)(n)); \ 1163} while (0) 1164#define WRITEMEM(ptr,nbytes) do { \ 1165 *(p + XDR_QUADLEN(nbytes) -1) = 0; \ 1166 memcpy(p, ptr, nbytes); \ 1167 p += XDR_QUADLEN(nbytes); \ 1168} while (0) 1169#define WRITECINFO(c) do { \ 1170 *p++ = htonl(c.atomic); \ 1171 *p++ = htonl(c.before_ctime_sec); \ 1172 *p++ = htonl(c.before_ctime_nsec); \ 1173 *p++ = htonl(c.after_ctime_sec); \ 1174 *p++ = htonl(c.after_ctime_nsec); \ 1175} while (0) 1176 1177#define RESERVE_SPACE(nbytes) do { \ 1178 p = resp->p; \ 1179 BUG_ON(p + XDR_QUADLEN(nbytes) > resp->end); \ 1180} while (0) 1181#define ADJUST_ARGS() resp->p = p 1182 1183/* 1184 * Header routine to setup seqid operation replay cache 1185 */ 1186#define ENCODE_SEQID_OP_HEAD \ 1187 __be32 *p; \ 1188 __be32 *save; \ 1189 \ 1190 save = resp->p; 1191 1192/* 1193 * Routine for encoding the result of a "seqid-mutating" NFSv4 operation. This 1194 * is where sequence id's are incremented, and the replay cache is filled. 1195 * Note that we increment sequence id's here, at the last moment, so we're sure 1196 * we know whether the error to be returned is a sequence id mutating error. 1197 */ 1198 1199#define ENCODE_SEQID_OP_TAIL(stateowner) do { \ 1200 if (seqid_mutating_err(nfserr) && stateowner) { \ 1201 stateowner->so_seqid++; \ 1202 stateowner->so_replay.rp_status = nfserr; \ 1203 stateowner->so_replay.rp_buflen = \ 1204 (((char *)(resp)->p - (char *)save)); \ 1205 memcpy(stateowner->so_replay.rp_buf, save, \ 1206 stateowner->so_replay.rp_buflen); \ 1207 } } while (0); 1208 1209/* Encode as an array of strings the string given with components 1210 * seperated @sep. 1211 */ 1212static __be32 nfsd4_encode_components(char sep, char *components, 1213 __be32 **pp, int *buflen) 1214{ 1215 __be32 *p = *pp; 1216 __be32 *countp = p; 1217 int strlen, count=0; 1218 char *str, *end; 1219 1220 dprintk("nfsd4_encode_components(%s)\n", components); 1221 if ((*buflen -= 4) < 0) 1222 return nfserr_resource; 1223 WRITE32(0); /* We will fill this in with @count later */ 1224 end = str = components; 1225 while (*end) { 1226 for (; *end && (*end != sep); end++) 1227 ; /* Point to end of component */ 1228 strlen = end - str; 1229 if (strlen) { 1230 if ((*buflen -= ((XDR_QUADLEN(strlen) << 2) + 4)) < 0) 1231 return nfserr_resource; 1232 WRITE32(strlen); 1233 WRITEMEM(str, strlen); 1234 count++; 1235 } 1236 else 1237 end++; 1238 str = end; 1239 } 1240 *pp = p; 1241 p = countp; 1242 WRITE32(count); 1243 return 0; 1244} 1245 1246/* 1247 * encode a location element of a fs_locations structure 1248 */ 1249static __be32 nfsd4_encode_fs_location4(struct nfsd4_fs_location *location, 1250 __be32 **pp, int *buflen) 1251{ 1252 __be32 status; 1253 __be32 *p = *pp; 1254 1255 status = nfsd4_encode_components(':', location->hosts, &p, buflen); 1256 if (status) 1257 return status; 1258 status = nfsd4_encode_components('/', location->path, &p, buflen); 1259 if (status) 1260 return status; 1261 *pp = p; 1262 return 0; 1263} 1264 1265/* 1266 * Return the path to an export point in the pseudo filesystem namespace 1267 * Returned string is safe to use as long as the caller holds a reference 1268 * to @exp. 1269 */ 1270static char *nfsd4_path(struct svc_rqst *rqstp, struct svc_export *exp, __be32 *stat) 1271{ 1272 struct svc_fh tmp_fh; 1273 char *path, *rootpath; 1274 1275 fh_init(&tmp_fh, NFS4_FHSIZE); 1276 *stat = exp_pseudoroot(rqstp->rq_client, &tmp_fh, &rqstp->rq_chandle); 1277 if (*stat) 1278 return NULL; 1279 rootpath = tmp_fh.fh_export->ex_path; 1280 1281 path = exp->ex_path; 1282 1283 if (strncmp(path, rootpath, strlen(rootpath))) { 1284 printk("nfsd: fs_locations failed;" 1285 "%s is not contained in %s\n", path, rootpath); 1286 *stat = nfserr_notsupp; 1287 return NULL; 1288 } 1289 1290 return path + strlen(rootpath); 1291} 1292 1293/* 1294 * encode a fs_locations structure 1295 */ 1296static __be32 nfsd4_encode_fs_locations(struct svc_rqst *rqstp, 1297 struct svc_export *exp, 1298 __be32 **pp, int *buflen) 1299{ 1300 __be32 status; 1301 int i; 1302 __be32 *p = *pp; 1303 struct nfsd4_fs_locations *fslocs = &exp->ex_fslocs; 1304 char *root = nfsd4_path(rqstp, exp, &status); 1305 1306 if (status) 1307 return status; 1308 status = nfsd4_encode_components('/', root, &p, buflen); 1309 if (status) 1310 return status; 1311 if ((*buflen -= 4) < 0) 1312 return nfserr_resource; 1313 WRITE32(fslocs->locations_count); 1314 for (i=0; i<fslocs->locations_count; i++) { 1315 status = nfsd4_encode_fs_location4(&fslocs->locations[i], 1316 &p, buflen); 1317 if (status) 1318 return status; 1319 } 1320 *pp = p; 1321 return 0; 1322} 1323 1324static u32 nfs4_ftypes[16] = { 1325 NF4BAD, NF4FIFO, NF4CHR, NF4BAD, 1326 NF4DIR, NF4BAD, NF4BLK, NF4BAD, 1327 NF4REG, NF4BAD, NF4LNK, NF4BAD, 1328 NF4SOCK, NF4BAD, NF4LNK, NF4BAD, 1329}; 1330 1331static __be32 1332nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group, 1333 __be32 **p, int *buflen) 1334{ 1335 int status; 1336 1337 if (*buflen < (XDR_QUADLEN(IDMAP_NAMESZ) << 2) + 4) 1338 return nfserr_resource; 1339 if (whotype != NFS4_ACL_WHO_NAMED) 1340 status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1)); 1341 else if (group) 1342 status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1)); 1343 else 1344 status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1)); 1345 if (status < 0) 1346 return nfserrno(status); 1347 *p = xdr_encode_opaque(*p, NULL, status); 1348 *buflen -= (XDR_QUADLEN(status) << 2) + 4; 1349 BUG_ON(*buflen < 0); 1350 return 0; 1351} 1352 1353static inline __be32 1354nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, __be32 **p, int *buflen) 1355{ 1356 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen); 1357} 1358 1359static inline __be32 1360nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, __be32 **p, int *buflen) 1361{ 1362 return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen); 1363} 1364 1365static inline __be32 1366nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group, 1367 __be32 **p, int *buflen) 1368{ 1369 return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen); 1370} 1371 1372#define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \ 1373 FATTR4_WORD0_RDATTR_ERROR) 1374#define WORD1_ABSENT_FS_ATTRS FATTR4_WORD1_MOUNTED_ON_FILEID 1375 1376static __be32 fattr_handle_absent_fs(u32 *bmval0, u32 *bmval1, u32 *rdattr_err) 1377{ 1378 /* As per referral draft: */ 1379 if (*bmval0 & ~WORD0_ABSENT_FS_ATTRS || 1380 *bmval1 & ~WORD1_ABSENT_FS_ATTRS) { 1381 if (*bmval0 & FATTR4_WORD0_RDATTR_ERROR || 1382 *bmval0 & FATTR4_WORD0_FS_LOCATIONS) 1383 *rdattr_err = NFSERR_MOVED; 1384 else 1385 return nfserr_moved; 1386 } 1387 *bmval0 &= WORD0_ABSENT_FS_ATTRS; 1388 *bmval1 &= WORD1_ABSENT_FS_ATTRS; 1389 return 0; 1390} 1391 1392/* 1393 * Note: @fhp can be NULL; in this case, we might have to compose the filehandle 1394 * ourselves. 1395 * 1396 * @countp is the buffer size in _words_; upon successful return this becomes 1397 * replaced with the number of words written. 1398 */ 1399__be32 1400nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, 1401 struct dentry *dentry, __be32 *buffer, int *countp, u32 *bmval, 1402 struct svc_rqst *rqstp) 1403{ 1404 u32 bmval0 = bmval[0]; 1405 u32 bmval1 = bmval[1]; 1406 struct kstat stat; 1407 struct svc_fh tempfh; 1408 struct kstatfs statfs; 1409 int buflen = *countp << 2; 1410 __be32 *attrlenp; 1411 u32 dummy; 1412 u64 dummy64; 1413 u32 rdattr_err = 0; 1414 __be32 *p = buffer; 1415 __be32 status; 1416 int err; 1417 int aclsupport = 0; 1418 struct nfs4_acl *acl = NULL; 1419 1420 BUG_ON(bmval1 & NFSD_WRITEONLY_ATTRS_WORD1); 1421 BUG_ON(bmval0 & ~NFSD_SUPPORTED_ATTRS_WORD0); 1422 BUG_ON(bmval1 & ~NFSD_SUPPORTED_ATTRS_WORD1); 1423 1424 if (exp->ex_fslocs.migrated) { 1425 status = fattr_handle_absent_fs(&bmval0, &bmval1, &rdattr_err); 1426 if (status) 1427 goto out; 1428 } 1429 1430 err = vfs_getattr(exp->ex_mnt, dentry, &stat); 1431 if (err) 1432 goto out_nfserr; 1433 if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) || 1434 (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | 1435 FATTR4_WORD1_SPACE_TOTAL))) { 1436 err = vfs_statfs(dentry, &statfs); 1437 if (err) 1438 goto out_nfserr; 1439 } 1440 if ((bmval0 & (FATTR4_WORD0_FILEHANDLE | FATTR4_WORD0_FSID)) && !fhp) { 1441 fh_init(&tempfh, NFS4_FHSIZE); 1442 status = fh_compose(&tempfh, exp, dentry, NULL); 1443 if (status) 1444 goto out; 1445 fhp = &tempfh; 1446 } 1447 if (bmval0 & (FATTR4_WORD0_ACL | FATTR4_WORD0_ACLSUPPORT 1448 | FATTR4_WORD0_SUPPORTED_ATTRS)) { 1449 err = nfsd4_get_nfs4_acl(rqstp, dentry, &acl); 1450 aclsupport = (err == 0); 1451 if (bmval0 & FATTR4_WORD0_ACL) { 1452 if (err == -EOPNOTSUPP) 1453 bmval0 &= ~FATTR4_WORD0_ACL; 1454 else if (err == -EINVAL) { 1455 status = nfserr_attrnotsupp; 1456 goto out; 1457 } else if (err != 0) 1458 goto out_nfserr; 1459 } 1460 } 1461 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { 1462 if (exp->ex_fslocs.locations == NULL) { 1463 bmval0 &= ~FATTR4_WORD0_FS_LOCATIONS; 1464 } 1465 } 1466 if ((buflen -= 16) < 0) 1467 goto out_resource; 1468 1469 WRITE32(2); 1470 WRITE32(bmval0); 1471 WRITE32(bmval1); 1472 attrlenp = p++; /* to be backfilled later */ 1473 1474 if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) { 1475 u32 word0 = NFSD_SUPPORTED_ATTRS_WORD0; 1476 if ((buflen -= 12) < 0) 1477 goto out_resource; 1478 if (!aclsupport) 1479 word0 &= ~FATTR4_WORD0_ACL; 1480 if (!exp->ex_fslocs.locations) 1481 word0 &= ~FATTR4_WORD0_FS_LOCATIONS; 1482 WRITE32(2); 1483 WRITE32(word0); 1484 WRITE32(NFSD_SUPPORTED_ATTRS_WORD1); 1485 } 1486 if (bmval0 & FATTR4_WORD0_TYPE) { 1487 if ((buflen -= 4) < 0) 1488 goto out_resource; 1489 dummy = nfs4_ftypes[(stat.mode & S_IFMT) >> 12]; 1490 if (dummy == NF4BAD) 1491 goto out_serverfault; 1492 WRITE32(dummy); 1493 } 1494 if (bmval0 & FATTR4_WORD0_FH_EXPIRE_TYPE) { 1495 if ((buflen -= 4) < 0) 1496 goto out_resource; 1497 if (exp->ex_flags & NFSEXP_NOSUBTREECHECK) 1498 WRITE32(NFS4_FH_PERSISTENT); 1499 else 1500 WRITE32(NFS4_FH_PERSISTENT|NFS4_FH_VOL_RENAME); 1501 } 1502 if (bmval0 & FATTR4_WORD0_CHANGE) { 1503 /* 1504 * Note: This _must_ be consistent with the scheme for writing 1505 * change_info, so any changes made here must be reflected there 1506 * as well. (See xdr4.h:set_change_info() and the WRITECINFO() 1507 * macro above.) 1508 */ 1509 if ((buflen -= 8) < 0) 1510 goto out_resource; 1511 WRITE32(stat.ctime.tv_sec); 1512 WRITE32(stat.ctime.tv_nsec); 1513 } 1514 if (bmval0 & FATTR4_WORD0_SIZE) { 1515 if ((buflen -= 8) < 0) 1516 goto out_resource; 1517 WRITE64(stat.size); 1518 } 1519 if (bmval0 & FATTR4_WORD0_LINK_SUPPORT) { 1520 if ((buflen -= 4) < 0) 1521 goto out_resource; 1522 WRITE32(1); 1523 } 1524 if (bmval0 & FATTR4_WORD0_SYMLINK_SUPPORT) { 1525 if ((buflen -= 4) < 0) 1526 goto out_resource; 1527 WRITE32(1); 1528 } 1529 if (bmval0 & FATTR4_WORD0_NAMED_ATTR) { 1530 if ((buflen -= 4) < 0) 1531 goto out_resource; 1532 WRITE32(0); 1533 } 1534 if (bmval0 & FATTR4_WORD0_FSID) { 1535 if ((buflen -= 16) < 0) 1536 goto out_resource; 1537 if (exp->ex_fslocs.migrated) { 1538 WRITE64(NFS4_REFERRAL_FSID_MAJOR); 1539 WRITE64(NFS4_REFERRAL_FSID_MINOR); 1540 } else switch(fsid_source(fhp)) { 1541 case FSIDSOURCE_FSID: 1542 WRITE64((u64)exp->ex_fsid); 1543 WRITE64((u64)0); 1544 break; 1545 case FSIDSOURCE_DEV: 1546 WRITE32(0); 1547 WRITE32(MAJOR(stat.dev)); 1548 WRITE32(0); 1549 WRITE32(MINOR(stat.dev)); 1550 break; 1551 case FSIDSOURCE_UUID: 1552 WRITEMEM(exp->ex_uuid, 16); 1553 break; 1554 } 1555 } 1556 if (bmval0 & FATTR4_WORD0_UNIQUE_HANDLES) { 1557 if ((buflen -= 4) < 0) 1558 goto out_resource; 1559 WRITE32(0); 1560 } 1561 if (bmval0 & FATTR4_WORD0_LEASE_TIME) { 1562 if ((buflen -= 4) < 0) 1563 goto out_resource; 1564 WRITE32(NFSD_LEASE_TIME); 1565 } 1566 if (bmval0 & FATTR4_WORD0_RDATTR_ERROR) { 1567 if ((buflen -= 4) < 0) 1568 goto out_resource; 1569 WRITE32(rdattr_err); 1570 } 1571 if (bmval0 & FATTR4_WORD0_ACL) { 1572 struct nfs4_ace *ace; 1573 1574 if (acl == NULL) { 1575 if ((buflen -= 4) < 0) 1576 goto out_resource; 1577 1578 WRITE32(0); 1579 goto out_acl; 1580 } 1581 if ((buflen -= 4) < 0) 1582 goto out_resource; 1583 WRITE32(acl->naces); 1584 1585 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) { 1586 if ((buflen -= 4*3) < 0) 1587 goto out_resource; 1588 WRITE32(ace->type); 1589 WRITE32(ace->flag); 1590 WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL); 1591 status = nfsd4_encode_aclname(rqstp, ace->whotype, 1592 ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP, 1593 &p, &buflen); 1594 if (status == nfserr_resource) 1595 goto out_resource; 1596 if (status) 1597 goto out; 1598 } 1599 } 1600out_acl: 1601 if (bmval0 & FATTR4_WORD0_ACLSUPPORT) { 1602 if ((buflen -= 4) < 0) 1603 goto out_resource; 1604 WRITE32(aclsupport ? 1605 ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL : 0); 1606 } 1607 if (bmval0 & FATTR4_WORD0_CANSETTIME) { 1608 if ((buflen -= 4) < 0) 1609 goto out_resource; 1610 WRITE32(1); 1611 } 1612 if (bmval0 & FATTR4_WORD0_CASE_INSENSITIVE) { 1613 if ((buflen -= 4) < 0) 1614 goto out_resource; 1615 WRITE32(1); 1616 } 1617 if (bmval0 & FATTR4_WORD0_CASE_PRESERVING) { 1618 if ((buflen -= 4) < 0) 1619 goto out_resource; 1620 WRITE32(1); 1621 } 1622 if (bmval0 & FATTR4_WORD0_CHOWN_RESTRICTED) { 1623 if ((buflen -= 4) < 0) 1624 goto out_resource; 1625 WRITE32(1); 1626 } 1627 if (bmval0 & FATTR4_WORD0_FILEHANDLE) { 1628 buflen -= (XDR_QUADLEN(fhp->fh_handle.fh_size) << 2) + 4; 1629 if (buflen < 0) 1630 goto out_resource; 1631 WRITE32(fhp->fh_handle.fh_size); 1632 WRITEMEM(&fhp->fh_handle.fh_base, fhp->fh_handle.fh_size); 1633 } 1634 if (bmval0 & FATTR4_WORD0_FILEID) { 1635 if ((buflen -= 8) < 0) 1636 goto out_resource; 1637 WRITE64((u64) stat.ino); 1638 } 1639 if (bmval0 & FATTR4_WORD0_FILES_AVAIL) { 1640 if ((buflen -= 8) < 0) 1641 goto out_resource; 1642 WRITE64((u64) statfs.f_ffree); 1643 } 1644 if (bmval0 & FATTR4_WORD0_FILES_FREE) { 1645 if ((buflen -= 8) < 0) 1646 goto out_resource; 1647 WRITE64((u64) statfs.f_ffree); 1648 } 1649 if (bmval0 & FATTR4_WORD0_FILES_TOTAL) { 1650 if ((buflen -= 8) < 0) 1651 goto out_resource; 1652 WRITE64((u64) statfs.f_files); 1653 } 1654 if (bmval0 & FATTR4_WORD0_FS_LOCATIONS) { 1655 status = nfsd4_encode_fs_locations(rqstp, exp, &p, &buflen); 1656 if (status == nfserr_resource) 1657 goto out_resource; 1658 if (status) 1659 goto out; 1660 } 1661 if (bmval0 & FATTR4_WORD0_HOMOGENEOUS) { 1662 if ((buflen -= 4) < 0) 1663 goto out_resource; 1664 WRITE32(1); 1665 } 1666 if (bmval0 & FATTR4_WORD0_MAXFILESIZE) { 1667 if ((buflen -= 8) < 0) 1668 goto out_resource; 1669 WRITE64(~(u64)0); 1670 } 1671 if (bmval0 & FATTR4_WORD0_MAXLINK) { 1672 if ((buflen -= 4) < 0) 1673 goto out_resource; 1674 WRITE32(255); 1675 } 1676 if (bmval0 & FATTR4_WORD0_MAXNAME) { 1677 if ((buflen -= 4) < 0) 1678 goto out_resource; 1679 WRITE32(~(u32) 0); 1680 } 1681 if (bmval0 & FATTR4_WORD0_MAXREAD) { 1682 if ((buflen -= 8) < 0) 1683 goto out_resource; 1684 WRITE64((u64) svc_max_payload(rqstp)); 1685 } 1686 if (bmval0 & FATTR4_WORD0_MAXWRITE) { 1687 if ((buflen -= 8) < 0) 1688 goto out_resource; 1689 WRITE64((u64) svc_max_payload(rqstp)); 1690 } 1691 if (bmval1 & FATTR4_WORD1_MODE) { 1692 if ((buflen -= 4) < 0) 1693 goto out_resource; 1694 WRITE32(stat.mode & S_IALLUGO); 1695 } 1696 if (bmval1 & FATTR4_WORD1_NO_TRUNC) { 1697 if ((buflen -= 4) < 0) 1698 goto out_resource; 1699 WRITE32(1); 1700 } 1701 if (bmval1 & FATTR4_WORD1_NUMLINKS) { 1702 if ((buflen -= 4) < 0) 1703 goto out_resource; 1704 WRITE32(stat.nlink); 1705 } 1706 if (bmval1 & FATTR4_WORD1_OWNER) { 1707 status = nfsd4_encode_user(rqstp, stat.uid, &p, &buflen); 1708 if (status == nfserr_resource) 1709 goto out_resource; 1710 if (status) 1711 goto out; 1712 } 1713 if (bmval1 & FATTR4_WORD1_OWNER_GROUP) { 1714 status = nfsd4_encode_group(rqstp, stat.gid, &p, &buflen); 1715 if (status == nfserr_resource) 1716 goto out_resource; 1717 if (status) 1718 goto out; 1719 } 1720 if (bmval1 & FATTR4_WORD1_RAWDEV) { 1721 if ((buflen -= 8) < 0) 1722 goto out_resource; 1723 WRITE32((u32) MAJOR(stat.rdev)); 1724 WRITE32((u32) MINOR(stat.rdev)); 1725 } 1726 if (bmval1 & FATTR4_WORD1_SPACE_AVAIL) { 1727 if ((buflen -= 8) < 0) 1728 goto out_resource; 1729 dummy64 = (u64)statfs.f_bavail * (u64)statfs.f_bsize; 1730 WRITE64(dummy64); 1731 } 1732 if (bmval1 & FATTR4_WORD1_SPACE_FREE) { 1733 if ((buflen -= 8) < 0) 1734 goto out_resource; 1735 dummy64 = (u64)statfs.f_bfree * (u64)statfs.f_bsize; 1736 WRITE64(dummy64); 1737 } 1738 if (bmval1 & FATTR4_WORD1_SPACE_TOTAL) { 1739 if ((buflen -= 8) < 0) 1740 goto out_resource; 1741 dummy64 = (u64)statfs.f_blocks * (u64)statfs.f_bsize; 1742 WRITE64(dummy64); 1743 } 1744 if (bmval1 & FATTR4_WORD1_SPACE_USED) { 1745 if ((buflen -= 8) < 0) 1746 goto out_resource; 1747 dummy64 = (u64)stat.blocks << 9; 1748 WRITE64(dummy64); 1749 } 1750 if (bmval1 & FATTR4_WORD1_TIME_ACCESS) { 1751 if ((buflen -= 12) < 0) 1752 goto out_resource; 1753 WRITE32(0); 1754 WRITE32(stat.atime.tv_sec); 1755 WRITE32(stat.atime.tv_nsec); 1756 } 1757 if (bmval1 & FATTR4_WORD1_TIME_DELTA) { 1758 if ((buflen -= 12) < 0) 1759 goto out_resource; 1760 WRITE32(0); 1761 WRITE32(1); 1762 WRITE32(0); 1763 } 1764 if (bmval1 & FATTR4_WORD1_TIME_METADATA) { 1765 if ((buflen -= 12) < 0) 1766 goto out_resource; 1767 WRITE32(0); 1768 WRITE32(stat.ctime.tv_sec); 1769 WRITE32(stat.ctime.tv_nsec); 1770 } 1771 if (bmval1 & FATTR4_WORD1_TIME_MODIFY) { 1772 if ((buflen -= 12) < 0) 1773 goto out_resource; 1774 WRITE32(0); 1775 WRITE32(stat.mtime.tv_sec); 1776 WRITE32(stat.mtime.tv_nsec); 1777 } 1778 if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { 1779 struct dentry *mnt_pnt, *mnt_root; 1780 1781 if ((buflen -= 8) < 0) 1782 goto out_resource; 1783 mnt_root = exp->ex_mnt->mnt_root; 1784 if (mnt_root->d_inode == dentry->d_inode) { 1785 mnt_pnt = exp->ex_mnt->mnt_mountpoint; 1786 WRITE64((u64) mnt_pnt->d_inode->i_ino); 1787 } else 1788 WRITE64((u64) stat.ino); 1789 } 1790 *attrlenp = htonl((char *)p - (char *)attrlenp - 4); 1791 *countp = p - buffer; 1792 status = nfs_ok; 1793 1794out: 1795 kfree(acl); 1796 if (fhp == &tempfh) 1797 fh_put(&tempfh); 1798 return status; 1799out_nfserr: 1800 status = nfserrno(err); 1801 goto out; 1802out_resource: 1803 *countp = 0; 1804 status = nfserr_resource; 1805 goto out; 1806out_serverfault: 1807 status = nfserr_serverfault; 1808 goto out; 1809} 1810 1811static __be32 1812nfsd4_encode_dirent_fattr(struct nfsd4_readdir *cd, 1813 const char *name, int namlen, __be32 *p, int *buflen) 1814{ 1815 struct svc_export *exp = cd->rd_fhp->fh_export; 1816 struct dentry *dentry; 1817 __be32 nfserr; 1818 1819 dentry = lookup_one_len(name, cd->rd_fhp->fh_dentry, namlen); 1820 if (IS_ERR(dentry)) 1821 return nfserrno(PTR_ERR(dentry)); 1822 1823 exp_get(exp); 1824 if (d_mountpoint(dentry)) { 1825 int err; 1826 1827 err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp); 1828 if (err) { 1829 nfserr = nfserrno(err); 1830 goto out_put; 1831 } 1832 1833 } 1834 nfserr = nfsd4_encode_fattr(NULL, exp, dentry, p, buflen, cd->rd_bmval, 1835 cd->rd_rqstp); 1836out_put: 1837 dput(dentry); 1838 exp_put(exp); 1839 return nfserr; 1840} 1841 1842static __be32 * 1843nfsd4_encode_rdattr_error(__be32 *p, int buflen, __be32 nfserr) 1844{ 1845 __be32 *attrlenp; 1846 1847 if (buflen < 6) 1848 return NULL; 1849 *p++ = htonl(2); 1850 *p++ = htonl(FATTR4_WORD0_RDATTR_ERROR); /* bmval0 */ 1851 *p++ = htonl(0); /* bmval1 */ 1852 1853 attrlenp = p++; 1854 *p++ = nfserr; /* no htonl */ 1855 *attrlenp = htonl((char *)p - (char *)attrlenp - 4); 1856 return p; 1857} 1858 1859static int 1860nfsd4_encode_dirent(void *ccdv, const char *name, int namlen, 1861 loff_t offset, u64 ino, unsigned int d_type) 1862{ 1863 struct readdir_cd *ccd = ccdv; 1864 struct nfsd4_readdir *cd = container_of(ccd, struct nfsd4_readdir, common); 1865 int buflen; 1866 __be32 *p = cd->buffer; 1867 __be32 nfserr = nfserr_toosmall; 1868 1869 /* In nfsv4, "." and ".." never make it onto the wire.. */ 1870 if (name && isdotent(name, namlen)) { 1871 cd->common.err = nfs_ok; 1872 return 0; 1873 } 1874 1875 if (cd->offset) 1876 xdr_encode_hyper(cd->offset, (u64) offset); 1877 1878 buflen = cd->buflen - 4 - XDR_QUADLEN(namlen); 1879 if (buflen < 0) 1880 goto fail; 1881 1882 *p++ = xdr_one; /* mark entry present */ 1883 cd->offset = p; /* remember pointer */ 1884 p = xdr_encode_hyper(p, NFS_OFFSET_MAX); /* offset of next entry */ 1885 p = xdr_encode_array(p, name, namlen); /* name length & name */ 1886 1887 nfserr = nfsd4_encode_dirent_fattr(cd, name, namlen, p, &buflen); 1888 switch (nfserr) { 1889 case nfs_ok: 1890 p += buflen; 1891 break; 1892 case nfserr_resource: 1893 nfserr = nfserr_toosmall; 1894 goto fail; 1895 case nfserr_dropit: 1896 goto fail; 1897 default: 1898 /* 1899 * If the client requested the RDATTR_ERROR attribute, 1900 * we stuff the error code into this attribute 1901 * and continue. If this attribute was not requested, 1902 * then in accordance with the spec, we fail the 1903 * entire READDIR operation(!) 1904 */ 1905 if (!(cd->rd_bmval[0] & FATTR4_WORD0_RDATTR_ERROR)) 1906 goto fail; 1907 p = nfsd4_encode_rdattr_error(p, buflen, nfserr); 1908 if (p == NULL) { 1909 nfserr = nfserr_toosmall; 1910 goto fail; 1911 } 1912 } 1913 cd->buflen -= (p - cd->buffer); 1914 cd->buffer = p; 1915 cd->common.err = nfs_ok; 1916 return 0; 1917fail: 1918 cd->common.err = nfserr; 1919 return -EINVAL; 1920} 1921 1922static void 1923nfsd4_encode_access(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_access *access) 1924{ 1925 ENCODE_HEAD; 1926 1927 if (!nfserr) { 1928 RESERVE_SPACE(8); 1929 WRITE32(access->ac_supported); 1930 WRITE32(access->ac_resp_access); 1931 ADJUST_ARGS(); 1932 } 1933} 1934 1935static void 1936nfsd4_encode_close(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_close *close) 1937{ 1938 ENCODE_SEQID_OP_HEAD; 1939 1940 if (!nfserr) { 1941 RESERVE_SPACE(sizeof(stateid_t)); 1942 WRITE32(close->cl_stateid.si_generation); 1943 WRITEMEM(&close->cl_stateid.si_opaque, sizeof(stateid_opaque_t)); 1944 ADJUST_ARGS(); 1945 } 1946 ENCODE_SEQID_OP_TAIL(close->cl_stateowner); 1947} 1948 1949 1950static void 1951nfsd4_encode_commit(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_commit *commit) 1952{ 1953 ENCODE_HEAD; 1954 1955 if (!nfserr) { 1956 RESERVE_SPACE(8); 1957 WRITEMEM(commit->co_verf.data, 8); 1958 ADJUST_ARGS(); 1959 } 1960} 1961 1962static void 1963nfsd4_encode_create(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_create *create) 1964{ 1965 ENCODE_HEAD; 1966 1967 if (!nfserr) { 1968 RESERVE_SPACE(32); 1969 WRITECINFO(create->cr_cinfo); 1970 WRITE32(2); 1971 WRITE32(create->cr_bmval[0]); 1972 WRITE32(create->cr_bmval[1]); 1973 ADJUST_ARGS(); 1974 } 1975} 1976 1977static __be32 1978nfsd4_encode_getattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_getattr *getattr) 1979{ 1980 struct svc_fh *fhp = getattr->ga_fhp; 1981 int buflen; 1982 1983 if (nfserr) 1984 return nfserr; 1985 1986 buflen = resp->end - resp->p - (COMPOUND_ERR_SLACK_SPACE >> 2); 1987 nfserr = nfsd4_encode_fattr(fhp, fhp->fh_export, fhp->fh_dentry, 1988 resp->p, &buflen, getattr->ga_bmval, 1989 resp->rqstp); 1990 if (!nfserr) 1991 resp->p += buflen; 1992 return nfserr; 1993} 1994 1995static void 1996nfsd4_encode_getfh(struct nfsd4_compoundres *resp, __be32 nfserr, struct svc_fh *fhp) 1997{ 1998 unsigned int len; 1999 ENCODE_HEAD; 2000 2001 if (!nfserr) { 2002 len = fhp->fh_handle.fh_size; 2003 RESERVE_SPACE(len + 4); 2004 WRITE32(len); 2005 WRITEMEM(&fhp->fh_handle.fh_base, len); 2006 ADJUST_ARGS(); 2007 } 2008} 2009 2010/* 2011* Including all fields other than the name, a LOCK4denied structure requires 2012* 8(clientid) + 4(namelen) + 8(offset) + 8(length) + 4(type) = 32 bytes. 2013*/ 2014static void 2015nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denied *ld) 2016{ 2017 ENCODE_HEAD; 2018 2019 RESERVE_SPACE(32 + XDR_LEN(ld->ld_sop ? ld->ld_sop->so_owner.len : 0)); 2020 WRITE64(ld->ld_start); 2021 WRITE64(ld->ld_length); 2022 WRITE32(ld->ld_type); 2023 if (ld->ld_sop) { 2024 WRITEMEM(&ld->ld_clientid, 8); 2025 WRITE32(ld->ld_sop->so_owner.len); 2026 WRITEMEM(ld->ld_sop->so_owner.data, ld->ld_sop->so_owner.len); 2027 kref_put(&ld->ld_sop->so_ref, nfs4_free_stateowner); 2028 } else { /* non - nfsv4 lock in conflict, no clientid nor owner */ 2029 WRITE64((u64)0); /* clientid */ 2030 WRITE32(0); /* length of owner name */ 2031 } 2032 ADJUST_ARGS(); 2033} 2034 2035static void 2036nfsd4_encode_lock(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lock *lock) 2037{ 2038 ENCODE_SEQID_OP_HEAD; 2039 2040 if (!nfserr) { 2041 RESERVE_SPACE(4 + sizeof(stateid_t)); 2042 WRITE32(lock->lk_resp_stateid.si_generation); 2043 WRITEMEM(&lock->lk_resp_stateid.si_opaque, sizeof(stateid_opaque_t)); 2044 ADJUST_ARGS(); 2045 } else if (nfserr == nfserr_denied) 2046 nfsd4_encode_lock_denied(resp, &lock->lk_denied); 2047 2048 ENCODE_SEQID_OP_TAIL(lock->lk_replay_owner); 2049} 2050 2051static void 2052nfsd4_encode_lockt(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_lockt *lockt) 2053{ 2054 if (nfserr == nfserr_denied) 2055 nfsd4_encode_lock_denied(resp, &lockt->lt_denied); 2056} 2057 2058static void 2059nfsd4_encode_locku(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_locku *locku) 2060{ 2061 ENCODE_SEQID_OP_HEAD; 2062 2063 if (!nfserr) { 2064 RESERVE_SPACE(sizeof(stateid_t)); 2065 WRITE32(locku->lu_stateid.si_generation); 2066 WRITEMEM(&locku->lu_stateid.si_opaque, sizeof(stateid_opaque_t)); 2067 ADJUST_ARGS(); 2068 } 2069 2070 ENCODE_SEQID_OP_TAIL(locku->lu_stateowner); 2071} 2072 2073 2074static void 2075nfsd4_encode_link(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_link *link) 2076{ 2077 ENCODE_HEAD; 2078 2079 if (!nfserr) { 2080 RESERVE_SPACE(20); 2081 WRITECINFO(link->li_cinfo); 2082 ADJUST_ARGS(); 2083 } 2084} 2085 2086 2087static void 2088nfsd4_encode_open(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open *open) 2089{ 2090 ENCODE_SEQID_OP_HEAD; 2091 2092 if (nfserr) 2093 goto out; 2094 2095 RESERVE_SPACE(36 + sizeof(stateid_t)); 2096 WRITE32(open->op_stateid.si_generation); 2097 WRITEMEM(&open->op_stateid.si_opaque, sizeof(stateid_opaque_t)); 2098 WRITECINFO(open->op_cinfo); 2099 WRITE32(open->op_rflags); 2100 WRITE32(2); 2101 WRITE32(open->op_bmval[0]); 2102 WRITE32(open->op_bmval[1]); 2103 WRITE32(open->op_delegate_type); 2104 ADJUST_ARGS(); 2105 2106 switch (open->op_delegate_type) { 2107 case NFS4_OPEN_DELEGATE_NONE: 2108 break; 2109 case NFS4_OPEN_DELEGATE_READ: 2110 RESERVE_SPACE(20 + sizeof(stateid_t)); 2111 WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t)); 2112 WRITE32(open->op_recall); 2113 2114 /* 2115 * TODO: ACE's in delegations 2116 */ 2117 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE); 2118 WRITE32(0); 2119 WRITE32(0); 2120 WRITE32(0); 2121 ADJUST_ARGS(); 2122 break; 2123 case NFS4_OPEN_DELEGATE_WRITE: 2124 RESERVE_SPACE(32 + sizeof(stateid_t)); 2125 WRITEMEM(&open->op_delegate_stateid, sizeof(stateid_t)); 2126 WRITE32(0); 2127 2128 /* 2129 * TODO: space_limit's in delegations 2130 */ 2131 WRITE32(NFS4_LIMIT_SIZE); 2132 WRITE32(~(u32)0); 2133 WRITE32(~(u32)0); 2134 2135 /* 2136 * TODO: ACE's in delegations 2137 */ 2138 WRITE32(NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE); 2139 WRITE32(0); 2140 WRITE32(0); 2141 WRITE32(0); 2142 ADJUST_ARGS(); 2143 break; 2144 default: 2145 BUG(); 2146 } 2147out: 2148 ENCODE_SEQID_OP_TAIL(open->op_stateowner); 2149} 2150 2151static void 2152nfsd4_encode_open_confirm(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_confirm *oc) 2153{ 2154 ENCODE_SEQID_OP_HEAD; 2155 2156 if (!nfserr) { 2157 RESERVE_SPACE(sizeof(stateid_t)); 2158 WRITE32(oc->oc_resp_stateid.si_generation); 2159 WRITEMEM(&oc->oc_resp_stateid.si_opaque, sizeof(stateid_opaque_t)); 2160 ADJUST_ARGS(); 2161 } 2162 2163 ENCODE_SEQID_OP_TAIL(oc->oc_stateowner); 2164} 2165 2166static void 2167nfsd4_encode_open_downgrade(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_open_downgrade *od) 2168{ 2169 ENCODE_SEQID_OP_HEAD; 2170 2171 if (!nfserr) { 2172 RESERVE_SPACE(sizeof(stateid_t)); 2173 WRITE32(od->od_stateid.si_generation); 2174 WRITEMEM(&od->od_stateid.si_opaque, sizeof(stateid_opaque_t)); 2175 ADJUST_ARGS(); 2176 } 2177 2178 ENCODE_SEQID_OP_TAIL(od->od_stateowner); 2179} 2180 2181static __be32 2182nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr, 2183 struct nfsd4_read *read) 2184{ 2185 u32 eof; 2186 int v, pn; 2187 unsigned long maxcount; 2188 long len; 2189 ENCODE_HEAD; 2190 2191 if (nfserr) 2192 return nfserr; 2193 if (resp->xbuf->page_len) 2194 return nfserr_resource; 2195 2196 RESERVE_SPACE(8); /* eof flag and byte count */ 2197 2198 maxcount = svc_max_payload(resp->rqstp); 2199 if (maxcount > read->rd_length) 2200 maxcount = read->rd_length; 2201 2202 len = maxcount; 2203 v = 0; 2204 while (len > 0) { 2205 pn = resp->rqstp->rq_resused++; 2206 resp->rqstp->rq_vec[v].iov_base = 2207 page_address(resp->rqstp->rq_respages[pn]); 2208 resp->rqstp->rq_vec[v].iov_len = 2209 len < PAGE_SIZE ? len : PAGE_SIZE; 2210 v++; 2211 len -= PAGE_SIZE; 2212 } 2213 read->rd_vlen = v; 2214 2215 nfserr = nfsd_read(read->rd_rqstp, read->rd_fhp, read->rd_filp, 2216 read->rd_offset, resp->rqstp->rq_vec, read->rd_vlen, 2217 &maxcount); 2218 2219 if (nfserr == nfserr_symlink) 2220 nfserr = nfserr_inval; 2221 if (nfserr) 2222 return nfserr; 2223 eof = (read->rd_offset + maxcount >= 2224 read->rd_fhp->fh_dentry->d_inode->i_size); 2225 2226 WRITE32(eof); 2227 WRITE32(maxcount); 2228 ADJUST_ARGS(); 2229 resp->xbuf->head[0].iov_len = (char*)p 2230 - (char*)resp->xbuf->head[0].iov_base; 2231 resp->xbuf->page_len = maxcount; 2232 2233 /* Use rest of head for padding and remaining ops: */ 2234 resp->xbuf->tail[0].iov_base = p; 2235 resp->xbuf->tail[0].iov_len = 0; 2236 if (maxcount&3) { 2237 RESERVE_SPACE(4); 2238 WRITE32(0); 2239 resp->xbuf->tail[0].iov_base += maxcount&3; 2240 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); 2241 ADJUST_ARGS(); 2242 } 2243 return 0; 2244} 2245 2246static __be32 2247nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink) 2248{ 2249 int maxcount; 2250 char *page; 2251 ENCODE_HEAD; 2252 2253 if (nfserr) 2254 return nfserr; 2255 if (resp->xbuf->page_len) 2256 return nfserr_resource; 2257 2258 page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); 2259 2260 maxcount = PAGE_SIZE; 2261 RESERVE_SPACE(4); 2262 2263 nfserr = nfsd_readlink(readlink->rl_rqstp, readlink->rl_fhp, page, &maxcount); 2264 if (nfserr == nfserr_isdir) 2265 return nfserr_inval; 2266 if (nfserr) 2267 return nfserr; 2268 2269 WRITE32(maxcount); 2270 ADJUST_ARGS(); 2271 resp->xbuf->head[0].iov_len = (char*)p 2272 - (char*)resp->xbuf->head[0].iov_base; 2273 resp->xbuf->page_len = maxcount; 2274 2275 /* Use rest of head for padding and remaining ops: */ 2276 resp->xbuf->tail[0].iov_base = p; 2277 resp->xbuf->tail[0].iov_len = 0; 2278 if (maxcount&3) { 2279 RESERVE_SPACE(4); 2280 WRITE32(0); 2281 resp->xbuf->tail[0].iov_base += maxcount&3; 2282 resp->xbuf->tail[0].iov_len = 4 - (maxcount&3); 2283 ADJUST_ARGS(); 2284 } 2285 return 0; 2286} 2287 2288static __be32 2289nfsd4_encode_readdir(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readdir *readdir) 2290{ 2291 int maxcount; 2292 loff_t offset; 2293 __be32 *page, *savep, *tailbase; 2294 ENCODE_HEAD; 2295 2296 if (nfserr) 2297 return nfserr; 2298 if (resp->xbuf->page_len) 2299 return nfserr_resource; 2300 2301 RESERVE_SPACE(8); /* verifier */ 2302 savep = p; 2303 2304 WRITE32(0); 2305 WRITE32(0); 2306 ADJUST_ARGS(); 2307 resp->xbuf->head[0].iov_len = ((char*)resp->p) - (char*)resp->xbuf->head[0].iov_base; 2308 tailbase = p; 2309 2310 maxcount = PAGE_SIZE; 2311 if (maxcount > readdir->rd_maxcount) 2312 maxcount = readdir->rd_maxcount; 2313 2314 /* 2315 * Convert from bytes to words, account for the two words already 2316 * written, make sure to leave two words at the end for the next 2317 * pointer and eof field. 2318 */ 2319 maxcount = (maxcount >> 2) - 4; 2320 if (maxcount < 0) { 2321 nfserr = nfserr_toosmall; 2322 goto err_no_verf; 2323 } 2324 2325 page = page_address(resp->rqstp->rq_respages[resp->rqstp->rq_resused++]); 2326 readdir->common.err = 0; 2327 readdir->buflen = maxcount; 2328 readdir->buffer = page; 2329 readdir->offset = NULL; 2330 2331 offset = readdir->rd_cookie; 2332 nfserr = nfsd_readdir(readdir->rd_rqstp, readdir->rd_fhp, 2333 &offset, 2334 &readdir->common, nfsd4_encode_dirent); 2335 if (nfserr == nfs_ok && 2336 readdir->common.err == nfserr_toosmall && 2337 readdir->buffer == page) 2338 nfserr = nfserr_toosmall; 2339 if (nfserr == nfserr_symlink) 2340 nfserr = nfserr_notdir; 2341 if (nfserr) 2342 goto err_no_verf; 2343 2344 if (readdir->offset) 2345 xdr_encode_hyper(readdir->offset, offset); 2346 2347 p = readdir->buffer; 2348 *p++ = 0; /* no more entries */ 2349 *p++ = htonl(readdir->common.err == nfserr_eof); 2350 resp->xbuf->page_len = ((char*)p) - (char*)page_address( 2351 resp->rqstp->rq_respages[resp->rqstp->rq_resused-1]); 2352 2353 /* Use rest of head for padding and remaining ops: */ 2354 resp->xbuf->tail[0].iov_base = tailbase; 2355 resp->xbuf->tail[0].iov_len = 0; 2356 resp->p = resp->xbuf->tail[0].iov_base; 2357 resp->end = resp->p + (PAGE_SIZE - resp->xbuf->head[0].iov_len)/4; 2358 2359 return 0; 2360err_no_verf: 2361 p = savep; 2362 ADJUST_ARGS(); 2363 return nfserr; 2364} 2365 2366static void 2367nfsd4_encode_remove(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_remove *remove) 2368{ 2369 ENCODE_HEAD; 2370 2371 if (!nfserr) { 2372 RESERVE_SPACE(20); 2373 WRITECINFO(remove->rm_cinfo); 2374 ADJUST_ARGS(); 2375 } 2376} 2377 2378static void 2379nfsd4_encode_rename(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_rename *rename) 2380{ 2381 ENCODE_HEAD; 2382 2383 if (!nfserr) { 2384 RESERVE_SPACE(40); 2385 WRITECINFO(rename->rn_sinfo); 2386 WRITECINFO(rename->rn_tinfo); 2387 ADJUST_ARGS(); 2388 } 2389} 2390 2391/* 2392 * The SETATTR encode routine is special -- it always encodes a bitmap, 2393 * regardless of the error status. 2394 */ 2395static void 2396nfsd4_encode_setattr(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setattr *setattr) 2397{ 2398 ENCODE_HEAD; 2399 2400 RESERVE_SPACE(12); 2401 if (nfserr) { 2402 WRITE32(2); 2403 WRITE32(0); 2404 WRITE32(0); 2405 } 2406 else { 2407 WRITE32(2); 2408 WRITE32(setattr->sa_bmval[0]); 2409 WRITE32(setattr->sa_bmval[1]); 2410 } 2411 ADJUST_ARGS(); 2412} 2413 2414static void 2415nfsd4_encode_setclientid(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_setclientid *scd) 2416{ 2417 ENCODE_HEAD; 2418 2419 if (!nfserr) { 2420 RESERVE_SPACE(8 + sizeof(nfs4_verifier)); 2421 WRITEMEM(&scd->se_clientid, 8); 2422 WRITEMEM(&scd->se_confirm, sizeof(nfs4_verifier)); 2423 ADJUST_ARGS(); 2424 } 2425 else if (nfserr == nfserr_clid_inuse) { 2426 RESERVE_SPACE(8); 2427 WRITE32(0); 2428 WRITE32(0); 2429 ADJUST_ARGS(); 2430 } 2431} 2432 2433static void 2434nfsd4_encode_write(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_write *write) 2435{ 2436 ENCODE_HEAD; 2437 2438 if (!nfserr) { 2439 RESERVE_SPACE(16); 2440 WRITE32(write->wr_bytes_written); 2441 WRITE32(write->wr_how_written); 2442 WRITEMEM(write->wr_verifier.data, 8); 2443 ADJUST_ARGS(); 2444 } 2445} 2446 2447void 2448nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op) 2449{ 2450 __be32 *statp; 2451 ENCODE_HEAD; 2452 2453 RESERVE_SPACE(8); 2454 WRITE32(op->opnum); 2455 statp = p++; /* to be backfilled at the end */ 2456 ADJUST_ARGS(); 2457 2458 switch (op->opnum) { 2459 case OP_ACCESS: 2460 nfsd4_encode_access(resp, op->status, &op->u.access); 2461 break; 2462 case OP_CLOSE: 2463 nfsd4_encode_close(resp, op->status, &op->u.close); 2464 break; 2465 case OP_COMMIT: 2466 nfsd4_encode_commit(resp, op->status, &op->u.commit); 2467 break; 2468 case OP_CREATE: 2469 nfsd4_encode_create(resp, op->status, &op->u.create); 2470 break; 2471 case OP_DELEGRETURN: 2472 break; 2473 case OP_GETATTR: 2474 op->status = nfsd4_encode_getattr(resp, op->status, &op->u.getattr); 2475 break; 2476 case OP_GETFH: 2477 nfsd4_encode_getfh(resp, op->status, op->u.getfh); 2478 break; 2479 case OP_LINK: 2480 nfsd4_encode_link(resp, op->status, &op->u.link); 2481 break; 2482 case OP_LOCK: 2483 nfsd4_encode_lock(resp, op->status, &op->u.lock); 2484 break; 2485 case OP_LOCKT: 2486 nfsd4_encode_lockt(resp, op->status, &op->u.lockt); 2487 break; 2488 case OP_LOCKU: 2489 nfsd4_encode_locku(resp, op->status, &op->u.locku); 2490 break; 2491 case OP_LOOKUP: 2492 break; 2493 case OP_LOOKUPP: 2494 break; 2495 case OP_NVERIFY: 2496 break; 2497 case OP_OPEN: 2498 nfsd4_encode_open(resp, op->status, &op->u.open); 2499 break; 2500 case OP_OPEN_CONFIRM: 2501 nfsd4_encode_open_confirm(resp, op->status, &op->u.open_confirm); 2502 break; 2503 case OP_OPEN_DOWNGRADE: 2504 nfsd4_encode_open_downgrade(resp, op->status, &op->u.open_downgrade); 2505 break; 2506 case OP_PUTFH: 2507 break; 2508 case OP_PUTROOTFH: 2509 break; 2510 case OP_READ: 2511 op->status = nfsd4_encode_read(resp, op->status, &op->u.read); 2512 break; 2513 case OP_READDIR: 2514 op->status = nfsd4_encode_readdir(resp, op->status, &op->u.readdir); 2515 break; 2516 case OP_READLINK: 2517 op->status = nfsd4_encode_readlink(resp, op->status, &op->u.readlink); 2518 break; 2519 case OP_REMOVE: 2520 nfsd4_encode_remove(resp, op->status, &op->u.remove); 2521 break; 2522 case OP_RENAME: 2523 nfsd4_encode_rename(resp, op->status, &op->u.rename); 2524 break; 2525 case OP_RENEW: 2526 break; 2527 case OP_RESTOREFH: 2528 break; 2529 case OP_SAVEFH: 2530 break; 2531 case OP_SETATTR: 2532 nfsd4_encode_setattr(resp, op->status, &op->u.setattr); 2533 break; 2534 case OP_SETCLIENTID: 2535 nfsd4_encode_setclientid(resp, op->status, &op->u.setclientid); 2536 break; 2537 case OP_SETCLIENTID_CONFIRM: 2538 break; 2539 case OP_VERIFY: 2540 break; 2541 case OP_WRITE: 2542 nfsd4_encode_write(resp, op->status, &op->u.write); 2543 break; 2544 case OP_RELEASE_LOCKOWNER: 2545 break; 2546 default: 2547 break; 2548 } 2549 2550 /* 2551 * Note: We write the status directly, instead of using WRITE32(), 2552 * since it is already in network byte order. 2553 */ 2554 *statp = op->status; 2555} 2556 2557/* 2558 * Encode the reply stored in the stateowner reply cache 2559 * 2560 * XDR note: do not encode rp->rp_buflen: the buffer contains the 2561 * previously sent already encoded operation. 2562 * 2563 * called with nfs4_lock_state() held 2564 */ 2565void 2566nfsd4_encode_replay(struct nfsd4_compoundres *resp, struct nfsd4_op *op) 2567{ 2568 ENCODE_HEAD; 2569 struct nfs4_replay *rp = op->replay; 2570 2571 BUG_ON(!rp); 2572 2573 RESERVE_SPACE(8); 2574 WRITE32(op->opnum); 2575 *p++ = rp->rp_status; /* already xdr'ed */ 2576 ADJUST_ARGS(); 2577 2578 RESERVE_SPACE(rp->rp_buflen); 2579 WRITEMEM(rp->rp_buf, rp->rp_buflen); 2580 ADJUST_ARGS(); 2581} 2582 2583/* 2584 * END OF "GENERIC" ENCODE ROUTINES. 2585 */ 2586 2587int 2588nfs4svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy) 2589{ 2590 return xdr_ressize_check(rqstp, p); 2591} 2592 2593void nfsd4_release_compoundargs(struct nfsd4_compoundargs *args) 2594{ 2595 if (args->ops != args->iops) { 2596 kfree(args->ops); 2597 args->ops = args->iops; 2598 } 2599 kfree(args->tmpp); 2600 args->tmpp = NULL; 2601 while (args->to_free) { 2602 struct tmpbuf *tb = args->to_free; 2603 args->to_free = tb->next; 2604 tb->release(tb->buf); 2605 kfree(tb); 2606 } 2607} 2608 2609int 2610nfs4svc_decode_compoundargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundargs *args) 2611{ 2612 __be32 status; 2613 2614 args->p = p; 2615 args->end = rqstp->rq_arg.head[0].iov_base + rqstp->rq_arg.head[0].iov_len; 2616 args->pagelist = rqstp->rq_arg.pages; 2617 args->pagelen = rqstp->rq_arg.page_len; 2618 args->tmpp = NULL; 2619 args->to_free = NULL; 2620 args->ops = args->iops; 2621 args->rqstp = rqstp; 2622 2623 status = nfsd4_decode_compound(args); 2624 if (status) { 2625 nfsd4_release_compoundargs(args); 2626 } 2627 return !status; 2628} 2629 2630int 2631nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compoundres *resp) 2632{ 2633 /* 2634 * All that remains is to write the tag and operation count... 2635 */ 2636 struct kvec *iov; 2637 p = resp->tagp; 2638 *p++ = htonl(resp->taglen); 2639 memcpy(p, resp->tag, resp->taglen); 2640 p += XDR_QUADLEN(resp->taglen); 2641 *p++ = htonl(resp->opcnt); 2642 2643 if (rqstp->rq_res.page_len) 2644 iov = &rqstp->rq_res.tail[0]; 2645 else 2646 iov = &rqstp->rq_res.head[0]; 2647 iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base; 2648 BUG_ON(iov->iov_len > PAGE_SIZE); 2649 return 1; 2650} 2651 2652/* 2653 * Local variables: 2654 * c-basic-offset: 8 2655 * End: 2656 */ 2657