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