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