1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Rick Macklem at The University of Guelph. 7 * 8 * %sccs.include.redist.c% 9 * 10 * @(#)nfs_vnops.c 7.66 (Berkeley) 01/22/92 11 */ 12 13 /* 14 * vnode op calls for sun nfs version 2 15 */ 16 17 #include "param.h" 18 #include "proc.h" 19 #include "kernel.h" 20 #include "systm.h" 21 #include "mount.h" 22 #include "buf.h" 23 #include "malloc.h" 24 #include "mbuf.h" 25 #include "conf.h" 26 #include "namei.h" 27 #include "vnode.h" 28 #include "specdev.h" 29 #include "fifo.h" 30 #include "map.h" 31 32 #include "ufs/ufs/quota.h" 33 #include "ufs/ufs/inode.h" 34 #include "ufs/ufs/dir.h" 35 36 #include "rpcv2.h" 37 #include "nfsv2.h" 38 #include "nfs.h" 39 #include "nfsnode.h" 40 #include "nfsmount.h" 41 #include "xdr_subs.h" 42 #include "nfsm_subs.h" 43 #include "nqnfs.h" 44 45 /* Defs */ 46 #define TRUE 1 47 #define FALSE 0 48 49 /* 50 * Global vfs data structures for nfs 51 */ 52 struct vnodeops nfsv2_vnodeops = { 53 nfs_lookup, /* lookup */ 54 nfs_create, /* create */ 55 nfs_mknod, /* mknod */ 56 nfs_open, /* open */ 57 nfs_close, /* close */ 58 nfs_access, /* access */ 59 nfs_getattr, /* getattr */ 60 nfs_setattr, /* setattr */ 61 nfs_read, /* read */ 62 nfs_write, /* write */ 63 nfs_ioctl, /* ioctl */ 64 nfs_select, /* select */ 65 nfs_mmap, /* mmap */ 66 nfs_fsync, /* fsync */ 67 nfs_seek, /* seek */ 68 nfs_remove, /* remove */ 69 nfs_link, /* link */ 70 nfs_rename, /* rename */ 71 nfs_mkdir, /* mkdir */ 72 nfs_rmdir, /* rmdir */ 73 nfs_symlink, /* symlink */ 74 nfs_readdir, /* readdir */ 75 nfs_readlink, /* readlink */ 76 nfs_abortop, /* abortop */ 77 nfs_inactive, /* inactive */ 78 nfs_reclaim, /* reclaim */ 79 nfs_lock, /* lock */ 80 nfs_unlock, /* unlock */ 81 nfs_bmap, /* bmap */ 82 nfs_strategy, /* strategy */ 83 nfs_print, /* print */ 84 nfs_islocked, /* islocked */ 85 nfs_advlock, /* advlock */ 86 nfs_blkatoff, /* blkatoff */ 87 nfs_vget, /* vget */ 88 nfs_valloc, /* valloc */ 89 nfs_vfree, /* vfree */ 90 nfs_truncate, /* truncate */ 91 nfs_update, /* update */ 92 bwrite, /* bwrite */ 93 }; 94 95 /* 96 * Special device vnode ops 97 */ 98 struct vnodeops spec_nfsv2nodeops = { 99 spec_lookup, /* lookup */ 100 spec_create, /* create */ 101 spec_mknod, /* mknod */ 102 spec_open, /* open */ 103 spec_close, /* close */ 104 nfs_access, /* access */ 105 nfs_getattr, /* getattr */ 106 nfs_setattr, /* setattr */ 107 spec_read, /* read */ 108 spec_write, /* write */ 109 spec_ioctl, /* ioctl */ 110 spec_select, /* select */ 111 spec_mmap, /* mmap */ 112 spec_fsync, /* fsync */ 113 spec_seek, /* seek */ 114 spec_remove, /* remove */ 115 spec_link, /* link */ 116 spec_rename, /* rename */ 117 spec_mkdir, /* mkdir */ 118 spec_rmdir, /* rmdir */ 119 spec_symlink, /* symlink */ 120 spec_readdir, /* readdir */ 121 spec_readlink, /* readlink */ 122 spec_abortop, /* abortop */ 123 nfs_inactive, /* inactive */ 124 nfs_reclaim, /* reclaim */ 125 nfs_lock, /* lock */ 126 nfs_unlock, /* unlock */ 127 spec_bmap, /* bmap */ 128 spec_strategy, /* strategy */ 129 nfs_print, /* print */ 130 nfs_islocked, /* islocked */ 131 spec_advlock, /* advlock */ 132 spec_blkatoff, /* blkatoff */ 133 spec_vget, /* vget */ 134 spec_valloc, /* valloc */ 135 spec_vfree, /* vfree */ 136 spec_truncate, /* truncate */ 137 nfs_update, /* update */ 138 bwrite, /* bwrite */ 139 }; 140 141 #ifdef FIFO 142 struct vnodeops fifo_nfsv2nodeops = { 143 fifo_lookup, /* lookup */ 144 fifo_create, /* create */ 145 fifo_mknod, /* mknod */ 146 fifo_open, /* open */ 147 fifo_close, /* close */ 148 nfs_access, /* access */ 149 nfs_getattr, /* getattr */ 150 nfs_setattr, /* setattr */ 151 fifo_read, /* read */ 152 fifo_write, /* write */ 153 fifo_ioctl, /* ioctl */ 154 fifo_select, /* select */ 155 fifo_mmap, /* mmap */ 156 fifo_fsync, /* fsync */ 157 fifo_seek, /* seek */ 158 fifo_remove, /* remove */ 159 fifo_link, /* link */ 160 fifo_rename, /* rename */ 161 fifo_mkdir, /* mkdir */ 162 fifo_rmdir, /* rmdir */ 163 fifo_symlink, /* symlink */ 164 fifo_readdir, /* readdir */ 165 fifo_readlink, /* readlink */ 166 fifo_abortop, /* abortop */ 167 nfs_inactive, /* inactive */ 168 nfs_reclaim, /* reclaim */ 169 nfs_lock, /* lock */ 170 nfs_unlock, /* unlock */ 171 fifo_bmap, /* bmap */ 172 fifo_badop, /* strategy */ 173 nfs_print, /* print */ 174 nfs_islocked, /* islocked */ 175 fifo_advlock, /* advlock */ 176 fifo_blkatoff, /* blkatoff */ 177 fifo_vget, /* vget */ 178 fifo_valloc, /* valloc */ 179 fifo_vfree, /* vfree */ 180 fifo_truncate, /* truncate */ 181 nfs_update, /* update */ 182 bwrite, /* bwrite */ 183 }; 184 #endif /* FIFO */ 185 186 /* 187 * Global variables 188 */ 189 extern u_long nfs_procids[NFS_NPROCS]; 190 extern u_long nfs_prog, nfs_vers; 191 extern char nfsiobuf[MAXPHYS+NBPG]; 192 struct buf nfs_bqueue; /* Queue head for nfsiod's */ 193 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 194 int nfs_numasync = 0; 195 #define DIRHDSIZ (sizeof (struct direct) - (MAXNAMLEN + 1)) 196 197 /* 198 * nfs null call from vfs. 199 */ 200 int 201 nfs_null(vp, cred, procp) 202 struct vnode *vp; 203 struct ucred *cred; 204 struct proc *procp; 205 { 206 caddr_t bpos, dpos; 207 int error = 0; 208 struct mbuf *mreq, *mrep, *md, *mb; 209 210 nfsm_reqhead(vp, NFSPROC_NULL, 0); 211 nfsm_request(vp, NFSPROC_NULL, procp, cred); 212 nfsm_reqdone; 213 return (error); 214 } 215 216 /* 217 * nfs access vnode op. 218 * Essentially just get vattr and then imitate iaccess() 219 */ 220 int 221 nfs_access(vp, mode, cred, procp) 222 struct vnode *vp; 223 int mode; 224 register struct ucred *cred; 225 struct proc *procp; 226 { 227 register struct vattr *vap; 228 register gid_t *gp; 229 struct vattr vattr; 230 register int i; 231 int error; 232 233 /* 234 * If you're the super-user, 235 * you always get access. 236 */ 237 if (cred->cr_uid == 0) 238 return (0); 239 vap = &vattr; 240 if (error = nfs_getattr(vp, vap, cred, procp)) 241 return (error); 242 /* 243 * Access check is based on only one of owner, group, public. 244 * If not owner, then check group. If not a member of the 245 * group, then check public access. 246 */ 247 if (cred->cr_uid != vap->va_uid) { 248 mode >>= 3; 249 gp = cred->cr_groups; 250 for (i = 0; i < cred->cr_ngroups; i++, gp++) 251 if (vap->va_gid == *gp) 252 goto found; 253 mode >>= 3; 254 found: 255 ; 256 } 257 if ((vap->va_mode & mode) != 0) 258 return (0); 259 return (EACCES); 260 } 261 262 /* 263 * nfs open vnode op 264 * Just check to see if the type is ok 265 * and that deletion is not in progress. 266 */ 267 /* ARGSUSED */ 268 int 269 nfs_open(vp, mode, cred, procp) 270 register struct vnode *vp; 271 int mode; 272 struct ucred *cred; 273 struct proc *procp; 274 { 275 276 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) 277 return (EACCES); 278 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0) 279 VTONFS(vp)->n_attrstamp = 0; /* For Open/Close consistency */ 280 return (0); 281 } 282 283 /* 284 * nfs close vnode op 285 * For reg files, invalidate any buffer cache entries. 286 */ 287 /* ARGSUSED */ 288 int 289 nfs_close(vp, fflags, cred, procp) 290 register struct vnode *vp; 291 int fflags; 292 struct ucred *cred; 293 struct proc *procp; 294 { 295 register struct nfsnode *np = VTONFS(vp); 296 int error = 0; 297 298 if ((np->n_flag & NMODIFIED) && 299 (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 && 300 vp->v_type == VREG) { 301 np->n_flag &= ~NMODIFIED; 302 vinvalbuf(vp, TRUE); 303 np->n_attrstamp = 0; 304 if (np->n_flag & NWRITEERR) { 305 np->n_flag &= ~NWRITEERR; 306 error = np->n_error; 307 } 308 } 309 return (error); 310 } 311 312 /* 313 * nfs getattr call from vfs. 314 */ 315 int 316 nfs_getattr(vp, vap, cred, procp) 317 register struct vnode *vp; 318 struct vattr *vap; 319 struct ucred *cred; 320 struct proc *procp; 321 { 322 register caddr_t cp; 323 caddr_t bpos, dpos; 324 int error = 0; 325 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 326 327 /* First look in the cache.. */ 328 if (nfs_getattrcache(vp, vap) == 0) 329 return (0); 330 nfsstats.rpccnt[NFSPROC_GETATTR]++; 331 nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH); 332 nfsm_fhtom(vp); 333 nfsm_request(vp, NFSPROC_GETATTR, procp, cred); 334 nfsm_loadattr(vp, vap); 335 nfsm_reqdone; 336 return (error); 337 } 338 339 /* 340 * nfs setattr call. 341 */ 342 int 343 nfs_setattr(vp, vap, cred, procp) 344 register struct vnode *vp; 345 register struct vattr *vap; 346 struct ucred *cred; 347 struct proc *procp; 348 { 349 register struct nfsv2_sattr *sp; 350 register caddr_t cp; 351 register long t1; 352 caddr_t bpos, dpos, cp2; 353 u_long *tl; 354 int error = 0; 355 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 356 struct nfsnode *np = VTONFS(vp); 357 u_quad_t frev; 358 359 nfsstats.rpccnt[NFSPROC_SETATTR]++; 360 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH+NFSX_SATTR); 361 nfsm_fhtom(vp); 362 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR); 363 if (vap->va_mode == 0xffff) 364 sp->sa_mode = VNOVAL; 365 else 366 sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode); 367 if (vap->va_uid == 0xffff) 368 sp->sa_uid = VNOVAL; 369 else 370 sp->sa_uid = txdr_unsigned(vap->va_uid); 371 if (vap->va_gid == 0xffff) 372 sp->sa_gid = VNOVAL; 373 else 374 sp->sa_gid = txdr_unsigned(vap->va_gid); 375 sp->sa_size = txdr_unsigned(vap->va_size); 376 sp->sa_atime.tv_sec = txdr_unsigned(vap->va_atime.tv_sec); 377 sp->sa_atime.tv_usec = txdr_unsigned(vap->va_flags); 378 txdr_time(&vap->va_mtime, &sp->sa_mtime); 379 if (vap->va_size != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || 380 vap->va_atime.tv_sec != VNOVAL) { 381 if (np->n_flag & NMODIFIED) { 382 np->n_flag &= ~NMODIFIED; 383 if (vap->va_size == 0) 384 vinvalbuf(vp, FALSE); 385 else 386 vinvalbuf(vp, TRUE); 387 } 388 } 389 nfsm_request(vp, NFSPROC_SETATTR, procp, cred); 390 nfsm_loadattr(vp, (struct vattr *)0); 391 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) && 392 NQNFS_CKCACHABLE(vp, NQL_WRITE)) { 393 nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED); 394 fxdr_hyper(tl, &frev); 395 if (QUADGT(frev, np->n_brev)) 396 np->n_brev = frev; 397 } 398 nfsm_reqdone; 399 return (error); 400 } 401 402 /* 403 * nfs lookup call, one step at a time... 404 * First look in cache 405 * If not found, unlock the directory nfsnode and do the rpc 406 */ 407 int 408 nfs_lookup(dvp, vpp, cnp) /* converted to CN */ 409 /* old: nfs_lookup(vp, ndp, procp) */ 410 struct vnode *dvp; 411 struct vnode **vpp; 412 struct componentname *cnp; 413 { 414 register struct vnode *vdp; 415 register u_long *tl; 416 register caddr_t cp; 417 register long t1, t2; 418 struct nfsmount *nmp; 419 struct nfsnode *tp; 420 caddr_t bpos, dpos, cp2; 421 time_t reqtime; 422 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 423 struct vnode *newvp; 424 long len; 425 nfsv2fh_t *fhp; 426 struct nfsnode *np; 427 int lockparent, wantparent, error = 0; 428 int nqlflag, cachable; 429 u_quad_t frev; 430 431 *vpp = NULL; 432 if (dvp->v_type != VDIR) 433 return (ENOTDIR); 434 lockparent = cnp->cn_flags & LOCKPARENT; 435 wantparent = cnp->cn_flags & (LOCKPARENT|WANTPARENT); 436 nmp = VFSTONFS(dvp->v_mount); 437 np = VTONFS(dvp); 438 if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) { 439 struct vattr vattr; 440 int vpid; 441 442 vdp = *vpp; 443 vpid = vdp->v_id; 444 /* 445 * See the comment starting `Step through' in ufs/ufs_lookup.c 446 * for an explanation of the locking protocol 447 */ 448 if (dvp == vdp) { 449 VREF(vdp); 450 error = 0; 451 } else 452 error = vget(vdp); 453 if (!error) { 454 if (vpid == vdp->v_id) { 455 if (nmp->nm_flag & NFSMNT_NQNFS) { 456 if (NQNFS_CKCACHABLE(dvp, NQL_READ)) { 457 if (QUADNE(np->n_lrev, np->n_brev) || 458 (np->n_flag & NMODIFIED)) { 459 np->n_direofoffset = 0; 460 cache_purge(dvp); 461 np->n_flag &= ~NMODIFIED; 462 vinvalbuf(dvp, FALSE); 463 np->n_brev = np->n_lrev; 464 } else { 465 nfsstats.lookupcache_hits++; 466 if (cnp->cn_nameiop != LOOKUP && 467 (cnp->cn_flags&ISLASTCN)) 468 cnp->cn_flags |= SAVENAME; 469 return (0); 470 } 471 } 472 } else if (!nfs_getattr(vdp, &vattr, cnp->cn_cred, cnp->cn_proc) && 473 vattr.va_ctime.tv_sec == VTONFS(vdp)->n_ctime) { 474 nfsstats.lookupcache_hits++; 475 if (cnp->cn_nameiop != LOOKUP && (cnp->cn_flags&ISLASTCN)) 476 cnp->cn_flags |= SAVENAME; 477 return (0); 478 } 479 cache_purge(vdp); 480 } 481 vrele(vdp); 482 } 483 *vpp = NULLVP; 484 } 485 error = 0; 486 nfsstats.lookupcache_misses++; 487 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 488 len = cnp->cn_namelen; 489 nfsm_reqhead(dvp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 490 491 /* 492 * For nqnfs optionally piggyback a getlease request for the name 493 * being looked up. 494 */ 495 if (nmp->nm_flag & NFSMNT_NQNFS) { 496 if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) && 497 ((cnp->cn_flags&MAKEENTRY) && (cnp->cn_nameiop != DELETE || !(cnp->cn_flags&ISLASTCN)))) { 498 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED); 499 *tl++ = txdr_unsigned(NQL_READ); 500 *tl = txdr_unsigned(nmp->nm_leaseterm); 501 } else { 502 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 503 *tl = 0; 504 } 505 } 506 nfsm_fhtom(dvp); 507 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 508 reqtime = time.tv_sec; 509 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 510 nfsmout: 511 if (error) { 512 if (cnp->cn_nameiop != LOOKUP && (cnp->cn_flags&ISLASTCN)) 513 cnp->cn_flags |= SAVENAME; 514 return (error); 515 } 516 if (nmp->nm_flag & NFSMNT_NQNFS) { 517 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 518 if (*tl) { 519 nqlflag = fxdr_unsigned(int, *tl); 520 nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED); 521 cachable = fxdr_unsigned(int, *tl++); 522 reqtime += fxdr_unsigned(int, *tl++); 523 fxdr_hyper(tl, &frev); 524 } else 525 nqlflag = 0; 526 } 527 nfsm_dissect(fhp, nfsv2fh_t *, NFSX_FH); 528 529 /* 530 * Handle RENAME case... 531 */ 532 if (cnp->cn_nameiop == RENAME && wantparent && (cnp->cn_flags&ISLASTCN)) { 533 if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 534 m_freem(mrep); 535 return (EISDIR); 536 } 537 if (error = nfs_nget(dvp->v_mount, fhp, &np)) { 538 m_freem(mrep); 539 return (error); 540 } 541 newvp = NFSTOV(np); 542 if (error = 543 nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 544 vrele(newvp); 545 m_freem(mrep); 546 return (error); 547 } 548 *vpp = newvp; 549 m_freem(mrep); 550 cnp->cn_flags |= SAVENAME; 551 return (0); 552 } 553 554 if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 555 VREF(dvp); 556 newvp = dvp; 557 } else { 558 if (error = nfs_nget(dvp->v_mount, fhp, &np)) { 559 m_freem(mrep); 560 return (error); 561 } 562 newvp = NFSTOV(np); 563 } 564 if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 565 vrele(newvp); 566 m_freem(mrep); 567 return (error); 568 } 569 m_freem(mrep); 570 *vpp = newvp; 571 if (cnp->cn_nameiop != LOOKUP && (cnp->cn_flags&ISLASTCN)) 572 cnp->cn_flags |= SAVENAME; 573 if ((cnp->cn_flags&MAKEENTRY) && (cnp->cn_nameiop != DELETE || !(cnp->cn_flags&ISLASTCN))) { 574 if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) 575 np->n_ctime = np->n_vattr.va_ctime.tv_sec; 576 else if (nqlflag && reqtime > time.tv_sec) { 577 if (np->n_tnext) { 578 if (np->n_tnext == (struct nfsnode *)nmp) 579 nmp->nm_tprev = np->n_tprev; 580 else 581 np->n_tnext->n_tprev = np->n_tprev; 582 if (np->n_tprev == (struct nfsnode *)nmp) 583 nmp->nm_tnext = np->n_tnext; 584 else 585 np->n_tprev->n_tnext = np->n_tnext; 586 if (nqlflag == NQL_WRITE) 587 np->n_flag |= NQNFSWRITE; 588 } else if (nqlflag == NQL_READ) 589 np->n_flag &= ~NQNFSWRITE; 590 else 591 np->n_flag |= NQNFSWRITE; 592 if (cachable) 593 np->n_flag &= ~NQNFSNONCACHE; 594 else 595 np->n_flag |= NQNFSNONCACHE; 596 np->n_expiry = reqtime; 597 np->n_lrev = frev; 598 tp = nmp->nm_tprev; 599 while (tp != (struct nfsnode *)nmp && tp->n_expiry > np->n_expiry) 600 tp = tp->n_tprev; 601 if (tp == (struct nfsnode *)nmp) { 602 np->n_tnext = nmp->nm_tnext; 603 nmp->nm_tnext = np; 604 } else { 605 np->n_tnext = tp->n_tnext; 606 tp->n_tnext = np; 607 } 608 np->n_tprev = tp; 609 if (np->n_tnext == (struct nfsnode *)nmp) 610 nmp->nm_tprev = np; 611 else 612 np->n_tnext->n_tprev = np; 613 } 614 cache_enter(dvp, *vpp, cnp); 615 } 616 return (0); 617 } 618 619 /* 620 * nfs read call. 621 * Just call nfs_bioread() to do the work. 622 */ 623 int 624 nfs_read(vp, uiop, ioflag, cred) 625 register struct vnode *vp; 626 struct uio *uiop; 627 int ioflag; 628 struct ucred *cred; 629 { 630 if (vp->v_type != VREG) 631 return (EPERM); 632 return (nfs_bioread(vp, uiop, ioflag, cred)); 633 } 634 635 /* 636 * nfs readlink call 637 */ 638 int 639 nfs_readlink(vp, uiop, cred) 640 struct vnode *vp; 641 struct uio *uiop; 642 struct ucred *cred; 643 { 644 if (vp->v_type != VLNK) 645 return (EPERM); 646 return (nfs_bioread(vp, uiop, 0, cred)); 647 } 648 649 /* 650 * Do a readlink rpc. 651 * Called by nfs_doio() from below the buffer cache. 652 */ 653 int 654 nfs_readlinkrpc(vp, uiop, cred) 655 register struct vnode *vp; 656 struct uio *uiop; 657 struct ucred *cred; 658 { 659 register u_long *tl; 660 register caddr_t cp; 661 register long t1; 662 caddr_t bpos, dpos, cp2; 663 int error = 0; 664 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 665 long len; 666 667 nfsstats.rpccnt[NFSPROC_READLINK]++; 668 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH); 669 nfsm_fhtom(vp); 670 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred); 671 nfsm_strsiz(len, NFS_MAXPATHLEN); 672 nfsm_mtouio(uiop, len); 673 nfsm_reqdone; 674 return (error); 675 } 676 677 /* 678 * nfs read rpc call 679 * Ditto above 680 */ 681 int 682 nfs_readrpc(vp, uiop, cred) 683 register struct vnode *vp; 684 struct uio *uiop; 685 struct ucred *cred; 686 { 687 register u_long *tl; 688 register caddr_t cp; 689 register long t1; 690 caddr_t bpos, dpos, cp2; 691 int error = 0; 692 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 693 struct nfsmount *nmp; 694 long len, retlen, tsiz; 695 696 nmp = VFSTONFS(vp->v_mount); 697 tsiz = uiop->uio_resid; 698 while (tsiz > 0) { 699 nfsstats.rpccnt[NFSPROC_READ]++; 700 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 701 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH+NFSX_UNSIGNED*3); 702 nfsm_fhtom(vp); 703 nfsm_build(tl, u_long *, NFSX_UNSIGNED*3); 704 *tl++ = txdr_unsigned(uiop->uio_offset); 705 *tl++ = txdr_unsigned(len); 706 *tl = 0; 707 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred); 708 nfsm_loadattr(vp, (struct vattr *)0); 709 nfsm_strsiz(retlen, nmp->nm_rsize); 710 nfsm_mtouio(uiop, retlen); 711 m_freem(mrep); 712 if (retlen < len) 713 tsiz = 0; 714 else 715 tsiz -= len; 716 } 717 nfsmout: 718 return (error); 719 } 720 721 /* 722 * nfs write call 723 */ 724 int 725 nfs_writerpc(vp, uiop, cred) 726 register struct vnode *vp; 727 struct uio *uiop; 728 struct ucred *cred; 729 { 730 register u_long *tl; 731 register caddr_t cp; 732 register long t1; 733 caddr_t bpos, dpos, cp2; 734 int error = 0; 735 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 736 struct nfsmount *nmp; 737 struct nfsnode *np = VTONFS(vp); 738 u_quad_t frev; 739 long len, tsiz; 740 741 nmp = VFSTONFS(vp->v_mount); 742 tsiz = uiop->uio_resid; 743 while (tsiz > 0) { 744 nfsstats.rpccnt[NFSPROC_WRITE]++; 745 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 746 nfsm_reqhead(vp, NFSPROC_WRITE, 747 NFSX_FH+NFSX_UNSIGNED*4+nfsm_rndup(len)); 748 nfsm_fhtom(vp); 749 nfsm_build(tl, u_long *, NFSX_UNSIGNED*4); 750 *(tl+1) = txdr_unsigned(uiop->uio_offset); 751 *(tl+3) = txdr_unsigned(len); 752 nfsm_uiotom(uiop, len); 753 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred); 754 nfsm_loadattr(vp, (struct vattr *)0); 755 if (nmp->nm_flag & NFSMNT_MYWRITE) 756 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec; 757 else if ((nmp->nm_flag & NFSMNT_NQNFS) && 758 NQNFS_CKCACHABLE(vp, NQL_WRITE)) { 759 nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED); 760 fxdr_hyper(tl, &frev); 761 if (QUADGT(frev, np->n_brev)) 762 np->n_brev = frev; 763 } 764 m_freem(mrep); 765 tsiz -= len; 766 } 767 nfsmout: 768 if (error) 769 uiop->uio_resid = tsiz; 770 return (error); 771 } 772 773 /* 774 * nfs mknod call 775 * This is a kludge. Use a create rpc but with the IFMT bits of the mode 776 * set to specify the file type and the size field for rdev. 777 */ 778 /* ARGSUSED */ 779 int 780 nfs_mknod(dvp, vpp, cnp, vap) /* converted to CN. */ 781 /* old: nfs_mknod(ndp, vap, cred, procp) */ 782 struct vnode *dvp; 783 struct vnode **vpp; 784 struct componentname *cnp; 785 struct vattr *vap; 786 { 787 register struct nfsv2_sattr *sp; 788 register u_long *tl; 789 register caddr_t cp; 790 register long t2; 791 caddr_t bpos, dpos; 792 int error = 0; 793 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 794 u_long rdev; 795 796 if (vap->va_type == VCHR || vap->va_type == VBLK) 797 rdev = txdr_unsigned(vap->va_rdev); 798 #ifdef FIFO 799 else if (vap->va_type == VFIFO) 800 rdev = 0xffffffff; 801 #endif /* FIFO */ 802 else { 803 VOP_ABORTOP(dvp, cnp); 804 vput(dvp); 805 return (EOPNOTSUPP); 806 } 807 nfsstats.rpccnt[NFSPROC_CREATE]++; 808 nfsm_reqhead(dvp, NFSPROC_CREATE, 809 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR); 810 nfsm_fhtom(dvp); 811 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 812 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR); 813 sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 814 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 815 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 816 sp->sa_size = rdev; 817 /* or should these be VNOVAL ?? */ 818 txdr_time(&vap->va_atime, &sp->sa_atime); 819 txdr_time(&vap->va_mtime, &sp->sa_mtime); 820 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 821 nfsm_reqdone; 822 FREE(cnp->cn_pnbuf, M_NAMEI); 823 VTONFS(dvp)->n_flag |= NMODIFIED; 824 vrele(dvp); 825 return (error); 826 } 827 828 /* 829 * nfs file create call 830 */ 831 int 832 nfs_create(dvp, vpp, cnp, vap) /* converted to CN. */ 833 /* old: nfs_create(ndp, vap, procp) */ 834 struct vnode *dvp; 835 struct vnode **vpp; 836 struct componentname *cnp; 837 struct vattr *vap; 838 { 839 register struct nfsv2_sattr *sp; 840 register u_long *tl; 841 register caddr_t cp; 842 register long t1, t2; 843 caddr_t bpos, dpos, cp2; 844 int error = 0; 845 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 846 847 nfsstats.rpccnt[NFSPROC_CREATE]++; 848 nfsm_reqhead(dvp, NFSPROC_CREATE, 849 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR); 850 nfsm_fhtom(dvp); 851 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 852 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR); 853 sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 854 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 855 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 856 sp->sa_size = txdr_unsigned(0); 857 /* or should these be VNOVAL ?? */ 858 txdr_time(&vap->va_atime, &sp->sa_atime); 859 txdr_time(&vap->va_mtime, &sp->sa_mtime); 860 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 861 nfsm_mtofh(dvp, *vpp); 862 nfsm_reqdone; 863 FREE(cnp->cn_pnbuf, M_NAMEI); 864 VTONFS(dvp)->n_flag |= NMODIFIED; 865 vrele(dvp); 866 return (error); 867 } 868 869 /* 870 * nfs file remove call 871 * To try and make nfs semantics closer to ufs semantics, a file that has 872 * other processes using the vnode is renamed instead of removed and then 873 * removed later on the last close. 874 * - If v_usecount > 1 875 * If a rename is not already in the works 876 * call nfs_sillyrename() to set it up 877 * else 878 * do the remove rpc 879 */ 880 int 881 nfs_remove(dvp, vp, cnp) /* converted to CN. */ 882 /* old: ufs_remove(ndp, p) */ 883 struct vnode *dvp, *vp; 884 struct componentname *cnp; 885 { 886 register struct nfsnode *np = VTONFS(vp); 887 register u_long *tl; 888 register caddr_t cp; 889 register long t2; 890 caddr_t bpos, dpos; 891 int error = 0; 892 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 893 894 if (vp->v_usecount > 1) { 895 if (!np->n_sillyrename) 896 error = nfs_sillyrename(dvp, vp, cnp); /* NEEDSWORK */ 897 } else { 898 /* 899 * Purge the name cache so that the chance of a lookup for 900 * the name succeeding while the remove is in progress is 901 * minimized. Without node locking it can still happen, such 902 * that an I/O op returns ESTALE, but since you get this if 903 * another host removes the file.. 904 */ 905 cache_purge(vp); 906 /* 907 * Throw away biocache buffers. Mainly to avoid 908 * unnecessary delayed writes. 909 */ 910 vinvalbuf(vp, FALSE); 911 /* Do the rpc */ 912 nfsstats.rpccnt[NFSPROC_REMOVE]++; 913 nfsm_reqhead(dvp, NFSPROC_REMOVE, 914 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 915 nfsm_fhtom(dvp); 916 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 917 nfsm_request(dvp, NFSPROC_REMOVE, cnp->cn_proc, cnp->cn_cred); 918 nfsm_reqdone; 919 FREE(cnp->cn_pnbuf, M_NAMEI); 920 VTONFS(dvp)->n_flag |= NMODIFIED; 921 /* 922 * Kludge City: If the first reply to the remove rpc is lost.. 923 * the reply to the retransmitted request will be ENOENT 924 * since the file was in fact removed 925 * Therefore, we cheat and return success. 926 */ 927 if (error == ENOENT) 928 error = 0; 929 } 930 np->n_attrstamp = 0; 931 vrele(dvp); 932 vrele(vp); 933 return (error); 934 } 935 936 /* 937 * nfs file remove rpc called from nfs_inactive 938 */ 939 int 940 nfs_removeit(sp, procp) 941 register struct sillyrename *sp; 942 struct proc *procp; 943 { 944 register u_long *tl; 945 register caddr_t cp; 946 register long t2; 947 caddr_t bpos, dpos; 948 int error = 0; 949 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 950 951 nfsstats.rpccnt[NFSPROC_REMOVE]++; 952 nfsm_reqhead(sp->s_dvp, NFSPROC_REMOVE, 953 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(sp->s_namlen)); 954 nfsm_fhtom(sp->s_dvp); 955 nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN); 956 nfsm_request(sp->s_dvp, NFSPROC_REMOVE, procp, sp->s_cred); 957 nfsm_reqdone; 958 VTONFS(sp->s_dvp)->n_flag |= NMODIFIED; 959 return (error); 960 } 961 962 /* 963 * nfs file rename call 964 */ 965 int 966 nfs_rename(fdvp, fvp, fcnp, 967 tdvp, tvp, tcnp) /* converted to CN. */ 968 /* old: nfs_rename(sndp, tndp, procp) */ 969 struct vnode *fdvp, *fvp; 970 struct componentname *fcnp; 971 struct vnode *tdvp, *tvp; 972 struct componentname *tcnp; 973 { 974 register u_long *tl; 975 register caddr_t cp; 976 register long t2; 977 caddr_t bpos, dpos; 978 int error = 0; 979 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 980 981 nfsstats.rpccnt[NFSPROC_RENAME]++; 982 nfsm_reqhead(fdvp, NFSPROC_RENAME, 983 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(fcnp->cn_namelen)+ 984 nfsm_rndup(fcnp->cn_namelen)); /* or fcnp->cn_cred?*/ 985 nfsm_fhtom(fdvp); 986 nfsm_strtom(fcnp->cn_nameptr, fcnp->cn_namelen, NFS_MAXNAMLEN); 987 nfsm_fhtom(tdvp); 988 nfsm_strtom(tcnp->cn_nameptr, tcnp->cn_namelen, NFS_MAXNAMLEN); 989 nfsm_request(fdvp, NFSPROC_RENAME, tcnp->cn_proc, tcnp->cn_cred); 990 nfsm_reqdone; 991 VTONFS(fdvp)->n_flag |= NMODIFIED; 992 VTONFS(tdvp)->n_flag |= NMODIFIED; 993 if (fvp->v_type == VDIR) { 994 if (tvp != NULL && tvp->v_type == VDIR) 995 cache_purge(tdvp); 996 cache_purge(fdvp); 997 } 998 if (tdvp == tvp) 999 vrele(tdvp); 1000 else 1001 vput(tdvp); 1002 if (tvp) 1003 vput(tvp); 1004 vrele(fdvp); 1005 vrele(fvp); 1006 /* 1007 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1008 */ 1009 if (error == ENOENT) 1010 error = 0; 1011 return (error); 1012 } 1013 1014 /* 1015 * nfs file rename rpc called from nfs_remove() above 1016 */ 1017 int 1018 nfs_renameit(sdvp, scnp, sp) 1019 struct vnode *sdvp; 1020 struct componentname *scnp; 1021 register struct sillyrename *sp; 1022 { 1023 register u_long *tl; 1024 register caddr_t cp; 1025 register long t2; 1026 caddr_t bpos, dpos; 1027 int error = 0; 1028 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1029 1030 nfsstats.rpccnt[NFSPROC_RENAME]++; 1031 nfsm_reqhead(sdvp, NFSPROC_RENAME, 1032 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(scnp->cn_namelen)+ 1033 nfsm_rndup(sp->s_namlen)); 1034 nfsm_fhtom(sdvp); 1035 nfsm_strtom(scnp->cn_nameptr, scnp->cn_namelen, NFS_MAXNAMLEN); 1036 nfsm_fhtom(sdvp); 1037 nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN); 1038 nfsm_request(sdvp, NFSPROC_RENAME, scnp->cn_proc, scnp->cn_cred); 1039 nfsm_reqdone; 1040 FREE(scnp->cn_pnbuf, M_NAMEI); 1041 VTONFS(sdvp)->n_flag |= NMODIFIED; 1042 return (error); 1043 } 1044 1045 /* 1046 * nfs hard link create call 1047 */ 1048 int 1049 nfs_link(vp, tdvp, cnp) /* converted to CN. */ 1050 /* old: nfs_link(vp, ndp, procp) */ 1051 register struct vnode *vp; /* source vnode */ 1052 struct vnode *tdvp; 1053 struct componentname *cnp; 1054 { 1055 register u_long *tl; 1056 register caddr_t cp; 1057 register long t2; 1058 caddr_t bpos, dpos; 1059 int error = 0; 1060 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1061 1062 nfsstats.rpccnt[NFSPROC_LINK]++; 1063 nfsm_reqhead(vp, NFSPROC_LINK, 1064 NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 1065 nfsm_fhtom(vp); 1066 nfsm_fhtom(tdvp); 1067 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1068 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); 1069 nfsm_reqdone; 1070 FREE(cnp->cn_pnbuf, M_NAMEI); 1071 VTONFS(vp)->n_attrstamp = 0; 1072 VTONFS(tdvp)->n_flag |= NMODIFIED; 1073 vrele(tdvp); 1074 /* 1075 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1076 */ 1077 if (error == EEXIST) 1078 error = 0; 1079 return (error); 1080 } 1081 1082 /* 1083 * nfs symbolic link create call 1084 */ 1085 /* start here */ 1086 int 1087 nfs_symlink(dvp, vpp, cnp, vap, nm) /* converted to CN. */ 1088 /* old: nfs_symlink(ndp, vap, nm, procp) */ 1089 struct vnode *dvp; 1090 struct vnode **vpp; 1091 struct componentname *cnp; 1092 struct vattr *vap; 1093 char *nm; 1094 { 1095 register struct nfsv2_sattr *sp; 1096 register u_long *tl; 1097 register caddr_t cp; 1098 register long t2; 1099 caddr_t bpos, dpos; 1100 int slen, error = 0; 1101 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1102 1103 nfsstats.rpccnt[NFSPROC_SYMLINK]++; 1104 slen = strlen(nm); 1105 nfsm_reqhead(dvp, NFSPROC_SYMLINK, 1106 NFSX_FH+2*NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+nfsm_rndup(slen)+NFSX_SATTR); 1107 nfsm_fhtom(dvp); 1108 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1109 nfsm_strtom(nm, slen, NFS_MAXPATHLEN); 1110 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR); 1111 sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode); 1112 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1113 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 1114 sp->sa_size = txdr_unsigned(VNOVAL); 1115 txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */ 1116 txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */ 1117 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred); 1118 nfsm_reqdone; 1119 FREE(cnp->cn_pnbuf, M_NAMEI); 1120 VTONFS(dvp)->n_flag |= NMODIFIED; 1121 vrele(dvp); 1122 /* 1123 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1124 */ 1125 /* 1126 * NEEDSWORK: what about *vpp? 1127 */ 1128 if (error == EEXIST) 1129 error = 0; 1130 return (error); 1131 } 1132 1133 /* 1134 * nfs make dir call 1135 */ 1136 int 1137 nfs_mkdir(dvp, vpp, cnp, vap) /* converted to CN. */ 1138 /* old: nfs_mkdir(ndp, vap, procp) */ 1139 struct vnode *dvp; 1140 struct vnode **vpp; 1141 struct componentname *cnp; 1142 struct vattr *vap; 1143 { 1144 register struct nfsv2_sattr *sp; 1145 register u_long *tl; 1146 register caddr_t cp; 1147 register long t1, t2; 1148 register int len; 1149 caddr_t bpos, dpos, cp2; 1150 int error = 0, firsttry = 1; 1151 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1152 1153 len = cnp->cn_namelen; 1154 nfsstats.rpccnt[NFSPROC_MKDIR]++; 1155 nfsm_reqhead(dvp, NFSPROC_MKDIR, 1156 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)+NFSX_SATTR); 1157 nfsm_fhtom(dvp); 1158 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1159 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR); 1160 sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode); 1161 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1162 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 1163 sp->sa_size = txdr_unsigned(VNOVAL); 1164 txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */ 1165 txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */ 1166 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred); 1167 nfsm_mtofh(dvp, *vpp); 1168 nfsm_reqdone; 1169 VTONFS(dvp)->n_flag |= NMODIFIED; 1170 /* 1171 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 1172 * if we can succeed in looking up the directory. 1173 * "firsttry" is necessary since the macros may "goto nfsmout" which 1174 * is above the if on errors. (Ugh) 1175 */ 1176 if (error == EEXIST && firsttry) { 1177 firsttry = 0; 1178 error = 0; 1179 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 1180 *vpp = NULL; 1181 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 1182 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 1183 nfsm_fhtom(dvp); 1184 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1185 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 1186 nfsm_mtofh(dvp, *vpp); 1187 if ((*vpp)->v_type != VDIR) { 1188 vput(*vpp); 1189 error = EEXIST; 1190 } 1191 m_freem(mrep); 1192 } 1193 FREE(cnp->cn_pnbuf, M_NAMEI); 1194 vrele(dvp); 1195 return (error); 1196 } 1197 1198 /* 1199 * nfs remove directory call 1200 */ 1201 int 1202 nfs_rmdir(dvp, vp, cnp) /* converted to CN. */ 1203 /* old: nfs_rmdir(ndp, procp) */ 1204 struct vnode *dvp, *vp; 1205 struct componentname *cnp; 1206 { 1207 register u_long *tl; 1208 register caddr_t cp; 1209 register long t2; 1210 caddr_t bpos, dpos; 1211 int error = 0; 1212 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1213 1214 if (dvp == vp) { 1215 vrele(dvp); 1216 vrele(dvp); 1217 FREE(cnp->cn_pnbuf, M_NAMEI); 1218 return (EINVAL); 1219 } 1220 nfsstats.rpccnt[NFSPROC_RMDIR]++; 1221 nfsm_reqhead(dvp, NFSPROC_RMDIR, 1222 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 1223 nfsm_fhtom(dvp); 1224 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1225 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred); 1226 nfsm_reqdone; 1227 FREE(cnp->cn_pnbuf, M_NAMEI); 1228 VTONFS(dvp)->n_flag |= NMODIFIED; 1229 cache_purge(dvp); 1230 cache_purge(vp); 1231 vrele(vp); 1232 vrele(dvp); 1233 /* 1234 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 1235 */ 1236 if (error == ENOENT) 1237 error = 0; 1238 return (error); 1239 } 1240 1241 /* 1242 * nfs readdir call 1243 * Although cookie is defined as opaque, I translate it to/from net byte 1244 * order so that it looks more sensible. This appears consistent with the 1245 * Ultrix implementation of NFS. 1246 */ 1247 int 1248 nfs_readdir(vp, uiop, cred, eofflagp) 1249 register struct vnode *vp; 1250 struct uio *uiop; 1251 struct ucred *cred; 1252 int *eofflagp; 1253 { 1254 register struct nfsnode *np = VTONFS(vp); 1255 int tresid, error; 1256 struct vattr vattr; 1257 1258 if (vp->v_type != VDIR) 1259 return (EPERM); 1260 /* 1261 * First, check for hit on the EOF offset cache 1262 */ 1263 if (uiop->uio_offset != 0 && uiop->uio_offset == np->n_direofoffset && 1264 (np->n_flag & NMODIFIED) == 0) { 1265 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { 1266 if (NQNFS_CKCACHABLE(vp, NQL_READ)) { 1267 *eofflagp = 1; 1268 nfsstats.direofcache_hits++; 1269 return (0); 1270 } 1271 } else if (nfs_getattr(vp, &vattr, cred, uiop->uio_procp) == 0 && 1272 np->n_mtime == vattr.va_mtime.tv_sec) { 1273 *eofflagp = 1; 1274 nfsstats.direofcache_hits++; 1275 return (0); 1276 } 1277 } 1278 1279 /* 1280 * Call nfs_bioread() to do the real work. 1281 */ 1282 tresid = uiop->uio_resid; 1283 error = nfs_bioread(vp, uiop, 0, cred); 1284 1285 if (!error && uiop->uio_resid == tresid) { 1286 *eofflagp = 1; 1287 nfsstats.direofcache_misses++; 1288 } else 1289 *eofflagp = 0; 1290 return (error); 1291 } 1292 1293 /* 1294 * Readdir rpc call. 1295 * Called from below the buffer cache by nfs_doio(). 1296 */ 1297 int 1298 nfs_readdirrpc(vp, uiop, cred) 1299 register struct vnode *vp; 1300 struct uio *uiop; 1301 struct ucred *cred; 1302 { 1303 register long len; 1304 register struct direct *dp; 1305 register u_long *tl; 1306 register caddr_t cp; 1307 register long t1; 1308 long tlen, lastlen; 1309 caddr_t bpos, dpos, cp2; 1310 int error = 0; 1311 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1312 struct mbuf *md2; 1313 caddr_t dpos2; 1314 int siz; 1315 int more_dirs = 1; 1316 off_t off, savoff; 1317 struct direct *savdp; 1318 struct nfsmount *nmp; 1319 struct nfsnode *np = VTONFS(vp); 1320 long tresid; 1321 1322 nmp = VFSTONFS(vp->v_mount); 1323 tresid = uiop->uio_resid; 1324 /* 1325 * Loop around doing readdir rpc's of size uio_resid or nm_rsize, 1326 * whichever is smaller, truncated to a multiple of NFS_DIRBLKSIZ. 1327 * The stopping criteria is EOF or buffer full. 1328 */ 1329 while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) { 1330 nfsstats.rpccnt[NFSPROC_READDIR]++; 1331 nfsm_reqhead(vp, NFSPROC_READDIR, 1332 NFSX_FH+2*NFSX_UNSIGNED); 1333 nfsm_fhtom(vp); 1334 nfsm_build(tl, u_long *, 2*NFSX_UNSIGNED); 1335 *tl++ = txdr_unsigned(uiop->uio_offset); 1336 *tl = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ? 1337 nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1)); 1338 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred); 1339 siz = 0; 1340 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1341 more_dirs = fxdr_unsigned(int, *tl); 1342 1343 /* Save the position so that we can do nfsm_mtouio() later */ 1344 dpos2 = dpos; 1345 md2 = md; 1346 1347 /* loop thru the dir entries, doctoring them to 4bsd form */ 1348 off = uiop->uio_offset; 1349 #ifdef lint 1350 dp = (struct direct *)0; 1351 #endif /* lint */ 1352 while (more_dirs && siz < uiop->uio_resid) { 1353 savoff = off; /* Hold onto offset and dp */ 1354 savdp = dp; 1355 nfsm_dissecton(tl, u_long *, 2*NFSX_UNSIGNED); 1356 dp = (struct direct *)tl; 1357 dp->d_ino = fxdr_unsigned(u_long, *tl++); 1358 len = fxdr_unsigned(int, *tl); 1359 if (len <= 0 || len > NFS_MAXNAMLEN) { 1360 error = EBADRPC; 1361 m_freem(mrep); 1362 goto nfsmout; 1363 } 1364 dp->d_namlen = (u_short)len; 1365 nfsm_adv(len); /* Point past name */ 1366 tlen = nfsm_rndup(len); 1367 /* 1368 * This should not be necessary, but some servers have 1369 * broken XDR such that these bytes are not null filled. 1370 */ 1371 if (tlen != len) { 1372 *dpos = '\0'; /* Null-terminate */ 1373 nfsm_adv(tlen - len); 1374 len = tlen; 1375 } 1376 nfsm_dissecton(tl, u_long *, 2*NFSX_UNSIGNED); 1377 off = fxdr_unsigned(off_t, *tl); 1378 *tl++ = 0; /* Ensures null termination of name */ 1379 more_dirs = fxdr_unsigned(int, *tl); 1380 dp->d_reclen = len+4*NFSX_UNSIGNED; 1381 siz += dp->d_reclen; 1382 } 1383 /* 1384 * If at end of rpc data, get the eof boolean 1385 */ 1386 if (!more_dirs) { 1387 nfsm_dissecton(tl, u_long *, NFSX_UNSIGNED); 1388 more_dirs = (fxdr_unsigned(int, *tl) == 0); 1389 1390 /* 1391 * If at EOF, cache directory offset 1392 */ 1393 if (!more_dirs) 1394 np->n_direofoffset = off; 1395 } 1396 /* 1397 * If there is too much to fit in the data buffer, use savoff and 1398 * savdp to trim off the last record. 1399 * --> we are not at eof 1400 */ 1401 if (siz > uiop->uio_resid) { 1402 off = savoff; 1403 siz -= dp->d_reclen; 1404 dp = savdp; 1405 more_dirs = 0; /* Paranoia */ 1406 } 1407 if (siz > 0) { 1408 lastlen = dp->d_reclen; 1409 md = md2; 1410 dpos = dpos2; 1411 nfsm_mtouio(uiop, siz); 1412 uiop->uio_offset = off; 1413 } else 1414 more_dirs = 0; /* Ugh, never happens, but in case.. */ 1415 m_freem(mrep); 1416 } 1417 /* 1418 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 1419 * by increasing d_reclen for the last record. 1420 */ 1421 if (uiop->uio_resid < tresid) { 1422 len = uiop->uio_resid & (NFS_DIRBLKSIZ - 1); 1423 if (len > 0) { 1424 dp = (struct direct *) 1425 (uiop->uio_iov->iov_base - lastlen); 1426 dp->d_reclen += len; 1427 uiop->uio_iov->iov_base += len; 1428 uiop->uio_iov->iov_len -= len; 1429 uiop->uio_resid -= len; 1430 } 1431 } 1432 nfsmout: 1433 return (error); 1434 } 1435 1436 /* 1437 * Nqnfs readdir_and_lookup RPC. Used in place of nfs_readdirrpc() when 1438 * the "rdirlook" mount option is specified. 1439 */ 1440 int 1441 nfs_readdirlookrpc(vp, uiop, cred) 1442 struct vnode *vp; 1443 register struct uio *uiop; 1444 struct ucred *cred; 1445 { 1446 register int len; 1447 register struct direct *dp; 1448 register u_long *tl; 1449 register caddr_t cp; 1450 register long t1; 1451 caddr_t bpos, dpos, cp2; 1452 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1453 struct nameidata nami, *ndp = &nami; 1454 off_t off, endoff; 1455 time_t reqtime, ltime; 1456 struct nfsmount *nmp; 1457 struct nfsnode *np, *tp; 1458 struct vnode *newvp; 1459 nfsv2fh_t *fhp; 1460 u_long fileno; 1461 u_quad_t frev; 1462 int error = 0, tlen, more_dirs = 1, tresid, doit, bigenough, i; 1463 int cachable; 1464 1465 if (uiop->uio_iovcnt != 1) 1466 panic("nfs rdirlook"); 1467 nmp = VFSTONFS(vp->v_mount); 1468 tresid = uiop->uio_resid; 1469 ndp->ni_dvp = vp; 1470 newvp = NULLVP; 1471 /* 1472 * Loop around doing readdir rpc's of size uio_resid or nm_rsize, 1473 * whichever is smaller, truncated to a multiple of NFS_DIRBLKSIZ. 1474 * The stopping criteria is EOF or buffer full. 1475 */ 1476 while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) { 1477 nfsstats.rpccnt[NQNFSPROC_READDIRLOOK]++; 1478 nfsm_reqhead(vp, NQNFSPROC_READDIRLOOK, 1479 NFSX_FH+3*NFSX_UNSIGNED); 1480 nfsm_fhtom(vp); 1481 nfsm_build(tl, u_long *, 3*NFSX_UNSIGNED); 1482 *tl++ = txdr_unsigned(uiop->uio_offset); 1483 *tl++ = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ? 1484 nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1)); 1485 *tl = txdr_unsigned(nmp->nm_leaseterm); 1486 reqtime = time.tv_sec; 1487 nfsm_request(vp, NQNFSPROC_READDIRLOOK, uiop->uio_procp, cred); 1488 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1489 more_dirs = fxdr_unsigned(int, *tl); 1490 1491 /* loop thru the dir entries, doctoring them to 4bsd form */ 1492 off = uiop->uio_offset; 1493 bigenough = 1; 1494 while (more_dirs && bigenough) { 1495 doit = 1; 1496 nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED); 1497 cachable = fxdr_unsigned(int, *tl++); 1498 ltime = reqtime + fxdr_unsigned(int, *tl++); 1499 fxdr_hyper(tl, &frev); 1500 nfsm_dissect(fhp, nfsv2fh_t *, NFSX_FH); 1501 if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 1502 VREF(vp); 1503 newvp = vp; 1504 np = VTONFS(vp); 1505 } else { 1506 if (error = nfs_nget(vp->v_mount, fhp, &np)) 1507 doit = 0; 1508 newvp = NFSTOV(np); 1509 } 1510 if (error = nfs_loadattrcache(&newvp, &md, &dpos, 1511 (struct vattr *)0)) 1512 doit = 0; 1513 nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED); 1514 fileno = fxdr_unsigned(u_long, *tl++); 1515 len = fxdr_unsigned(int, *tl); 1516 if (len <= 0 || len > NFS_MAXNAMLEN) { 1517 error = EBADRPC; 1518 m_freem(mrep); 1519 goto nfsmout; 1520 } 1521 tlen = (len + 4) & ~0x3; 1522 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 1523 bigenough = 0; 1524 if (bigenough && doit) { 1525 dp = (struct direct *)uiop->uio_iov->iov_base; 1526 dp->d_ino = fileno; 1527 dp->d_namlen = len; 1528 dp->d_reclen = tlen + DIRHDSIZ; 1529 uiop->uio_resid -= DIRHDSIZ; 1530 uiop->uio_iov->iov_base += DIRHDSIZ; 1531 uiop->uio_iov->iov_len -= DIRHDSIZ; 1532 ndp->ni_ptr = uiop->uio_iov->iov_base; 1533 ndp->ni_namelen = len; 1534 ndp->ni_vp = newvp; 1535 nfsm_mtouio(uiop, len); 1536 cp = uiop->uio_iov->iov_base; 1537 tlen -= len; 1538 for (i = 0; i < tlen; i++) 1539 *cp++ = '\0'; 1540 uiop->uio_iov->iov_base += tlen; 1541 uiop->uio_iov->iov_len -= tlen; 1542 uiop->uio_resid -= tlen; 1543 ndp->ni_hash = 0; 1544 for (cp = ndp->ni_ptr, i = 1; i <= len; i++, cp++) 1545 ndp->ni_hash += (unsigned char)*cp * i; 1546 if (ltime > time.tv_sec) { 1547 if (np->n_tnext) { 1548 if (np->n_tnext == (struct nfsnode *)nmp) 1549 nmp->nm_tprev = np->n_tprev; 1550 else 1551 np->n_tnext->n_tprev = np->n_tprev; 1552 if (np->n_tprev == (struct nfsnode *)nmp) 1553 nmp->nm_tnext = np->n_tnext; 1554 else 1555 np->n_tprev->n_tnext = np->n_tnext; 1556 } else 1557 np->n_flag &= ~NQNFSWRITE; 1558 if (cachable) 1559 np->n_flag &= ~NQNFSNONCACHE; 1560 else 1561 np->n_flag |= NQNFSNONCACHE; 1562 np->n_expiry = ltime; 1563 np->n_lrev = frev; 1564 tp = nmp->nm_tprev; 1565 while (tp != (struct nfsnode *)nmp && tp->n_expiry > np->n_expiry) 1566 tp = tp->n_tprev; 1567 if (tp == (struct nfsnode *)nmp) { 1568 np->n_tnext = nmp->nm_tnext; 1569 nmp->nm_tnext = np; 1570 } else { 1571 np->n_tnext = tp->n_tnext; 1572 tp->n_tnext = np; 1573 } 1574 np->n_tprev = tp; 1575 if (np->n_tnext == (struct nfsnode *)nmp) 1576 nmp->nm_tprev = np; 1577 else 1578 np->n_tnext->n_tprev = np; 1579 cache_enter(ndp); 1580 } 1581 } else { 1582 nfsm_adv(nfsm_rndup(len)); 1583 } 1584 if (newvp != NULLVP) { 1585 vrele(newvp); 1586 newvp = NULLVP; 1587 } 1588 nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED); 1589 if (bigenough) 1590 endoff = off = fxdr_unsigned(off_t, *tl++); 1591 else 1592 endoff = fxdr_unsigned(off_t, *tl++); 1593 more_dirs = fxdr_unsigned(int, *tl); 1594 } 1595 /* 1596 * If at end of rpc data, get the eof boolean 1597 */ 1598 if (!more_dirs) { 1599 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1600 more_dirs = (fxdr_unsigned(int, *tl) == 0); 1601 1602 /* 1603 * If at EOF, cache directory offset 1604 */ 1605 if (!more_dirs) 1606 VTONFS(vp)->n_direofoffset = endoff; 1607 } 1608 if (uiop->uio_resid < tresid) 1609 uiop->uio_offset = off; 1610 else 1611 more_dirs = 0; 1612 m_freem(mrep); 1613 } 1614 /* 1615 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 1616 * by increasing d_reclen for the last record. 1617 */ 1618 if (uiop->uio_resid < tresid) { 1619 len = uiop->uio_resid & (NFS_DIRBLKSIZ - 1); 1620 if (len > 0) { 1621 dp->d_reclen += len; 1622 uiop->uio_iov->iov_base += len; 1623 uiop->uio_iov->iov_len -= len; 1624 uiop->uio_resid -= len; 1625 } 1626 } 1627 nfsmout: 1628 if (newvp != NULLVP) 1629 vrele(newvp); 1630 return (error); 1631 } 1632 static char hextoasc[] = "0123456789abcdef"; 1633 1634 /* 1635 * Silly rename. To make the NFS filesystem that is stateless look a little 1636 * more like the "ufs" a remove of an active vnode is translated to a rename 1637 * to a funny looking filename that is removed by nfs_inactive on the 1638 * nfsnode. There is the potential for another process on a different client 1639 * to create the same funny name between the nfs_lookitup() fails and the 1640 * nfs_rename() completes, but... 1641 */ 1642 int 1643 nfs_sillyrename(dvp, vp, cnp) /* NEEDSWORK */ 1644 /* old: nfs_sillyrename(ndp, p) */ 1645 struct vnode *dvp, *vp; 1646 struct componentname *cnp; 1647 { 1648 register struct nfsnode *np; 1649 register struct sillyrename *sp; 1650 int error; 1651 short pid; 1652 1653 cache_purge(dvp); 1654 np = VTONFS(vp); 1655 #ifdef SILLYSEPARATE 1656 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 1657 M_NFSREQ, M_WAITOK); 1658 #else 1659 sp = &np->n_silly; 1660 #endif 1661 sp->s_cred = crdup(cnp->cn_cred); 1662 sp->s_dvp = dvp; 1663 VREF(dvp); 1664 1665 /* Fudge together a funny name */ 1666 pid = cnp->cn_proc->p_pid; 1667 bcopy(".nfsAxxxx4.4", sp->s_name, 13); 1668 sp->s_namlen = 12; 1669 sp->s_name[8] = hextoasc[pid & 0xf]; 1670 sp->s_name[7] = hextoasc[(pid >> 4) & 0xf]; 1671 sp->s_name[6] = hextoasc[(pid >> 8) & 0xf]; 1672 sp->s_name[5] = hextoasc[(pid >> 12) & 0xf]; 1673 1674 /* Try lookitups until we get one that isn't there */ 1675 while (nfs_lookitup(sp, (nfsv2fh_t *)0, cnp->cn_proc) == 0) { 1676 sp->s_name[4]++; 1677 if (sp->s_name[4] > 'z') { 1678 error = EINVAL; 1679 goto bad; 1680 } 1681 } 1682 if (error = nfs_renameit(dvp, cnp, sp)) 1683 goto bad; 1684 nfs_lookitup(sp, &np->n_fh, cnp->cn_proc); 1685 np->n_sillyrename = sp; 1686 return (0); 1687 bad: 1688 vrele(sp->s_dvp); 1689 crfree(sp->s_cred); 1690 #ifdef SILLYSEPARATE 1691 free((caddr_t)sp, M_NFSREQ); 1692 #endif 1693 return (error); 1694 } 1695 1696 /* 1697 * Look up a file name for silly rename stuff. 1698 * Just like nfs_lookup() except that it doesn't load returned values 1699 * into the nfsnode table. 1700 * If fhp != NULL it copies the returned file handle out 1701 */ 1702 int 1703 nfs_lookitup(sp, fhp, procp) 1704 register struct sillyrename *sp; 1705 nfsv2fh_t *fhp; 1706 struct proc *procp; 1707 { 1708 register struct vnode *vp = sp->s_dvp; 1709 register u_long *tl; 1710 register caddr_t cp; 1711 register long t1, t2; 1712 caddr_t bpos, dpos, cp2; 1713 u_long xid; 1714 int error = 0; 1715 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1716 long len; 1717 1718 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 1719 len = sp->s_namlen; 1720 nfsm_reqhead(vp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 1721 nfsm_fhtom(vp); 1722 nfsm_strtom(sp->s_name, len, NFS_MAXNAMLEN); 1723 nfsm_request(vp, NFSPROC_LOOKUP, procp, sp->s_cred); 1724 if (fhp != NULL) { 1725 nfsm_dissect(cp, caddr_t, NFSX_FH); 1726 bcopy(cp, (caddr_t)fhp, NFSX_FH); 1727 } 1728 nfsm_reqdone; 1729 return (error); 1730 } 1731 1732 /* 1733 * Kludge City.. 1734 * - make nfs_bmap() essentially a no-op that does no translation 1735 * - do nfs_strategy() by faking physical I/O with nfs_readrpc/nfs_writerpc 1736 * after mapping the physical addresses into Kernel Virtual space in the 1737 * nfsiobuf area. 1738 * (Maybe I could use the process's page mapping, but I was concerned that 1739 * Kernel Write might not be enabled and also figured copyout() would do 1740 * a lot more work than bcopy() and also it currently happens in the 1741 * context of the swapper process (2). 1742 */ 1743 int 1744 nfs_bmap(vp, bn, vpp, bnp) 1745 struct vnode *vp; 1746 daddr_t bn; 1747 struct vnode **vpp; 1748 daddr_t *bnp; 1749 { 1750 if (vpp != NULL) 1751 *vpp = vp; 1752 if (bnp != NULL) 1753 *bnp = bn * btodb(vp->v_mount->mnt_stat.f_iosize); 1754 return (0); 1755 } 1756 1757 /* 1758 * Strategy routine for phys. i/o 1759 * If the biod's are running, queue a request 1760 * otherwise just call nfs_doio() to get it done 1761 */ 1762 int 1763 nfs_strategy(bp) 1764 register struct buf *bp; 1765 { 1766 register struct buf *dp; 1767 register int i; 1768 int error = 0; 1769 int fnd = 0; 1770 1771 /* 1772 * Set b_proc. It seems a bit silly to do it here, but since bread() 1773 * doesn't set it, I will. 1774 * Set b_proc == NULL for asynchronous ops, since these may still 1775 * be hanging about after the process terminates. 1776 */ 1777 if ((bp->b_flags & B_PHYS) == 0) { 1778 if (bp->b_flags & B_ASYNC) 1779 bp->b_proc = (struct proc *)0; 1780 else 1781 bp->b_proc = curproc; 1782 } 1783 /* 1784 * If the op is asynchronous and an i/o daemon is waiting 1785 * queue the request, wake it up and wait for completion 1786 * otherwise just do it ourselves. 1787 */ 1788 if ((bp->b_flags & B_ASYNC) == 0 || nfs_numasync == 0) 1789 return (nfs_doio(bp)); 1790 for (i = 0; i < NFS_MAXASYNCDAEMON; i++) { 1791 if (nfs_iodwant[i]) { 1792 dp = &nfs_bqueue; 1793 if (dp->b_actf == NULL) { 1794 dp->b_actl = bp; 1795 bp->b_actf = dp; 1796 } else { 1797 dp->b_actf->b_actl = bp; 1798 bp->b_actf = dp->b_actf; 1799 } 1800 dp->b_actf = bp; 1801 bp->b_actl = dp; 1802 fnd++; 1803 wakeup((caddr_t)&nfs_iodwant[i]); 1804 break; 1805 } 1806 } 1807 if (!fnd) 1808 error = nfs_doio(bp); 1809 return (error); 1810 } 1811 1812 /* 1813 * Fun and games with i/o 1814 * Essentially play ubasetup() and disk interrupt service routine by 1815 * mapping the data buffer into kernel virtual space and doing the 1816 * nfs read or write rpc's from it. 1817 * If the nfsiod's are not running, this is just called from nfs_strategy(), 1818 * otherwise it is called by the nfsiods to do what would normally be 1819 * partially disk interrupt driven. 1820 */ 1821 int 1822 nfs_doio(bp) 1823 register struct buf *bp; 1824 { 1825 register struct uio *uiop; 1826 register struct vnode *vp; 1827 struct nfsnode *np; 1828 struct ucred *cr; 1829 int error; 1830 struct uio uio; 1831 struct iovec io; 1832 1833 vp = bp->b_vp; 1834 np = VTONFS(vp); 1835 uiop = &uio; 1836 uiop->uio_iov = &io; 1837 uiop->uio_iovcnt = 1; 1838 uiop->uio_segflg = UIO_SYSSPACE; 1839 uiop->uio_procp = bp->b_proc; 1840 1841 /* 1842 * For phys i/o, map the b_addr into kernel virtual space using 1843 * the Nfsiomap pte's 1844 * Also, add a temporary b_rcred for reading using the process's uid 1845 * and a guess at a group 1846 */ 1847 if (bp->b_flags & B_PHYS) { 1848 if (bp->b_flags & B_DIRTY) 1849 uiop->uio_procp = pageproc; 1850 cr = crcopy(uiop->uio_procp->p_ucred); 1851 /* mapping was already done by vmapbuf */ 1852 io.iov_base = bp->b_un.b_addr; 1853 1854 /* 1855 * And do the i/o rpc 1856 */ 1857 io.iov_len = uiop->uio_resid = bp->b_bcount; 1858 uiop->uio_offset = bp->b_blkno * DEV_BSIZE; 1859 if (bp->b_flags & B_READ) { 1860 uiop->uio_rw = UIO_READ; 1861 nfsstats.read_physios++; 1862 bp->b_error = error = nfs_readrpc(vp, uiop, cr); 1863 (void) vnode_pager_uncache(vp); 1864 } else { 1865 uiop->uio_rw = UIO_WRITE; 1866 nfsstats.write_physios++; 1867 bp->b_error = error = nfs_writerpc(vp, uiop, cr); 1868 } 1869 1870 /* 1871 * Finally, release pte's used by physical i/o 1872 */ 1873 crfree(cr); 1874 } else { 1875 if (bp->b_flags & B_READ) { 1876 io.iov_len = uiop->uio_resid = bp->b_bcount; 1877 io.iov_base = bp->b_un.b_addr; 1878 uiop->uio_rw = UIO_READ; 1879 switch (vp->v_type) { 1880 case VREG: 1881 uiop->uio_offset = bp->b_blkno * DEV_BSIZE; 1882 nfsstats.read_bios++; 1883 error = nfs_readrpc(vp, uiop, bp->b_rcred); 1884 break; 1885 case VLNK: 1886 uiop->uio_offset = 0; 1887 nfsstats.readlink_bios++; 1888 error = nfs_readlinkrpc(vp, uiop, bp->b_rcred); 1889 break; 1890 case VDIR: 1891 uiop->uio_offset = bp->b_lblkno; 1892 nfsstats.readdir_bios++; 1893 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_RDIRALOOK) 1894 error = nfs_readdirlookrpc(vp, uiop, bp->b_rcred); 1895 else 1896 error = nfs_readdirrpc(vp, uiop, bp->b_rcred); 1897 /* 1898 * Save offset cookie in b_blkno. 1899 */ 1900 bp->b_blkno = uiop->uio_offset; 1901 break; 1902 }; 1903 bp->b_error = error; 1904 } else { 1905 io.iov_len = uiop->uio_resid = bp->b_dirtyend 1906 - bp->b_dirtyoff; 1907 uiop->uio_offset = (bp->b_blkno * DEV_BSIZE) 1908 + bp->b_dirtyoff; 1909 io.iov_base = bp->b_un.b_addr + bp->b_dirtyoff; 1910 uiop->uio_rw = UIO_WRITE; 1911 nfsstats.write_bios++; 1912 bp->b_error = error = nfs_writerpc(vp, uiop, 1913 bp->b_wcred); 1914 if (error) { 1915 np->n_error = error; 1916 np->n_flag |= NWRITEERR; 1917 } 1918 bp->b_dirtyoff = bp->b_dirtyend = 0; 1919 } 1920 } 1921 if (error) 1922 bp->b_flags |= B_ERROR; 1923 bp->b_resid = uiop->uio_resid; 1924 biodone(bp); 1925 return (error); 1926 } 1927 1928 /* 1929 * Mmap a file 1930 * 1931 * NB Currently unsupported. 1932 */ 1933 /* ARGSUSED */ 1934 int 1935 nfs_mmap(vp, fflags, cred, p) 1936 struct vnode *vp; 1937 int fflags; 1938 struct ucred *cred; 1939 struct proc *p; 1940 { 1941 1942 return (EINVAL); 1943 } 1944 1945 /* 1946 * Flush all the blocks associated with a vnode. 1947 * Walk through the buffer pool and push any dirty pages 1948 * associated with the vnode. 1949 */ 1950 /* ARGSUSED */ 1951 int 1952 nfs_fsync(vp, fflags, cred, waitfor, p) 1953 register struct vnode *vp; 1954 int fflags; 1955 struct ucred *cred; 1956 int waitfor; 1957 struct proc *p; 1958 { 1959 register struct nfsnode *np = VTONFS(vp); 1960 int error = 0; 1961 1962 if (np->n_flag & NMODIFIED) { 1963 np->n_flag &= ~NMODIFIED; 1964 vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0); 1965 } 1966 if (!error && (np->n_flag & NWRITEERR)) 1967 error = np->n_error; 1968 return (error); 1969 } 1970 1971 /* 1972 * NFS advisory byte-level locks. 1973 * Currently unsupported. 1974 */ 1975 int 1976 nfs_advlock(vp, id, op, fl, flags) 1977 struct vnode *vp; 1978 caddr_t id; 1979 int op; 1980 struct flock *fl; 1981 int flags; 1982 { 1983 1984 return (EOPNOTSUPP); 1985 } 1986 1987 /* 1988 * Print out the contents of an nfsnode. 1989 */ 1990 int 1991 nfs_print(vp) 1992 struct vnode *vp; 1993 { 1994 register struct nfsnode *np = VTONFS(vp); 1995 1996 printf("tag VT_NFS, fileid %d fsid 0x%x", 1997 np->n_vattr.va_fileid, np->n_vattr.va_fsid); 1998 #ifdef FIFO 1999 if (vp->v_type == VFIFO) 2000 fifo_printinfo(vp); 2001 #endif /* FIFO */ 2002 printf("\n"); 2003 } 2004 2005 /* 2006 * NFS directory offset lookup. 2007 * Currently unsupported. 2008 */ 2009 int 2010 nfs_blkatoff(vp, offset, res, bpp) 2011 struct vnode *vp; 2012 off_t offset; 2013 char **res; 2014 struct buf **bpp; 2015 { 2016 2017 return (EOPNOTSUPP); 2018 } 2019 2020 /* 2021 * NFS flat namespace lookup. 2022 * Currently unsupported. 2023 */ 2024 int 2025 nfs_vget(mp, ino, vpp) 2026 struct mount *mp; 2027 ino_t ino; 2028 struct vnode **vpp; 2029 { 2030 2031 return (EOPNOTSUPP); 2032 } 2033 2034 /* 2035 * NFS flat namespace allocation. 2036 * Currently unsupported. 2037 */ 2038 int 2039 nfs_valloc(pvp, mode, cred, vpp) 2040 struct vnode *pvp; 2041 int mode; 2042 struct ucred *cred; 2043 struct vnode **vpp; 2044 { 2045 2046 return (EOPNOTSUPP); 2047 } 2048 2049 /* 2050 * NFS flat namespace free. 2051 * Currently unsupported. 2052 */ 2053 void 2054 nfs_vfree(pvp, ino, mode) 2055 struct vnode *pvp; 2056 ino_t ino; 2057 int mode; 2058 { 2059 2060 return; 2061 } 2062 2063 /* 2064 * NFS file truncation. 2065 */ 2066 int 2067 nfs_truncate(vp, length, flags) 2068 struct vnode *vp; 2069 u_long length; 2070 int flags; 2071 { 2072 2073 /* Use nfs_setattr */ 2074 printf("nfs_truncate: need to implement!!"); 2075 return (EOPNOTSUPP); 2076 } 2077 2078 /* 2079 * NFS update. 2080 */ 2081 int 2082 nfs_update(vp, ta, tm, waitfor) 2083 struct vnode *vp; 2084 struct timeval *ta; 2085 struct timeval *tm; 2086 int waitfor; 2087 { 2088 2089 /* Use nfs_setattr */ 2090 printf("nfs_update: need to implement!!"); 2091 return (EOPNOTSUPP); 2092 } 2093