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