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