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