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