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