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 u32 eof; 175 176 dprintk("nfsd: READ %s %d bytes at %d\n", 177 SVCFH_fmt(&argp->fh), 178 argp->count, argp->offset); 179 180 /* Obtain buffer pointer for payload. 19 is 1 word for 181 * status, 17 words for fattr, and 1 word for the byte count. 182 */ 183 184 if (NFSSVC_MAXBLKSIZE_V2 < argp->count) { 185 char buf[RPC_MAX_ADDRBUFLEN]; 186 printk(KERN_NOTICE 187 "oversized read request from %s (%d bytes)\n", 188 svc_print_addr(rqstp, buf, sizeof(buf)), 189 argp->count); 190 argp->count = NFSSVC_MAXBLKSIZE_V2; 191 } 192 svc_reserve_auth(rqstp, (19<<2) + argp->count + 4); 193 194 resp->count = argp->count; 195 resp->status = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh), 196 argp->offset, 197 rqstp->rq_vec, argp->vlen, 198 &resp->count, 199 &eof); 200 if (resp->status == nfs_ok) 201 resp->status = fh_getattr(&resp->fh, &resp->stat); 202 else if (resp->status == nfserr_jukebox) 203 return rpc_drop_reply; 204 return rpc_success; 205 } 206 207 /* Reserved */ 208 static __be32 209 nfsd_proc_writecache(struct svc_rqst *rqstp) 210 { 211 return rpc_success; 212 } 213 214 /* 215 * Write data to a file 216 * N.B. After this call resp->fh needs an fh_put 217 */ 218 static __be32 219 nfsd_proc_write(struct svc_rqst *rqstp) 220 { 221 struct nfsd_writeargs *argp = rqstp->rq_argp; 222 struct nfsd_attrstat *resp = rqstp->rq_resp; 223 unsigned long cnt = argp->len; 224 unsigned int nvecs; 225 226 dprintk("nfsd: WRITE %s %d bytes at %d\n", 227 SVCFH_fmt(&argp->fh), 228 argp->len, argp->offset); 229 230 nvecs = svc_fill_write_vector(rqstp, rqstp->rq_arg.pages, 231 &argp->first, cnt); 232 if (!nvecs) { 233 resp->status = nfserr_io; 234 goto out; 235 } 236 237 resp->status = nfsd_write(rqstp, fh_copy(&resp->fh, &argp->fh), 238 argp->offset, rqstp->rq_vec, nvecs, 239 &cnt, NFS_DATA_SYNC, NULL); 240 if (resp->status == nfs_ok) 241 resp->status = fh_getattr(&resp->fh, &resp->stat); 242 else if (resp->status == nfserr_jukebox) 243 return rpc_drop_reply; 244 out: 245 return rpc_success; 246 } 247 248 /* 249 * CREATE processing is complicated. The keyword here is `overloaded.' 250 * The parent directory is kept locked between the check for existence 251 * and the actual create() call in compliance with VFS protocols. 252 * N.B. After this call _both_ argp->fh and resp->fh need an fh_put 253 */ 254 static __be32 255 nfsd_proc_create(struct svc_rqst *rqstp) 256 { 257 struct nfsd_createargs *argp = rqstp->rq_argp; 258 struct nfsd_diropres *resp = rqstp->rq_resp; 259 svc_fh *dirfhp = &argp->fh; 260 svc_fh *newfhp = &resp->fh; 261 struct iattr *attr = &argp->attrs; 262 struct inode *inode; 263 struct dentry *dchild; 264 int type, mode; 265 int hosterr; 266 dev_t rdev = 0, wanted = new_decode_dev(attr->ia_size); 267 268 dprintk("nfsd: CREATE %s %.*s\n", 269 SVCFH_fmt(dirfhp), argp->len, argp->name); 270 271 /* First verify the parent file handle */ 272 resp->status = fh_verify(rqstp, dirfhp, S_IFDIR, NFSD_MAY_EXEC); 273 if (resp->status != nfs_ok) 274 goto done; /* must fh_put dirfhp even on error */ 275 276 /* Check for NFSD_MAY_WRITE in nfsd_create if necessary */ 277 278 resp->status = nfserr_exist; 279 if (isdotent(argp->name, argp->len)) 280 goto done; 281 hosterr = fh_want_write(dirfhp); 282 if (hosterr) { 283 resp->status = nfserrno(hosterr); 284 goto done; 285 } 286 287 fh_lock_nested(dirfhp, I_MUTEX_PARENT); 288 dchild = lookup_one_len(argp->name, dirfhp->fh_dentry, argp->len); 289 if (IS_ERR(dchild)) { 290 resp->status = nfserrno(PTR_ERR(dchild)); 291 goto out_unlock; 292 } 293 fh_init(newfhp, NFS_FHSIZE); 294 resp->status = fh_compose(newfhp, dirfhp->fh_export, dchild, dirfhp); 295 if (!resp->status && d_really_is_negative(dchild)) 296 resp->status = nfserr_noent; 297 dput(dchild); 298 if (resp->status) { 299 if (resp->status != nfserr_noent) 300 goto out_unlock; 301 /* 302 * If the new file handle wasn't verified, we can't tell 303 * whether the file exists or not. Time to bail ... 304 */ 305 resp->status = nfserr_acces; 306 if (!newfhp->fh_dentry) { 307 printk(KERN_WARNING 308 "nfsd_proc_create: file handle not verified\n"); 309 goto out_unlock; 310 } 311 } 312 313 inode = d_inode(newfhp->fh_dentry); 314 315 /* Unfudge the mode bits */ 316 if (attr->ia_valid & ATTR_MODE) { 317 type = attr->ia_mode & S_IFMT; 318 mode = attr->ia_mode & ~S_IFMT; 319 if (!type) { 320 /* no type, so if target exists, assume same as that, 321 * else assume a file */ 322 if (inode) { 323 type = inode->i_mode & S_IFMT; 324 switch(type) { 325 case S_IFCHR: 326 case S_IFBLK: 327 /* reserve rdev for later checking */ 328 rdev = inode->i_rdev; 329 attr->ia_valid |= ATTR_SIZE; 330 331 fallthrough; 332 case S_IFIFO: 333 /* this is probably a permission check.. 334 * at least IRIX implements perm checking on 335 * echo thing > device-special-file-or-pipe 336 * by doing a CREATE with type==0 337 */ 338 resp->status = nfsd_permission(rqstp, 339 newfhp->fh_export, 340 newfhp->fh_dentry, 341 NFSD_MAY_WRITE|NFSD_MAY_LOCAL_ACCESS); 342 if (resp->status && resp->status != nfserr_rofs) 343 goto out_unlock; 344 } 345 } else 346 type = S_IFREG; 347 } 348 } else if (inode) { 349 type = inode->i_mode & S_IFMT; 350 mode = inode->i_mode & ~S_IFMT; 351 } else { 352 type = S_IFREG; 353 mode = 0; /* ??? */ 354 } 355 356 attr->ia_valid |= ATTR_MODE; 357 attr->ia_mode = mode; 358 359 /* Special treatment for non-regular files according to the 360 * gospel of sun micro 361 */ 362 if (type != S_IFREG) { 363 if (type != S_IFBLK && type != S_IFCHR) { 364 rdev = 0; 365 } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) { 366 /* If you think you've seen the worst, grok this. */ 367 type = S_IFIFO; 368 } else { 369 /* Okay, char or block special */ 370 if (!rdev) 371 rdev = wanted; 372 } 373 374 /* we've used the SIZE information, so discard it */ 375 attr->ia_valid &= ~ATTR_SIZE; 376 377 /* Make sure the type and device matches */ 378 resp->status = nfserr_exist; 379 if (inode && type != (inode->i_mode & S_IFMT)) 380 goto out_unlock; 381 } 382 383 resp->status = nfs_ok; 384 if (!inode) { 385 /* File doesn't exist. Create it and set attrs */ 386 resp->status = nfsd_create_locked(rqstp, dirfhp, argp->name, 387 argp->len, attr, type, rdev, 388 newfhp); 389 } else if (type == S_IFREG) { 390 dprintk("nfsd: existing %s, valid=%x, size=%ld\n", 391 argp->name, attr->ia_valid, (long) attr->ia_size); 392 /* File already exists. We ignore all attributes except 393 * size, so that creat() behaves exactly like 394 * open(..., O_CREAT|O_TRUNC|O_WRONLY). 395 */ 396 attr->ia_valid &= ATTR_SIZE; 397 if (attr->ia_valid) 398 resp->status = nfsd_setattr(rqstp, newfhp, attr, 0, 399 (time64_t)0); 400 } 401 402 out_unlock: 403 /* We don't really need to unlock, as fh_put does it. */ 404 fh_unlock(dirfhp); 405 fh_drop_write(dirfhp); 406 done: 407 fh_put(dirfhp); 408 if (resp->status != nfs_ok) 409 goto out; 410 resp->status = fh_getattr(&resp->fh, &resp->stat); 411 out: 412 return rpc_success; 413 } 414 415 static __be32 416 nfsd_proc_remove(struct svc_rqst *rqstp) 417 { 418 struct nfsd_diropargs *argp = rqstp->rq_argp; 419 struct nfsd_stat *resp = rqstp->rq_resp; 420 421 dprintk("nfsd: REMOVE %s %.*s\n", SVCFH_fmt(&argp->fh), 422 argp->len, argp->name); 423 424 /* Unlink. -SIFDIR means file must not be a directory */ 425 resp->status = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, 426 argp->name, argp->len); 427 fh_put(&argp->fh); 428 return rpc_success; 429 } 430 431 static __be32 432 nfsd_proc_rename(struct svc_rqst *rqstp) 433 { 434 struct nfsd_renameargs *argp = rqstp->rq_argp; 435 struct nfsd_stat *resp = rqstp->rq_resp; 436 437 dprintk("nfsd: RENAME %s %.*s -> \n", 438 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname); 439 dprintk("nfsd: -> %s %.*s\n", 440 SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname); 441 442 resp->status = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen, 443 &argp->tfh, argp->tname, argp->tlen); 444 fh_put(&argp->ffh); 445 fh_put(&argp->tfh); 446 return rpc_success; 447 } 448 449 static __be32 450 nfsd_proc_link(struct svc_rqst *rqstp) 451 { 452 struct nfsd_linkargs *argp = rqstp->rq_argp; 453 struct nfsd_stat *resp = rqstp->rq_resp; 454 455 dprintk("nfsd: LINK %s ->\n", 456 SVCFH_fmt(&argp->ffh)); 457 dprintk("nfsd: %s %.*s\n", 458 SVCFH_fmt(&argp->tfh), 459 argp->tlen, 460 argp->tname); 461 462 resp->status = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen, 463 &argp->ffh); 464 fh_put(&argp->ffh); 465 fh_put(&argp->tfh); 466 return rpc_success; 467 } 468 469 static __be32 470 nfsd_proc_symlink(struct svc_rqst *rqstp) 471 { 472 struct nfsd_symlinkargs *argp = rqstp->rq_argp; 473 struct nfsd_stat *resp = rqstp->rq_resp; 474 struct svc_fh newfh; 475 476 if (argp->tlen > NFS_MAXPATHLEN) { 477 resp->status = nfserr_nametoolong; 478 goto out; 479 } 480 481 argp->tname = svc_fill_symlink_pathname(rqstp, &argp->first, 482 page_address(rqstp->rq_arg.pages[0]), 483 argp->tlen); 484 if (IS_ERR(argp->tname)) { 485 resp->status = nfserrno(PTR_ERR(argp->tname)); 486 goto out; 487 } 488 489 dprintk("nfsd: SYMLINK %s %.*s -> %.*s\n", 490 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname, 491 argp->tlen, argp->tname); 492 493 fh_init(&newfh, NFS_FHSIZE); 494 resp->status = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen, 495 argp->tname, &newfh); 496 497 kfree(argp->tname); 498 fh_put(&argp->ffh); 499 fh_put(&newfh); 500 out: 501 return rpc_success; 502 } 503 504 /* 505 * Make directory. This operation is not idempotent. 506 * N.B. After this call resp->fh needs an fh_put 507 */ 508 static __be32 509 nfsd_proc_mkdir(struct svc_rqst *rqstp) 510 { 511 struct nfsd_createargs *argp = rqstp->rq_argp; 512 struct nfsd_diropres *resp = rqstp->rq_resp; 513 514 dprintk("nfsd: MKDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); 515 516 if (resp->fh.fh_dentry) { 517 printk(KERN_WARNING 518 "nfsd_proc_mkdir: response already verified??\n"); 519 } 520 521 argp->attrs.ia_valid &= ~ATTR_SIZE; 522 fh_init(&resp->fh, NFS_FHSIZE); 523 resp->status = nfsd_create(rqstp, &argp->fh, argp->name, argp->len, 524 &argp->attrs, S_IFDIR, 0, &resp->fh); 525 fh_put(&argp->fh); 526 if (resp->status != nfs_ok) 527 goto out; 528 529 resp->status = fh_getattr(&resp->fh, &resp->stat); 530 out: 531 return rpc_success; 532 } 533 534 /* 535 * Remove a directory 536 */ 537 static __be32 538 nfsd_proc_rmdir(struct svc_rqst *rqstp) 539 { 540 struct nfsd_diropargs *argp = rqstp->rq_argp; 541 struct nfsd_stat *resp = rqstp->rq_resp; 542 543 dprintk("nfsd: RMDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); 544 545 resp->status = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, 546 argp->name, argp->len); 547 fh_put(&argp->fh); 548 return rpc_success; 549 } 550 551 /* 552 * Read a portion of a directory. 553 */ 554 static __be32 555 nfsd_proc_readdir(struct svc_rqst *rqstp) 556 { 557 struct nfsd_readdirargs *argp = rqstp->rq_argp; 558 struct nfsd_readdirres *resp = rqstp->rq_resp; 559 int count; 560 loff_t offset; 561 562 dprintk("nfsd: READDIR %s %d bytes at %d\n", 563 SVCFH_fmt(&argp->fh), 564 argp->count, argp->cookie); 565 566 /* Shrink to the client read size */ 567 count = (argp->count >> 2) - 2; 568 569 /* Make sure we've room for the NULL ptr & eof flag */ 570 count -= 2; 571 if (count < 0) 572 count = 0; 573 574 resp->buffer = argp->buffer; 575 resp->offset = NULL; 576 resp->buflen = count; 577 resp->common.err = nfs_ok; 578 /* Read directory and encode entries on the fly */ 579 offset = argp->cookie; 580 resp->status = nfsd_readdir(rqstp, &argp->fh, &offset, 581 &resp->common, nfssvc_encode_entry); 582 583 resp->count = resp->buffer - argp->buffer; 584 if (resp->offset) 585 *resp->offset = htonl(offset); 586 587 fh_put(&argp->fh); 588 return rpc_success; 589 } 590 591 /* 592 * Get file system info 593 */ 594 static __be32 595 nfsd_proc_statfs(struct svc_rqst *rqstp) 596 { 597 struct nfsd_fhandle *argp = rqstp->rq_argp; 598 struct nfsd_statfsres *resp = rqstp->rq_resp; 599 600 dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh)); 601 602 resp->status = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 603 NFSD_MAY_BYPASS_GSS_ON_ROOT); 604 fh_put(&argp->fh); 605 return rpc_success; 606 } 607 608 /* 609 * NFSv2 Server procedures. 610 * Only the results of non-idempotent operations are cached. 611 */ 612 613 #define ST 1 /* status */ 614 #define FH 8 /* filehandle */ 615 #define AT 18 /* attributes */ 616 617 static const struct svc_procedure nfsd_procedures2[18] = { 618 [NFSPROC_NULL] = { 619 .pc_func = nfsd_proc_null, 620 .pc_decode = nfssvc_decode_voidarg, 621 .pc_encode = nfssvc_encode_voidres, 622 .pc_argsize = sizeof(struct nfsd_voidargs), 623 .pc_ressize = sizeof(struct nfsd_voidres), 624 .pc_cachetype = RC_NOCACHE, 625 .pc_xdrressize = 0, 626 }, 627 [NFSPROC_GETATTR] = { 628 .pc_func = nfsd_proc_getattr, 629 .pc_decode = nfssvc_decode_fhandle, 630 .pc_encode = nfssvc_encode_attrstat, 631 .pc_release = nfssvc_release_attrstat, 632 .pc_argsize = sizeof(struct nfsd_fhandle), 633 .pc_ressize = sizeof(struct nfsd_attrstat), 634 .pc_cachetype = RC_NOCACHE, 635 .pc_xdrressize = ST+AT, 636 }, 637 [NFSPROC_SETATTR] = { 638 .pc_func = nfsd_proc_setattr, 639 .pc_decode = nfssvc_decode_sattrargs, 640 .pc_encode = nfssvc_encode_attrstat, 641 .pc_release = nfssvc_release_attrstat, 642 .pc_argsize = sizeof(struct nfsd_sattrargs), 643 .pc_ressize = sizeof(struct nfsd_attrstat), 644 .pc_cachetype = RC_REPLBUFF, 645 .pc_xdrressize = ST+AT, 646 }, 647 [NFSPROC_ROOT] = { 648 .pc_func = nfsd_proc_root, 649 .pc_decode = nfssvc_decode_voidarg, 650 .pc_encode = nfssvc_encode_voidres, 651 .pc_argsize = sizeof(struct nfsd_voidargs), 652 .pc_ressize = sizeof(struct nfsd_voidres), 653 .pc_cachetype = RC_NOCACHE, 654 .pc_xdrressize = 0, 655 }, 656 [NFSPROC_LOOKUP] = { 657 .pc_func = nfsd_proc_lookup, 658 .pc_decode = nfssvc_decode_diropargs, 659 .pc_encode = nfssvc_encode_diropres, 660 .pc_release = nfssvc_release_diropres, 661 .pc_argsize = sizeof(struct nfsd_diropargs), 662 .pc_ressize = sizeof(struct nfsd_diropres), 663 .pc_cachetype = RC_NOCACHE, 664 .pc_xdrressize = ST+FH+AT, 665 }, 666 [NFSPROC_READLINK] = { 667 .pc_func = nfsd_proc_readlink, 668 .pc_decode = nfssvc_decode_readlinkargs, 669 .pc_encode = nfssvc_encode_readlinkres, 670 .pc_argsize = sizeof(struct nfsd_readlinkargs), 671 .pc_ressize = sizeof(struct nfsd_readlinkres), 672 .pc_cachetype = RC_NOCACHE, 673 .pc_xdrressize = ST+1+NFS_MAXPATHLEN/4, 674 }, 675 [NFSPROC_READ] = { 676 .pc_func = nfsd_proc_read, 677 .pc_decode = nfssvc_decode_readargs, 678 .pc_encode = nfssvc_encode_readres, 679 .pc_release = nfssvc_release_readres, 680 .pc_argsize = sizeof(struct nfsd_readargs), 681 .pc_ressize = sizeof(struct nfsd_readres), 682 .pc_cachetype = RC_NOCACHE, 683 .pc_xdrressize = ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4, 684 }, 685 [NFSPROC_WRITECACHE] = { 686 .pc_func = nfsd_proc_writecache, 687 .pc_decode = nfssvc_decode_voidarg, 688 .pc_encode = nfssvc_encode_voidres, 689 .pc_argsize = sizeof(struct nfsd_voidargs), 690 .pc_ressize = sizeof(struct nfsd_voidres), 691 .pc_cachetype = RC_NOCACHE, 692 .pc_xdrressize = 0, 693 }, 694 [NFSPROC_WRITE] = { 695 .pc_func = nfsd_proc_write, 696 .pc_decode = nfssvc_decode_writeargs, 697 .pc_encode = nfssvc_encode_attrstat, 698 .pc_release = nfssvc_release_attrstat, 699 .pc_argsize = sizeof(struct nfsd_writeargs), 700 .pc_ressize = sizeof(struct nfsd_attrstat), 701 .pc_cachetype = RC_REPLBUFF, 702 .pc_xdrressize = ST+AT, 703 }, 704 [NFSPROC_CREATE] = { 705 .pc_func = nfsd_proc_create, 706 .pc_decode = nfssvc_decode_createargs, 707 .pc_encode = nfssvc_encode_diropres, 708 .pc_release = nfssvc_release_diropres, 709 .pc_argsize = sizeof(struct nfsd_createargs), 710 .pc_ressize = sizeof(struct nfsd_diropres), 711 .pc_cachetype = RC_REPLBUFF, 712 .pc_xdrressize = ST+FH+AT, 713 }, 714 [NFSPROC_REMOVE] = { 715 .pc_func = nfsd_proc_remove, 716 .pc_decode = nfssvc_decode_diropargs, 717 .pc_encode = nfssvc_encode_stat, 718 .pc_argsize = sizeof(struct nfsd_diropargs), 719 .pc_ressize = sizeof(struct nfsd_stat), 720 .pc_cachetype = RC_REPLSTAT, 721 .pc_xdrressize = ST, 722 }, 723 [NFSPROC_RENAME] = { 724 .pc_func = nfsd_proc_rename, 725 .pc_decode = nfssvc_decode_renameargs, 726 .pc_encode = nfssvc_encode_stat, 727 .pc_argsize = sizeof(struct nfsd_renameargs), 728 .pc_ressize = sizeof(struct nfsd_stat), 729 .pc_cachetype = RC_REPLSTAT, 730 .pc_xdrressize = ST, 731 }, 732 [NFSPROC_LINK] = { 733 .pc_func = nfsd_proc_link, 734 .pc_decode = nfssvc_decode_linkargs, 735 .pc_encode = nfssvc_encode_stat, 736 .pc_argsize = sizeof(struct nfsd_linkargs), 737 .pc_ressize = sizeof(struct nfsd_stat), 738 .pc_cachetype = RC_REPLSTAT, 739 .pc_xdrressize = ST, 740 }, 741 [NFSPROC_SYMLINK] = { 742 .pc_func = nfsd_proc_symlink, 743 .pc_decode = nfssvc_decode_symlinkargs, 744 .pc_encode = nfssvc_encode_stat, 745 .pc_argsize = sizeof(struct nfsd_symlinkargs), 746 .pc_ressize = sizeof(struct nfsd_stat), 747 .pc_cachetype = RC_REPLSTAT, 748 .pc_xdrressize = ST, 749 }, 750 [NFSPROC_MKDIR] = { 751 .pc_func = nfsd_proc_mkdir, 752 .pc_decode = nfssvc_decode_createargs, 753 .pc_encode = nfssvc_encode_diropres, 754 .pc_release = nfssvc_release_diropres, 755 .pc_argsize = sizeof(struct nfsd_createargs), 756 .pc_ressize = sizeof(struct nfsd_diropres), 757 .pc_cachetype = RC_REPLBUFF, 758 .pc_xdrressize = ST+FH+AT, 759 }, 760 [NFSPROC_RMDIR] = { 761 .pc_func = nfsd_proc_rmdir, 762 .pc_decode = nfssvc_decode_diropargs, 763 .pc_encode = nfssvc_encode_stat, 764 .pc_argsize = sizeof(struct nfsd_diropargs), 765 .pc_ressize = sizeof(struct nfsd_stat), 766 .pc_cachetype = RC_REPLSTAT, 767 .pc_xdrressize = ST, 768 }, 769 [NFSPROC_READDIR] = { 770 .pc_func = nfsd_proc_readdir, 771 .pc_decode = nfssvc_decode_readdirargs, 772 .pc_encode = nfssvc_encode_readdirres, 773 .pc_argsize = sizeof(struct nfsd_readdirargs), 774 .pc_ressize = sizeof(struct nfsd_readdirres), 775 .pc_cachetype = RC_NOCACHE, 776 }, 777 [NFSPROC_STATFS] = { 778 .pc_func = nfsd_proc_statfs, 779 .pc_decode = nfssvc_decode_fhandle, 780 .pc_encode = nfssvc_encode_statfsres, 781 .pc_argsize = sizeof(struct nfsd_fhandle), 782 .pc_ressize = sizeof(struct nfsd_statfsres), 783 .pc_cachetype = RC_NOCACHE, 784 .pc_xdrressize = ST+5, 785 }, 786 }; 787 788 789 static unsigned int nfsd_count2[ARRAY_SIZE(nfsd_procedures2)]; 790 const struct svc_version nfsd_version2 = { 791 .vs_vers = 2, 792 .vs_nproc = 18, 793 .vs_proc = nfsd_procedures2, 794 .vs_count = nfsd_count2, 795 .vs_dispatch = nfsd_dispatch, 796 .vs_xdrsize = NFS2_SVC_XDRSIZE, 797 }; 798 799 /* 800 * Map errnos to NFS errnos. 801 */ 802 __be32 803 nfserrno (int errno) 804 { 805 static struct { 806 __be32 nfserr; 807 int syserr; 808 } nfs_errtbl[] = { 809 { nfs_ok, 0 }, 810 { nfserr_perm, -EPERM }, 811 { nfserr_noent, -ENOENT }, 812 { nfserr_io, -EIO }, 813 { nfserr_nxio, -ENXIO }, 814 { nfserr_fbig, -E2BIG }, 815 { nfserr_acces, -EACCES }, 816 { nfserr_exist, -EEXIST }, 817 { nfserr_xdev, -EXDEV }, 818 { nfserr_mlink, -EMLINK }, 819 { nfserr_nodev, -ENODEV }, 820 { nfserr_notdir, -ENOTDIR }, 821 { nfserr_isdir, -EISDIR }, 822 { nfserr_inval, -EINVAL }, 823 { nfserr_fbig, -EFBIG }, 824 { nfserr_nospc, -ENOSPC }, 825 { nfserr_rofs, -EROFS }, 826 { nfserr_mlink, -EMLINK }, 827 { nfserr_nametoolong, -ENAMETOOLONG }, 828 { nfserr_notempty, -ENOTEMPTY }, 829 #ifdef EDQUOT 830 { nfserr_dquot, -EDQUOT }, 831 #endif 832 { nfserr_stale, -ESTALE }, 833 { nfserr_jukebox, -ETIMEDOUT }, 834 { nfserr_jukebox, -ERESTARTSYS }, 835 { nfserr_jukebox, -EAGAIN }, 836 { nfserr_jukebox, -EWOULDBLOCK }, 837 { nfserr_jukebox, -ENOMEM }, 838 { nfserr_io, -ETXTBSY }, 839 { nfserr_notsupp, -EOPNOTSUPP }, 840 { nfserr_toosmall, -ETOOSMALL }, 841 { nfserr_serverfault, -ESERVERFAULT }, 842 { nfserr_serverfault, -ENFILE }, 843 { nfserr_io, -EUCLEAN }, 844 { nfserr_perm, -ENOKEY }, 845 }; 846 int i; 847 848 for (i = 0; i < ARRAY_SIZE(nfs_errtbl); i++) { 849 if (nfs_errtbl[i].syserr == errno) 850 return nfs_errtbl[i].nfserr; 851 } 852 WARN_ONCE(1, "nfsd: non-standard errno: %d\n", errno); 853 return nfserr_io; 854 } 855 856