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