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