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), NULL, 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 int is_borc = 0; 294 if (type != S_IFBLK && type != S_IFCHR) { 295 rdev = 0; 296 } else if (type == S_IFCHR && !(attr->ia_valid & ATTR_SIZE)) { 297 /* If you think you've seen the worst, grok this. */ 298 type = S_IFIFO; 299 } else { 300 /* Okay, char or block special */ 301 is_borc = 1; 302 if (!rdev) 303 rdev = wanted; 304 } 305 306 /* we've used the SIZE information, so discard it */ 307 attr->ia_valid &= ~ATTR_SIZE; 308 309 /* Make sure the type and device matches */ 310 nfserr = nfserr_exist; 311 if (inode && type != (inode->i_mode & S_IFMT)) 312 goto out_unlock; 313 } 314 315 nfserr = 0; 316 if (!inode) { 317 /* File doesn't exist. Create it and set attrs */ 318 nfserr = nfsd_create(rqstp, dirfhp, argp->name, argp->len, 319 attr, type, rdev, newfhp); 320 } else if (type == S_IFREG) { 321 dprintk("nfsd: existing %s, valid=%x, size=%ld\n", 322 argp->name, attr->ia_valid, (long) attr->ia_size); 323 /* File already exists. We ignore all attributes except 324 * size, so that creat() behaves exactly like 325 * open(..., O_CREAT|O_TRUNC|O_WRONLY). 326 */ 327 attr->ia_valid &= ATTR_SIZE; 328 if (attr->ia_valid) 329 nfserr = nfsd_setattr(rqstp, newfhp, attr, 0, (time_t)0); 330 } 331 332 out_unlock: 333 /* We don't really need to unlock, as fh_put does it. */ 334 fh_unlock(dirfhp); 335 336 done: 337 fh_put(dirfhp); 338 return nfsd_return_dirop(nfserr, resp); 339 } 340 341 static __be32 342 nfsd_proc_remove(struct svc_rqst *rqstp, struct nfsd_diropargs *argp, 343 void *resp) 344 { 345 __be32 nfserr; 346 347 dprintk("nfsd: REMOVE %s %.*s\n", SVCFH_fmt(&argp->fh), 348 argp->len, argp->name); 349 350 /* Unlink. -SIFDIR means file must not be a directory */ 351 nfserr = nfsd_unlink(rqstp, &argp->fh, -S_IFDIR, argp->name, argp->len); 352 fh_put(&argp->fh); 353 return nfserr; 354 } 355 356 static __be32 357 nfsd_proc_rename(struct svc_rqst *rqstp, struct nfsd_renameargs *argp, 358 void *resp) 359 { 360 __be32 nfserr; 361 362 dprintk("nfsd: RENAME %s %.*s -> \n", 363 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname); 364 dprintk("nfsd: -> %s %.*s\n", 365 SVCFH_fmt(&argp->tfh), argp->tlen, argp->tname); 366 367 nfserr = nfsd_rename(rqstp, &argp->ffh, argp->fname, argp->flen, 368 &argp->tfh, argp->tname, argp->tlen); 369 fh_put(&argp->ffh); 370 fh_put(&argp->tfh); 371 return nfserr; 372 } 373 374 static __be32 375 nfsd_proc_link(struct svc_rqst *rqstp, struct nfsd_linkargs *argp, 376 void *resp) 377 { 378 __be32 nfserr; 379 380 dprintk("nfsd: LINK %s ->\n", 381 SVCFH_fmt(&argp->ffh)); 382 dprintk("nfsd: %s %.*s\n", 383 SVCFH_fmt(&argp->tfh), 384 argp->tlen, 385 argp->tname); 386 387 nfserr = nfsd_link(rqstp, &argp->tfh, argp->tname, argp->tlen, 388 &argp->ffh); 389 fh_put(&argp->ffh); 390 fh_put(&argp->tfh); 391 return nfserr; 392 } 393 394 static __be32 395 nfsd_proc_symlink(struct svc_rqst *rqstp, struct nfsd_symlinkargs *argp, 396 void *resp) 397 { 398 struct svc_fh newfh; 399 __be32 nfserr; 400 401 dprintk("nfsd: SYMLINK %s %.*s -> %.*s\n", 402 SVCFH_fmt(&argp->ffh), argp->flen, argp->fname, 403 argp->tlen, argp->tname); 404 405 fh_init(&newfh, NFS_FHSIZE); 406 /* 407 * Create the link, look up new file and set attrs. 408 */ 409 nfserr = nfsd_symlink(rqstp, &argp->ffh, argp->fname, argp->flen, 410 argp->tname, argp->tlen, 411 &newfh, &argp->attrs); 412 413 414 fh_put(&argp->ffh); 415 fh_put(&newfh); 416 return nfserr; 417 } 418 419 /* 420 * Make directory. This operation is not idempotent. 421 * N.B. After this call resp->fh needs an fh_put 422 */ 423 static __be32 424 nfsd_proc_mkdir(struct svc_rqst *rqstp, struct nfsd_createargs *argp, 425 struct nfsd_diropres *resp) 426 { 427 __be32 nfserr; 428 429 dprintk("nfsd: MKDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); 430 431 if (resp->fh.fh_dentry) { 432 printk(KERN_WARNING 433 "nfsd_proc_mkdir: response already verified??\n"); 434 } 435 436 argp->attrs.ia_valid &= ~ATTR_SIZE; 437 fh_init(&resp->fh, NFS_FHSIZE); 438 nfserr = nfsd_create(rqstp, &argp->fh, argp->name, argp->len, 439 &argp->attrs, S_IFDIR, 0, &resp->fh); 440 fh_put(&argp->fh); 441 return nfsd_return_dirop(nfserr, resp); 442 } 443 444 /* 445 * Remove a directory 446 */ 447 static __be32 448 nfsd_proc_rmdir(struct svc_rqst *rqstp, struct nfsd_diropargs *argp, 449 void *resp) 450 { 451 __be32 nfserr; 452 453 dprintk("nfsd: RMDIR %s %.*s\n", SVCFH_fmt(&argp->fh), argp->len, argp->name); 454 455 nfserr = nfsd_unlink(rqstp, &argp->fh, S_IFDIR, argp->name, argp->len); 456 fh_put(&argp->fh); 457 return nfserr; 458 } 459 460 /* 461 * Read a portion of a directory. 462 */ 463 static __be32 464 nfsd_proc_readdir(struct svc_rqst *rqstp, struct nfsd_readdirargs *argp, 465 struct nfsd_readdirres *resp) 466 { 467 int count; 468 __be32 nfserr; 469 loff_t offset; 470 471 dprintk("nfsd: READDIR %s %d bytes at %d\n", 472 SVCFH_fmt(&argp->fh), 473 argp->count, argp->cookie); 474 475 /* Shrink to the client read size */ 476 count = (argp->count >> 2) - 2; 477 478 /* Make sure we've room for the NULL ptr & eof flag */ 479 count -= 2; 480 if (count < 0) 481 count = 0; 482 483 resp->buffer = argp->buffer; 484 resp->offset = NULL; 485 resp->buflen = count; 486 resp->common.err = nfs_ok; 487 /* Read directory and encode entries on the fly */ 488 offset = argp->cookie; 489 nfserr = nfsd_readdir(rqstp, &argp->fh, &offset, 490 &resp->common, nfssvc_encode_entry); 491 492 resp->count = resp->buffer - argp->buffer; 493 if (resp->offset) 494 *resp->offset = htonl(offset); 495 496 fh_put(&argp->fh); 497 return nfserr; 498 } 499 500 /* 501 * Get file system info 502 */ 503 static __be32 504 nfsd_proc_statfs(struct svc_rqst * rqstp, struct nfsd_fhandle *argp, 505 struct nfsd_statfsres *resp) 506 { 507 __be32 nfserr; 508 509 dprintk("nfsd: STATFS %s\n", SVCFH_fmt(&argp->fh)); 510 511 nfserr = nfsd_statfs(rqstp, &argp->fh, &resp->stats, 512 NFSD_MAY_BYPASS_GSS_ON_ROOT); 513 fh_put(&argp->fh); 514 return nfserr; 515 } 516 517 /* 518 * NFSv2 Server procedures. 519 * Only the results of non-idempotent operations are cached. 520 */ 521 struct nfsd_void { int dummy; }; 522 523 #define ST 1 /* status */ 524 #define FH 8 /* filehandle */ 525 #define AT 18 /* attributes */ 526 527 static struct svc_procedure nfsd_procedures2[18] = { 528 [NFSPROC_NULL] = { 529 .pc_func = (svc_procfunc) nfsd_proc_null, 530 .pc_decode = (kxdrproc_t) nfssvc_decode_void, 531 .pc_encode = (kxdrproc_t) nfssvc_encode_void, 532 .pc_argsize = sizeof(struct nfsd_void), 533 .pc_ressize = sizeof(struct nfsd_void), 534 .pc_cachetype = RC_NOCACHE, 535 .pc_xdrressize = ST, 536 }, 537 [NFSPROC_GETATTR] = { 538 .pc_func = (svc_procfunc) nfsd_proc_getattr, 539 .pc_decode = (kxdrproc_t) nfssvc_decode_fhandle, 540 .pc_encode = (kxdrproc_t) nfssvc_encode_attrstat, 541 .pc_release = (kxdrproc_t) nfssvc_release_fhandle, 542 .pc_argsize = sizeof(struct nfsd_fhandle), 543 .pc_ressize = sizeof(struct nfsd_attrstat), 544 .pc_cachetype = RC_NOCACHE, 545 .pc_xdrressize = ST+AT, 546 }, 547 [NFSPROC_SETATTR] = { 548 .pc_func = (svc_procfunc) nfsd_proc_setattr, 549 .pc_decode = (kxdrproc_t) nfssvc_decode_sattrargs, 550 .pc_encode = (kxdrproc_t) nfssvc_encode_attrstat, 551 .pc_release = (kxdrproc_t) nfssvc_release_fhandle, 552 .pc_argsize = sizeof(struct nfsd_sattrargs), 553 .pc_ressize = sizeof(struct nfsd_attrstat), 554 .pc_cachetype = RC_REPLBUFF, 555 .pc_xdrressize = ST+AT, 556 }, 557 [NFSPROC_ROOT] = { 558 .pc_decode = (kxdrproc_t) nfssvc_decode_void, 559 .pc_encode = (kxdrproc_t) nfssvc_encode_void, 560 .pc_argsize = sizeof(struct nfsd_void), 561 .pc_ressize = sizeof(struct nfsd_void), 562 .pc_cachetype = RC_NOCACHE, 563 .pc_xdrressize = ST, 564 }, 565 [NFSPROC_LOOKUP] = { 566 .pc_func = (svc_procfunc) nfsd_proc_lookup, 567 .pc_decode = (kxdrproc_t) nfssvc_decode_diropargs, 568 .pc_encode = (kxdrproc_t) nfssvc_encode_diropres, 569 .pc_release = (kxdrproc_t) nfssvc_release_fhandle, 570 .pc_argsize = sizeof(struct nfsd_diropargs), 571 .pc_ressize = sizeof(struct nfsd_diropres), 572 .pc_cachetype = RC_NOCACHE, 573 .pc_xdrressize = ST+FH+AT, 574 }, 575 [NFSPROC_READLINK] = { 576 .pc_func = (svc_procfunc) nfsd_proc_readlink, 577 .pc_decode = (kxdrproc_t) nfssvc_decode_readlinkargs, 578 .pc_encode = (kxdrproc_t) nfssvc_encode_readlinkres, 579 .pc_argsize = sizeof(struct nfsd_readlinkargs), 580 .pc_ressize = sizeof(struct nfsd_readlinkres), 581 .pc_cachetype = RC_NOCACHE, 582 .pc_xdrressize = ST+1+NFS_MAXPATHLEN/4, 583 }, 584 [NFSPROC_READ] = { 585 .pc_func = (svc_procfunc) nfsd_proc_read, 586 .pc_decode = (kxdrproc_t) nfssvc_decode_readargs, 587 .pc_encode = (kxdrproc_t) nfssvc_encode_readres, 588 .pc_release = (kxdrproc_t) nfssvc_release_fhandle, 589 .pc_argsize = sizeof(struct nfsd_readargs), 590 .pc_ressize = sizeof(struct nfsd_readres), 591 .pc_cachetype = RC_NOCACHE, 592 .pc_xdrressize = ST+AT+1+NFSSVC_MAXBLKSIZE_V2/4, 593 }, 594 [NFSPROC_WRITECACHE] = { 595 .pc_decode = (kxdrproc_t) nfssvc_decode_void, 596 .pc_encode = (kxdrproc_t) nfssvc_encode_void, 597 .pc_argsize = sizeof(struct nfsd_void), 598 .pc_ressize = sizeof(struct nfsd_void), 599 .pc_cachetype = RC_NOCACHE, 600 .pc_xdrressize = ST, 601 }, 602 [NFSPROC_WRITE] = { 603 .pc_func = (svc_procfunc) nfsd_proc_write, 604 .pc_decode = (kxdrproc_t) nfssvc_decode_writeargs, 605 .pc_encode = (kxdrproc_t) nfssvc_encode_attrstat, 606 .pc_release = (kxdrproc_t) nfssvc_release_fhandle, 607 .pc_argsize = sizeof(struct nfsd_writeargs), 608 .pc_ressize = sizeof(struct nfsd_attrstat), 609 .pc_cachetype = RC_REPLBUFF, 610 .pc_xdrressize = ST+AT, 611 }, 612 [NFSPROC_CREATE] = { 613 .pc_func = (svc_procfunc) nfsd_proc_create, 614 .pc_decode = (kxdrproc_t) nfssvc_decode_createargs, 615 .pc_encode = (kxdrproc_t) nfssvc_encode_diropres, 616 .pc_release = (kxdrproc_t) nfssvc_release_fhandle, 617 .pc_argsize = sizeof(struct nfsd_createargs), 618 .pc_ressize = sizeof(struct nfsd_diropres), 619 .pc_cachetype = RC_REPLBUFF, 620 .pc_xdrressize = ST+FH+AT, 621 }, 622 [NFSPROC_REMOVE] = { 623 .pc_func = (svc_procfunc) nfsd_proc_remove, 624 .pc_decode = (kxdrproc_t) nfssvc_decode_diropargs, 625 .pc_encode = (kxdrproc_t) nfssvc_encode_void, 626 .pc_argsize = sizeof(struct nfsd_diropargs), 627 .pc_ressize = sizeof(struct nfsd_void), 628 .pc_cachetype = RC_REPLSTAT, 629 .pc_xdrressize = ST, 630 }, 631 [NFSPROC_RENAME] = { 632 .pc_func = (svc_procfunc) nfsd_proc_rename, 633 .pc_decode = (kxdrproc_t) nfssvc_decode_renameargs, 634 .pc_encode = (kxdrproc_t) nfssvc_encode_void, 635 .pc_argsize = sizeof(struct nfsd_renameargs), 636 .pc_ressize = sizeof(struct nfsd_void), 637 .pc_cachetype = RC_REPLSTAT, 638 .pc_xdrressize = ST, 639 }, 640 [NFSPROC_LINK] = { 641 .pc_func = (svc_procfunc) nfsd_proc_link, 642 .pc_decode = (kxdrproc_t) nfssvc_decode_linkargs, 643 .pc_encode = (kxdrproc_t) nfssvc_encode_void, 644 .pc_argsize = sizeof(struct nfsd_linkargs), 645 .pc_ressize = sizeof(struct nfsd_void), 646 .pc_cachetype = RC_REPLSTAT, 647 .pc_xdrressize = ST, 648 }, 649 [NFSPROC_SYMLINK] = { 650 .pc_func = (svc_procfunc) nfsd_proc_symlink, 651 .pc_decode = (kxdrproc_t) nfssvc_decode_symlinkargs, 652 .pc_encode = (kxdrproc_t) nfssvc_encode_void, 653 .pc_argsize = sizeof(struct nfsd_symlinkargs), 654 .pc_ressize = sizeof(struct nfsd_void), 655 .pc_cachetype = RC_REPLSTAT, 656 .pc_xdrressize = ST, 657 }, 658 [NFSPROC_MKDIR] = { 659 .pc_func = (svc_procfunc) nfsd_proc_mkdir, 660 .pc_decode = (kxdrproc_t) nfssvc_decode_createargs, 661 .pc_encode = (kxdrproc_t) nfssvc_encode_diropres, 662 .pc_release = (kxdrproc_t) nfssvc_release_fhandle, 663 .pc_argsize = sizeof(struct nfsd_createargs), 664 .pc_ressize = sizeof(struct nfsd_diropres), 665 .pc_cachetype = RC_REPLBUFF, 666 .pc_xdrressize = ST+FH+AT, 667 }, 668 [NFSPROC_RMDIR] = { 669 .pc_func = (svc_procfunc) nfsd_proc_rmdir, 670 .pc_decode = (kxdrproc_t) nfssvc_decode_diropargs, 671 .pc_encode = (kxdrproc_t) nfssvc_encode_void, 672 .pc_argsize = sizeof(struct nfsd_diropargs), 673 .pc_ressize = sizeof(struct nfsd_void), 674 .pc_cachetype = RC_REPLSTAT, 675 .pc_xdrressize = ST, 676 }, 677 [NFSPROC_READDIR] = { 678 .pc_func = (svc_procfunc) nfsd_proc_readdir, 679 .pc_decode = (kxdrproc_t) nfssvc_decode_readdirargs, 680 .pc_encode = (kxdrproc_t) nfssvc_encode_readdirres, 681 .pc_argsize = sizeof(struct nfsd_readdirargs), 682 .pc_ressize = sizeof(struct nfsd_readdirres), 683 .pc_cachetype = RC_NOCACHE, 684 }, 685 [NFSPROC_STATFS] = { 686 .pc_func = (svc_procfunc) nfsd_proc_statfs, 687 .pc_decode = (kxdrproc_t) nfssvc_decode_fhandle, 688 .pc_encode = (kxdrproc_t) nfssvc_encode_statfsres, 689 .pc_argsize = sizeof(struct nfsd_fhandle), 690 .pc_ressize = sizeof(struct nfsd_statfsres), 691 .pc_cachetype = RC_NOCACHE, 692 .pc_xdrressize = ST+5, 693 }, 694 }; 695 696 697 struct svc_version nfsd_version2 = { 698 .vs_vers = 2, 699 .vs_nproc = 18, 700 .vs_proc = nfsd_procedures2, 701 .vs_dispatch = nfsd_dispatch, 702 .vs_xdrsize = NFS2_SVC_XDRSIZE, 703 }; 704 705 /* 706 * Map errnos to NFS errnos. 707 */ 708 __be32 709 nfserrno (int errno) 710 { 711 static struct { 712 __be32 nfserr; 713 int syserr; 714 } nfs_errtbl[] = { 715 { nfs_ok, 0 }, 716 { nfserr_perm, -EPERM }, 717 { nfserr_noent, -ENOENT }, 718 { nfserr_io, -EIO }, 719 { nfserr_nxio, -ENXIO }, 720 { nfserr_acces, -EACCES }, 721 { nfserr_exist, -EEXIST }, 722 { nfserr_xdev, -EXDEV }, 723 { nfserr_mlink, -EMLINK }, 724 { nfserr_nodev, -ENODEV }, 725 { nfserr_notdir, -ENOTDIR }, 726 { nfserr_isdir, -EISDIR }, 727 { nfserr_inval, -EINVAL }, 728 { nfserr_fbig, -EFBIG }, 729 { nfserr_nospc, -ENOSPC }, 730 { nfserr_rofs, -EROFS }, 731 { nfserr_mlink, -EMLINK }, 732 { nfserr_nametoolong, -ENAMETOOLONG }, 733 { nfserr_notempty, -ENOTEMPTY }, 734 #ifdef EDQUOT 735 { nfserr_dquot, -EDQUOT }, 736 #endif 737 { nfserr_stale, -ESTALE }, 738 { nfserr_jukebox, -ETIMEDOUT }, 739 { nfserr_jukebox, -ERESTARTSYS }, 740 { nfserr_dropit, -EAGAIN }, 741 { nfserr_dropit, -ENOMEM }, 742 { nfserr_badname, -ESRCH }, 743 { nfserr_io, -ETXTBSY }, 744 { nfserr_notsupp, -EOPNOTSUPP }, 745 { nfserr_toosmall, -ETOOSMALL }, 746 { nfserr_serverfault, -ESERVERFAULT }, 747 }; 748 int i; 749 750 for (i = 0; i < ARRAY_SIZE(nfs_errtbl); i++) { 751 if (nfs_errtbl[i].syserr == errno) 752 return nfs_errtbl[i].nfserr; 753 } 754 printk (KERN_INFO "nfsd: non-standard errno: %d\n", errno); 755 return nfserr_io; 756 } 757 758