1 /* 2 * fs/nfsd/nfs4proc.c 3 * 4 * Server-side procedures 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 * Note: some routines in this file are just trivial wrappers 38 * (e.g. nfsd4_lookup()) defined solely for the sake of consistent 39 * naming. Since all such routines have been declared "inline", 40 * there shouldn't be any associated overhead. At some point in 41 * the future, I might inline these "by hand" to clean up a 42 * little. 43 */ 44 45 #include <linux/param.h> 46 #include <linux/major.h> 47 #include <linux/slab.h> 48 49 #include <linux/sunrpc/svc.h> 50 #include <linux/nfsd/nfsd.h> 51 #include <linux/nfsd/cache.h> 52 #include <linux/nfs4.h> 53 #include <linux/nfsd/state.h> 54 #include <linux/nfsd/xdr4.h> 55 #include <linux/nfs4_acl.h> 56 57 #define NFSDDBG_FACILITY NFSDDBG_PROC 58 59 static inline void 60 fh_dup2(struct svc_fh *dst, struct svc_fh *src) 61 { 62 fh_put(dst); 63 dget(src->fh_dentry); 64 if (src->fh_export) 65 cache_get(&src->fh_export->h); 66 *dst = *src; 67 } 68 69 static int 70 do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) 71 { 72 int accmode, status; 73 74 if (open->op_truncate && 75 !(open->op_share_access & NFS4_SHARE_ACCESS_WRITE)) 76 return nfserr_inval; 77 78 accmode = MAY_NOP; 79 if (open->op_share_access & NFS4_SHARE_ACCESS_READ) 80 accmode = MAY_READ; 81 if (open->op_share_deny & NFS4_SHARE_ACCESS_WRITE) 82 accmode |= (MAY_WRITE | MAY_TRUNC); 83 accmode |= MAY_OWNER_OVERRIDE; 84 85 status = fh_verify(rqstp, current_fh, S_IFREG, accmode); 86 87 return status; 88 } 89 90 static int 91 do_open_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) 92 { 93 struct svc_fh resfh; 94 int status; 95 96 fh_init(&resfh, NFS4_FHSIZE); 97 open->op_truncate = 0; 98 99 if (open->op_create) { 100 /* 101 * Note: create modes (UNCHECKED,GUARDED...) are the same 102 * in NFSv4 as in v3. 103 */ 104 status = nfsd_create_v3(rqstp, current_fh, open->op_fname.data, 105 open->op_fname.len, &open->op_iattr, 106 &resfh, open->op_createmode, 107 (u32 *)open->op_verf.data, &open->op_truncate); 108 } 109 else { 110 status = nfsd_lookup(rqstp, current_fh, 111 open->op_fname.data, open->op_fname.len, &resfh); 112 fh_unlock(current_fh); 113 } 114 115 if (!status) { 116 set_change_info(&open->op_cinfo, current_fh); 117 118 /* set reply cache */ 119 fh_dup2(current_fh, &resfh); 120 open->op_stateowner->so_replay.rp_openfh_len = 121 resfh.fh_handle.fh_size; 122 memcpy(open->op_stateowner->so_replay.rp_openfh, 123 &resfh.fh_handle.fh_base, 124 resfh.fh_handle.fh_size); 125 126 status = do_open_permission(rqstp, current_fh, open); 127 } 128 129 fh_put(&resfh); 130 return status; 131 } 132 133 static int 134 do_open_fhandle(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) 135 { 136 int status; 137 138 /* Only reclaims from previously confirmed clients are valid */ 139 if ((status = nfs4_check_open_reclaim(&open->op_clientid))) 140 return status; 141 142 /* We don't know the target directory, and therefore can not 143 * set the change info 144 */ 145 146 memset(&open->op_cinfo, 0, sizeof(struct nfsd4_change_info)); 147 148 /* set replay cache */ 149 open->op_stateowner->so_replay.rp_openfh_len = current_fh->fh_handle.fh_size; 150 memcpy(open->op_stateowner->so_replay.rp_openfh, 151 ¤t_fh->fh_handle.fh_base, 152 current_fh->fh_handle.fh_size); 153 154 open->op_truncate = (open->op_iattr.ia_valid & ATTR_SIZE) && 155 (open->op_iattr.ia_size == 0); 156 157 status = do_open_permission(rqstp, current_fh, open); 158 159 return status; 160 } 161 162 163 static inline int 164 nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) 165 { 166 int status; 167 dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n", 168 (int)open->op_fname.len, open->op_fname.data, 169 open->op_stateowner); 170 171 if (nfs4_in_grace() && open->op_claim_type != NFS4_OPEN_CLAIM_PREVIOUS) 172 return nfserr_grace; 173 174 if (!nfs4_in_grace() && open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS) 175 return nfserr_no_grace; 176 177 /* This check required by spec. */ 178 if (open->op_create && open->op_claim_type != NFS4_OPEN_CLAIM_NULL) 179 return nfserr_inval; 180 181 nfs4_lock_state(); 182 183 /* check seqid for replay. set nfs4_owner */ 184 status = nfsd4_process_open1(open); 185 if (status == NFSERR_REPLAY_ME) { 186 struct nfs4_replay *rp = &open->op_stateowner->so_replay; 187 fh_put(current_fh); 188 current_fh->fh_handle.fh_size = rp->rp_openfh_len; 189 memcpy(¤t_fh->fh_handle.fh_base, rp->rp_openfh, 190 rp->rp_openfh_len); 191 status = fh_verify(rqstp, current_fh, 0, MAY_NOP); 192 if (status) 193 dprintk("nfsd4_open: replay failed" 194 " restoring previous filehandle\n"); 195 else 196 status = NFSERR_REPLAY_ME; 197 } 198 if (status) 199 goto out; 200 switch (open->op_claim_type) { 201 case NFS4_OPEN_CLAIM_NULL: 202 /* 203 * (1) set CURRENT_FH to the file being opened, 204 * creating it if necessary, (2) set open->op_cinfo, 205 * (3) set open->op_truncate if the file is to be 206 * truncated after opening, (4) do permission checking. 207 */ 208 status = do_open_lookup(rqstp, current_fh, open); 209 if (status) 210 goto out; 211 break; 212 case NFS4_OPEN_CLAIM_PREVIOUS: 213 /* 214 * The CURRENT_FH is already set to the file being 215 * opened. (1) set open->op_cinfo, (2) set 216 * open->op_truncate if the file is to be truncated 217 * after opening, (3) do permission checking. 218 */ 219 status = do_open_fhandle(rqstp, current_fh, open); 220 if (status) 221 goto out; 222 break; 223 case NFS4_OPEN_CLAIM_DELEGATE_CUR: 224 case NFS4_OPEN_CLAIM_DELEGATE_PREV: 225 printk("NFSD: unsupported OPEN claim type %d\n", 226 open->op_claim_type); 227 status = nfserr_notsupp; 228 goto out; 229 default: 230 printk("NFSD: Invalid OPEN claim type %d\n", 231 open->op_claim_type); 232 status = nfserr_inval; 233 goto out; 234 } 235 /* 236 * nfsd4_process_open2() does the actual opening of the file. If 237 * successful, it (1) truncates the file if open->op_truncate was 238 * set, (2) sets open->op_stateid, (3) sets open->op_delegation. 239 */ 240 status = nfsd4_process_open2(rqstp, current_fh, open); 241 out: 242 if (open->op_stateowner) 243 nfs4_get_stateowner(open->op_stateowner); 244 nfs4_unlock_state(); 245 return status; 246 } 247 248 /* 249 * filehandle-manipulating ops. 250 */ 251 static inline int 252 nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh) 253 { 254 if (!current_fh->fh_dentry) 255 return nfserr_nofilehandle; 256 257 *getfh = current_fh; 258 return nfs_ok; 259 } 260 261 static inline int 262 nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putfh *putfh) 263 { 264 fh_put(current_fh); 265 current_fh->fh_handle.fh_size = putfh->pf_fhlen; 266 memcpy(¤t_fh->fh_handle.fh_base, putfh->pf_fhval, putfh->pf_fhlen); 267 return fh_verify(rqstp, current_fh, 0, MAY_NOP); 268 } 269 270 static inline int 271 nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh) 272 { 273 int status; 274 275 fh_put(current_fh); 276 status = exp_pseudoroot(rqstp->rq_client, current_fh, 277 &rqstp->rq_chandle); 278 if (!status) 279 status = nfserrno(nfsd_setuser(rqstp, current_fh->fh_export)); 280 return status; 281 } 282 283 static inline int 284 nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh) 285 { 286 if (!save_fh->fh_dentry) 287 return nfserr_restorefh; 288 289 fh_dup2(current_fh, save_fh); 290 return nfs_ok; 291 } 292 293 static inline int 294 nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh) 295 { 296 if (!current_fh->fh_dentry) 297 return nfserr_nofilehandle; 298 299 fh_dup2(save_fh, current_fh); 300 return nfs_ok; 301 } 302 303 /* 304 * misc nfsv4 ops 305 */ 306 static inline int 307 nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_access *access) 308 { 309 if (access->ac_req_access & ~NFS3_ACCESS_FULL) 310 return nfserr_inval; 311 312 access->ac_resp_access = access->ac_req_access; 313 return nfsd_access(rqstp, current_fh, &access->ac_resp_access, &access->ac_supported); 314 } 315 316 static inline int 317 nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit) 318 { 319 int status; 320 321 u32 *p = (u32 *)commit->co_verf.data; 322 *p++ = nfssvc_boot.tv_sec; 323 *p++ = nfssvc_boot.tv_usec; 324 325 status = nfsd_commit(rqstp, current_fh, commit->co_offset, commit->co_count); 326 if (status == nfserr_symlink) 327 status = nfserr_inval; 328 return status; 329 } 330 331 static int 332 nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create) 333 { 334 struct svc_fh resfh; 335 int status; 336 dev_t rdev; 337 338 fh_init(&resfh, NFS4_FHSIZE); 339 340 status = fh_verify(rqstp, current_fh, S_IFDIR, MAY_CREATE); 341 if (status == nfserr_symlink) 342 status = nfserr_notdir; 343 if (status) 344 return status; 345 346 switch (create->cr_type) { 347 case NF4LNK: 348 /* ugh! we have to null-terminate the linktext, or 349 * vfs_symlink() will choke. it is always safe to 350 * null-terminate by brute force, since at worst we 351 * will overwrite the first byte of the create namelen 352 * in the XDR buffer, which has already been extracted 353 * during XDR decode. 354 */ 355 create->cr_linkname[create->cr_linklen] = 0; 356 357 status = nfsd_symlink(rqstp, current_fh, create->cr_name, 358 create->cr_namelen, create->cr_linkname, 359 create->cr_linklen, &resfh, &create->cr_iattr); 360 break; 361 362 case NF4BLK: 363 rdev = MKDEV(create->cr_specdata1, create->cr_specdata2); 364 if (MAJOR(rdev) != create->cr_specdata1 || 365 MINOR(rdev) != create->cr_specdata2) 366 return nfserr_inval; 367 status = nfsd_create(rqstp, current_fh, create->cr_name, 368 create->cr_namelen, &create->cr_iattr, 369 S_IFBLK, rdev, &resfh); 370 break; 371 372 case NF4CHR: 373 rdev = MKDEV(create->cr_specdata1, create->cr_specdata2); 374 if (MAJOR(rdev) != create->cr_specdata1 || 375 MINOR(rdev) != create->cr_specdata2) 376 return nfserr_inval; 377 status = nfsd_create(rqstp, current_fh, create->cr_name, 378 create->cr_namelen, &create->cr_iattr, 379 S_IFCHR, rdev, &resfh); 380 break; 381 382 case NF4SOCK: 383 status = nfsd_create(rqstp, current_fh, create->cr_name, 384 create->cr_namelen, &create->cr_iattr, 385 S_IFSOCK, 0, &resfh); 386 break; 387 388 case NF4FIFO: 389 status = nfsd_create(rqstp, current_fh, create->cr_name, 390 create->cr_namelen, &create->cr_iattr, 391 S_IFIFO, 0, &resfh); 392 break; 393 394 case NF4DIR: 395 create->cr_iattr.ia_valid &= ~ATTR_SIZE; 396 status = nfsd_create(rqstp, current_fh, create->cr_name, 397 create->cr_namelen, &create->cr_iattr, 398 S_IFDIR, 0, &resfh); 399 break; 400 401 default: 402 status = nfserr_badtype; 403 } 404 405 if (!status) { 406 fh_unlock(current_fh); 407 set_change_info(&create->cr_cinfo, current_fh); 408 fh_dup2(current_fh, &resfh); 409 } 410 411 fh_put(&resfh); 412 return status; 413 } 414 415 static inline int 416 nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_getattr *getattr) 417 { 418 int status; 419 420 status = fh_verify(rqstp, current_fh, 0, MAY_NOP); 421 if (status) 422 return status; 423 424 if (getattr->ga_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1) 425 return nfserr_inval; 426 427 getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0; 428 getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1; 429 430 getattr->ga_fhp = current_fh; 431 return nfs_ok; 432 } 433 434 static inline int 435 nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh, 436 struct svc_fh *save_fh, struct nfsd4_link *link) 437 { 438 int status = nfserr_nofilehandle; 439 440 if (!save_fh->fh_dentry) 441 return status; 442 status = nfsd_link(rqstp, current_fh, link->li_name, link->li_namelen, save_fh); 443 if (!status) 444 set_change_info(&link->li_cinfo, current_fh); 445 return status; 446 } 447 448 static int 449 nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh) 450 { 451 struct svc_fh tmp_fh; 452 int ret; 453 454 fh_init(&tmp_fh, NFS4_FHSIZE); 455 if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh, 456 &rqstp->rq_chandle)) != 0) 457 return ret; 458 if (tmp_fh.fh_dentry == current_fh->fh_dentry) { 459 fh_put(&tmp_fh); 460 return nfserr_noent; 461 } 462 fh_put(&tmp_fh); 463 return nfsd_lookup(rqstp, current_fh, "..", 2, current_fh); 464 } 465 466 static inline int 467 nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lookup *lookup) 468 { 469 return nfsd_lookup(rqstp, current_fh, lookup->lo_name, lookup->lo_len, current_fh); 470 } 471 472 static inline int 473 nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read) 474 { 475 int status; 476 struct file *filp = NULL; 477 478 /* no need to check permission - this will be done in nfsd_read() */ 479 480 if (read->rd_offset >= OFFSET_MAX) 481 return nfserr_inval; 482 483 nfs4_lock_state(); 484 /* check stateid */ 485 if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid, 486 CHECK_FH | RD_STATE, &filp))) { 487 dprintk("NFSD: nfsd4_read: couldn't process stateid!\n"); 488 goto out; 489 } 490 status = nfs_ok; 491 out: 492 nfs4_unlock_state(); 493 read->rd_rqstp = rqstp; 494 read->rd_fhp = current_fh; 495 read->rd_filp = filp; 496 return status; 497 } 498 499 static inline int 500 nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir) 501 { 502 u64 cookie = readdir->rd_cookie; 503 static const nfs4_verifier zeroverf; 504 505 /* no need to check permission - this will be done in nfsd_readdir() */ 506 507 if (readdir->rd_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1) 508 return nfserr_inval; 509 510 readdir->rd_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0; 511 readdir->rd_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1; 512 513 if ((cookie > ~(u32)0) || (cookie == 1) || (cookie == 2) || 514 (cookie == 0 && memcmp(readdir->rd_verf.data, zeroverf.data, NFS4_VERIFIER_SIZE))) 515 return nfserr_bad_cookie; 516 517 readdir->rd_rqstp = rqstp; 518 readdir->rd_fhp = current_fh; 519 return nfs_ok; 520 } 521 522 static inline int 523 nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readlink *readlink) 524 { 525 readlink->rl_rqstp = rqstp; 526 readlink->rl_fhp = current_fh; 527 return nfs_ok; 528 } 529 530 static inline int 531 nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_remove *remove) 532 { 533 int status; 534 535 status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen); 536 if (status == nfserr_symlink) 537 return nfserr_notdir; 538 if (!status) { 539 fh_unlock(current_fh); 540 set_change_info(&remove->rm_cinfo, current_fh); 541 } 542 return status; 543 } 544 545 static inline int 546 nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh, 547 struct svc_fh *save_fh, struct nfsd4_rename *rename) 548 { 549 int status = nfserr_nofilehandle; 550 551 if (!save_fh->fh_dentry) 552 return status; 553 status = nfsd_rename(rqstp, save_fh, rename->rn_sname, 554 rename->rn_snamelen, current_fh, 555 rename->rn_tname, rename->rn_tnamelen); 556 557 /* the underlying filesystem returns different error's than required 558 * by NFSv4. both save_fh and current_fh have been verified.. */ 559 if (status == nfserr_isdir) 560 status = nfserr_exist; 561 else if ((status == nfserr_notdir) && 562 (S_ISDIR(save_fh->fh_dentry->d_inode->i_mode) && 563 S_ISDIR(current_fh->fh_dentry->d_inode->i_mode))) 564 status = nfserr_exist; 565 else if (status == nfserr_symlink) 566 status = nfserr_notdir; 567 568 if (!status) { 569 set_change_info(&rename->rn_sinfo, current_fh); 570 set_change_info(&rename->rn_tinfo, save_fh); 571 } 572 return status; 573 } 574 575 static inline int 576 nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr) 577 { 578 int status = nfs_ok; 579 580 if (!current_fh->fh_dentry) 581 return nfserr_nofilehandle; 582 583 status = nfs_ok; 584 if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { 585 nfs4_lock_state(); 586 if ((status = nfs4_preprocess_stateid_op(current_fh, 587 &setattr->sa_stateid, 588 CHECK_FH | WR_STATE, NULL))) { 589 dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n"); 590 goto out_unlock; 591 } 592 nfs4_unlock_state(); 593 } 594 status = nfs_ok; 595 if (setattr->sa_acl != NULL) 596 status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl); 597 if (status) 598 goto out; 599 status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr, 600 0, (time_t)0); 601 out: 602 return status; 603 out_unlock: 604 nfs4_unlock_state(); 605 return status; 606 } 607 608 static inline int 609 nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write) 610 { 611 stateid_t *stateid = &write->wr_stateid; 612 struct file *filp = NULL; 613 u32 *p; 614 int status = nfs_ok; 615 616 /* no need to check permission - this will be done in nfsd_write() */ 617 618 if (write->wr_offset >= OFFSET_MAX) 619 return nfserr_inval; 620 621 nfs4_lock_state(); 622 if ((status = nfs4_preprocess_stateid_op(current_fh, stateid, 623 CHECK_FH | WR_STATE, &filp))) { 624 dprintk("NFSD: nfsd4_write: couldn't process stateid!\n"); 625 goto out; 626 } 627 nfs4_unlock_state(); 628 629 write->wr_bytes_written = write->wr_buflen; 630 write->wr_how_written = write->wr_stable_how; 631 p = (u32 *)write->wr_verifier.data; 632 *p++ = nfssvc_boot.tv_sec; 633 *p++ = nfssvc_boot.tv_usec; 634 635 status = nfsd_write(rqstp, current_fh, filp, write->wr_offset, 636 write->wr_vec, write->wr_vlen, write->wr_buflen, 637 &write->wr_how_written); 638 639 if (status == nfserr_symlink) 640 status = nfserr_inval; 641 return status; 642 out: 643 nfs4_unlock_state(); 644 return status; 645 } 646 647 /* This routine never returns NFS_OK! If there are no other errors, it 648 * will return NFSERR_SAME or NFSERR_NOT_SAME depending on whether the 649 * attributes matched. VERIFY is implemented by mapping NFSERR_SAME 650 * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK. 651 */ 652 static int 653 nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_verify *verify) 654 { 655 u32 *buf, *p; 656 int count; 657 int status; 658 659 status = fh_verify(rqstp, current_fh, 0, MAY_NOP); 660 if (status) 661 return status; 662 663 if ((verify->ve_bmval[0] & ~NFSD_SUPPORTED_ATTRS_WORD0) 664 || (verify->ve_bmval[1] & ~NFSD_SUPPORTED_ATTRS_WORD1)) 665 return nfserr_attrnotsupp; 666 if ((verify->ve_bmval[0] & FATTR4_WORD0_RDATTR_ERROR) 667 || (verify->ve_bmval[1] & NFSD_WRITEONLY_ATTRS_WORD1)) 668 return nfserr_inval; 669 if (verify->ve_attrlen & 3) 670 return nfserr_inval; 671 672 /* count in words: 673 * bitmap_len(1) + bitmap(2) + attr_len(1) = 4 674 */ 675 count = 4 + (verify->ve_attrlen >> 2); 676 buf = kmalloc(count << 2, GFP_KERNEL); 677 if (!buf) 678 return nfserr_resource; 679 680 status = nfsd4_encode_fattr(current_fh, current_fh->fh_export, 681 current_fh->fh_dentry, buf, 682 &count, verify->ve_bmval, 683 rqstp); 684 685 /* this means that nfsd4_encode_fattr() ran out of space */ 686 if (status == nfserr_resource && count == 0) 687 status = nfserr_not_same; 688 if (status) 689 goto out_kfree; 690 691 p = buf + 3; 692 status = nfserr_not_same; 693 if (ntohl(*p++) != verify->ve_attrlen) 694 goto out_kfree; 695 if (!memcmp(p, verify->ve_attrval, verify->ve_attrlen)) 696 status = nfserr_same; 697 698 out_kfree: 699 kfree(buf); 700 return status; 701 } 702 703 /* 704 * NULL call. 705 */ 706 static int 707 nfsd4_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) 708 { 709 return nfs_ok; 710 } 711 712 713 /* 714 * COMPOUND call. 715 */ 716 static int 717 nfsd4_proc_compound(struct svc_rqst *rqstp, 718 struct nfsd4_compoundargs *args, 719 struct nfsd4_compoundres *resp) 720 { 721 struct nfsd4_op *op; 722 struct svc_fh *current_fh = NULL; 723 struct svc_fh *save_fh = NULL; 724 struct nfs4_stateowner *replay_owner = NULL; 725 int slack_space; /* in words, not bytes! */ 726 int status; 727 728 status = nfserr_resource; 729 current_fh = kmalloc(sizeof(*current_fh), GFP_KERNEL); 730 if (current_fh == NULL) 731 goto out; 732 fh_init(current_fh, NFS4_FHSIZE); 733 save_fh = kmalloc(sizeof(*save_fh), GFP_KERNEL); 734 if (save_fh == NULL) 735 goto out; 736 fh_init(save_fh, NFS4_FHSIZE); 737 738 resp->xbuf = &rqstp->rq_res; 739 resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len; 740 resp->tagp = resp->p; 741 /* reserve space for: taglen, tag, and opcnt */ 742 resp->p += 2 + XDR_QUADLEN(args->taglen); 743 resp->end = rqstp->rq_res.head[0].iov_base + PAGE_SIZE; 744 resp->taglen = args->taglen; 745 resp->tag = args->tag; 746 resp->opcnt = 0; 747 resp->rqstp = rqstp; 748 749 /* 750 * According to RFC3010, this takes precedence over all other errors. 751 */ 752 status = nfserr_minor_vers_mismatch; 753 if (args->minorversion > NFSD_SUPPORTED_MINOR_VERSION) 754 goto out; 755 756 status = nfs_ok; 757 while (!status && resp->opcnt < args->opcnt) { 758 op = &args->ops[resp->opcnt++]; 759 760 /* 761 * The XDR decode routines may have pre-set op->status; 762 * for example, if there is a miscellaneous XDR error 763 * it will be set to nfserr_bad_xdr. 764 */ 765 if (op->status) 766 goto encode_op; 767 768 /* We must be able to encode a successful response to 769 * this operation, with enough room left over to encode a 770 * failed response to the next operation. If we don't 771 * have enough room, fail with ERR_RESOURCE. 772 */ 773 /* FIXME - is slack_space *really* words, or bytes??? - neilb */ 774 slack_space = (char *)resp->end - (char *)resp->p; 775 if (slack_space < COMPOUND_SLACK_SPACE + COMPOUND_ERR_SLACK_SPACE) { 776 BUG_ON(slack_space < COMPOUND_ERR_SLACK_SPACE); 777 op->status = nfserr_resource; 778 goto encode_op; 779 } 780 781 /* All operations except RENEW, SETCLIENTID, RESTOREFH 782 * SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH 783 * require a valid current filehandle 784 * 785 * SETATTR NOFILEHANDLE error handled in nfsd4_setattr 786 * due to required returned bitmap argument 787 */ 788 if ((!current_fh->fh_dentry) && 789 !((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) || 790 (op->opnum == OP_SETCLIENTID) || 791 (op->opnum == OP_SETCLIENTID_CONFIRM) || 792 (op->opnum == OP_RENEW) || (op->opnum == OP_RESTOREFH) || 793 (op->opnum == OP_RELEASE_LOCKOWNER) || 794 (op->opnum == OP_SETATTR))) { 795 op->status = nfserr_nofilehandle; 796 goto encode_op; 797 } 798 switch (op->opnum) { 799 case OP_ACCESS: 800 op->status = nfsd4_access(rqstp, current_fh, &op->u.access); 801 break; 802 case OP_CLOSE: 803 op->status = nfsd4_close(rqstp, current_fh, &op->u.close); 804 replay_owner = op->u.close.cl_stateowner; 805 break; 806 case OP_COMMIT: 807 op->status = nfsd4_commit(rqstp, current_fh, &op->u.commit); 808 break; 809 case OP_CREATE: 810 op->status = nfsd4_create(rqstp, current_fh, &op->u.create); 811 break; 812 case OP_DELEGRETURN: 813 op->status = nfsd4_delegreturn(rqstp, current_fh, &op->u.delegreturn); 814 break; 815 case OP_GETATTR: 816 op->status = nfsd4_getattr(rqstp, current_fh, &op->u.getattr); 817 break; 818 case OP_GETFH: 819 op->status = nfsd4_getfh(current_fh, &op->u.getfh); 820 break; 821 case OP_LINK: 822 op->status = nfsd4_link(rqstp, current_fh, save_fh, &op->u.link); 823 break; 824 case OP_LOCK: 825 op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock); 826 replay_owner = op->u.lock.lk_stateowner; 827 break; 828 case OP_LOCKT: 829 op->status = nfsd4_lockt(rqstp, current_fh, &op->u.lockt); 830 break; 831 case OP_LOCKU: 832 op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku); 833 replay_owner = op->u.locku.lu_stateowner; 834 break; 835 case OP_LOOKUP: 836 op->status = nfsd4_lookup(rqstp, current_fh, &op->u.lookup); 837 break; 838 case OP_LOOKUPP: 839 op->status = nfsd4_lookupp(rqstp, current_fh); 840 break; 841 case OP_NVERIFY: 842 op->status = nfsd4_verify(rqstp, current_fh, &op->u.nverify); 843 if (op->status == nfserr_not_same) 844 op->status = nfs_ok; 845 break; 846 case OP_OPEN: 847 op->status = nfsd4_open(rqstp, current_fh, &op->u.open); 848 replay_owner = op->u.open.op_stateowner; 849 break; 850 case OP_OPEN_CONFIRM: 851 op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm); 852 replay_owner = op->u.open_confirm.oc_stateowner; 853 break; 854 case OP_OPEN_DOWNGRADE: 855 op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade); 856 replay_owner = op->u.open_downgrade.od_stateowner; 857 break; 858 case OP_PUTFH: 859 op->status = nfsd4_putfh(rqstp, current_fh, &op->u.putfh); 860 break; 861 case OP_PUTROOTFH: 862 op->status = nfsd4_putrootfh(rqstp, current_fh); 863 break; 864 case OP_READ: 865 op->status = nfsd4_read(rqstp, current_fh, &op->u.read); 866 break; 867 case OP_READDIR: 868 op->status = nfsd4_readdir(rqstp, current_fh, &op->u.readdir); 869 break; 870 case OP_READLINK: 871 op->status = nfsd4_readlink(rqstp, current_fh, &op->u.readlink); 872 break; 873 case OP_REMOVE: 874 op->status = nfsd4_remove(rqstp, current_fh, &op->u.remove); 875 break; 876 case OP_RENAME: 877 op->status = nfsd4_rename(rqstp, current_fh, save_fh, &op->u.rename); 878 break; 879 case OP_RENEW: 880 op->status = nfsd4_renew(&op->u.renew); 881 break; 882 case OP_RESTOREFH: 883 op->status = nfsd4_restorefh(current_fh, save_fh); 884 break; 885 case OP_SAVEFH: 886 op->status = nfsd4_savefh(current_fh, save_fh); 887 break; 888 case OP_SETATTR: 889 op->status = nfsd4_setattr(rqstp, current_fh, &op->u.setattr); 890 break; 891 case OP_SETCLIENTID: 892 op->status = nfsd4_setclientid(rqstp, &op->u.setclientid); 893 break; 894 case OP_SETCLIENTID_CONFIRM: 895 op->status = nfsd4_setclientid_confirm(rqstp, &op->u.setclientid_confirm); 896 break; 897 case OP_VERIFY: 898 op->status = nfsd4_verify(rqstp, current_fh, &op->u.verify); 899 if (op->status == nfserr_same) 900 op->status = nfs_ok; 901 break; 902 case OP_WRITE: 903 op->status = nfsd4_write(rqstp, current_fh, &op->u.write); 904 break; 905 case OP_RELEASE_LOCKOWNER: 906 op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner); 907 break; 908 default: 909 BUG_ON(op->status == nfs_ok); 910 break; 911 } 912 913 encode_op: 914 if (op->status == NFSERR_REPLAY_ME) { 915 op->replay = &replay_owner->so_replay; 916 nfsd4_encode_replay(resp, op); 917 status = op->status = op->replay->rp_status; 918 } else { 919 nfsd4_encode_operation(resp, op); 920 status = op->status; 921 } 922 if (replay_owner && (replay_owner != (void *)(-1))) { 923 nfs4_put_stateowner(replay_owner); 924 replay_owner = NULL; 925 } 926 } 927 928 out: 929 nfsd4_release_compoundargs(args); 930 if (current_fh) 931 fh_put(current_fh); 932 kfree(current_fh); 933 if (save_fh) 934 fh_put(save_fh); 935 kfree(save_fh); 936 return status; 937 } 938 939 #define nfs4svc_decode_voidargs NULL 940 #define nfs4svc_release_void NULL 941 #define nfsd4_voidres nfsd4_voidargs 942 #define nfs4svc_release_compound NULL 943 struct nfsd4_voidargs { int dummy; }; 944 945 #define PROC(name, argt, rest, relt, cache, respsize) \ 946 { (svc_procfunc) nfsd4_proc_##name, \ 947 (kxdrproc_t) nfs4svc_decode_##argt##args, \ 948 (kxdrproc_t) nfs4svc_encode_##rest##res, \ 949 (kxdrproc_t) nfs4svc_release_##relt, \ 950 sizeof(struct nfsd4_##argt##args), \ 951 sizeof(struct nfsd4_##rest##res), \ 952 0, \ 953 cache, \ 954 respsize, \ 955 } 956 957 /* 958 * TODO: At the present time, the NFSv4 server does not do XID caching 959 * of requests. Implementing XID caching would not be a serious problem, 960 * although it would require a mild change in interfaces since one 961 * doesn't know whether an NFSv4 request is idempotent until after the 962 * XDR decode. However, XID caching totally confuses pynfs (Peter 963 * Astrand's regression testsuite for NFSv4 servers), which reuses 964 * XID's liberally, so I've left it unimplemented until pynfs generates 965 * better XID's. 966 */ 967 static struct svc_procedure nfsd_procedures4[2] = { 968 PROC(null, void, void, void, RC_NOCACHE, 1), 969 PROC(compound, compound, compound, compound, RC_NOCACHE, NFSD_BUFSIZE) 970 }; 971 972 struct svc_version nfsd_version4 = { 973 .vs_vers = 4, 974 .vs_nproc = 2, 975 .vs_proc = nfsd_procedures4, 976 .vs_dispatch = nfsd_dispatch, 977 .vs_xdrsize = NFS4_SVC_XDRSIZE, 978 }; 979 980 /* 981 * Local variables: 982 * c-basic-offset: 8 983 * End: 984 */ 985