1 /* 2 * Process version 3 NFS requests. 3 * 4 * Copyright (C) 1996, 1997, 1998 Olaf Kirch <okir@monad.swb.de> 5 */ 6 7 #include <linux/fs.h> 8 #include <linux/ext2_fs.h> 9 #include <linux/magic.h> 10 11 #include "cache.h" 12 #include "xdr3.h" 13 #include "vfs.h" 14 15 #define NFSDDBG_FACILITY NFSDDBG_PROC 16 17 #define RETURN_STATUS(st) { resp->status = (st); return (st); } 18 19 static int nfs3_ftypes[] = { 20 0, /* NF3NON */ 21 S_IFREG, /* NF3REG */ 22 S_IFDIR, /* NF3DIR */ 23 S_IFBLK, /* NF3BLK */ 24 S_IFCHR, /* NF3CHR */ 25 S_IFLNK, /* NF3LNK */ 26 S_IFSOCK, /* NF3SOCK */ 27 S_IFIFO, /* NF3FIFO */ 28 }; 29 30 /* 31 * NULL call. 32 */ 33 static __be32 34 nfsd3_proc_null(struct svc_rqst *rqstp, void *argp, void *resp) 35 { 36 return nfs_ok; 37 } 38 39 /* 40 * Get a file's attributes 41 */ 42 static __be32 43 nfsd3_proc_getattr(struct svc_rqst *rqstp, struct nfsd_fhandle *argp, 44 struct nfsd3_attrstat *resp) 45 { 46 __be32 nfserr; 47 48 dprintk("nfsd: GETATTR(3) %s\n", 49 SVCFH_fmt(&argp->fh)); 50 51 fh_copy(&resp->fh, &argp->fh); 52 nfserr = fh_verify(rqstp, &resp->fh, 0, 53 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT); 54 if (nfserr) 55 RETURN_STATUS(nfserr); 56 57 nfserr = fh_getattr(&resp->fh, &resp->stat); 58 59 RETURN_STATUS(nfserr); 60 } 61 62 /* 63 * Set a file's attributes 64 */ 65 static __be32 66 nfsd3_proc_setattr(struct svc_rqst *rqstp, struct nfsd3_sattrargs *argp, 67 struct nfsd3_attrstat *resp) 68 { 69 __be32 nfserr; 70 71 dprintk("nfsd: SETATTR(3) %s\n", 72 SVCFH_fmt(&argp->fh)); 73 74 fh_copy(&resp->fh, &argp->fh); 75 nfserr = nfsd_setattr(rqstp, &resp->fh, &argp->attrs, 76 argp->check_guard, argp->guardtime); 77 RETURN_STATUS(nfserr); 78 } 79 80 /* 81 * Look up a path name component 82 */ 83 static __be32 84 nfsd3_proc_lookup(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, 85 struct nfsd3_diropres *resp) 86 { 87 __be32 nfserr; 88 89 dprintk("nfsd: LOOKUP(3) %s %.*s\n", 90 SVCFH_fmt(&argp->fh), 91 argp->len, 92 argp->name); 93 94 fh_copy(&resp->dirfh, &argp->fh); 95 fh_init(&resp->fh, NFS3_FHSIZE); 96 97 nfserr = nfsd_lookup(rqstp, &resp->dirfh, 98 argp->name, 99 argp->len, 100 &resp->fh); 101 RETURN_STATUS(nfserr); 102 } 103 104 /* 105 * Check file access 106 */ 107 static __be32 108 nfsd3_proc_access(struct svc_rqst *rqstp, struct nfsd3_accessargs *argp, 109 struct nfsd3_accessres *resp) 110 { 111 __be32 nfserr; 112 113 dprintk("nfsd: ACCESS(3) %s 0x%x\n", 114 SVCFH_fmt(&argp->fh), 115 argp->access); 116 117 fh_copy(&resp->fh, &argp->fh); 118 resp->access = argp->access; 119 nfserr = nfsd_access(rqstp, &resp->fh, &resp->access, NULL); 120 RETURN_STATUS(nfserr); 121 } 122 123 /* 124 * Read a symlink. 125 */ 126 static __be32 127 nfsd3_proc_readlink(struct svc_rqst *rqstp, struct nfsd3_readlinkargs *argp, 128 struct nfsd3_readlinkres *resp) 129 { 130 __be32 nfserr; 131 132 dprintk("nfsd: READLINK(3) %s\n", SVCFH_fmt(&argp->fh)); 133 134 /* Read the symlink. */ 135 fh_copy(&resp->fh, &argp->fh); 136 resp->len = NFS3_MAXPATHLEN; 137 nfserr = nfsd_readlink(rqstp, &resp->fh, argp->buffer, &resp->len); 138 RETURN_STATUS(nfserr); 139 } 140 141 /* 142 * Read a portion of a file. 143 */ 144 static __be32 145 nfsd3_proc_read(struct svc_rqst *rqstp, struct nfsd3_readargs *argp, 146 struct nfsd3_readres *resp) 147 { 148 __be32 nfserr; 149 u32 max_blocksize = svc_max_payload(rqstp); 150 151 dprintk("nfsd: READ(3) %s %lu bytes at %Lu\n", 152 SVCFH_fmt(&argp->fh), 153 (unsigned long) argp->count, 154 (unsigned long long) argp->offset); 155 156 /* Obtain buffer pointer for payload. 157 * 1 (status) + 22 (post_op_attr) + 1 (count) + 1 (eof) 158 * + 1 (xdr opaque byte count) = 26 159 */ 160 resp->count = min(argp->count, max_blocksize); 161 svc_reserve_auth(rqstp, ((1 + NFS3_POST_OP_ATTR_WORDS + 3)<<2) + resp->count +4); 162 163 fh_copy(&resp->fh, &argp->fh); 164 nfserr = nfsd_read(rqstp, &resp->fh, 165 argp->offset, 166 rqstp->rq_vec, argp->vlen, 167 &resp->count); 168 if (nfserr == 0) { 169 struct inode *inode = resp->fh.fh_dentry->d_inode; 170 171 resp->eof = (argp->offset + resp->count) >= inode->i_size; 172 } 173 174 RETURN_STATUS(nfserr); 175 } 176 177 /* 178 * Write data to a file 179 */ 180 static __be32 181 nfsd3_proc_write(struct svc_rqst *rqstp, struct nfsd3_writeargs *argp, 182 struct nfsd3_writeres *resp) 183 { 184 __be32 nfserr; 185 unsigned long cnt = argp->len; 186 187 dprintk("nfsd: WRITE(3) %s %d bytes at %Lu%s\n", 188 SVCFH_fmt(&argp->fh), 189 argp->len, 190 (unsigned long long) argp->offset, 191 argp->stable? " stable" : ""); 192 193 fh_copy(&resp->fh, &argp->fh); 194 resp->committed = argp->stable; 195 nfserr = nfsd_write(rqstp, &resp->fh, NULL, 196 argp->offset, 197 rqstp->rq_vec, argp->vlen, 198 &cnt, 199 &resp->committed); 200 resp->count = cnt; 201 RETURN_STATUS(nfserr); 202 } 203 204 /* 205 * With NFSv3, CREATE processing is a lot easier than with NFSv2. 206 * At least in theory; we'll see how it fares in practice when the 207 * first reports about SunOS compatibility problems start to pour in... 208 */ 209 static __be32 210 nfsd3_proc_create(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, 211 struct nfsd3_diropres *resp) 212 { 213 svc_fh *dirfhp, *newfhp = NULL; 214 struct iattr *attr; 215 __be32 nfserr; 216 217 dprintk("nfsd: CREATE(3) %s %.*s\n", 218 SVCFH_fmt(&argp->fh), 219 argp->len, 220 argp->name); 221 222 dirfhp = fh_copy(&resp->dirfh, &argp->fh); 223 newfhp = fh_init(&resp->fh, NFS3_FHSIZE); 224 attr = &argp->attrs; 225 226 /* Get the directory inode */ 227 nfserr = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_CREATE); 228 if (nfserr) 229 RETURN_STATUS(nfserr); 230 231 /* Unfudge the mode bits */ 232 attr->ia_mode &= ~S_IFMT; 233 if (!(attr->ia_valid & ATTR_MODE)) { 234 attr->ia_valid |= ATTR_MODE; 235 attr->ia_mode = S_IFREG; 236 } else { 237 attr->ia_mode = (attr->ia_mode & ~S_IFMT) | S_IFREG; 238 } 239 240 /* Now create the file and set attributes */ 241 nfserr = do_nfsd_create(rqstp, dirfhp, argp->name, argp->len, 242 attr, newfhp, 243 argp->createmode, (u32 *)argp->verf, NULL, NULL); 244 245 RETURN_STATUS(nfserr); 246 } 247 248 /* 249 * Make directory. This operation is not idempotent. 250 */ 251 static __be32 252 nfsd3_proc_mkdir(struct svc_rqst *rqstp, struct nfsd3_createargs *argp, 253 struct nfsd3_diropres *resp) 254 { 255 __be32 nfserr; 256 257 dprintk("nfsd: MKDIR(3) %s %.*s\n", 258 SVCFH_fmt(&argp->fh), 259 argp->len, 260 argp->name); 261 262 argp->attrs.ia_valid &= ~ATTR_SIZE; 263 fh_copy(&resp->dirfh, &argp->fh); 264 fh_init(&resp->fh, NFS3_FHSIZE); 265 nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, 266 &argp->attrs, S_IFDIR, 0, &resp->fh); 267 fh_unlock(&resp->dirfh); 268 RETURN_STATUS(nfserr); 269 } 270 271 static __be32 272 nfsd3_proc_symlink(struct svc_rqst *rqstp, struct nfsd3_symlinkargs *argp, 273 struct nfsd3_diropres *resp) 274 { 275 __be32 nfserr; 276 277 dprintk("nfsd: SYMLINK(3) %s %.*s -> %.*s\n", 278 SVCFH_fmt(&argp->ffh), 279 argp->flen, argp->fname, 280 argp->tlen, argp->tname); 281 282 fh_copy(&resp->dirfh, &argp->ffh); 283 fh_init(&resp->fh, NFS3_FHSIZE); 284 nfserr = nfsd_symlink(rqstp, &resp->dirfh, argp->fname, argp->flen, 285 argp->tname, &resp->fh); 286 RETURN_STATUS(nfserr); 287 } 288 289 /* 290 * Make socket/fifo/device. 291 */ 292 static __be32 293 nfsd3_proc_mknod(struct svc_rqst *rqstp, struct nfsd3_mknodargs *argp, 294 struct nfsd3_diropres *resp) 295 { 296 __be32 nfserr; 297 int type; 298 dev_t rdev = 0; 299 300 dprintk("nfsd: MKNOD(3) %s %.*s\n", 301 SVCFH_fmt(&argp->fh), 302 argp->len, 303 argp->name); 304 305 fh_copy(&resp->dirfh, &argp->fh); 306 fh_init(&resp->fh, NFS3_FHSIZE); 307 308 if (argp->ftype == 0 || argp->ftype >= NF3BAD) 309 RETURN_STATUS(nfserr_inval); 310 if (argp->ftype == NF3CHR || argp->ftype == NF3BLK) { 311 rdev = MKDEV(argp->major, argp->minor); 312 if (MAJOR(rdev) != argp->major || 313 MINOR(rdev) != argp->minor) 314 RETURN_STATUS(nfserr_inval); 315 } else 316 if (argp->ftype != NF3SOCK && argp->ftype != NF3FIFO) 317 RETURN_STATUS(nfserr_inval); 318 319 type = nfs3_ftypes[argp->ftype]; 320 nfserr = nfsd_create(rqstp, &resp->dirfh, argp->name, argp->len, 321 &argp->attrs, type, rdev, &resp->fh); 322 fh_unlock(&resp->dirfh); 323 RETURN_STATUS(nfserr); 324 } 325 326 /* 327 * Remove file/fifo/socket etc. 328 */ 329 static __be32 330 nfsd3_proc_remove(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, 331 struct nfsd3_attrstat *resp) 332 { 333 __be32 nfserr; 334 335 dprintk("nfsd: REMOVE(3) %s %.*s\n", 336 SVCFH_fmt(&argp->fh), 337 argp->len, 338 argp->name); 339 340 /* Unlink. -S_IFDIR means file must not be a directory */ 341 fh_copy(&resp->fh, &argp->fh); 342 nfserr = nfsd_unlink(rqstp, &resp->fh, -S_IFDIR, argp->name, argp->len); 343 fh_unlock(&resp->fh); 344 RETURN_STATUS(nfserr); 345 } 346 347 /* 348 * Remove a directory 349 */ 350 static __be32 351 nfsd3_proc_rmdir(struct svc_rqst *rqstp, struct nfsd3_diropargs *argp, 352 struct nfsd3_attrstat *resp) 353 { 354 __be32 nfserr; 355 356 dprintk("nfsd: RMDIR(3) %s %.*s\n", 357 SVCFH_fmt(&argp->fh), 358 argp->len, 359 argp->name); 360 361 fh_copy(&resp->fh, &argp->fh); 362 nfserr = nfsd_unlink(rqstp, &resp->fh, S_IFDIR, argp->name, argp->len); 363 fh_unlock(&resp->fh); 364 RETURN_STATUS(nfserr); 365 } 366 367 static __be32 368 nfsd3_proc_rename(struct svc_rqst *rqstp, struct nfsd3_renameargs *argp, 369 struct nfsd3_renameres *resp) 370 { 371 __be32 nfserr; 372 373 dprintk("nfsd: RENAME(3) %s %.*s ->\n", 374 SVCFH_fmt(&argp->ffh), 375 argp->flen, 376 argp->fname); 377 dprintk("nfsd: -> %s %.*s\n", 378 SVCFH_fmt(&argp->tfh), 379 argp->tlen, 380 argp->tname); 381 382 fh_copy(&resp->ffh, &argp->ffh); 383 fh_copy(&resp->tfh, &argp->tfh); 384 nfserr = nfsd_rename(rqstp, &resp->ffh, argp->fname, argp->flen, 385 &resp->tfh, argp->tname, argp->tlen); 386 RETURN_STATUS(nfserr); 387 } 388 389 static __be32 390 nfsd3_proc_link(struct svc_rqst *rqstp, struct nfsd3_linkargs *argp, 391 struct nfsd3_linkres *resp) 392 { 393 __be32 nfserr; 394 395 dprintk("nfsd: LINK(3) %s ->\n", 396 SVCFH_fmt(&argp->ffh)); 397 dprintk("nfsd: -> %s %.*s\n", 398 SVCFH_fmt(&argp->tfh), 399 argp->tlen, 400 argp->tname); 401 402 fh_copy(&resp->fh, &argp->ffh); 403 fh_copy(&resp->tfh, &argp->tfh); 404 nfserr = nfsd_link(rqstp, &resp->tfh, argp->tname, argp->tlen, 405 &resp->fh); 406 RETURN_STATUS(nfserr); 407 } 408 409 /* 410 * Read a portion of a directory. 411 */ 412 static __be32 413 nfsd3_proc_readdir(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp, 414 struct nfsd3_readdirres *resp) 415 { 416 __be32 nfserr; 417 int count; 418 419 dprintk("nfsd: READDIR(3) %s %d bytes at %d\n", 420 SVCFH_fmt(&argp->fh), 421 argp->count, (u32) argp->cookie); 422 423 /* Make sure we've room for the NULL ptr & eof flag, and shrink to 424 * client read size */ 425 count = (argp->count >> 2) - 2; 426 427 /* Read directory and encode entries on the fly */ 428 fh_copy(&resp->fh, &argp->fh); 429 430 resp->buflen = count; 431 resp->common.err = nfs_ok; 432 resp->buffer = argp->buffer; 433 resp->rqstp = rqstp; 434 nfserr = nfsd_readdir(rqstp, &resp->fh, (loff_t*) &argp->cookie, 435 &resp->common, nfs3svc_encode_entry); 436 memcpy(resp->verf, argp->verf, 8); 437 resp->count = resp->buffer - argp->buffer; 438 if (resp->offset) 439 xdr_encode_hyper(resp->offset, argp->cookie); 440 441 RETURN_STATUS(nfserr); 442 } 443 444 /* 445 * Read a portion of a directory, including file handles and attrs. 446 * For now, we choose to ignore the dircount parameter. 447 */ 448 static __be32 449 nfsd3_proc_readdirplus(struct svc_rqst *rqstp, struct nfsd3_readdirargs *argp, 450 struct nfsd3_readdirres *resp) 451 { 452 __be32 nfserr; 453 int count = 0; 454 loff_t offset; 455 struct page **p; 456 caddr_t page_addr = NULL; 457 458 dprintk("nfsd: READDIR+(3) %s %d bytes at %d\n", 459 SVCFH_fmt(&argp->fh), 460 argp->count, (u32) argp->cookie); 461 462 /* Convert byte count to number of words (i.e. >> 2), 463 * and reserve room for the NULL ptr & eof flag (-2 words) */ 464 resp->count = (argp->count >> 2) - 2; 465 466 /* Read directory and encode entries on the fly */ 467 fh_copy(&resp->fh, &argp->fh); 468 469 resp->common.err = nfs_ok; 470 resp->buffer = argp->buffer; 471 resp->buflen = resp->count; 472 resp->rqstp = rqstp; 473 offset = argp->cookie; 474 nfserr = nfsd_readdir(rqstp, &resp->fh, 475 &offset, 476 &resp->common, 477 nfs3svc_encode_entry_plus); 478 memcpy(resp->verf, argp->verf, 8); 479 for (p = rqstp->rq_respages + 1; p < rqstp->rq_next_page; p++) { 480 page_addr = page_address(*p); 481 482 if (((caddr_t)resp->buffer >= page_addr) && 483 ((caddr_t)resp->buffer < page_addr + PAGE_SIZE)) { 484 count += (caddr_t)resp->buffer - page_addr; 485 break; 486 } 487 count += PAGE_SIZE; 488 } 489 resp->count = count >> 2; 490 if (resp->offset) { 491 if (unlikely(resp->offset1)) { 492 /* we ended up with offset on a page boundary */ 493 *resp->offset = htonl(offset >> 32); 494 *resp->offset1 = htonl(offset & 0xffffffff); 495 resp->offset1 = NULL; 496 } else { 497 xdr_encode_hyper(resp->offset, offset); 498 } 499 } 500 501 RETURN_STATUS(nfserr); 502 } 503 504 /* 505 * Get file system stats 506 */ 507 static __be32 508 nfsd3_proc_fsstat(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, 509 struct nfsd3_fsstatres *resp) 510 { 511 __be32 nfserr; 512 513 dprintk("nfsd: FSSTAT(3) %s\n", 514 SVCFH_fmt(&argp->fh)); 515 516 nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 0); 517 fh_put(&argp->fh); 518 RETURN_STATUS(nfserr); 519 } 520 521 /* 522 * Get file system info 523 */ 524 static __be32 525 nfsd3_proc_fsinfo(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, 526 struct nfsd3_fsinfores *resp) 527 { 528 __be32 nfserr; 529 u32 max_blocksize = svc_max_payload(rqstp); 530 531 dprintk("nfsd: FSINFO(3) %s\n", 532 SVCFH_fmt(&argp->fh)); 533 534 resp->f_rtmax = max_blocksize; 535 resp->f_rtpref = max_blocksize; 536 resp->f_rtmult = PAGE_SIZE; 537 resp->f_wtmax = max_blocksize; 538 resp->f_wtpref = max_blocksize; 539 resp->f_wtmult = PAGE_SIZE; 540 resp->f_dtpref = PAGE_SIZE; 541 resp->f_maxfilesize = ~(u32) 0; 542 resp->f_properties = NFS3_FSF_DEFAULT; 543 544 nfserr = fh_verify(rqstp, &argp->fh, 0, 545 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT); 546 547 /* Check special features of the file system. May request 548 * different read/write sizes for file systems known to have 549 * problems with large blocks */ 550 if (nfserr == 0) { 551 struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb; 552 553 /* Note that we don't care for remote fs's here */ 554 if (sb->s_magic == MSDOS_SUPER_MAGIC) { 555 resp->f_properties = NFS3_FSF_BILLYBOY; 556 } 557 resp->f_maxfilesize = sb->s_maxbytes; 558 } 559 560 fh_put(&argp->fh); 561 RETURN_STATUS(nfserr); 562 } 563 564 /* 565 * Get pathconf info for the specified file 566 */ 567 static __be32 568 nfsd3_proc_pathconf(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, 569 struct nfsd3_pathconfres *resp) 570 { 571 __be32 nfserr; 572 573 dprintk("nfsd: PATHCONF(3) %s\n", 574 SVCFH_fmt(&argp->fh)); 575 576 /* Set default pathconf */ 577 resp->p_link_max = 255; /* at least */ 578 resp->p_name_max = 255; /* at least */ 579 resp->p_no_trunc = 0; 580 resp->p_chown_restricted = 1; 581 resp->p_case_insensitive = 0; 582 resp->p_case_preserving = 1; 583 584 nfserr = fh_verify(rqstp, &argp->fh, 0, NFSD_MAY_NOP); 585 586 if (nfserr == 0) { 587 struct super_block *sb = argp->fh.fh_dentry->d_inode->i_sb; 588 589 /* Note that we don't care for remote fs's here */ 590 switch (sb->s_magic) { 591 case EXT2_SUPER_MAGIC: 592 resp->p_link_max = EXT2_LINK_MAX; 593 resp->p_name_max = EXT2_NAME_LEN; 594 break; 595 case MSDOS_SUPER_MAGIC: 596 resp->p_case_insensitive = 1; 597 resp->p_case_preserving = 0; 598 break; 599 } 600 } 601 602 fh_put(&argp->fh); 603 RETURN_STATUS(nfserr); 604 } 605 606 607 /* 608 * Commit a file (range) to stable storage. 609 */ 610 static __be32 611 nfsd3_proc_commit(struct svc_rqst * rqstp, struct nfsd3_commitargs *argp, 612 struct nfsd3_commitres *resp) 613 { 614 __be32 nfserr; 615 616 dprintk("nfsd: COMMIT(3) %s %u@%Lu\n", 617 SVCFH_fmt(&argp->fh), 618 argp->count, 619 (unsigned long long) argp->offset); 620 621 if (argp->offset > NFS_OFFSET_MAX) 622 RETURN_STATUS(nfserr_inval); 623 624 fh_copy(&resp->fh, &argp->fh); 625 nfserr = nfsd_commit(rqstp, &resp->fh, argp->offset, argp->count); 626 627 RETURN_STATUS(nfserr); 628 } 629 630 631 /* 632 * NFSv3 Server procedures. 633 * Only the results of non-idempotent operations are cached. 634 */ 635 #define nfs3svc_decode_fhandleargs nfs3svc_decode_fhandle 636 #define nfs3svc_encode_attrstatres nfs3svc_encode_attrstat 637 #define nfs3svc_encode_wccstatres nfs3svc_encode_wccstat 638 #define nfsd3_mkdirargs nfsd3_createargs 639 #define nfsd3_readdirplusargs nfsd3_readdirargs 640 #define nfsd3_fhandleargs nfsd_fhandle 641 #define nfsd3_fhandleres nfsd3_attrstat 642 #define nfsd3_attrstatres nfsd3_attrstat 643 #define nfsd3_wccstatres nfsd3_attrstat 644 #define nfsd3_createres nfsd3_diropres 645 #define nfsd3_voidres nfsd3_voidargs 646 struct nfsd3_voidargs { int dummy; }; 647 648 #define PROC(name, argt, rest, relt, cache, respsize) \ 649 { (svc_procfunc) nfsd3_proc_##name, \ 650 (kxdrproc_t) nfs3svc_decode_##argt##args, \ 651 (kxdrproc_t) nfs3svc_encode_##rest##res, \ 652 (kxdrproc_t) nfs3svc_release_##relt, \ 653 sizeof(struct nfsd3_##argt##args), \ 654 sizeof(struct nfsd3_##rest##res), \ 655 0, \ 656 cache, \ 657 respsize, \ 658 } 659 660 #define ST 1 /* status*/ 661 #define FH 17 /* filehandle with length */ 662 #define AT 21 /* attributes */ 663 #define pAT (1+AT) /* post attributes - conditional */ 664 #define WC (7+pAT) /* WCC attributes */ 665 666 static struct svc_procedure nfsd_procedures3[22] = { 667 [NFS3PROC_NULL] = { 668 .pc_func = (svc_procfunc) nfsd3_proc_null, 669 .pc_encode = (kxdrproc_t) nfs3svc_encode_voidres, 670 .pc_argsize = sizeof(struct nfsd3_voidargs), 671 .pc_ressize = sizeof(struct nfsd3_voidres), 672 .pc_cachetype = RC_NOCACHE, 673 .pc_xdrressize = ST, 674 }, 675 [NFS3PROC_GETATTR] = { 676 .pc_func = (svc_procfunc) nfsd3_proc_getattr, 677 .pc_decode = (kxdrproc_t) nfs3svc_decode_fhandleargs, 678 .pc_encode = (kxdrproc_t) nfs3svc_encode_attrstatres, 679 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle, 680 .pc_argsize = sizeof(struct nfsd3_fhandleargs), 681 .pc_ressize = sizeof(struct nfsd3_attrstatres), 682 .pc_cachetype = RC_NOCACHE, 683 .pc_xdrressize = ST+AT, 684 }, 685 [NFS3PROC_SETATTR] = { 686 .pc_func = (svc_procfunc) nfsd3_proc_setattr, 687 .pc_decode = (kxdrproc_t) nfs3svc_decode_sattrargs, 688 .pc_encode = (kxdrproc_t) nfs3svc_encode_wccstatres, 689 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle, 690 .pc_argsize = sizeof(struct nfsd3_sattrargs), 691 .pc_ressize = sizeof(struct nfsd3_wccstatres), 692 .pc_cachetype = RC_REPLBUFF, 693 .pc_xdrressize = ST+WC, 694 }, 695 [NFS3PROC_LOOKUP] = { 696 .pc_func = (svc_procfunc) nfsd3_proc_lookup, 697 .pc_decode = (kxdrproc_t) nfs3svc_decode_diropargs, 698 .pc_encode = (kxdrproc_t) nfs3svc_encode_diropres, 699 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2, 700 .pc_argsize = sizeof(struct nfsd3_diropargs), 701 .pc_ressize = sizeof(struct nfsd3_diropres), 702 .pc_cachetype = RC_NOCACHE, 703 .pc_xdrressize = ST+FH+pAT+pAT, 704 }, 705 [NFS3PROC_ACCESS] = { 706 .pc_func = (svc_procfunc) nfsd3_proc_access, 707 .pc_decode = (kxdrproc_t) nfs3svc_decode_accessargs, 708 .pc_encode = (kxdrproc_t) nfs3svc_encode_accessres, 709 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle, 710 .pc_argsize = sizeof(struct nfsd3_accessargs), 711 .pc_ressize = sizeof(struct nfsd3_accessres), 712 .pc_cachetype = RC_NOCACHE, 713 .pc_xdrressize = ST+pAT+1, 714 }, 715 [NFS3PROC_READLINK] = { 716 .pc_func = (svc_procfunc) nfsd3_proc_readlink, 717 .pc_decode = (kxdrproc_t) nfs3svc_decode_readlinkargs, 718 .pc_encode = (kxdrproc_t) nfs3svc_encode_readlinkres, 719 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle, 720 .pc_argsize = sizeof(struct nfsd3_readlinkargs), 721 .pc_ressize = sizeof(struct nfsd3_readlinkres), 722 .pc_cachetype = RC_NOCACHE, 723 .pc_xdrressize = ST+pAT+1+NFS3_MAXPATHLEN/4, 724 }, 725 [NFS3PROC_READ] = { 726 .pc_func = (svc_procfunc) nfsd3_proc_read, 727 .pc_decode = (kxdrproc_t) nfs3svc_decode_readargs, 728 .pc_encode = (kxdrproc_t) nfs3svc_encode_readres, 729 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle, 730 .pc_argsize = sizeof(struct nfsd3_readargs), 731 .pc_ressize = sizeof(struct nfsd3_readres), 732 .pc_cachetype = RC_NOCACHE, 733 .pc_xdrressize = ST+pAT+4+NFSSVC_MAXBLKSIZE/4, 734 }, 735 [NFS3PROC_WRITE] = { 736 .pc_func = (svc_procfunc) nfsd3_proc_write, 737 .pc_decode = (kxdrproc_t) nfs3svc_decode_writeargs, 738 .pc_encode = (kxdrproc_t) nfs3svc_encode_writeres, 739 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle, 740 .pc_argsize = sizeof(struct nfsd3_writeargs), 741 .pc_ressize = sizeof(struct nfsd3_writeres), 742 .pc_cachetype = RC_REPLBUFF, 743 .pc_xdrressize = ST+WC+4, 744 }, 745 [NFS3PROC_CREATE] = { 746 .pc_func = (svc_procfunc) nfsd3_proc_create, 747 .pc_decode = (kxdrproc_t) nfs3svc_decode_createargs, 748 .pc_encode = (kxdrproc_t) nfs3svc_encode_createres, 749 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2, 750 .pc_argsize = sizeof(struct nfsd3_createargs), 751 .pc_ressize = sizeof(struct nfsd3_createres), 752 .pc_cachetype = RC_REPLBUFF, 753 .pc_xdrressize = ST+(1+FH+pAT)+WC, 754 }, 755 [NFS3PROC_MKDIR] = { 756 .pc_func = (svc_procfunc) nfsd3_proc_mkdir, 757 .pc_decode = (kxdrproc_t) nfs3svc_decode_mkdirargs, 758 .pc_encode = (kxdrproc_t) nfs3svc_encode_createres, 759 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2, 760 .pc_argsize = sizeof(struct nfsd3_mkdirargs), 761 .pc_ressize = sizeof(struct nfsd3_createres), 762 .pc_cachetype = RC_REPLBUFF, 763 .pc_xdrressize = ST+(1+FH+pAT)+WC, 764 }, 765 [NFS3PROC_SYMLINK] = { 766 .pc_func = (svc_procfunc) nfsd3_proc_symlink, 767 .pc_decode = (kxdrproc_t) nfs3svc_decode_symlinkargs, 768 .pc_encode = (kxdrproc_t) nfs3svc_encode_createres, 769 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2, 770 .pc_argsize = sizeof(struct nfsd3_symlinkargs), 771 .pc_ressize = sizeof(struct nfsd3_createres), 772 .pc_cachetype = RC_REPLBUFF, 773 .pc_xdrressize = ST+(1+FH+pAT)+WC, 774 }, 775 [NFS3PROC_MKNOD] = { 776 .pc_func = (svc_procfunc) nfsd3_proc_mknod, 777 .pc_decode = (kxdrproc_t) nfs3svc_decode_mknodargs, 778 .pc_encode = (kxdrproc_t) nfs3svc_encode_createres, 779 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2, 780 .pc_argsize = sizeof(struct nfsd3_mknodargs), 781 .pc_ressize = sizeof(struct nfsd3_createres), 782 .pc_cachetype = RC_REPLBUFF, 783 .pc_xdrressize = ST+(1+FH+pAT)+WC, 784 }, 785 [NFS3PROC_REMOVE] = { 786 .pc_func = (svc_procfunc) nfsd3_proc_remove, 787 .pc_decode = (kxdrproc_t) nfs3svc_decode_diropargs, 788 .pc_encode = (kxdrproc_t) nfs3svc_encode_wccstatres, 789 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle, 790 .pc_argsize = sizeof(struct nfsd3_diropargs), 791 .pc_ressize = sizeof(struct nfsd3_wccstatres), 792 .pc_cachetype = RC_REPLBUFF, 793 .pc_xdrressize = ST+WC, 794 }, 795 [NFS3PROC_RMDIR] = { 796 .pc_func = (svc_procfunc) nfsd3_proc_rmdir, 797 .pc_decode = (kxdrproc_t) nfs3svc_decode_diropargs, 798 .pc_encode = (kxdrproc_t) nfs3svc_encode_wccstatres, 799 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle, 800 .pc_argsize = sizeof(struct nfsd3_diropargs), 801 .pc_ressize = sizeof(struct nfsd3_wccstatres), 802 .pc_cachetype = RC_REPLBUFF, 803 .pc_xdrressize = ST+WC, 804 }, 805 [NFS3PROC_RENAME] = { 806 .pc_func = (svc_procfunc) nfsd3_proc_rename, 807 .pc_decode = (kxdrproc_t) nfs3svc_decode_renameargs, 808 .pc_encode = (kxdrproc_t) nfs3svc_encode_renameres, 809 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2, 810 .pc_argsize = sizeof(struct nfsd3_renameargs), 811 .pc_ressize = sizeof(struct nfsd3_renameres), 812 .pc_cachetype = RC_REPLBUFF, 813 .pc_xdrressize = ST+WC+WC, 814 }, 815 [NFS3PROC_LINK] = { 816 .pc_func = (svc_procfunc) nfsd3_proc_link, 817 .pc_decode = (kxdrproc_t) nfs3svc_decode_linkargs, 818 .pc_encode = (kxdrproc_t) nfs3svc_encode_linkres, 819 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle2, 820 .pc_argsize = sizeof(struct nfsd3_linkargs), 821 .pc_ressize = sizeof(struct nfsd3_linkres), 822 .pc_cachetype = RC_REPLBUFF, 823 .pc_xdrressize = ST+pAT+WC, 824 }, 825 [NFS3PROC_READDIR] = { 826 .pc_func = (svc_procfunc) nfsd3_proc_readdir, 827 .pc_decode = (kxdrproc_t) nfs3svc_decode_readdirargs, 828 .pc_encode = (kxdrproc_t) nfs3svc_encode_readdirres, 829 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle, 830 .pc_argsize = sizeof(struct nfsd3_readdirargs), 831 .pc_ressize = sizeof(struct nfsd3_readdirres), 832 .pc_cachetype = RC_NOCACHE, 833 }, 834 [NFS3PROC_READDIRPLUS] = { 835 .pc_func = (svc_procfunc) nfsd3_proc_readdirplus, 836 .pc_decode = (kxdrproc_t) nfs3svc_decode_readdirplusargs, 837 .pc_encode = (kxdrproc_t) nfs3svc_encode_readdirres, 838 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle, 839 .pc_argsize = sizeof(struct nfsd3_readdirplusargs), 840 .pc_ressize = sizeof(struct nfsd3_readdirres), 841 .pc_cachetype = RC_NOCACHE, 842 }, 843 [NFS3PROC_FSSTAT] = { 844 .pc_func = (svc_procfunc) nfsd3_proc_fsstat, 845 .pc_decode = (kxdrproc_t) nfs3svc_decode_fhandleargs, 846 .pc_encode = (kxdrproc_t) nfs3svc_encode_fsstatres, 847 .pc_argsize = sizeof(struct nfsd3_fhandleargs), 848 .pc_ressize = sizeof(struct nfsd3_fsstatres), 849 .pc_cachetype = RC_NOCACHE, 850 .pc_xdrressize = ST+pAT+2*6+1, 851 }, 852 [NFS3PROC_FSINFO] = { 853 .pc_func = (svc_procfunc) nfsd3_proc_fsinfo, 854 .pc_decode = (kxdrproc_t) nfs3svc_decode_fhandleargs, 855 .pc_encode = (kxdrproc_t) nfs3svc_encode_fsinfores, 856 .pc_argsize = sizeof(struct nfsd3_fhandleargs), 857 .pc_ressize = sizeof(struct nfsd3_fsinfores), 858 .pc_cachetype = RC_NOCACHE, 859 .pc_xdrressize = ST+pAT+12, 860 }, 861 [NFS3PROC_PATHCONF] = { 862 .pc_func = (svc_procfunc) nfsd3_proc_pathconf, 863 .pc_decode = (kxdrproc_t) nfs3svc_decode_fhandleargs, 864 .pc_encode = (kxdrproc_t) nfs3svc_encode_pathconfres, 865 .pc_argsize = sizeof(struct nfsd3_fhandleargs), 866 .pc_ressize = sizeof(struct nfsd3_pathconfres), 867 .pc_cachetype = RC_NOCACHE, 868 .pc_xdrressize = ST+pAT+6, 869 }, 870 [NFS3PROC_COMMIT] = { 871 .pc_func = (svc_procfunc) nfsd3_proc_commit, 872 .pc_decode = (kxdrproc_t) nfs3svc_decode_commitargs, 873 .pc_encode = (kxdrproc_t) nfs3svc_encode_commitres, 874 .pc_release = (kxdrproc_t) nfs3svc_release_fhandle, 875 .pc_argsize = sizeof(struct nfsd3_commitargs), 876 .pc_ressize = sizeof(struct nfsd3_commitres), 877 .pc_cachetype = RC_NOCACHE, 878 .pc_xdrressize = ST+WC+2, 879 }, 880 }; 881 882 struct svc_version nfsd_version3 = { 883 .vs_vers = 3, 884 .vs_nproc = 22, 885 .vs_proc = nfsd_procedures3, 886 .vs_dispatch = nfsd_dispatch, 887 .vs_xdrsize = NFS3_SVC_XDRSIZE, 888 }; 889