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