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