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 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the University of California, Berkeley. The name of the 14 * University may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * @(#)nfs_vnops.c 7.23 (Berkeley) 01/15/90 21 */ 22 23 /* 24 * vnode op calls for sun nfs version 2 25 */ 26 27 #include "machine/pte.h" 28 #include "machine/mtpr.h" 29 #include "strings.h" 30 #include "param.h" 31 #include "user.h" 32 #include "proc.h" 33 #include "mount.h" 34 #include "buf.h" 35 #include "vm.h" 36 #include "../ufs/dir.h" 37 #include "malloc.h" 38 #include "mbuf.h" 39 #include "uio.h" 40 #include "ucred.h" 41 #include "namei.h" 42 #include "errno.h" 43 #include "file.h" 44 #include "conf.h" 45 #include "vnode.h" 46 #include "../ufs/inode.h" 47 #include "map.h" 48 #include "nfsv2.h" 49 #include "nfs.h" 50 #include "nfsnode.h" 51 #include "nfsmount.h" 52 #include "xdr_subs.h" 53 #include "nfsm_subs.h" 54 #include "nfsiom.h" 55 56 /* Defs */ 57 #define TRUE 1 58 #define FALSE 0 59 60 /* Global vars */ 61 int nfs_lookup(), 62 nfs_create(), 63 nfs_mknod(), 64 nfs_open(), 65 nfs_close(), 66 nfs_access(), 67 nfs_getattr(), 68 nfs_setattr(), 69 nfs_read(), 70 nfs_write(), 71 vfs_noop(), 72 vfs_nullop(), 73 nfs_remove(), 74 nfs_link(), 75 nfs_rename(), 76 nfs_mkdir(), 77 nfs_rmdir(), 78 nfs_symlink(), 79 nfs_readdir(), 80 nfs_readlink(), 81 nfs_abortop(), 82 nfs_lock(), 83 nfs_unlock(), 84 nfs_bmap(), 85 nfs_strategy(), 86 nfs_fsync(), 87 nfs_inactive(), 88 nfs_reclaim(), 89 nfs_print(), 90 nfs_islocked(); 91 92 struct vnodeops nfsv2_vnodeops = { 93 nfs_lookup, /* lookup */ 94 nfs_create, /* create */ 95 nfs_mknod, /* mknod */ 96 nfs_open, /* open */ 97 nfs_close, /* close */ 98 nfs_access, /* access */ 99 nfs_getattr, /* getattr */ 100 nfs_setattr, /* setattr */ 101 nfs_read, /* read */ 102 nfs_write, /* write */ 103 vfs_noop, /* ioctl */ 104 vfs_noop, /* select */ 105 vfs_noop, /* mmap */ 106 nfs_fsync, /* fsync */ 107 vfs_nullop, /* seek */ 108 nfs_remove, /* remove */ 109 nfs_link, /* link */ 110 nfs_rename, /* rename */ 111 nfs_mkdir, /* mkdir */ 112 nfs_rmdir, /* rmdir */ 113 nfs_symlink, /* symlink */ 114 nfs_readdir, /* readdir */ 115 nfs_readlink, /* readlink */ 116 nfs_abortop, /* abortop */ 117 nfs_inactive, /* inactive */ 118 nfs_reclaim, /* reclaim */ 119 nfs_lock, /* lock */ 120 nfs_unlock, /* unlock */ 121 nfs_bmap, /* bmap */ 122 nfs_strategy, /* strategy */ 123 nfs_print, /* print */ 124 nfs_islocked, /* islocked */ 125 }; 126 127 /* Special device vnode ops */ 128 int spec_lookup(), 129 spec_open(), 130 spec_read(), 131 spec_write(), 132 spec_strategy(), 133 spec_bmap(), 134 spec_ioctl(), 135 spec_select(), 136 spec_close(), 137 spec_badop(), 138 spec_nullop(); 139 140 struct vnodeops spec_nfsv2nodeops = { 141 spec_lookup, /* lookup */ 142 spec_badop, /* create */ 143 spec_badop, /* mknod */ 144 spec_open, /* open */ 145 spec_close, /* close */ 146 nfs_access, /* access */ 147 nfs_getattr, /* getattr */ 148 nfs_setattr, /* setattr */ 149 spec_read, /* read */ 150 spec_write, /* write */ 151 spec_ioctl, /* ioctl */ 152 spec_select, /* select */ 153 spec_badop, /* mmap */ 154 spec_nullop, /* fsync */ 155 spec_badop, /* seek */ 156 spec_badop, /* remove */ 157 spec_badop, /* link */ 158 spec_badop, /* rename */ 159 spec_badop, /* mkdir */ 160 spec_badop, /* rmdir */ 161 spec_badop, /* symlink */ 162 spec_badop, /* readdir */ 163 spec_badop, /* readlink */ 164 spec_badop, /* abortop */ 165 nfs_inactive, /* inactive */ 166 nfs_reclaim, /* reclaim */ 167 nfs_lock, /* lock */ 168 nfs_unlock, /* unlock */ 169 spec_bmap, /* bmap */ 170 spec_strategy, /* strategy */ 171 nfs_print, /* print */ 172 nfs_islocked, /* islocked */ 173 }; 174 175 extern u_long nfs_procids[NFS_NPROCS]; 176 extern u_long nfs_prog, nfs_vers; 177 extern char nfsiobuf[MAXPHYS+NBPG]; 178 struct map nfsmap[NFS_MSIZ]; 179 enum vtype v_type[NFLNK+1]; 180 struct buf nfs_bqueue; /* Queue head for nfsiod's */ 181 int nfs_asyncdaemons = 0; 182 struct proc *nfs_iodwant[MAX_ASYNCDAEMON]; 183 static int nfsmap_want = 0; 184 185 /* 186 * nfs null call from vfs. 187 */ 188 nfs_null(vp, cred) 189 struct vnode *vp; 190 struct ucred *cred; 191 { 192 caddr_t bpos, dpos; 193 u_long xid; 194 int error = 0; 195 struct mbuf *mreq, *mrep, *md, *mb; 196 197 nfsm_reqhead(nfs_procids[NFSPROC_NULL], cred, 0); 198 nfsm_request(vp); 199 nfsm_reqdone; 200 return (error); 201 } 202 203 /* 204 * nfs access vnode op. 205 * Essentially just get vattr and then imitate iaccess() 206 */ 207 nfs_access(vp, mode, cred) 208 struct vnode *vp; 209 int mode; 210 register struct ucred *cred; 211 { 212 register struct vattr *vap; 213 register gid_t *gp; 214 struct vattr vattr; 215 register int i; 216 int error; 217 218 /* 219 * If you're the super-user, 220 * you always get access. 221 */ 222 if (cred->cr_uid == 0) 223 return (0); 224 vap = &vattr; 225 if (error = nfs_getattr(vp, vap, cred)) 226 return (error); 227 /* 228 * Access check is based on only one of owner, group, public. 229 * If not owner, then check group. If not a member of the 230 * group, then check public access. 231 */ 232 if (cred->cr_uid != vap->va_uid) { 233 mode >>= 3; 234 gp = cred->cr_groups; 235 for (i = 0; i < cred->cr_ngroups; i++, gp++) 236 if (vap->va_gid == *gp) 237 goto found; 238 mode >>= 3; 239 found: 240 ; 241 } 242 if ((vap->va_mode & mode) != 0) 243 return (0); 244 return (EACCES); 245 } 246 247 /* 248 * nfs open vnode op 249 * Just check to see if the type is ok 250 */ 251 /* ARGSUSED */ 252 nfs_open(vp, mode, cred) 253 struct vnode *vp; 254 int mode; 255 struct ucred *cred; 256 { 257 register enum vtype vtyp; 258 259 vtyp = vp->v_type; 260 if (vtyp == VREG || vtyp == VDIR || vtyp == VLNK) 261 return (0); 262 else 263 return (EACCES); 264 } 265 266 /* 267 * nfs close vnode op 268 * For reg files, invalidate any buffer cache entries. 269 */ 270 /* ARGSUSED */ 271 nfs_close(vp, fflags, cred) 272 register struct vnode *vp; 273 int fflags; 274 struct ucred *cred; 275 { 276 register struct nfsnode *np = VTONFS(vp); 277 int error = 0; 278 279 if (vp->v_type == VREG && ((np->n_flag & NMODIFIED) || 280 ((np->n_flag & NBUFFERED) && np->n_sillyrename))) { 281 nfs_lock(vp); 282 np->n_flag &= ~(NMODIFIED|NBUFFERED); 283 vinvalbuf(vp, TRUE); 284 if (np->n_flag & NWRITEERR) { 285 np->n_flag &= ~NWRITEERR; 286 error = np->n_error; 287 } 288 nfs_unlock(vp); 289 } 290 return (error); 291 } 292 293 /* 294 * nfs getattr call from vfs. 295 */ 296 nfs_getattr(vp, vap, cred) 297 register struct vnode *vp; 298 struct vattr *vap; 299 struct ucred *cred; 300 { 301 register caddr_t cp; 302 register long t1; 303 caddr_t bpos, dpos; 304 u_long xid; 305 int error = 0; 306 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 307 308 /* First look in the cache.. */ 309 if (nfs_getattrcache(vp, vap) == 0) 310 return (0); 311 nfsstats.rpccnt[NFSPROC_GETATTR]++; 312 nfsm_reqhead(nfs_procids[NFSPROC_GETATTR], cred, NFSX_FH); 313 nfsm_fhtom(vp); 314 nfsm_request(vp); 315 nfsm_loadattr(vp, vap); 316 nfsm_reqdone; 317 return (error); 318 } 319 320 /* 321 * nfs setattr call. 322 */ 323 nfs_setattr(vp, vap, cred) 324 register struct vnode *vp; 325 register struct vattr *vap; 326 struct ucred *cred; 327 { 328 register struct nfsv2_sattr *sp; 329 register caddr_t cp; 330 register long t1; 331 caddr_t bpos, dpos; 332 u_long xid; 333 int error = 0; 334 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 335 struct nfsnode *np; 336 337 nfsstats.rpccnt[NFSPROC_SETATTR]++; 338 nfsm_reqhead(nfs_procids[NFSPROC_SETATTR], cred, NFSX_FH+NFSX_SATTR); 339 nfsm_fhtom(vp); 340 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR); 341 if (vap->va_mode == 0xffff) 342 sp->sa_mode = VNOVAL; 343 else 344 sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode); 345 if (vap->va_uid == 0xffff) 346 sp->sa_uid = VNOVAL; 347 else 348 sp->sa_uid = txdr_unsigned(vap->va_uid); 349 if (vap->va_gid == 0xffff) 350 sp->sa_gid = VNOVAL; 351 else 352 sp->sa_gid = txdr_unsigned(vap->va_gid); 353 sp->sa_size = txdr_unsigned(vap->va_size); 354 if (vap->va_size != VNOVAL) { 355 np = VTONFS(vp); 356 if (np->n_flag & NMODIFIED) { 357 np->n_flag &= ~NMODIFIED; 358 vinvalbuf(vp, TRUE); 359 } 360 } 361 sp->sa_atime.tv_sec = txdr_unsigned(vap->va_atime.tv_sec); 362 sp->sa_atime.tv_usec = txdr_unsigned(vap->va_flags); 363 txdr_time(&vap->va_mtime, &sp->sa_mtime); 364 nfsm_request(vp); 365 nfsm_loadattr(vp, (struct vattr *)0); 366 /* should we fill in any vap fields ?? */ 367 nfsm_reqdone; 368 return (error); 369 } 370 371 /* 372 * nfs lookup call, one step at a time... 373 * First look in cache 374 * If not found, unlock the directory nfsnode and do the rpc 375 */ 376 nfs_lookup(vp, ndp) 377 register struct vnode *vp; 378 register struct nameidata *ndp; 379 { 380 register struct vnode *vdp; 381 register u_long *p; 382 register caddr_t cp; 383 register long t1, t2; 384 caddr_t bpos, dpos, cp2; 385 u_long xid; 386 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 387 struct vnode *newvp; 388 long len; 389 nfsv2fh_t *fhp; 390 struct nfsnode *np; 391 int lockparent, wantparent, flag, error = 0; 392 393 ndp->ni_dvp = vp; 394 ndp->ni_vp = NULL; 395 if (vp->v_type != VDIR) 396 return (ENOTDIR); 397 lockparent = ndp->ni_nameiop & LOCKPARENT; 398 flag = ndp->ni_nameiop & OPFLAG; 399 wantparent = ndp->ni_nameiop & (LOCKPARENT|WANTPARENT); 400 if ((error = cache_lookup(ndp)) && error != ENOENT) { 401 struct vattr vattr; 402 int vpid; 403 404 if (vp == ndp->ni_rdir && ndp->ni_isdotdot) 405 panic("nfs_lookup: .. through root"); 406 vdp = ndp->ni_vp; 407 vpid = vdp->v_id; 408 /* 409 * See the comment starting `Step through' in ufs/ufs_lookup.c 410 * for an explanation of the locking protocol 411 */ 412 if (vp == vdp) { 413 VREF(vdp); 414 error = 0; 415 } else if (ndp->ni_isdotdot) { 416 nfs_unlock(vp); 417 error = vget(vdp); 418 } else { 419 error = vget(vdp); 420 nfs_unlock(vp); 421 } 422 if (!error) { 423 if (vpid == vdp->v_id && 424 !nfs_getattr(vdp, &vattr, ndp->ni_cred)) { 425 nfsstats.lookupcache_hits++; 426 return (0); 427 } else { 428 nfs_nput(vdp); 429 } 430 } 431 ndp->ni_vp = (struct vnode *)0; 432 } else 433 nfs_unlock(vp); 434 error = 0; 435 nfsstats.lookupcache_misses++; 436 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 437 len = ndp->ni_namelen; 438 nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 439 nfsm_fhtom(vp); 440 nfsm_strtom(ndp->ni_ptr, len, NFS_MAXNAMLEN); 441 nfsm_request(vp); 442 nfsmout: 443 if (error) { 444 if (lockparent || (flag != CREATE && flag != RENAME) || 445 *ndp->ni_next != 0) 446 nfs_lock(vp); 447 return (ENOENT); 448 } 449 nfsm_disect(fhp,nfsv2fh_t *,NFSX_FH); 450 451 /* 452 * Handle DELETE and RENAME cases... 453 */ 454 if (flag == DELETE && *ndp->ni_next == 0) { 455 if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 456 VREF(vp); 457 newvp = vp; 458 np = VTONFS(vp); 459 } else { 460 if (error = nfs_nget(vp->v_mount, fhp, &np)) { 461 nfs_lock(vp); 462 m_freem(mrep); 463 return (error); 464 } 465 newvp = NFSTOV(np); 466 } 467 if (error = 468 nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 469 nfs_lock(vp); 470 if (newvp != vp) 471 nfs_nput(newvp); 472 else 473 vrele(vp); 474 m_freem(mrep); 475 return (error); 476 } 477 ndp->ni_vp = newvp; 478 if (lockparent || vp == newvp) 479 nfs_lock(vp); 480 m_freem(mrep); 481 return (0); 482 } 483 484 if (flag == RENAME && wantparent && *ndp->ni_next == 0) { 485 if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 486 nfs_lock(vp); 487 m_freem(mrep); 488 return (EISDIR); 489 } 490 if (error = nfs_nget(vp->v_mount, fhp, &np)) { 491 nfs_lock(vp); 492 m_freem(mrep); 493 return (error); 494 } 495 newvp = NFSTOV(np); 496 if (error = 497 nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 498 nfs_lock(vp); 499 nfs_nput(newvp); 500 m_freem(mrep); 501 return (error); 502 } 503 ndp->ni_vp = newvp; 504 if (lockparent) 505 nfs_lock(vp); 506 return (0); 507 } 508 509 if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 510 VREF(vp); 511 newvp = vp; 512 np = VTONFS(vp); 513 } else if (ndp->ni_isdotdot) { 514 if (error = nfs_nget(vp->v_mount, fhp, &np)) { 515 nfs_lock(vp); 516 m_freem(mrep); 517 return (error); 518 } 519 newvp = NFSTOV(np); 520 } else { 521 if (error = nfs_nget(vp->v_mount, fhp, &np)) { 522 nfs_lock(vp); 523 m_freem(mrep); 524 return (error); 525 } 526 newvp = NFSTOV(np); 527 } 528 if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 529 nfs_lock(vp); 530 if (newvp != vp) 531 nfs_nput(newvp); 532 else 533 vrele(vp); 534 m_freem(mrep); 535 return (error); 536 } 537 m_freem(mrep); 538 539 if (vp == newvp || (lockparent && *ndp->ni_next == '\0')) 540 nfs_lock(vp); 541 ndp->ni_vp = newvp; 542 if (error == 0 && ndp->ni_makeentry) 543 cache_enter(ndp); 544 return (error); 545 } 546 547 /* 548 * nfs readlink call 549 */ 550 nfs_readlink(vp, uiop, cred) 551 register struct vnode *vp; 552 struct uio *uiop; 553 struct ucred *cred; 554 { 555 register u_long *p; 556 register caddr_t cp; 557 register long t1; 558 caddr_t bpos, dpos, cp2; 559 u_long xid; 560 int error = 0; 561 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 562 long len; 563 564 nfsstats.rpccnt[NFSPROC_READLINK]++; 565 nfsm_reqhead(nfs_procids[NFSPROC_READLINK], cred, NFSX_FH); 566 nfsm_fhtom(vp); 567 nfsm_request(vp); 568 nfsm_strsiz(len, NFS_MAXPATHLEN); 569 nfsm_mtouio(uiop, len); 570 nfsm_reqdone; 571 return (error); 572 } 573 574 /* 575 * nfs read call 576 */ 577 nfs_readrpc(vp, uiop, cred) 578 register struct vnode *vp; 579 struct uio *uiop; 580 struct ucred *cred; 581 { 582 register u_long *p; 583 register caddr_t cp; 584 register long t1; 585 caddr_t bpos, dpos, cp2; 586 u_long xid; 587 int error = 0; 588 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 589 struct nfsmount *nmp; 590 long len, retlen, tsiz; 591 592 nmp = vfs_to_nfs(vp->v_mount); 593 tsiz = uiop->uio_resid; 594 while (tsiz > 0) { 595 nfsstats.rpccnt[NFSPROC_READ]++; 596 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 597 nfsm_reqhead(nfs_procids[NFSPROC_READ], cred, NFSX_FH+NFSX_UNSIGNED*3); 598 nfsm_fhtom(vp); 599 nfsm_build(p, u_long *, NFSX_UNSIGNED*3); 600 *p++ = txdr_unsigned(uiop->uio_offset); 601 *p++ = txdr_unsigned(len); 602 *p = 0; 603 nfsm_request(vp); 604 nfsm_loadattr(vp, (struct vattr *)0); 605 nfsm_strsiz(retlen, nmp->nm_rsize); 606 nfsm_mtouio(uiop, retlen); 607 m_freem(mrep); 608 if (retlen < len) 609 tsiz = 0; 610 else 611 tsiz -= len; 612 } 613 nfsmout: 614 return (error); 615 } 616 617 /* 618 * nfs write call 619 */ 620 nfs_writerpc(vp, uiop, cred) 621 register struct vnode *vp; 622 struct uio *uiop; 623 struct ucred *cred; 624 { 625 register u_long *p; 626 register caddr_t cp; 627 register long t1; 628 caddr_t bpos, dpos; 629 u_long xid; 630 int error = 0; 631 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 632 struct nfsmount *nmp; 633 long len, tsiz; 634 635 nmp = vfs_to_nfs(vp->v_mount); 636 tsiz = uiop->uio_resid; 637 while (tsiz > 0) { 638 nfsstats.rpccnt[NFSPROC_WRITE]++; 639 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 640 nfsm_reqhead(nfs_procids[NFSPROC_WRITE], cred, 641 NFSX_FH+NFSX_UNSIGNED*4); 642 nfsm_fhtom(vp); 643 nfsm_build(p, u_long *, NFSX_UNSIGNED*4); 644 *(p+1) = txdr_unsigned(uiop->uio_offset); 645 *(p+3) = txdr_unsigned(len); 646 nfsm_uiotom(uiop, len); 647 nfsm_request(vp); 648 nfsm_loadattr(vp, (struct vattr *)0); 649 m_freem(mrep); 650 tsiz -= len; 651 } 652 nfsmout: 653 return (error); 654 } 655 656 /* 657 * nfs mknod call 658 * This call is currently not supported. 659 */ 660 /* ARGSUSED */ 661 nfs_mknod(ndp, vap, cred) 662 struct nameidata *ndp; 663 struct ucred *cred; 664 struct vattr *vap; 665 { 666 667 nfs_abortop(ndp); 668 return (EOPNOTSUPP); 669 } 670 671 /* 672 * nfs file create call 673 */ 674 nfs_create(ndp, vap) 675 register struct nameidata *ndp; 676 register struct vattr *vap; 677 { 678 register struct nfsv2_sattr *sp; 679 register u_long *p; 680 register caddr_t cp; 681 register long t1, t2; 682 caddr_t bpos, dpos, cp2; 683 u_long xid; 684 int error = 0; 685 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 686 687 nfsstats.rpccnt[NFSPROC_CREATE]++; 688 nfsm_reqhead(nfs_procids[NFSPROC_CREATE], ndp->ni_cred, 689 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_SATTR); 690 nfsm_fhtom(ndp->ni_dvp); 691 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 692 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR); 693 sp->sa_mode = vtonfs_mode(VREG, vap->va_mode); 694 sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid); 695 sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid); 696 sp->sa_size = txdr_unsigned(0); 697 /* or should these be VNOVAL ?? */ 698 txdr_time(&vap->va_atime, &sp->sa_atime); 699 txdr_time(&vap->va_mtime, &sp->sa_mtime); 700 nfsm_request(ndp->ni_dvp); 701 nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp); 702 nfsm_reqdone; 703 nfs_nput(ndp->ni_dvp); 704 return (error); 705 } 706 707 /* 708 * nfs file remove call 709 * To try and make nfs semantics closer to vfs semantics, a file that has 710 * other references to the vnode is renamed instead of removed and then 711 * removed later on the last close. 712 * Unfortunately you must flush the buffer cache and cmap to get rid of 713 * all extraneous vnode references before you check the reference cnt. 714 * 1 - If the file could have blocks in the buffer cache 715 * flush them out and invalidate them 716 * mpurge the vnode to flush out cmap references 717 * (This is necessary to update the vnode ref cnt as well as sensible 718 * for actual removes, to free up the buffers) 719 * 2 - If v_usecount > 1 720 * If a rename is not already in the works 721 * call nfs_sillyrename() to set it up 722 * else 723 * do the remove rpc 724 */ 725 nfs_remove(ndp) 726 register struct nameidata *ndp; 727 { 728 register struct vnode *vp = ndp->ni_vp; 729 register struct nfsnode *np = VTONFS(ndp->ni_vp); 730 register u_long *p; 731 register caddr_t cp; 732 register long t1, t2; 733 caddr_t bpos, dpos; 734 u_long xid; 735 int error = 0; 736 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 737 738 if (vp->v_type == VREG) { 739 if (np->n_flag & (NMODIFIED|NBUFFERED)) { 740 np->n_flag &= ~(NMODIFIED|NBUFFERED); 741 vinvalbuf(vp, TRUE); 742 } 743 if (np->n_flag & NPAGEDON) { 744 np->n_flag &= ~NPAGEDON; 745 mpurge(vp); /* In case cmap entries still ref it */ 746 } 747 } 748 if (vp->v_usecount > 1) { 749 if (!np->n_sillyrename) 750 error = nfs_sillyrename(ndp, REMOVE); 751 } else { 752 nfsstats.rpccnt[NFSPROC_REMOVE]++; 753 nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], ndp->ni_cred, 754 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)); 755 nfsm_fhtom(ndp->ni_dvp); 756 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 757 nfsm_request(ndp->ni_dvp); 758 nfsm_reqdone; 759 /* 760 * Kludge City: If the first reply to the remove rpc is lost.. 761 * the reply to the retransmitted request will be ENOENT 762 * since the file was in fact removed 763 * Therefore, we cheat and return success. 764 */ 765 if (error == ENOENT) 766 error = 0; 767 } 768 if (ndp->ni_dvp == ndp->ni_vp) 769 vrele(ndp->ni_vp); 770 else 771 nfs_nput(ndp->ni_vp); 772 nfs_nput(ndp->ni_dvp); 773 return (error); 774 } 775 776 /* 777 * nfs file remove rpc called from nfs_inactive 778 */ 779 nfs_removeit(ndp) 780 register struct nameidata *ndp; 781 { 782 register u_long *p; 783 register caddr_t cp; 784 register long t1, t2; 785 caddr_t bpos, dpos; 786 u_long xid; 787 int error = 0; 788 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 789 790 nfsstats.rpccnt[NFSPROC_REMOVE]++; 791 nfsm_reqhead(nfs_procids[NFSPROC_REMOVE], ndp->ni_cred, 792 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)); 793 nfsm_fhtom(ndp->ni_dvp); 794 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 795 nfsm_request(ndp->ni_dvp); 796 nfsm_reqdone; 797 return (error); 798 } 799 800 /* 801 * nfs file rename call 802 */ 803 nfs_rename(sndp, tndp) 804 register struct nameidata *sndp, *tndp; 805 { 806 register u_long *p; 807 register caddr_t cp; 808 register long t1, t2; 809 caddr_t bpos, dpos; 810 u_long xid; 811 int error = 0; 812 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 813 814 nfsstats.rpccnt[NFSPROC_RENAME]++; 815 nfsm_reqhead(nfs_procids[NFSPROC_RENAME], tndp->ni_cred, 816 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_dent.d_namlen)+ 817 nfsm_rndup(tndp->ni_dent.d_namlen)); /* or sndp->ni_cred?*/ 818 nfsm_fhtom(sndp->ni_dvp); 819 nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN); 820 nfsm_fhtom(tndp->ni_dvp); 821 nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN); 822 nfsm_request(sndp->ni_dvp); 823 nfsm_reqdone; 824 if (sndp->ni_vp->v_type == VDIR) { 825 if (tndp->ni_vp != NULL && tndp->ni_vp->v_type == VDIR) 826 cache_purge(tndp->ni_dvp); 827 cache_purge(sndp->ni_dvp); 828 } 829 nfs_abortop(sndp); 830 nfs_abortop(tndp); 831 return (error); 832 } 833 834 /* 835 * nfs file rename rpc called from above 836 */ 837 nfs_renameit(sndp, tndp) 838 register struct nameidata *sndp, *tndp; 839 { 840 register u_long *p; 841 register caddr_t cp; 842 register long t1, t2; 843 caddr_t bpos, dpos; 844 u_long xid; 845 int error = 0; 846 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 847 848 nfsstats.rpccnt[NFSPROC_RENAME]++; 849 nfsm_reqhead(nfs_procids[NFSPROC_RENAME], tndp->ni_cred, 850 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(sndp->ni_dent.d_namlen)+ 851 nfsm_rndup(tndp->ni_dent.d_namlen)); /* or sndp->ni_cred?*/ 852 nfsm_fhtom(sndp->ni_dvp); 853 nfsm_strtom(sndp->ni_dent.d_name,sndp->ni_dent.d_namlen,NFS_MAXNAMLEN); 854 nfsm_fhtom(tndp->ni_dvp); 855 nfsm_strtom(tndp->ni_dent.d_name,tndp->ni_dent.d_namlen,NFS_MAXNAMLEN); 856 nfsm_request(sndp->ni_dvp); 857 nfsm_reqdone; 858 return (error); 859 } 860 861 /* 862 * nfs hard link create call 863 */ 864 nfs_link(vp, ndp) 865 register struct vnode *vp; 866 register struct nameidata *ndp; 867 { 868 register u_long *p; 869 register caddr_t cp; 870 register long t1, t2; 871 caddr_t bpos, dpos; 872 u_long xid; 873 int error = 0; 874 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 875 876 if (ndp->ni_dvp != vp) 877 nfs_lock(vp); 878 nfsstats.rpccnt[NFSPROC_LINK]++; 879 nfsm_reqhead(nfs_procids[NFSPROC_LINK], ndp->ni_cred, 880 NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)); 881 nfsm_fhtom(vp); 882 nfsm_fhtom(ndp->ni_dvp); 883 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 884 nfsm_request(vp); 885 nfsm_reqdone; 886 if (ndp->ni_dvp != vp) 887 nfs_unlock(vp); 888 nfs_nput(ndp->ni_dvp); 889 return (error); 890 } 891 892 /* 893 * nfs symbolic link create call 894 */ 895 nfs_symlink(ndp, vap, nm) 896 struct nameidata *ndp; 897 struct vattr *vap; 898 char *nm; /* is this the path ?? */ 899 { 900 register struct nfsv2_sattr *sp; 901 register u_long *p; 902 register caddr_t cp; 903 register long t1, t2; 904 caddr_t bpos, dpos; 905 u_long xid; 906 int error = 0; 907 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 908 909 nfsstats.rpccnt[NFSPROC_SYMLINK]++; 910 nfsm_reqhead(nfs_procids[NFSPROC_SYMLINK], ndp->ni_cred, 911 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_UNSIGNED); 912 nfsm_fhtom(ndp->ni_dvp); 913 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 914 nfsm_strtom(nm, strlen(nm), NFS_MAXPATHLEN); 915 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR); 916 sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode); 917 sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid); 918 sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid); 919 sp->sa_size = txdr_unsigned(VNOVAL); 920 txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */ 921 txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */ 922 nfsm_request(ndp->ni_dvp); 923 nfsm_reqdone; 924 nfs_nput(ndp->ni_dvp); 925 return (error); 926 } 927 928 /* 929 * nfs make dir call 930 */ 931 nfs_mkdir(ndp, vap) 932 register struct nameidata *ndp; 933 struct vattr *vap; 934 { 935 register struct nfsv2_sattr *sp; 936 register u_long *p; 937 register caddr_t cp; 938 register long t1, t2; 939 caddr_t bpos, dpos, cp2; 940 u_long xid; 941 int error = 0; 942 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 943 944 nfsstats.rpccnt[NFSPROC_MKDIR]++; 945 nfsm_reqhead(nfs_procids[NFSPROC_MKDIR], ndp->ni_cred, 946 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)+NFSX_SATTR); 947 nfsm_fhtom(ndp->ni_dvp); 948 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 949 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR); 950 sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode); 951 sp->sa_uid = txdr_unsigned(ndp->ni_cred->cr_uid); 952 sp->sa_gid = txdr_unsigned(ndp->ni_cred->cr_gid); 953 sp->sa_size = txdr_unsigned(VNOVAL); 954 txdr_time(&vap->va_atime, &sp->sa_atime); /* or VNOVAL ?? */ 955 txdr_time(&vap->va_mtime, &sp->sa_mtime); /* or VNOVAL ?? */ 956 nfsm_request(ndp->ni_dvp); 957 nfsm_mtofh(ndp->ni_dvp, ndp->ni_vp); 958 nfsm_reqdone; 959 nfs_nput(ndp->ni_dvp); 960 return (error); 961 } 962 963 /* 964 * nfs remove directory call 965 */ 966 nfs_rmdir(ndp) 967 register struct nameidata *ndp; 968 { 969 register u_long *p; 970 register caddr_t cp; 971 register long t1, t2; 972 caddr_t bpos, dpos; 973 u_long xid; 974 int error = 0; 975 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 976 977 if (ndp->ni_dvp == ndp->ni_vp) { 978 vrele(ndp->ni_dvp); 979 nfs_nput(ndp->ni_dvp); 980 return (EINVAL); 981 } 982 nfsstats.rpccnt[NFSPROC_RMDIR]++; 983 nfsm_reqhead(nfs_procids[NFSPROC_RMDIR], ndp->ni_cred, 984 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(ndp->ni_dent.d_namlen)); 985 nfsm_fhtom(ndp->ni_dvp); 986 nfsm_strtom(ndp->ni_dent.d_name, ndp->ni_dent.d_namlen, NFS_MAXNAMLEN); 987 nfsm_request(ndp->ni_dvp); 988 nfsm_reqdone; 989 cache_purge(ndp->ni_dvp); 990 cache_purge(ndp->ni_vp); 991 nfs_nput(ndp->ni_vp); 992 nfs_nput(ndp->ni_dvp); 993 return (error); 994 } 995 996 /* 997 * nfs readdir call 998 * Although cookie is defined as opaque, I translate it to/from net byte 999 * order so that it looks more sensible. This appears consistent with the 1000 * Ultrix implementation of NFS. 1001 */ 1002 nfs_readdir(vp, uiop, cred) 1003 register struct vnode *vp; 1004 struct uio *uiop; 1005 struct ucred *cred; 1006 { 1007 register long len; 1008 register struct direct *dp; 1009 register u_long *p; 1010 register caddr_t cp; 1011 register long t1; 1012 caddr_t bpos, dpos, cp2; 1013 u_long xid; 1014 int error = 0; 1015 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1016 struct mbuf *md2; 1017 caddr_t dpos2; 1018 int siz; 1019 int more_dirs; 1020 off_t off, savoff; 1021 struct direct *savdp; 1022 1023 nfsstats.rpccnt[NFSPROC_READDIR]++; 1024 nfsm_reqhead(nfs_procids[NFSPROC_READDIR], cred, xid); 1025 nfsm_fhtom(vp); 1026 nfsm_build(p, u_long *, 2*NFSX_UNSIGNED); 1027 *p++ = txdr_unsigned(uiop->uio_offset); 1028 *p = txdr_unsigned(uiop->uio_resid); 1029 nfsm_request(vp); 1030 siz = 0; 1031 nfsm_disect(p, u_long *, NFSX_UNSIGNED); 1032 more_dirs = fxdr_unsigned(int, *p); 1033 1034 /* Save the position so that we can do nfsm_mtouio() later */ 1035 dpos2 = dpos; 1036 md2 = md; 1037 1038 /* loop thru the dir entries, doctoring them to 4bsd form */ 1039 savoff = off = 0; 1040 savdp = dp = NULL; 1041 while (more_dirs && siz < uiop->uio_resid) { 1042 savoff = off; /* Hold onto offset and dp */ 1043 savdp = dp; 1044 nfsm_disecton(p, u_long *, 2*NFSX_UNSIGNED); 1045 dp = (struct direct *)p; 1046 dp->d_ino = fxdr_unsigned(u_long, *p++); 1047 len = fxdr_unsigned(int, *p); 1048 if (len <= 0 || len > NFS_MAXNAMLEN) { 1049 error = EBADRPC; 1050 m_freem(mrep); 1051 goto nfsmout; 1052 } 1053 dp->d_namlen = (u_short)len; 1054 len = nfsm_rndup(len); 1055 nfsm_adv(len); 1056 nfsm_disecton(p, u_long *, 2*NFSX_UNSIGNED); 1057 off = fxdr_unsigned(off_t, *p); 1058 *p++ = 0; /* Ensures null termination of name */ 1059 more_dirs = fxdr_unsigned(int, *p); 1060 dp->d_reclen = len+4*NFSX_UNSIGNED; 1061 siz += dp->d_reclen; 1062 } 1063 /* 1064 * If at end of rpc data, get the eof boolean 1065 */ 1066 if (!more_dirs) 1067 nfsm_disecton(p, u_long *, NFSX_UNSIGNED); 1068 /* 1069 * If there is too much to fit in the data buffer, use savoff and 1070 * savdp to trim off the last record. 1071 * --> we are not at eof 1072 */ 1073 if (siz > uiop->uio_resid) { 1074 off = savoff; 1075 siz -= dp->d_reclen; 1076 dp = savdp; 1077 } 1078 if (siz > 0) { 1079 md = md2; 1080 dpos = dpos2; 1081 nfsm_mtouio(uiop, siz); 1082 uiop->uio_offset = off; 1083 } 1084 nfsm_reqdone; 1085 return (error); 1086 } 1087 1088 /* 1089 * nfs statfs call 1090 * (Actually a vfsop, not a vnode op) 1091 */ 1092 nfs_statfs(mp, sbp) 1093 struct mount *mp; 1094 register struct statfs *sbp; 1095 { 1096 register struct vnode *vp; 1097 register struct nfsv2_statfs *sfp; 1098 register caddr_t cp; 1099 register long t1; 1100 caddr_t bpos, dpos, cp2; 1101 u_long xid; 1102 int error = 0; 1103 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1104 struct nfsmount *nmp; 1105 struct ucred *cred; 1106 struct nfsnode *np; 1107 1108 nmp = vfs_to_nfs(mp); 1109 if (error = nfs_nget(mp, &nmp->nm_fh, &np)) 1110 return (error); 1111 vp = NFSTOV(np); 1112 nfsstats.rpccnt[NFSPROC_STATFS]++; 1113 cred = crget(); 1114 cred->cr_ngroups = 1; 1115 nfsm_reqhead(nfs_procids[NFSPROC_STATFS], cred, NFSX_FH); 1116 nfsm_fhtom(vp); 1117 nfsm_request(vp); 1118 nfsm_disect(sfp, struct nfsv2_statfs *, NFSX_STATFS); 1119 sbp->f_type = MOUNT_NFS; 1120 sbp->f_flags = nmp->nm_flag; 1121 sbp->f_bsize = fxdr_unsigned(long, sfp->sf_tsize); 1122 sbp->f_fsize = fxdr_unsigned(long, sfp->sf_bsize); 1123 sbp->f_blocks = fxdr_unsigned(long, sfp->sf_blocks); 1124 sbp->f_bfree = fxdr_unsigned(long, sfp->sf_bfree); 1125 sbp->f_bavail = fxdr_unsigned(long, sfp->sf_bavail); 1126 sbp->f_files = 0; 1127 sbp->f_ffree = 0; 1128 sbp->f_fsid.val[0] = mp->m_fsid.val[0]; 1129 sbp->f_fsid.val[1] = mp->m_fsid.val[1]; 1130 bcopy(nmp->nm_path, sbp->f_mntonname, MNAMELEN); 1131 bcopy(nmp->nm_host, sbp->f_mntfromname, MNAMELEN); 1132 nfsm_reqdone; 1133 nfs_nput(vp); 1134 crfree(cred); 1135 return (error); 1136 } 1137 1138 static char hextoasc[] = "0123456789abcdef"; 1139 1140 /* 1141 * Silly rename. To make the NFS filesystem that is stateless look a little 1142 * more like the "ufs" a remove of an active vnode is translated to a rename 1143 * to a funny looking filename that is removed by nfs_inactive on the 1144 * nfsnode. There is the potential for another process on a different client 1145 * to create the same funny name between the nfs_lookitup() fails and the 1146 * nfs_rename() completes, but... 1147 */ 1148 nfs_sillyrename(ndp, flag) 1149 register struct nameidata *ndp; 1150 int flag; 1151 { 1152 register struct nfsnode *np; 1153 register struct sillyrename *sp; 1154 register struct nameidata *tndp; 1155 int error; 1156 short pid; 1157 1158 np = VTONFS(ndp->ni_dvp); 1159 cache_purge(ndp->ni_dvp); 1160 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 1161 M_TEMP, M_WAITOK); 1162 sp->s_flag = flag; 1163 bcopy((caddr_t)&np->n_fh, (caddr_t)&sp->s_fh, NFSX_FH); 1164 np = VTONFS(ndp->ni_vp); 1165 tndp = &sp->s_namei; 1166 tndp->ni_cred = crdup(ndp->ni_cred); 1167 1168 /* Fudge together a funny name */ 1169 pid = u.u_procp->p_pid; 1170 bcopy(".nfsAxxxx4.4", tndp->ni_dent.d_name, 13); 1171 tndp->ni_dent.d_namlen = 12; 1172 tndp->ni_dent.d_name[8] = hextoasc[pid & 0xf]; 1173 tndp->ni_dent.d_name[7] = hextoasc[(pid >> 4) & 0xf]; 1174 tndp->ni_dent.d_name[6] = hextoasc[(pid >> 8) & 0xf]; 1175 tndp->ni_dent.d_name[5] = hextoasc[(pid >> 12) & 0xf]; 1176 1177 /* Try lookitups until we get one that isn't there */ 1178 while (nfs_lookitup(ndp->ni_dvp, tndp, (nfsv2fh_t *)0) == 0) { 1179 tndp->ni_dent.d_name[4]++; 1180 if (tndp->ni_dent.d_name[4] > 'z') { 1181 error = EINVAL; 1182 goto bad; 1183 } 1184 } 1185 if (error = nfs_renameit(ndp, tndp)) 1186 goto bad; 1187 nfs_lookitup(ndp->ni_dvp, tndp, &np->n_fh); 1188 np->n_sillyrename = sp; 1189 return (0); 1190 bad: 1191 crfree(tndp->ni_cred); 1192 free((caddr_t)sp, M_TEMP); 1193 return (error); 1194 } 1195 1196 /* 1197 * Look up a file name for silly rename stuff. 1198 * Just like nfs_lookup() except that it doesn't load returned values 1199 * into the nfsnode table. 1200 * If fhp != NULL it copies the returned file handle out 1201 */ 1202 nfs_lookitup(vp, ndp, fhp) 1203 register struct vnode *vp; 1204 register struct nameidata *ndp; 1205 nfsv2fh_t *fhp; 1206 { 1207 register u_long *p; 1208 register caddr_t cp; 1209 register long t1, t2; 1210 caddr_t bpos, dpos, cp2; 1211 u_long xid; 1212 int error = 0; 1213 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1214 long len; 1215 1216 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 1217 ndp->ni_dvp = vp; 1218 ndp->ni_vp = NULL; 1219 len = ndp->ni_dent.d_namlen; 1220 nfsm_reqhead(nfs_procids[NFSPROC_LOOKUP], ndp->ni_cred, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 1221 nfsm_fhtom(vp); 1222 nfsm_strtom(ndp->ni_dent.d_name, len, NFS_MAXNAMLEN); 1223 nfsm_request(vp); 1224 if (fhp != NULL) { 1225 nfsm_disect(cp, caddr_t, NFSX_FH); 1226 bcopy(cp, (caddr_t)fhp, NFSX_FH); 1227 } 1228 nfsm_reqdone; 1229 return (error); 1230 } 1231 1232 /* 1233 * Kludge City.. 1234 * - make nfs_bmap() essentially a no-op that does no translation 1235 * - do nfs_strategy() by faking physical I/O with nfs_readit/nfs_writeit 1236 * after mapping the physical addresses into Kernel Virtual space in the 1237 * nfsiobuf area. 1238 * (Maybe I could use the process's page mapping, but I was concerned that 1239 * Kernel Write might not be enabled and also figured copyout() would do 1240 * a lot more work than bcopy() and also it currently happens in the 1241 * context of the swapper process (2). 1242 */ 1243 nfs_bmap(vp, bn, vpp, bnp) 1244 struct vnode *vp; 1245 daddr_t bn; 1246 struct vnode **vpp; 1247 daddr_t *bnp; 1248 { 1249 if (vpp != NULL) 1250 *vpp = vp; 1251 if (bnp != NULL) 1252 *bnp = bn * btodb(vp->v_mount->m_bsize); 1253 return (0); 1254 } 1255 1256 /* 1257 * Strategy routine for phys. i/o 1258 * If the biod's are running, queue a request 1259 * otherwise just call nfs_doio() to get it done 1260 */ 1261 nfs_strategy(bp) 1262 register struct buf *bp; 1263 { 1264 register struct buf *dp; 1265 register int i; 1266 struct proc *rp; 1267 int error = 0; 1268 int fnd = 0; 1269 1270 /* 1271 * If an i/o daemon is waiting 1272 * queue the request, wake it up and wait for completion 1273 * otherwise just do it ourselves 1274 */ 1275 for (i = 0; i < nfs_asyncdaemons; i++) { 1276 if (rp = nfs_iodwant[i]) { 1277 /* 1278 * Ensure that the async_daemon is still waiting here 1279 */ 1280 if (rp->p_stat != SSLEEP || 1281 rp->p_wchan != ((caddr_t)&nfs_iodwant[i])) { 1282 nfs_iodwant[i] = (struct proc *)0; 1283 continue; 1284 } 1285 dp = &nfs_bqueue; 1286 if (dp->b_actf == NULL) { 1287 dp->b_actl = bp; 1288 bp->b_actf = dp; 1289 } else { 1290 dp->b_actf->b_actl = bp; 1291 bp->b_actf = dp->b_actf; 1292 } 1293 dp->b_actf = bp; 1294 bp->b_actl = dp; 1295 fnd++; 1296 nfs_iodwant[i] = (struct proc *)0; 1297 wakeup((caddr_t)&nfs_iodwant[i]); 1298 break; 1299 } 1300 } 1301 if (!fnd) 1302 error = nfs_doio(bp); 1303 return (error); 1304 } 1305 1306 /* 1307 * Fun and games with i/o 1308 * Essentially play ubasetup() and disk interrupt service routine by 1309 * mapping the data buffer into kernel virtual space and doing the 1310 * nfs read or write rpc's from it. 1311 * If the biod's are not running, this is just called from nfs_strategy(), 1312 * otherwise it is called by the biod's to do what would normally be 1313 * partially disk interrupt driven. 1314 */ 1315 nfs_doio(bp) 1316 register struct buf *bp; 1317 { 1318 register struct pte *pte, *ppte; 1319 register caddr_t vaddr; 1320 register struct uio *uiop; 1321 register struct vnode *vp; 1322 struct nfsnode *np; 1323 struct ucred *cr; 1324 int npf, npf2; 1325 int reg; 1326 caddr_t vbase; 1327 unsigned v; 1328 struct proc *rp; 1329 int o, error; 1330 struct uio uio; 1331 struct iovec io; 1332 1333 vp = bp->b_vp; 1334 uiop = &uio; 1335 uiop->uio_iov = &io; 1336 uiop->uio_iovcnt = 1; 1337 uiop->uio_segflg = UIO_SYSSPACE; 1338 1339 /* 1340 * For phys i/o, map the b_addr into kernel virtual space using 1341 * the Nfsiomap pte's 1342 * Also, add a temporary b_rcred for reading using the process's uid 1343 * and a guess at a group 1344 */ 1345 if (bp->b_flags & B_PHYS) { 1346 VTONFS(vp)->n_flag |= NPAGEDON; 1347 bp->b_rcred = cr = crget(); 1348 rp = (bp->b_flags & B_DIRTY) ? &proc[2] : bp->b_proc; 1349 cr->cr_uid = rp->p_uid; 1350 cr->cr_gid = 0; /* Anything ?? */ 1351 cr->cr_ngroups = 1; 1352 o = (int)bp->b_un.b_addr & PGOFSET; 1353 npf2 = npf = btoc(bp->b_bcount + o); 1354 1355 /* 1356 * Get some mapping page table entries 1357 */ 1358 while ((reg = rmalloc(nfsmap, (long)npf)) == 0) { 1359 nfsmap_want++; 1360 sleep((caddr_t)&nfsmap_want, PZERO-1); 1361 } 1362 reg--; 1363 if (bp->b_flags & B_PAGET) 1364 pte = &Usrptmap[btokmx((struct pte *)bp->b_un.b_addr)]; 1365 else { 1366 v = btop(bp->b_un.b_addr); 1367 if (bp->b_flags & B_UAREA) 1368 pte = &rp->p_addr[v]; 1369 else 1370 pte = vtopte(rp, v); 1371 } 1372 1373 /* 1374 * Play vmaccess() but with the Nfsiomap page table 1375 */ 1376 ppte = &Nfsiomap[reg]; 1377 vbase = vaddr = &nfsiobuf[reg*NBPG]; 1378 while (npf != 0) { 1379 mapin(ppte, (u_int)vaddr, pte->pg_pfnum, (int)(PG_V|PG_KW)); 1380 #if defined(tahoe) 1381 mtpr(P1DC, vaddr); 1382 #endif 1383 ppte++; 1384 pte++; 1385 vaddr += NBPG; 1386 --npf; 1387 } 1388 1389 /* 1390 * And do the i/o rpc 1391 */ 1392 io.iov_base = vbase+o; 1393 io.iov_len = uiop->uio_resid = bp->b_bcount; 1394 uiop->uio_offset = bp->b_blkno * DEV_BSIZE; 1395 if (bp->b_flags & B_READ) { 1396 uiop->uio_rw = UIO_READ; 1397 nfsstats.read_physios++; 1398 bp->b_error = error = nfs_readrpc(vp, uiop, bp->b_rcred); 1399 } else { 1400 uiop->uio_rw = UIO_WRITE; 1401 nfsstats.write_physios++; 1402 bp->b_error = error = nfs_writerpc(vp, uiop, bp->b_wcred); 1403 } 1404 1405 /* 1406 * Finally, release pte's used by physical i/o 1407 */ 1408 crfree(cr); 1409 rmfree(nfsmap, (long)npf2, (long)++reg); 1410 if (nfsmap_want) { 1411 nfsmap_want = 0; 1412 wakeup((caddr_t)&nfsmap_want); 1413 } 1414 } else { 1415 if (bp->b_flags & B_READ) { 1416 io.iov_len = uiop->uio_resid = bp->b_bcount; 1417 uiop->uio_offset = bp->b_blkno * DEV_BSIZE; 1418 io.iov_base = bp->b_un.b_addr; 1419 uiop->uio_rw = UIO_READ; 1420 nfsstats.read_bios++; 1421 bp->b_error = error = nfs_readrpc(vp, uiop, bp->b_rcred); 1422 } else { 1423 io.iov_len = uiop->uio_resid = bp->b_dirtyend 1424 - bp->b_dirtyoff; 1425 uiop->uio_offset = (bp->b_blkno * DEV_BSIZE) 1426 + bp->b_dirtyoff; 1427 io.iov_base = bp->b_un.b_addr + bp->b_dirtyoff; 1428 uiop->uio_rw = UIO_WRITE; 1429 nfsstats.write_bios++; 1430 bp->b_error = error = nfs_writerpc(vp, uiop, bp->b_wcred); 1431 if (error) { 1432 np = VTONFS(vp); 1433 np->n_error = error; 1434 np->n_flag |= NWRITEERR; 1435 } 1436 bp->b_dirtyoff = bp->b_dirtyend = 0; 1437 } 1438 } 1439 if (error) 1440 bp->b_flags |= B_ERROR; 1441 bp->b_resid = uiop->uio_resid; 1442 biodone(bp); 1443 return (error); 1444 } 1445 1446 /* 1447 * Flush all the blocks associated with a vnode. 1448 * Walk through the buffer pool and push any dirty pages 1449 * associated with the vnode. 1450 */ 1451 /* ARGSUSED */ 1452 nfs_fsync(vp, fflags, cred, waitfor) 1453 register struct vnode *vp; 1454 int fflags; 1455 struct ucred *cred; 1456 int waitfor; 1457 { 1458 register struct nfsnode *np = VTONFS(vp); 1459 int error = 0; 1460 1461 if (np->n_flag & NMODIFIED) { 1462 np->n_flag &= ~NMODIFIED; 1463 vflushbuf(vp, waitfor == MNT_WAIT ? B_SYNC : 0); 1464 } 1465 if (!error && (np->n_flag & NWRITEERR)) 1466 error = np->n_error; 1467 return (error); 1468 } 1469 1470 /* 1471 * Print out the contents of an nfsnode. 1472 */ 1473 nfs_print(vp) 1474 struct vnode *vp; 1475 { 1476 register struct nfsnode *np = VTONFS(vp); 1477 1478 printf("tag VT_NFS, fileid %d fsid 0x%x%s\n", 1479 np->n_vattr.va_fileid, np->n_vattr.va_fsid, 1480 (np->n_flag & NLOCKED) ? " (LOCKED)" : ""); 1481 } 1482