1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Process version 2 NFS requests. 4 * 5 * Copyright (C) 1995-1997 Olaf Kirch <okir@monad.swb.de> 6 */ 7 8 #include <linux/namei.h> 9 10 #include "cache.h" 11 #include "xdr.h" 12 #include "vfs.h" 13 14 #define NFSDDBG_FACILITY NFSDDBG_PROC 15 16 static __be32 17 nfsd_proc_null(struct svc_rqst *rqstp) 18 { 19 return rpc_success; 20 } 21 22 /* 23 * Get a file's attributes 24 * N.B. After this call resp->fh needs an fh_put 25 */ 26 static __be32 27 nfsd_proc_getattr(struct svc_rqst *rqstp) 28 { 29 struct nfsd_fhandle *argp = rqstp->rq_argp; 30 struct nfsd_attrstat *resp = rqstp->rq_resp; 31 32 dprintk("nfsd: GETATTR %s\n", SVCFH_fmt(&argp->fh)); 33 34 fh_copy(&resp->fh, &argp->fh); 35 resp->status = fh_verify(rqstp, &resp->fh, 0, 36 NFSD_MAY_NOP | NFSD_MAY_BYPASS_GSS_ON_ROOT); 37 if (resp->status != nfs_ok) 38 goto out; 39 resp->status = fh_getattr(&resp->fh, &resp->stat); 40 out: 41 return rpc_success; 42 } 43 44 /* 45 * Set a file's attributes 46 * N.B. After this call resp->fh needs an fh_put 47 */ 48 static __be32 49 nfsd_proc_setattr(struct svc_rqst *rqstp) 50 { 51 struct nfsd_sattrargs *argp = rqstp->rq_argp; 52 struct nfsd_attrstat *resp = rqstp->rq_resp; 53 struct iattr *iap = &argp->attrs; 54 struct svc_fh *fhp; 55 56 dprintk("nfsd: SETATTR %s, valid=%x, size=%ld\n", 57 SVCFH_fmt(&argp->fh), 58 argp->attrs.ia_valid, (long) argp->attrs.ia_size); 59 60 fhp = fh_copy(&resp->fh, &argp->fh); 61 62 /* 63 * NFSv2 does not differentiate between "set-[ac]time-to-now" 64 * which only requires access, and "set-[ac]time-to-X" which 65 * requires ownership. 66 * So if it looks like it might be "set both to the same time which 67 * is close to now", and if setattr_prepare fails, then we 68 * convert to "set to now" instead of "set to explicit time" 69 * 70 * We only call setattr_prepare as the last test as technically 71 * it is not an interface that we should be using. 72 */ 73 #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET) 74 #define MAX_TOUCH_TIME_ERROR (30*60) 75 if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET && 76 iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec) { 77 /* 78 * Looks probable. 79 * 80 * Now just make sure time is in the right ballpark. 81 * Solaris, at least, doesn't seem to care what the time 82 * request is. We require it be within 30 minutes of now. 83 */ 84 time64_t delta = iap->ia_atime.tv_sec - ktime_get_real_seconds(); 85 86 resp->status = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP); 87 if (resp->status != nfs_ok) 88 goto out; 89 90 if (delta < 0) 91 delta = -delta; 92 if (delta < MAX_TOUCH_TIME_ERROR && 93 setattr_prepare(fhp->fh_dentry, iap) != 0) { 94 /* 95 * Turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME. 96 * This will cause notify_change to set these times 97 * to "now" 98 */ 99 iap->ia_valid &= ~BOTH_TIME_SET; 100 } 101 } 102 103 resp->status = nfsd_setattr(rqstp, fhp, iap, 0, (time64_t)0); 104 if (resp->status != nfs_ok) 105 goto out; 106 107 resp->status = fh_getattr(&resp->fh, &resp->stat); 108 out: 109 return rpc_success; 110 } 111 112 /* Obsolete, replaced by MNTPROC_MNT. */ 113 static __be32 114 nfsd_proc_root(struct svc_rqst *rqstp) 115 { 116 return rpc_success; 117 } 118 119 /* 120 * Look up a path name component 121 * Note: the dentry in the resp->fh may be negative if the file 122 * doesn't exist yet. 123 * N.B. After this call resp->fh needs an fh_put 124 */ 125 static __be32 126 nfsd_proc_lookup(struct svc_rqst *rqstp) 127 { 128 struct nfsd_diropargs *argp = rqstp->rq_argp; 129 struct nfsd_diropres *resp = rqstp->rq_resp; 130 131 dprintk("nfsd: LOOKUP %s %.*s\n", 132 SVCFH_fmt(&argp->fh), argp->len, argp->name); 133 134 fh_init(&resp->fh, NFS_FHSIZE); 135 resp->status = nfsd_lookup(rqstp, &argp->fh, argp->name, argp->len, 136 &resp->fh); 137 fh_put(&argp->fh); 138 if (resp->status != nfs_ok) 139 goto out; 140 141 resp->status = fh_getattr(&resp->fh, &resp->stat); 142 out: 143 return rpc_success; 144 } 145 146 /* 147 * Read a symlink. 148 */ 149 static __be32 150 nfsd_proc_readlink(struct svc_rqst *rqstp) 151 { 152 struct nfsd_readlinkargs *argp = rqstp->rq_argp; 153 struct nfsd_readlinkres *resp = rqstp->rq_resp; 154 155 dprintk("nfsd: READLINK %s\n", SVCFH_fmt(&argp->fh)); 156 157 /* Read the symlink. */ 158 resp->len = NFS_MAXPATHLEN; 159 resp->status = nfsd_readlink(rqstp, &argp->fh, argp->buffer, &resp->len); 160 161 fh_put(&argp->fh); 162 return rpc_success; 163 } 164 165 /* 166 * Read a portion of a file. 167 * N.B. After this call resp->fh needs an fh_put 168 */ 169 static __be32 170 nfsd_proc_read(struct svc_rqst *rqstp) 171 { 172 struct nfsd_readargs *argp = rqstp->rq_argp; 173 struct nfsd_readres *resp = rqstp->rq_resp; 174 unsigned int len; 175 u32 eof; 176 int v; 177 178 dprintk("nfsd: READ %s %d bytes at %d\n", 179 SVCFH_fmt(&argp->fh), 180 argp->count, argp->offset); 181 182 argp->count = min_t(u32, argp->count, NFSSVC_MAXBLKSIZE_V2); 183 184 v = 0; 185 len = argp->count; 186 while (len > 0) { 187 struct page *page = *(rqstp->rq_next_page++); 188 189 rqstp->rq_vec[v].iov_base = page_address(page); 190 rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE); 191 len -= rqstp->rq_vec[v].iov_len; 192 v++; 193 } 194 195 /* Obtain buffer pointer for payload. 19 is 1 word for 196 * status, 17 words for fattr, and 1 word for the byte count. 197 */ 198 svc_reserve_auth(rqstp, (19<<2) + argp->count + 4); 199 200 resp->count = argp->count; 201 fh_copy(&resp->fh, &argp->fh); 202 resp->status = nfsd_read(rqstp, &resp->fh, argp->offset, 203 rqstp->rq_vec, v, &resp->count, &eof); 204 if (resp->status == nfs_ok) 205 resp->status = fh_getattr(&resp->fh, &resp->stat); 206 else if (resp->status == nfserr_jukebox) 207 return rpc_drop_reply; 208 return rpc_success; 209 } 210 211 /* Reserved */ 212 static __be32 213 nfsd_proc_writecache(struct svc_rqst *rqstp) 214 { 215 return rpc_success; 216 } 217 218 /* 219 * Write data to a file 220 * N.B. After this call resp->fh needs an fh_put 221 */ 222 static __be32 223 nfsd_proc_write(struct svc_rqst *rqstp) 224 { 225 struct nfsd_writeargs *argp = rqstp->rq_argp; 226 struct nfsd_attrstat *resp = rqstp->rq_resp; 227 unsigned long cnt = argp->len; 228 unsigned int nvecs; 229 230 dprintk("nfsd: WRITE %s %d bytes at %d\n", 231 SVCFH_fmt(&argp->fh), 232 argp->len, argp->offset); 233 234 nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages, 235 &argp->first, cnt); 236 if (!nvecs) { 237 resp->status = nfserr_io; 238 goto out; 239 } 240 241 resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh), 242 argp->offset, rqstp->rq_vec, nvecs, 243 &cnt, NFS_DATA_SYNC, NULL); 244 if (resp->status == nfs_ok) 245 resp->status = fh_getattr(&resp->fh, &resp->stat); 246 else if (resp->status == nfserr_jukebox) 247 return rpc_drop_reply; 248 out: 249 return rpc_success; 250 } 251 252 /* 253 * CREATE processing is complicated. The keyword here is `overloaded.' 254 * The parent directory is kept locked between the check for existence 255 * and the actual create() call in compliance with VFS protocols. 256 * N.B. After this call _both_ argp->fh and resp->fh need an fh_put 257 */ 258 static __be32 259 nfsd_proc_create(struct svc_rqst *rqstp) 260 { 261 struct nfsd_createargs *argp = rqstp->rq_argp; 262 struct nfsd_diropres *resp = rqstp->rq_resp; 263 svc_fh *dirfhp = &argp->fh; 264 svc_fh *newfhp = &resp->fh; 265 struct iattr *attr = &argp->attrs; 266 struct inode *inode; 267 struct dentry *dchild; 268 int type, mode; 269 int hosterr; 270 dev_t rdev = 0, wanted = new_decode_dev(attr->ia_size); 271 272 dprintk("nfsd: CREATE %s %.*s\n", 273 SVCFH_fmt(dirfhp), argp->len, argp->name); 274 275 /* First verify the parent file handle */ 276 resp->status = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC); 277 if (resp->status != nfs_ok) 278 goto done; /* must fh_put dirfhp even on error */ 279 280 /* Check for NFSD_MAY_WRITE in nfsd_create if necessary */ 281 282 resp->status = nfserr_exist; 283 if (isdotent(argp->name, argp->len)) 284 goto done; 285 hosterr = fh_want_write(dirfhp); 286 if (hosterr) { 287 resp->status = nfserrno(hosterr); 288 goto done; 289 } 290 291 fh_lock_nested(dirfhp, I_MUTEX_PARENT); 292 dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len); 293 if (IS_ERR(dchild)) { 294 resp->status = nfserrno(PTR_ERR(dchild)); 295 goto out_unlock; 296 } 297 fh_init(newfhp, NFS_FHSIZE); 298 resp->status = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp); 299 if (!resp->status && d_really_is_negative(dchild)) 300 resp->status = nfserr_noent; 301 dput(dchild); 302 if (resp->status) { 303 if (resp->status != nfserr_noent) 304 goto out_unlock; 305 /* 306 * If the new file handle wasn't verified, we can't tell 307 * whether the file exists or not. Time to bail ... 308 */ 309 resp->status = nfserr_acces; 310 if (!newfhp->fh_dentry) { 311 printk(KERN_WARNING 312 "nfsd_proc_create: file handle not verified\n"); 313 goto out_unlock; 314 } 315 } 316 317 inode = d_inode(newfhp->fh_dentry); 318 319 /* Unfudge the mode bits */ 320 if (attr->ia_valid & ATTR_MODE) { 321 type = attr->ia_mode & S_IFMT; 322 mode = attr->ia_mode & ~S_IFMT; 323 if (!type) { 324 /* no type, so if target exists, assume same as that, 325 * else assume a file */ 326 if (inode) { 327 type = inode->i_mode & S_IFMT; 328 switch(type) { 329 case S_IFCHR: 330 case S_IFBLK: 331 /* reserve rdev for later checking */ 332 rdev = inode->i_rdev; 333 attr->ia_valid |= ATTR_SIZE; 334 335 fallthrough; 336 case S_IFIFO: 337 /* this is probably a permission check.. 338 * at least IRIX implements perm checking on 339 * echo thing > device-special-file-or-pipe 340 * by doing a CREATE with type==0 341 */ 342 resp->status = nfsd_permission(rqstp, 343 newfhp->fh_export, 344 newfhp->fh_dentry, 345 NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS); 346 if (resp->status && resp->status != nfserr_rofs) 347 goto out_unlock; 348 } 349 } else 350 type = S_IFREG; 351 } 352 } else if (inode) { 353 type = inode->i_mode & S_IFMT; 354 mode = inode->i_mode & ~S_IFMT; 355 } else { 356 type = S_IFREG; 357 mode = 0; /* ??? */ 358 } 359 360 attr->ia_valid |= ATTR_MODE; 361 attr->ia_mode = mode; 362 363 /* Special treatment for non-regular files according to the 364 * gospel of sun micro 365 */ 366 if (type != S_IFREG) { 367 if (type != S_IFBLK && type != S_IFCHR) { 368 rdev = 0; 369 } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) { 370 /* If you think you've seen the worst, grok this. */ 371 type = S_IFIFO; 372 } else { 373 /* Okay, char or block special */ 374 if (!rdev) 375 rdev = wanted; 376 } 377 378 /* we've used the SIZE information, so discard it */ 379 attr->ia_valid &= ~ATTR_SIZE; 380 381 /* Make sure the type and device matches */ 382 resp->status = nfserr_exist; 383 if (inode && type != (inode->i_mode & S_IFMT)) 384 goto out_unlock; 385 } 386 387 resp->status = nfs_ok; 388 if (!inode) { 389 /* File doesn't exist. Create it and set attrs */ 390 resp->status = nfsd_create_locked(rqstp, dirfhp, argp->name, 391 argp->len, attr, type, rdev, 392 newfhp); 393 } else if (type == S_IFREG) { 394 dprintk("nfsd: existing %s, valid=%x, size=%ld\n", 395 argp->name, attr->ia_valid, (long) attr->ia_size); 396 /* File already exists. We ignore all attributes except 397 * size, so that creat() behaves exactly like 398 * open(..., O_CREAT|O_TRUNC|O_WRONLY). 399 */ 400 attr->ia_valid &= ATTR_SIZE; 401 if (attr->ia_valid) 402 resp->status = nfsd_setattr(rqstp, newfhp, attr, 0, 403 (time64_t)0); 404 } 405 406 out_unlock: 407 /* We don't really need to unlock, as fh_put does it. */ 408 fh_unlock(dirfhp); 409 fh_drop_write(dirfhp); 410 done: 411 fh_put(dirfhp); 412 if (resp->status != nfs_ok) 413 goto out; 414 resp->status = fh_getattr(&resp->fh, &resp->stat); 415 out: 416 return rpc_success; 417 } 418 419 static __be32 420 nfsd_proc_remove(struct svc_rqst *rqstp) 421 { 422 struct nfsd_diropargs *argp = rqstp->rq_argp; 423 struct nfsd_stat *resp = rqstp->rq_resp; 424 425 dprintk("nfsd: REMOVE %s %.*s\n", SVCFH_fmt(&argp->fh), 426 argp->len, argp->name); 427 428 /* Unlink. -SIFDIR means file must not be a directory */ 429 resp->status = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, 430 argp->name, argp->len); 431 fh_put(&argp->fh); 432 return rpc_success; 433 } 434 435 static __be32 436 nfsd_proc_rename(struct svc_rqst *rqstp) 437 { 438 struct nfsd_renameargs *argp = rqstp->rq_argp; 439 struct nfsd_stat *resp = rqstp->rq_resp; 440 441 dprintk("nfsd: RENAME %s %.*s -> \n", 442 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname); 443 dprintk("nfsd: -> %s %.*s\n", 444 SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname); 445 446 resp->status = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen, 447 &argp->tfh, argp->tname, argp->tlen); 448 fh_put(&argp->ffh); 449 fh_put(&argp->tfh); 450 return rpc_success; 451 } 452 453 static __be32 454 nfsd_proc_link(struct svc_rqst *rqstp) 455 { 456 struct nfsd_linkargs *argp = rqstp->rq_argp; 457 struct nfsd_stat *resp = rqstp->rq_resp; 458 459 dprintk("nfsd: LINK %s ->\n", 460 SVCFH_fmt(&argp->ffh)); 461 dprintk("nfsd: %s %.*s\n", 462 SVCFH_fmt(&argp->tfh), 463 argp->tlen, 464 argp->tname); 465 466 resp->status = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen, 467 &argp->ffh); 468 fh_put(&argp->ffh); 469 fh_put(&argp->tfh); 470 return rpc_success; 471 } 472 473 static __be32 474 nfsd_proc_symlink(struct svc_rqst *rqstp) 475 { 476 struct nfsd_symlinkargs *argp = rqstp->rq_argp; 477 struct nfsd_stat *resp = rqstp->rq_resp; 478 struct svc_fh newfh; 479 480 if (argp->tlen > NFS_MAXPATHLEN) { 481 resp->status = nfserr_nametoolong; 482 goto out; 483 } 484 485 argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first, 486 page_address(rqstp->rq_arg.pages[0]), 487 argp->tlen); 488 if (IS_ERR(argp->tname)) { 489 resp->status = nfserrno(PTR_ERR(argp->tname)); 490 goto out; 491 } 492 493 dprintk("nfsd: SYMLINK %s %.*s -> %.*s\n", 494 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname, 495 argp->tlen, argp->tname); 496 497 fh_init(&newfh, NFS_FHSIZE); 498 resp->status = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen, 499 argp->tname, &newfh); 500 501 kfree(argp->tname); 502 fh_put(&argp->ffh); 503 fh_put(&newfh); 504 out: 505 return rpc_success; 506 } 507 508 /* 509 * Make directory. This operation is not idempotent. 510 * N.B. After this call resp->fh needs an fh_put 511 */ 512 static __be32 513 nfsd_proc_mkdir(struct svc_rqst *rqstp) 514 { 515 struct nfsd_createargs *argp = rqstp->rq_argp; 516 struct nfsd_diropres *resp = rqstp->rq_resp; 517 518 dprintk("nfsd: MKDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); 519 520 if (resp->fh.fh_dentry) { 521 printk(KERN_WARNING 522 "nfsd_proc_mkdir: response already verified??\n"); 523 } 524 525 argp->attrs.ia_valid &= ~ATTR_SIZE; 526 fh_init(&resp->fh, NFS_FHSIZE); 527 resp->status = nfsd_create(rqstp, &argp->fh, argp->name, argp->len, 528 &argp->attrs, S_IFDIR, 0, &resp->fh); 529 fh_put(&argp->fh); 530 if (resp->status != nfs_ok) 531 goto out; 532 533 resp->status = fh_getattr(&resp->fh, &resp->stat); 534 out: 535 return rpc_success; 536 } 537 538 /* 539 * Remove a directory 540 */ 541 static __be32 542 nfsd_proc_rmdir(struct svc_rqst *rqstp) 543 { 544 struct nfsd_diropargs *argp = rqstp->rq_argp; 545 struct nfsd_stat *resp = rqstp->rq_resp; 546 547 dprintk("nfsd: RMDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); 548 549 resp->status = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, 550 argp->name, argp->len); 551 fh_put(&argp->fh); 552 return rpc_success; 553 } 554 555 /* 556 * Read a portion of a directory. 557 */ 558 static __be32 559 nfsd_proc_readdir(struct svc_rqst *rqstp) 560 { 561 struct nfsd_readdirargs *argp = rqstp->rq_argp; 562 struct nfsd_readdirres *resp = rqstp->rq_resp; 563 int count; 564 loff_t offset; 565 566 dprintk("nfsd: READDIR %s %d bytes at %d\n", 567 SVCFH_fmt(&argp->fh), 568 argp->count, argp->cookie); 569 570 /* Shrink to the client read size */ 571 count = (argp->count >> 2) - 2; 572 573 /* Make sure we've room for the NULL ptr & eof flag */ 574 count -= 2; 575 if (count < 0) 576 count = 0; 577 578 resp->buffer = argp->buffer; 579 resp->offset = NULL; 580 resp->buflen = count; 581 resp->common.err = nfs_ok; 582 /* Read directory and encode entries on the fly */ 583 offset = argp->cookie; 584 resp->status = nfsd_readdir(rqstp, &argp->fh, &offset, 585 &resp->common, nfssvc_encode_entry); 586 587 resp->count = resp->buffer - argp->buffer; 588 if (resp->offset) 589 *resp->offset = htonl(offset); 590 591 fh_put(&argp->fh); 592 return rpc_success; 593 } 594 595 /* 596 * Get file system info 597 */ 598 static __be32 599 nfsd_proc_statfs(struct svc_rqst *rqstp) 600 { 601 struct nfsd_fhandle *argp = rqstp->rq_argp; 602 struct nfsd_statfsres *resp = rqstp->rq_resp; 603 604 dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh)); 605 606 resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 607 NFSD_MAY_BYPASS_GSS_ON_ROOT); 608 fh_put(&argp->fh); 609 return rpc_success; 610 } 611 612 /* 613 * NFSv2 Server procedures. 614 * Only the results of non-idempotent operations are cached. 615 */ 616 617 #define ST 1 /* status */ 618 #define FH 8 /* filehandle */ 619 #define AT 18 /* attributes */ 620 621 static const struct svc_procedure nfsd_procedures2[18] = { 622 [NFSPROC_NULL] = { 623 .pc_func = nfsd_proc_null, 624 .pc_decode = nfssvc_decode_voidarg, 625 .pc_encode = nfssvc_encode_voidres, 626 .pc_argsize = sizeof(struct nfsd_voidargs), 627 .pc_ressize = sizeof(struct nfsd_voidres), 628 .pc_cachetype = RC_NOCACHE, 629 .pc_xdrressize = 0, 630 .pc_name = "NULL", 631 }, 632 [NFSPROC_GETATTR] = { 633 .pc_func = nfsd_proc_getattr, 634 .pc_decode = nfssvc_decode_fhandleargs, 635 .pc_encode = nfssvc_encode_attrstat, 636 .pc_release = nfssvc_release_attrstat, 637 .pc_argsize = sizeof(struct nfsd_fhandle), 638 .pc_ressize = sizeof(struct nfsd_attrstat), 639 .pc_cachetype = RC_NOCACHE, 640 .pc_xdrressize = ST+AT, 641 .pc_name = "GETATTR", 642 }, 643 [NFSPROC_SETATTR] = { 644 .pc_func = nfsd_proc_setattr, 645 .pc_decode = nfssvc_decode_sattrargs, 646 .pc_encode = nfssvc_encode_attrstat, 647 .pc_release = nfssvc_release_attrstat, 648 .pc_argsize = sizeof(struct nfsd_sattrargs), 649 .pc_ressize = sizeof(struct nfsd_attrstat), 650 .pc_cachetype = RC_REPLBUFF, 651 .pc_xdrressize = ST+AT, 652 .pc_name = "SETATTR", 653 }, 654 [NFSPROC_ROOT] = { 655 .pc_func = nfsd_proc_root, 656 .pc_decode = nfssvc_decode_voidarg, 657 .pc_encode = nfssvc_encode_voidres, 658 .pc_argsize = sizeof(struct nfsd_voidargs), 659 .pc_ressize = sizeof(struct nfsd_voidres), 660 .pc_cachetype = RC_NOCACHE, 661 .pc_xdrressize = 0, 662 .pc_name = "ROOT", 663 }, 664 [NFSPROC_LOOKUP] = { 665 .pc_func = nfsd_proc_lookup, 666 .pc_decode = nfssvc_decode_diropargs, 667 .pc_encode = nfssvc_encode_diropres, 668 .pc_release = nfssvc_release_diropres, 669 .pc_argsize = sizeof(struct nfsd_diropargs), 670 .pc_ressize = sizeof(struct nfsd_diropres), 671 .pc_cachetype = RC_NOCACHE, 672 .pc_xdrressize = ST+FH+AT, 673 .pc_name = "LOOKUP", 674 }, 675 [NFSPROC_READLINK] = { 676 .pc_func = nfsd_proc_readlink, 677 .pc_decode = nfssvc_decode_readlinkargs, 678 .pc_encode = nfssvc_encode_readlinkres, 679 .pc_argsize = sizeof(struct nfsd_readlinkargs), 680 .pc_ressize = sizeof(struct nfsd_readlinkres), 681 .pc_cachetype = RC_NOCACHE, 682 .pc_xdrressize = ST+1+NFS_MAXPATHLEN/4, 683 .pc_name = "READLINK", 684 }, 685 [NFSPROC_READ] = { 686 .pc_func = nfsd_proc_read, 687 .pc_decode = nfssvc_decode_readargs, 688 .pc_encode = nfssvc_encode_readres, 689 .pc_release = nfssvc_release_readres, 690 .pc_argsize = sizeof(struct nfsd_readargs), 691 .pc_ressize = sizeof(struct nfsd_readres), 692 .pc_cachetype = RC_NOCACHE, 693 .pc_xdrressize = ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4, 694 .pc_name = "READ", 695 }, 696 [NFSPROC_WRITECACHE] = { 697 .pc_func = nfsd_proc_writecache, 698 .pc_decode = nfssvc_decode_voidarg, 699 .pc_encode = nfssvc_encode_voidres, 700 .pc_argsize = sizeof(struct nfsd_voidargs), 701 .pc_ressize = sizeof(struct nfsd_voidres), 702 .pc_cachetype = RC_NOCACHE, 703 .pc_xdrressize = 0, 704 .pc_name = "WRITECACHE", 705 }, 706 [NFSPROC_WRITE] = { 707 .pc_func = nfsd_proc_write, 708 .pc_decode = nfssvc_decode_writeargs, 709 .pc_encode = nfssvc_encode_attrstat, 710 .pc_release = nfssvc_release_attrstat, 711 .pc_argsize = sizeof(struct nfsd_writeargs), 712 .pc_ressize = sizeof(struct nfsd_attrstat), 713 .pc_cachetype = RC_REPLBUFF, 714 .pc_xdrressize = ST+AT, 715 .pc_name = "WRITE", 716 }, 717 [NFSPROC_CREATE] = { 718 .pc_func = nfsd_proc_create, 719 .pc_decode = nfssvc_decode_createargs, 720 .pc_encode = nfssvc_encode_diropres, 721 .pc_release = nfssvc_release_diropres, 722 .pc_argsize = sizeof(struct nfsd_createargs), 723 .pc_ressize = sizeof(struct nfsd_diropres), 724 .pc_cachetype = RC_REPLBUFF, 725 .pc_xdrressize = ST+FH+AT, 726 .pc_name = "CREATE", 727 }, 728 [NFSPROC_REMOVE] = { 729 .pc_func = nfsd_proc_remove, 730 .pc_decode = nfssvc_decode_diropargs, 731 .pc_encode = nfssvc_encode_stat, 732 .pc_argsize = sizeof(struct nfsd_diropargs), 733 .pc_ressize = sizeof(struct nfsd_stat), 734 .pc_cachetype = RC_REPLSTAT, 735 .pc_xdrressize = ST, 736 .pc_name = "REMOVE", 737 }, 738 [NFSPROC_RENAME] = { 739 .pc_func = nfsd_proc_rename, 740 .pc_decode = nfssvc_decode_renameargs, 741 .pc_encode = nfssvc_encode_stat, 742 .pc_argsize = sizeof(struct nfsd_renameargs), 743 .pc_ressize = sizeof(struct nfsd_stat), 744 .pc_cachetype = RC_REPLSTAT, 745 .pc_xdrressize = ST, 746 .pc_name = "RENAME", 747 }, 748 [NFSPROC_LINK] = { 749 .pc_func = nfsd_proc_link, 750 .pc_decode = nfssvc_decode_linkargs, 751 .pc_encode = nfssvc_encode_stat, 752 .pc_argsize = sizeof(struct nfsd_linkargs), 753 .pc_ressize = sizeof(struct nfsd_stat), 754 .pc_cachetype = RC_REPLSTAT, 755 .pc_xdrressize = ST, 756 .pc_name = "LINK", 757 }, 758 [NFSPROC_SYMLINK] = { 759 .pc_func = nfsd_proc_symlink, 760 .pc_decode = nfssvc_decode_symlinkargs, 761 .pc_encode = nfssvc_encode_stat, 762 .pc_argsize = sizeof(struct nfsd_symlinkargs), 763 .pc_ressize = sizeof(struct nfsd_stat), 764 .pc_cachetype = RC_REPLSTAT, 765 .pc_xdrressize = ST, 766 .pc_name = "SYMLINK", 767 }, 768 [NFSPROC_MKDIR] = { 769 .pc_func = nfsd_proc_mkdir, 770 .pc_decode = nfssvc_decode_createargs, 771 .pc_encode = nfssvc_encode_diropres, 772 .pc_release = nfssvc_release_diropres, 773 .pc_argsize = sizeof(struct nfsd_createargs), 774 .pc_ressize = sizeof(struct nfsd_diropres), 775 .pc_cachetype = RC_REPLBUFF, 776 .pc_xdrressize = ST+FH+AT, 777 .pc_name = "MKDIR", 778 }, 779 [NFSPROC_RMDIR] = { 780 .pc_func = nfsd_proc_rmdir, 781 .pc_decode = nfssvc_decode_diropargs, 782 .pc_encode = nfssvc_encode_stat, 783 .pc_argsize = sizeof(struct nfsd_diropargs), 784 .pc_ressize = sizeof(struct nfsd_stat), 785 .pc_cachetype = RC_REPLSTAT, 786 .pc_xdrressize = ST, 787 .pc_name = "RMDIR", 788 }, 789 [NFSPROC_READDIR] = { 790 .pc_func = nfsd_proc_readdir, 791 .pc_decode = nfssvc_decode_readdirargs, 792 .pc_encode = nfssvc_encode_readdirres, 793 .pc_argsize = sizeof(struct nfsd_readdirargs), 794 .pc_ressize = sizeof(struct nfsd_readdirres), 795 .pc_cachetype = RC_NOCACHE, 796 .pc_name = "READDIR", 797 }, 798 [NFSPROC_STATFS] = { 799 .pc_func = nfsd_proc_statfs, 800 .pc_decode = nfssvc_decode_fhandleargs, 801 .pc_encode = nfssvc_encode_statfsres, 802 .pc_argsize = sizeof(struct nfsd_fhandle), 803 .pc_ressize = sizeof(struct nfsd_statfsres), 804 .pc_cachetype = RC_NOCACHE, 805 .pc_xdrressize = ST+5, 806 .pc_name = "STATFS", 807 }, 808 }; 809 810 811 static unsigned int nfsd_count2[ARRAY_SIZE(nfsd_procedures2)]; 812 const struct svc_version nfsd_version2 = { 813 .vs_vers = 2, 814 .vs_nproc = 18, 815 .vs_proc = nfsd_procedures2, 816 .vs_count = nfsd_count2, 817 .vs_dispatch = nfsd_dispatch, 818 .vs_xdrsize = NFS2_SVC_XDRSIZE, 819 }; 820 821 /* 822 * Map errnos to NFS errnos. 823 */ 824 __be32 825 nfserrno (int errno) 826 { 827 static struct { 828 __be32 nfserr; 829 int syserr; 830 } nfs_errtbl[] = { 831 { nfs_ok, 0 }, 832 { nfserr_perm, -EPERM }, 833 { nfserr_noent, -ENOENT }, 834 { nfserr_io, -EIO }, 835 { nfserr_nxio, -ENXIO }, 836 { nfserr_fbig, -E2BIG }, 837 { nfserr_acces, -EACCES }, 838 { nfserr_exist, -EEXIST }, 839 { nfserr_xdev, -EXDEV }, 840 { nfserr_mlink, -EMLINK }, 841 { nfserr_nodev, -ENODEV }, 842 { nfserr_notdir, -ENOTDIR }, 843 { nfserr_isdir, -EISDIR }, 844 { nfserr_inval, -EINVAL }, 845 { nfserr_fbig, -EFBIG }, 846 { nfserr_nospc, -ENOSPC }, 847 { nfserr_rofs, -EROFS }, 848 { nfserr_mlink, -EMLINK }, 849 { nfserr_nametoolong, -ENAMETOOLONG }, 850 { nfserr_notempty, -ENOTEMPTY }, 851 #ifdef EDQUOT 852 { nfserr_dquot, -EDQUOT }, 853 #endif 854 { nfserr_stale, -ESTALE }, 855 { nfserr_jukebox, -ETIMEDOUT }, 856 { nfserr_jukebox, -ERESTARTSYS }, 857 { nfserr_jukebox, -EAGAIN }, 858 { nfserr_jukebox, -EWOULDBLOCK }, 859 { nfserr_jukebox, -ENOMEM }, 860 { nfserr_io, -ETXTBSY }, 861 { nfserr_notsupp, -EOPNOTSUPP }, 862 { nfserr_toosmall, -ETOOSMALL }, 863 { nfserr_serverfault, -ESERVERFAULT }, 864 { nfserr_serverfault, -ENFILE }, 865 { nfserr_io, -EUCLEAN }, 866 { nfserr_perm, -ENOKEY }, 867 }; 868 int i; 869 870 for (i = 0; i < ARRAY_SIZE(nfs_errtbl); i++) { 871 if (nfs_errtbl[i].syserr == errno) 872 return nfs_errtbl[i].nfserr; 873 } 874 WARN_ONCE(1, "nfsd: non-standard errno: %d\n", errno); 875 return nfserr_io; 876 } 877 878