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