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.105 (Berkeley) 04/17/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 struct vattr vattr; 923 char *cp2; 924 caddr_t bpos, dpos; 925 int error = 0, isnq; 926 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 927 u_long rdev; 928 929 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 930 if (vap->va_type == VCHR || vap->va_type == VBLK) 931 rdev = txdr_unsigned(vap->va_rdev); 932 #ifdef FIFO 933 else if (vap->va_type == VFIFO) 934 rdev = 0xffffffff; 935 #endif /* FIFO */ 936 else { 937 VOP_ABORTOP(dvp, cnp); 938 vput(dvp); 939 return (EOPNOTSUPP); 940 } 941 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 942 VOP_ABORTOP(dvp, cnp); 943 vput(dvp); 944 return (error); 945 } 946 nfsstats.rpccnt[NFSPROC_CREATE]++; 947 nfsm_reqhead(dvp, NFSPROC_CREATE, 948 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR(isnq)); 949 nfsm_fhtom(dvp); 950 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 951 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 952 sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 953 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 954 sp->sa_gid = txdr_unsigned(vattr.va_gid); 955 if (isnq) { 956 sp->sa_nqrdev = rdev; 957 sp->sa_nqflags = 0; 958 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 959 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 960 } else { 961 sp->sa_nfssize = rdev; 962 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 963 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 964 } 965 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 966 nfsm_mtofh(dvp, newvp); 967 nfsm_reqdone; 968 if (!error && (cnp->cn_flags & MAKEENTRY)) 969 cache_enter(dvp, newvp, cnp); 970 FREE(cnp->cn_pnbuf, M_NAMEI); 971 VTONFS(dvp)->n_flag |= NMODIFIED; 972 vrele(dvp); 973 return (error); 974 } 975 976 /* 977 * nfs file create call 978 */ 979 int 980 nfs_create(ap) 981 struct vop_create_args /* { 982 struct vnode *a_dvp; 983 struct vnode **a_vpp; 984 struct componentname *a_cnp; 985 struct vattr *a_vap; 986 } */ *ap; 987 { 988 register struct vnode *dvp = ap->a_dvp; 989 register struct vattr *vap = ap->a_vap; 990 register struct componentname *cnp = ap->a_cnp; 991 register struct nfsv2_sattr *sp; 992 register u_long *tl; 993 register caddr_t cp; 994 register long t1, t2; 995 caddr_t bpos, dpos, cp2; 996 int error = 0, isnq; 997 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 998 struct vattr vattr; 999 1000 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1001 VOP_ABORTOP(dvp, cnp); 1002 vput(dvp); 1003 return (error); 1004 } 1005 nfsstats.rpccnt[NFSPROC_CREATE]++; 1006 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 1007 nfsm_reqhead(dvp, NFSPROC_CREATE, 1008 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR(isnq)); 1009 nfsm_fhtom(dvp); 1010 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1011 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 1012 sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 1013 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1014 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1015 if (isnq) { 1016 u_quad_t qval = 0; 1017 1018 txdr_hyper(&qval, &sp->sa_nqsize); 1019 sp->sa_nqflags = 0; 1020 sp->sa_nqrdev = -1; 1021 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 1022 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 1023 } else { 1024 sp->sa_nfssize = 0; 1025 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 1026 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 1027 } 1028 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1029 nfsm_mtofh(dvp, *ap->a_vpp); 1030 nfsm_reqdone; 1031 if (!error && (cnp->cn_flags & MAKEENTRY)) 1032 cache_enter(dvp, *ap->a_vpp, cnp); 1033 FREE(cnp->cn_pnbuf, M_NAMEI); 1034 VTONFS(dvp)->n_flag |= NMODIFIED; 1035 vrele(dvp); 1036 return (error); 1037 } 1038 1039 /* 1040 * nfs file remove call 1041 * To try and make nfs semantics closer to ufs semantics, a file that has 1042 * other processes using the vnode is renamed instead of removed and then 1043 * removed later on the last close. 1044 * - If v_usecount > 1 1045 * If a rename is not already in the works 1046 * call nfs_sillyrename() to set it up 1047 * else 1048 * do the remove rpc 1049 */ 1050 int 1051 nfs_remove(ap) 1052 struct vop_remove_args /* { 1053 struct vnodeop_desc *a_desc; 1054 struct vnode * a_dvp; 1055 struct vnode * a_vp; 1056 struct componentname * a_cnp; 1057 } */ *ap; 1058 { 1059 register struct vnode *vp = ap->a_vp; 1060 register struct vnode *dvp = ap->a_dvp; 1061 register struct componentname *cnp = ap->a_cnp; 1062 register struct nfsnode *np = VTONFS(vp); 1063 register u_long *tl; 1064 register caddr_t cp; 1065 register long t2; 1066 caddr_t bpos, dpos; 1067 int error = 0; 1068 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1069 1070 if (vp->v_usecount > 1) { 1071 if (!np->n_sillyrename) 1072 error = nfs_sillyrename(dvp, vp, cnp); 1073 } else { 1074 /* 1075 * Purge the name cache so that the chance of a lookup for 1076 * the name succeeding while the remove is in progress is 1077 * minimized. Without node locking it can still happen, such 1078 * that an I/O op returns ESTALE, but since you get this if 1079 * another host removes the file.. 1080 */ 1081 cache_purge(vp); 1082 /* 1083 * Throw away biocache buffers. Mainly to avoid 1084 * unnecessary delayed writes. 1085 */ 1086 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1); 1087 if (error == EINTR) 1088 return (error); 1089 /* Do the rpc */ 1090 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1091 nfsm_reqhead(dvp, NFSPROC_REMOVE, 1092 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 1093 nfsm_fhtom(dvp); 1094 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1095 nfsm_request(dvp, NFSPROC_REMOVE, cnp->cn_proc, cnp->cn_cred); 1096 nfsm_reqdone; 1097 FREE(cnp->cn_pnbuf, M_NAMEI); 1098 VTONFS(dvp)->n_flag |= NMODIFIED; 1099 /* 1100 * Kludge City: If the first reply to the remove rpc is lost.. 1101 * the reply to the retransmitted request will be ENOENT 1102 * since the file was in fact removed 1103 * Therefore, we cheat and return success. 1104 */ 1105 if (error == ENOENT) 1106 error = 0; 1107 } 1108 np->n_attrstamp = 0; 1109 vrele(dvp); 1110 vrele(vp); 1111 return (error); 1112 } 1113 1114 /* 1115 * nfs file remove rpc called from nfs_inactive 1116 */ 1117 int 1118 nfs_removeit(sp) 1119 register struct sillyrename *sp; 1120 { 1121 register u_long *tl; 1122 register caddr_t cp; 1123 register long t2; 1124 caddr_t bpos, dpos; 1125 int error = 0; 1126 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1127 1128 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1129 nfsm_reqhead(sp->s_dvp, NFSPROC_REMOVE, 1130 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(sp->s_namlen)); 1131 nfsm_fhtom(sp->s_dvp); 1132 nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN); 1133 nfsm_request(sp->s_dvp, NFSPROC_REMOVE, NULL, sp->s_cred); 1134 nfsm_reqdone; 1135 VTONFS(sp->s_dvp)->n_flag |= NMODIFIED; 1136 return (error); 1137 } 1138 1139 /* 1140 * nfs file rename call 1141 */ 1142 int 1143 nfs_rename(ap) 1144 struct vop_rename_args /* { 1145 struct vnode *a_fdvp; 1146 struct vnode *a_fvp; 1147 struct componentname *a_fcnp; 1148 struct vnode *a_tdvp; 1149 struct vnode *a_tvp; 1150 struct componentname *a_tcnp; 1151 } */ *ap; 1152 { 1153 register struct vnode *fvp = ap->a_fvp; 1154 register struct vnode *tvp = ap->a_tvp; 1155 register struct vnode *fdvp = ap->a_fdvp; 1156 register struct vnode *tdvp = ap->a_tdvp; 1157 register struct componentname *tcnp = ap->a_tcnp; 1158 register struct componentname *fcnp = ap->a_fcnp; 1159 register u_long *tl; 1160 register caddr_t cp; 1161 register long t2; 1162 caddr_t bpos, dpos; 1163 int error = 0; 1164 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1165 1166 /* Check for cross-device rename */ 1167 if ((fvp->v_mount != tdvp->v_mount) || 1168 (tvp && (fvp->v_mount != tvp->v_mount))) { 1169 error = EXDEV; 1170 goto out; 1171 } 1172 1173 1174 nfsstats.rpccnt[NFSPROC_RENAME]++; 1175 nfsm_reqhead(fdvp, NFSPROC_RENAME, 1176 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(fcnp->cn_namelen)+ 1177 nfsm_rndup(fcnp->cn_namelen)); /* or fcnp->cn_cred?*/ 1178 nfsm_fhtom(fdvp); 1179 nfsm_strtom(fcnp->cn_nameptr, fcnp->cn_namelen, NFS_MAXNAMLEN); 1180 nfsm_fhtom(tdvp); 1181 nfsm_strtom(tcnp->cn_nameptr, tcnp->cn_namelen, NFS_MAXNAMLEN); 1182 nfsm_request(fdvp, NFSPROC_RENAME, tcnp->cn_proc, tcnp->cn_cred); 1183 nfsm_reqdone; 1184 VTONFS(fdvp)->n_flag |= NMODIFIED; 1185 VTONFS(tdvp)->n_flag |= NMODIFIED; 1186 if (fvp->v_type == VDIR) { 1187 if (tvp != NULL && tvp->v_type == VDIR) 1188 cache_purge(tdvp); 1189 cache_purge(fdvp); 1190 } 1191 out: 1192 if (tdvp == tvp) 1193 vrele(tdvp); 1194 else 1195 vput(tdvp); 1196 if (tvp) 1197 vput(tvp); 1198 vrele(fdvp); 1199 vrele(fvp); 1200 /* 1201 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1202 */ 1203 if (error == ENOENT) 1204 error = 0; 1205 return (error); 1206 } 1207 1208 /* 1209 * nfs file rename rpc called from nfs_remove() above 1210 */ 1211 int 1212 nfs_renameit(sdvp, scnp, sp) 1213 struct vnode *sdvp; 1214 struct componentname *scnp; 1215 register struct sillyrename *sp; 1216 { 1217 register u_long *tl; 1218 register caddr_t cp; 1219 register long t2; 1220 caddr_t bpos, dpos; 1221 int error = 0; 1222 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1223 1224 nfsstats.rpccnt[NFSPROC_RENAME]++; 1225 nfsm_reqhead(sdvp, NFSPROC_RENAME, 1226 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(scnp->cn_namelen)+ 1227 nfsm_rndup(sp->s_namlen)); 1228 nfsm_fhtom(sdvp); 1229 nfsm_strtom(scnp->cn_nameptr, scnp->cn_namelen, NFS_MAXNAMLEN); 1230 nfsm_fhtom(sdvp); 1231 nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN); 1232 nfsm_request(sdvp, NFSPROC_RENAME, scnp->cn_proc, scnp->cn_cred); 1233 nfsm_reqdone; 1234 FREE(scnp->cn_pnbuf, M_NAMEI); 1235 VTONFS(sdvp)->n_flag |= NMODIFIED; 1236 return (error); 1237 } 1238 1239 /* 1240 * nfs hard link create call 1241 */ 1242 int 1243 nfs_link(ap) 1244 struct vop_link_args /* { 1245 struct vnode *a_vp; 1246 struct vnode *a_tdvp; 1247 struct componentname *a_cnp; 1248 } */ *ap; 1249 { 1250 register struct vnode *vp = ap->a_vp; 1251 register struct vnode *tdvp = ap->a_tdvp; 1252 register struct componentname *cnp = ap->a_cnp; 1253 register u_long *tl; 1254 register caddr_t cp; 1255 register long t2; 1256 caddr_t bpos, dpos; 1257 int error = 0; 1258 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1259 1260 if (vp->v_mount != tdvp->v_mount) { 1261 /*VOP_ABORTOP(vp, cnp);*/ 1262 if (tdvp == vp) 1263 vrele(vp); 1264 else 1265 vput(vp); 1266 return (EXDEV); 1267 } 1268 1269 nfsstats.rpccnt[NFSPROC_LINK]++; 1270 nfsm_reqhead(tdvp, NFSPROC_LINK, 1271 NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 1272 nfsm_fhtom(tdvp); 1273 nfsm_fhtom(vp); 1274 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1275 nfsm_request(tdvp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); 1276 nfsm_reqdone; 1277 FREE(cnp->cn_pnbuf, M_NAMEI); 1278 VTONFS(tdvp)->n_attrstamp = 0; 1279 VTONFS(vp)->n_flag |= NMODIFIED; 1280 vrele(vp); 1281 /* 1282 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1283 */ 1284 if (error == EEXIST) 1285 error = 0; 1286 return (error); 1287 } 1288 1289 /* 1290 * nfs symbolic link create call 1291 */ 1292 /* start here */ 1293 int 1294 nfs_symlink(ap) 1295 struct vop_symlink_args /* { 1296 struct vnode *a_dvp; 1297 struct vnode **a_vpp; 1298 struct componentname *a_cnp; 1299 struct vattr *a_vap; 1300 char *a_target; 1301 } */ *ap; 1302 { 1303 register struct vnode *dvp = ap->a_dvp; 1304 register struct vattr *vap = ap->a_vap; 1305 register struct componentname *cnp = ap->a_cnp; 1306 register struct nfsv2_sattr *sp; 1307 register u_long *tl; 1308 register caddr_t cp; 1309 register long t2; 1310 caddr_t bpos, dpos; 1311 int slen, error = 0, isnq; 1312 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1313 1314 nfsstats.rpccnt[NFSPROC_SYMLINK]++; 1315 slen = strlen(ap->a_target); 1316 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 1317 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH+2*NFSX_UNSIGNED+ 1318 nfsm_rndup(cnp->cn_namelen)+nfsm_rndup(slen)+NFSX_SATTR(isnq)); 1319 nfsm_fhtom(dvp); 1320 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1321 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN); 1322 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 1323 sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode); 1324 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1325 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 1326 if (isnq) { 1327 quad_t qval = -1; 1328 1329 txdr_hyper(&qval, &sp->sa_nqsize); 1330 sp->sa_nqflags = 0; 1331 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 1332 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 1333 } else { 1334 sp->sa_nfssize = -1; 1335 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 1336 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 1337 } 1338 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred); 1339 nfsm_reqdone; 1340 FREE(cnp->cn_pnbuf, M_NAMEI); 1341 VTONFS(dvp)->n_flag |= NMODIFIED; 1342 vrele(dvp); 1343 /* 1344 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1345 */ 1346 if (error == EEXIST) 1347 error = 0; 1348 return (error); 1349 } 1350 1351 /* 1352 * nfs make dir call 1353 */ 1354 int 1355 nfs_mkdir(ap) 1356 struct vop_mkdir_args /* { 1357 struct vnode *a_dvp; 1358 struct vnode **a_vpp; 1359 struct componentname *a_cnp; 1360 struct vattr *a_vap; 1361 } */ *ap; 1362 { 1363 register struct vnode *dvp = ap->a_dvp; 1364 register struct vattr *vap = ap->a_vap; 1365 register struct componentname *cnp = ap->a_cnp; 1366 register struct vnode **vpp = ap->a_vpp; 1367 register struct nfsv2_sattr *sp; 1368 register u_long *tl; 1369 register caddr_t cp; 1370 register long t1, t2; 1371 register int len; 1372 caddr_t bpos, dpos, cp2; 1373 int error = 0, firsttry = 1, isnq; 1374 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1375 struct vattr vattr; 1376 1377 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1378 VOP_ABORTOP(dvp, cnp); 1379 vput(dvp); 1380 return (error); 1381 } 1382 len = cnp->cn_namelen; 1383 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 1384 nfsstats.rpccnt[NFSPROC_MKDIR]++; 1385 nfsm_reqhead(dvp, NFSPROC_MKDIR, 1386 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)+NFSX_SATTR(isnq)); 1387 nfsm_fhtom(dvp); 1388 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1389 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 1390 sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode); 1391 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1392 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1393 if (isnq) { 1394 quad_t qval = -1; 1395 1396 txdr_hyper(&qval, &sp->sa_nqsize); 1397 sp->sa_nqflags = 0; 1398 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 1399 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 1400 } else { 1401 sp->sa_nfssize = -1; 1402 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 1403 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 1404 } 1405 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred); 1406 nfsm_mtofh(dvp, *vpp); 1407 nfsm_reqdone; 1408 VTONFS(dvp)->n_flag |= NMODIFIED; 1409 /* 1410 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 1411 * if we can succeed in looking up the directory. 1412 * "firsttry" is necessary since the macros may "goto nfsmout" which 1413 * is above the if on errors. (Ugh) 1414 */ 1415 if (error == EEXIST && firsttry) { 1416 firsttry = 0; 1417 error = 0; 1418 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 1419 *vpp = NULL; 1420 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 1421 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 1422 nfsm_fhtom(dvp); 1423 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1424 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 1425 nfsm_mtofh(dvp, *vpp); 1426 if ((*vpp)->v_type != VDIR) { 1427 vput(*vpp); 1428 error = EEXIST; 1429 } 1430 m_freem(mrep); 1431 } 1432 FREE(cnp->cn_pnbuf, M_NAMEI); 1433 vrele(dvp); 1434 return (error); 1435 } 1436 1437 /* 1438 * nfs remove directory call 1439 */ 1440 int 1441 nfs_rmdir(ap) 1442 struct vop_rmdir_args /* { 1443 struct vnode *a_dvp; 1444 struct vnode *a_vp; 1445 struct componentname *a_cnp; 1446 } */ *ap; 1447 { 1448 register struct vnode *vp = ap->a_vp; 1449 register struct vnode *dvp = ap->a_dvp; 1450 register struct componentname *cnp = ap->a_cnp; 1451 register u_long *tl; 1452 register caddr_t cp; 1453 register long t2; 1454 caddr_t bpos, dpos; 1455 int error = 0; 1456 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1457 1458 if (dvp == vp) { 1459 vrele(dvp); 1460 vrele(dvp); 1461 FREE(cnp->cn_pnbuf, M_NAMEI); 1462 return (EINVAL); 1463 } 1464 nfsstats.rpccnt[NFSPROC_RMDIR]++; 1465 nfsm_reqhead(dvp, NFSPROC_RMDIR, 1466 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 1467 nfsm_fhtom(dvp); 1468 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1469 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred); 1470 nfsm_reqdone; 1471 FREE(cnp->cn_pnbuf, M_NAMEI); 1472 VTONFS(dvp)->n_flag |= NMODIFIED; 1473 cache_purge(dvp); 1474 cache_purge(vp); 1475 vrele(vp); 1476 vrele(dvp); 1477 /* 1478 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 1479 */ 1480 if (error == ENOENT) 1481 error = 0; 1482 return (error); 1483 } 1484 1485 /* 1486 * nfs readdir call 1487 * Although cookie is defined as opaque, I translate it to/from net byte 1488 * order so that it looks more sensible. This appears consistent with the 1489 * Ultrix implementation of NFS. 1490 */ 1491 int 1492 nfs_readdir(ap) 1493 struct vop_readdir_args /* { 1494 struct vnode *a_vp; 1495 struct uio *a_uio; 1496 struct ucred *a_cred; 1497 } */ *ap; 1498 { 1499 register struct vnode *vp = ap->a_vp; 1500 register struct nfsnode *np = VTONFS(vp); 1501 register struct uio *uio = ap->a_uio; 1502 int tresid, error; 1503 struct vattr vattr; 1504 1505 if (vp->v_type != VDIR) 1506 return (EPERM); 1507 /* 1508 * First, check for hit on the EOF offset cache 1509 */ 1510 if (uio->uio_offset != 0 && uio->uio_offset == np->n_direofoffset && 1511 (np->n_flag & NMODIFIED) == 0) { 1512 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { 1513 if (NQNFS_CKCACHABLE(vp, NQL_READ)) { 1514 nfsstats.direofcache_hits++; 1515 return (0); 1516 } 1517 } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 && 1518 np->n_mtime == vattr.va_mtime.ts_sec) { 1519 nfsstats.direofcache_hits++; 1520 return (0); 1521 } 1522 } 1523 1524 /* 1525 * Call nfs_bioread() to do the real work. 1526 */ 1527 tresid = uio->uio_resid; 1528 error = nfs_bioread(vp, uio, 0, ap->a_cred); 1529 1530 if (!error && uio->uio_resid == tresid) 1531 nfsstats.direofcache_misses++; 1532 return (error); 1533 } 1534 1535 /* 1536 * Readdir rpc call. 1537 * Called from below the buffer cache by nfs_doio(). 1538 */ 1539 int 1540 nfs_readdirrpc(vp, uiop, cred) 1541 register struct vnode *vp; 1542 struct uio *uiop; 1543 struct ucred *cred; 1544 { 1545 register long len; 1546 register struct dirent *dp; 1547 register u_long *tl; 1548 register caddr_t cp; 1549 register long t1; 1550 long tlen, lastlen; 1551 caddr_t bpos, dpos, cp2; 1552 int error = 0; 1553 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1554 struct mbuf *md2; 1555 caddr_t dpos2; 1556 int siz; 1557 int more_dirs = 1; 1558 u_long off, savoff; 1559 struct dirent *savdp; 1560 struct nfsmount *nmp; 1561 struct nfsnode *np = VTONFS(vp); 1562 long tresid; 1563 1564 nmp = VFSTONFS(vp->v_mount); 1565 tresid = uiop->uio_resid; 1566 /* 1567 * Loop around doing readdir rpc's of size uio_resid or nm_rsize, 1568 * whichever is smaller, truncated to a multiple of NFS_DIRBLKSIZ. 1569 * The stopping criteria is EOF or buffer full. 1570 */ 1571 while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) { 1572 nfsstats.rpccnt[NFSPROC_READDIR]++; 1573 nfsm_reqhead(vp, NFSPROC_READDIR, 1574 NFSX_FH + 2 * NFSX_UNSIGNED); 1575 nfsm_fhtom(vp); 1576 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 1577 off = (u_long)uiop->uio_offset; 1578 *tl++ = txdr_unsigned(off); 1579 *tl = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ? 1580 nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1)); 1581 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred); 1582 siz = 0; 1583 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1584 more_dirs = fxdr_unsigned(int, *tl); 1585 1586 /* Save the position so that we can do nfsm_mtouio() later */ 1587 dpos2 = dpos; 1588 md2 = md; 1589 1590 /* loop thru the dir entries, doctoring them to 4bsd form */ 1591 #ifdef lint 1592 dp = (struct dirent *)0; 1593 #endif /* lint */ 1594 while (more_dirs && siz < uiop->uio_resid) { 1595 savoff = off; /* Hold onto offset and dp */ 1596 savdp = dp; 1597 nfsm_dissecton(tl, u_long *, 2 * NFSX_UNSIGNED); 1598 dp = (struct dirent *)tl; 1599 dp->d_fileno = fxdr_unsigned(u_long, *tl++); 1600 len = fxdr_unsigned(int, *tl); 1601 if (len <= 0 || len > NFS_MAXNAMLEN) { 1602 error = EBADRPC; 1603 m_freem(mrep); 1604 goto nfsmout; 1605 } 1606 dp->d_namlen = (u_char)len; 1607 dp->d_type = DT_UNKNOWN; 1608 nfsm_adv(len); /* Point past name */ 1609 tlen = nfsm_rndup(len); 1610 /* 1611 * This should not be necessary, but some servers have 1612 * broken XDR such that these bytes are not null filled. 1613 */ 1614 if (tlen != len) { 1615 *dpos = '\0'; /* Null-terminate */ 1616 nfsm_adv(tlen - len); 1617 len = tlen; 1618 } 1619 nfsm_dissecton(tl, u_long *, 2 * NFSX_UNSIGNED); 1620 off = fxdr_unsigned(u_long, *tl); 1621 *tl++ = 0; /* Ensures null termination of name */ 1622 more_dirs = fxdr_unsigned(int, *tl); 1623 dp->d_reclen = len + 4 * NFSX_UNSIGNED; 1624 siz += dp->d_reclen; 1625 } 1626 /* 1627 * If at end of rpc data, get the eof boolean 1628 */ 1629 if (!more_dirs) { 1630 nfsm_dissecton(tl, u_long *, NFSX_UNSIGNED); 1631 more_dirs = (fxdr_unsigned(int, *tl) == 0); 1632 1633 /* 1634 * If at EOF, cache directory offset 1635 */ 1636 if (!more_dirs) 1637 np->n_direofoffset = off; 1638 } 1639 /* 1640 * If there is too much to fit in the data buffer, use savoff and 1641 * savdp to trim off the last record. 1642 * --> we are not at eof 1643 */ 1644 if (siz > uiop->uio_resid) { 1645 off = savoff; 1646 siz -= dp->d_reclen; 1647 dp = savdp; 1648 more_dirs = 0; /* Paranoia */ 1649 } 1650 if (siz > 0) { 1651 lastlen = dp->d_reclen; 1652 md = md2; 1653 dpos = dpos2; 1654 nfsm_mtouio(uiop, siz); 1655 uiop->uio_offset = (off_t)off; 1656 } else 1657 more_dirs = 0; /* Ugh, never happens, but in case.. */ 1658 m_freem(mrep); 1659 } 1660 /* 1661 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 1662 * by increasing d_reclen for the last record. 1663 */ 1664 if (uiop->uio_resid < tresid) { 1665 len = uiop->uio_resid & (NFS_DIRBLKSIZ - 1); 1666 if (len > 0) { 1667 dp = (struct dirent *) 1668 (uiop->uio_iov->iov_base - lastlen); 1669 dp->d_reclen += len; 1670 uiop->uio_iov->iov_base += len; 1671 uiop->uio_iov->iov_len -= len; 1672 uiop->uio_resid -= len; 1673 } 1674 } 1675 nfsmout: 1676 return (error); 1677 } 1678 1679 /* 1680 * Nqnfs readdir_and_lookup RPC. Used in place of nfs_readdirrpc(). 1681 */ 1682 int 1683 nfs_readdirlookrpc(vp, uiop, cred) 1684 struct vnode *vp; 1685 register struct uio *uiop; 1686 struct ucred *cred; 1687 { 1688 register int len; 1689 register struct dirent *dp; 1690 register u_long *tl; 1691 register caddr_t cp; 1692 register long t1; 1693 caddr_t bpos, dpos, cp2; 1694 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1695 struct nameidata nami, *ndp = &nami; 1696 struct componentname *cnp = &ndp->ni_cnd; 1697 u_long off, endoff, fileno; 1698 time_t reqtime, ltime; 1699 struct nfsmount *nmp; 1700 struct nfsnode *np, *tp; 1701 struct vnode *newvp; 1702 nfsv2fh_t *fhp; 1703 u_quad_t frev; 1704 int error = 0, tlen, more_dirs = 1, tresid, doit, bigenough, i; 1705 int cachable; 1706 1707 if (uiop->uio_iovcnt != 1) 1708 panic("nfs rdirlook"); 1709 nmp = VFSTONFS(vp->v_mount); 1710 tresid = uiop->uio_resid; 1711 ndp->ni_dvp = vp; 1712 newvp = NULLVP; 1713 /* 1714 * Loop around doing readdir rpc's of size uio_resid or nm_rsize, 1715 * whichever is smaller, truncated to a multiple of NFS_DIRBLKSIZ. 1716 * The stopping criteria is EOF or buffer full. 1717 */ 1718 while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) { 1719 nfsstats.rpccnt[NQNFSPROC_READDIRLOOK]++; 1720 nfsm_reqhead(vp, NQNFSPROC_READDIRLOOK, 1721 NFSX_FH + 3 * NFSX_UNSIGNED); 1722 nfsm_fhtom(vp); 1723 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 1724 off = (u_long)uiop->uio_offset; 1725 *tl++ = txdr_unsigned(off); 1726 *tl++ = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ? 1727 nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1)); 1728 if (nmp->nm_flag & NFSMNT_NQLOOKLEASE) 1729 *tl = txdr_unsigned(nmp->nm_leaseterm); 1730 else 1731 *tl = 0; 1732 reqtime = time.tv_sec; 1733 nfsm_request(vp, NQNFSPROC_READDIRLOOK, uiop->uio_procp, cred); 1734 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1735 more_dirs = fxdr_unsigned(int, *tl); 1736 1737 /* loop thru the dir entries, doctoring them to 4bsd form */ 1738 bigenough = 1; 1739 while (more_dirs && bigenough) { 1740 doit = 1; 1741 nfsm_dissect(tl, u_long *, 4 * NFSX_UNSIGNED); 1742 if (nmp->nm_flag & NFSMNT_NQLOOKLEASE) { 1743 cachable = fxdr_unsigned(int, *tl++); 1744 ltime = reqtime + fxdr_unsigned(int, *tl++); 1745 fxdr_hyper(tl, &frev); 1746 } 1747 nfsm_dissect(fhp, nfsv2fh_t *, NFSX_FH); 1748 if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 1749 VREF(vp); 1750 newvp = vp; 1751 np = VTONFS(vp); 1752 } else { 1753 if (error = nfs_nget(vp->v_mount, fhp, &np)) 1754 doit = 0; 1755 newvp = NFSTOV(np); 1756 } 1757 if (error = nfs_loadattrcache(&newvp, &md, &dpos, 1758 (struct vattr *)0)) 1759 doit = 0; 1760 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1761 fileno = fxdr_unsigned(u_long, *tl++); 1762 len = fxdr_unsigned(int, *tl); 1763 if (len <= 0 || len > NFS_MAXNAMLEN) { 1764 error = EBADRPC; 1765 m_freem(mrep); 1766 goto nfsmout; 1767 } 1768 tlen = (len + 4) & ~0x3; 1769 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 1770 bigenough = 0; 1771 if (bigenough && doit) { 1772 dp = (struct dirent *)uiop->uio_iov->iov_base; 1773 dp->d_fileno = fileno; 1774 dp->d_namlen = len; 1775 dp->d_reclen = tlen + DIRHDSIZ; 1776 dp->d_type = 1777 IFTODT(VTTOIF(np->n_vattr.va_type)); 1778 uiop->uio_resid -= DIRHDSIZ; 1779 uiop->uio_iov->iov_base += DIRHDSIZ; 1780 uiop->uio_iov->iov_len -= DIRHDSIZ; 1781 cnp->cn_nameptr = uiop->uio_iov->iov_base; 1782 cnp->cn_namelen = len; 1783 ndp->ni_vp = newvp; 1784 nfsm_mtouio(uiop, len); 1785 cp = uiop->uio_iov->iov_base; 1786 tlen -= len; 1787 for (i = 0; i < tlen; i++) 1788 *cp++ = '\0'; 1789 uiop->uio_iov->iov_base += tlen; 1790 uiop->uio_iov->iov_len -= tlen; 1791 uiop->uio_resid -= tlen; 1792 cnp->cn_hash = 0; 1793 for (cp = cnp->cn_nameptr, i = 1; i <= len; i++, cp++) 1794 cnp->cn_hash += (unsigned char)*cp * i; 1795 if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) && 1796 ltime > time.tv_sec) 1797 nqnfs_clientlease(nmp, np, NQL_READ, 1798 cachable, ltime, frev); 1799 if (cnp->cn_namelen <= NCHNAMLEN) 1800 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp); 1801 } else { 1802 nfsm_adv(nfsm_rndup(len)); 1803 } 1804 if (newvp != NULLVP) { 1805 vrele(newvp); 1806 newvp = NULLVP; 1807 } 1808 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1809 if (bigenough) 1810 endoff = off = fxdr_unsigned(u_long, *tl++); 1811 else 1812 endoff = fxdr_unsigned(u_long, *tl++); 1813 more_dirs = fxdr_unsigned(int, *tl); 1814 } 1815 /* 1816 * If at end of rpc data, get the eof boolean 1817 */ 1818 if (!more_dirs) { 1819 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1820 more_dirs = (fxdr_unsigned(int, *tl) == 0); 1821 1822 /* 1823 * If at EOF, cache directory offset 1824 */ 1825 if (!more_dirs) 1826 VTONFS(vp)->n_direofoffset = endoff; 1827 } 1828 if (uiop->uio_resid < tresid) 1829 uiop->uio_offset = (off_t)off; 1830 else 1831 more_dirs = 0; 1832 m_freem(mrep); 1833 } 1834 /* 1835 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 1836 * by increasing d_reclen for the last record. 1837 */ 1838 if (uiop->uio_resid < tresid) { 1839 len = uiop->uio_resid & (NFS_DIRBLKSIZ - 1); 1840 if (len > 0) { 1841 dp->d_reclen += len; 1842 uiop->uio_iov->iov_base += len; 1843 uiop->uio_iov->iov_len -= len; 1844 uiop->uio_resid -= len; 1845 } 1846 } 1847 nfsmout: 1848 if (newvp != NULLVP) 1849 vrele(newvp); 1850 return (error); 1851 } 1852 static char hextoasc[] = "0123456789abcdef"; 1853 1854 /* 1855 * Silly rename. To make the NFS filesystem that is stateless look a little 1856 * more like the "ufs" a remove of an active vnode is translated to a rename 1857 * to a funny looking filename that is removed by nfs_inactive on the 1858 * nfsnode. There is the potential for another process on a different client 1859 * to create the same funny name between the nfs_lookitup() fails and the 1860 * nfs_rename() completes, but... 1861 */ 1862 int 1863 nfs_sillyrename(dvp, vp, cnp) 1864 struct vnode *dvp, *vp; 1865 struct componentname *cnp; 1866 { 1867 register struct nfsnode *np; 1868 register struct sillyrename *sp; 1869 int error; 1870 short pid; 1871 1872 cache_purge(dvp); 1873 np = VTONFS(vp); 1874 #ifdef SILLYSEPARATE 1875 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 1876 M_NFSREQ, M_WAITOK); 1877 #else 1878 sp = &np->n_silly; 1879 #endif 1880 sp->s_cred = crdup(cnp->cn_cred); 1881 sp->s_dvp = dvp; 1882 VREF(dvp); 1883 1884 /* Fudge together a funny name */ 1885 pid = cnp->cn_proc->p_pid; 1886 bcopy(".nfsAxxxx4.4", sp->s_name, 13); 1887 sp->s_namlen = 12; 1888 sp->s_name[8] = hextoasc[pid & 0xf]; 1889 sp->s_name[7] = hextoasc[(pid >> 4) & 0xf]; 1890 sp->s_name[6] = hextoasc[(pid >> 8) & 0xf]; 1891 sp->s_name[5] = hextoasc[(pid >> 12) & 0xf]; 1892 1893 /* Try lookitups until we get one that isn't there */ 1894 while (nfs_lookitup(sp, (nfsv2fh_t *)0, cnp->cn_proc) == 0) { 1895 sp->s_name[4]++; 1896 if (sp->s_name[4] > 'z') { 1897 error = EINVAL; 1898 goto bad; 1899 } 1900 } 1901 if (error = nfs_renameit(dvp, cnp, sp)) 1902 goto bad; 1903 nfs_lookitup(sp, &np->n_fh, cnp->cn_proc); 1904 np->n_sillyrename = sp; 1905 return (0); 1906 bad: 1907 vrele(sp->s_dvp); 1908 crfree(sp->s_cred); 1909 #ifdef SILLYSEPARATE 1910 free((caddr_t)sp, M_NFSREQ); 1911 #endif 1912 return (error); 1913 } 1914 1915 /* 1916 * Look up a file name for silly rename stuff. 1917 * Just like nfs_lookup() except that it doesn't load returned values 1918 * into the nfsnode table. 1919 * If fhp != NULL it copies the returned file handle out 1920 */ 1921 int 1922 nfs_lookitup(sp, fhp, procp) 1923 register struct sillyrename *sp; 1924 nfsv2fh_t *fhp; 1925 struct proc *procp; 1926 { 1927 register struct vnode *vp = sp->s_dvp; 1928 register u_long *tl; 1929 register caddr_t cp; 1930 register long t1, t2; 1931 caddr_t bpos, dpos, cp2; 1932 u_long xid; 1933 int error = 0, isnq; 1934 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1935 long len; 1936 1937 isnq = (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS); 1938 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 1939 len = sp->s_namlen; 1940 nfsm_reqhead(vp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 1941 if (isnq) { 1942 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 1943 *tl = 0; 1944 } 1945 nfsm_fhtom(vp); 1946 nfsm_strtom(sp->s_name, len, NFS_MAXNAMLEN); 1947 nfsm_request(vp, NFSPROC_LOOKUP, procp, sp->s_cred); 1948 if (fhp != NULL) { 1949 if (isnq) 1950 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1951 nfsm_dissect(cp, caddr_t, NFSX_FH); 1952 bcopy(cp, (caddr_t)fhp, NFSX_FH); 1953 } 1954 nfsm_reqdone; 1955 return (error); 1956 } 1957 1958 /* 1959 * Kludge City.. 1960 * - make nfs_bmap() essentially a no-op that does no translation 1961 * - do nfs_strategy() by faking physical I/O with nfs_readrpc/nfs_writerpc 1962 * after mapping the physical addresses into Kernel Virtual space in the 1963 * nfsiobuf area. 1964 * (Maybe I could use the process's page mapping, but I was concerned that 1965 * Kernel Write might not be enabled and also figured copyout() would do 1966 * a lot more work than bcopy() and also it currently happens in the 1967 * context of the swapper process (2). 1968 */ 1969 int 1970 nfs_bmap(ap) 1971 struct vop_bmap_args /* { 1972 struct vnode *a_vp; 1973 daddr_t a_bn; 1974 struct vnode **a_vpp; 1975 daddr_t *a_bnp; 1976 int *a_runp; 1977 } */ *ap; 1978 { 1979 register struct vnode *vp = ap->a_vp; 1980 1981 if (ap->a_vpp != NULL) 1982 *ap->a_vpp = vp; 1983 if (ap->a_bnp != NULL) 1984 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize); 1985 return (0); 1986 } 1987 1988 /* 1989 * Strategy routine. 1990 * For async requests when nfsiod(s) are running, queue the request by 1991 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the 1992 * request. 1993 */ 1994 int 1995 nfs_strategy(ap) 1996 struct vop_strategy_args *ap; 1997 { 1998 register struct buf *bp = ap->a_bp; 1999 struct ucred *cr; 2000 struct proc *p; 2001 int error = 0; 2002 2003 if (bp->b_flags & B_PHYS) 2004 panic("nfs physio"); 2005 if (bp->b_flags & B_ASYNC) 2006 p = (struct proc *)0; 2007 else 2008 p = curproc; /* XXX */ 2009 if (bp->b_flags & B_READ) 2010 cr = bp->b_rcred; 2011 else 2012 cr = bp->b_wcred; 2013 /* 2014 * If the op is asynchronous and an i/o daemon is waiting 2015 * queue the request, wake it up and wait for completion 2016 * otherwise just do it ourselves. 2017 */ 2018 if ((bp->b_flags & B_ASYNC) == 0 || 2019 nfs_asyncio(bp, NOCRED)) 2020 error = nfs_doio(bp, cr, p); 2021 return (error); 2022 } 2023 2024 /* 2025 * Mmap a file 2026 * 2027 * NB Currently unsupported. 2028 */ 2029 /* ARGSUSED */ 2030 int 2031 nfs_mmap(ap) 2032 struct vop_mmap_args /* { 2033 struct vnode *a_vp; 2034 int a_fflags; 2035 struct ucred *a_cred; 2036 struct proc *a_p; 2037 } */ *ap; 2038 { 2039 2040 return (EINVAL); 2041 } 2042 2043 /* 2044 * Flush all the blocks associated with a vnode. 2045 * Walk through the buffer pool and push any dirty pages 2046 * associated with the vnode. 2047 */ 2048 /* ARGSUSED */ 2049 int 2050 nfs_fsync(ap) 2051 struct vop_fsync_args /* { 2052 struct vnodeop_desc *a_desc; 2053 struct vnode * a_vp; 2054 struct ucred * a_cred; 2055 int a_waitfor; 2056 struct proc * a_p; 2057 } */ *ap; 2058 { 2059 register struct vnode *vp = ap->a_vp; 2060 register struct nfsnode *np = VTONFS(vp); 2061 register struct buf *bp; 2062 struct buf *nbp; 2063 struct nfsmount *nmp; 2064 int s, error = 0, slptimeo = 0, slpflag = 0; 2065 2066 nmp = VFSTONFS(vp->v_mount); 2067 if (nmp->nm_flag & NFSMNT_INT) 2068 slpflag = PCATCH; 2069 loop: 2070 s = splbio(); 2071 for (bp = vp->v_dirtyblkhd.le_next; bp; bp = nbp) { 2072 nbp = bp->b_vnbufs.qe_next; 2073 if (bp->b_flags & B_BUSY) { 2074 if (ap->a_waitfor != MNT_WAIT) 2075 continue; 2076 bp->b_flags |= B_WANTED; 2077 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), 2078 "nfsfsync", slptimeo); 2079 splx(s); 2080 if (error) { 2081 if (nfs_sigintr(nmp, (struct nfsreq *)0, ap->a_p)) 2082 return (EINTR); 2083 if (slpflag == PCATCH) { 2084 slpflag = 0; 2085 slptimeo = 2 * hz; 2086 } 2087 } 2088 goto loop; 2089 } 2090 if ((bp->b_flags & B_DELWRI) == 0) 2091 panic("nfs_fsync: not dirty"); 2092 bremfree(bp); 2093 bp->b_flags |= B_BUSY; 2094 splx(s); 2095 bp->b_flags |= B_ASYNC; 2096 VOP_BWRITE(bp); 2097 goto loop; 2098 } 2099 splx(s); 2100 if (ap->a_waitfor == MNT_WAIT) { 2101 while (vp->v_numoutput) { 2102 vp->v_flag |= VBWAIT; 2103 error = tsleep((caddr_t)&vp->v_numoutput, 2104 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); 2105 if (error) { 2106 if (nfs_sigintr(nmp, (struct nfsreq *)0, ap->a_p)) 2107 return (EINTR); 2108 if (slpflag == PCATCH) { 2109 slpflag = 0; 2110 slptimeo = 2 * hz; 2111 } 2112 } 2113 } 2114 if (vp->v_dirtyblkhd.le_next) { 2115 #ifdef DIAGNOSTIC 2116 vprint("nfs_fsync: dirty", vp); 2117 #endif 2118 goto loop; 2119 } 2120 } 2121 if (np->n_flag & NWRITEERR) { 2122 error = np->n_error; 2123 np->n_flag &= ~NWRITEERR; 2124 } 2125 return (error); 2126 } 2127 2128 /* 2129 * NFS advisory byte-level locks. 2130 * Currently unsupported. 2131 */ 2132 int 2133 nfs_advlock(ap) 2134 struct vop_advlock_args /* { 2135 struct vnode *a_vp; 2136 caddr_t a_id; 2137 int a_op; 2138 struct flock *a_fl; 2139 int a_flags; 2140 } */ *ap; 2141 { 2142 2143 return (EOPNOTSUPP); 2144 } 2145 2146 /* 2147 * Print out the contents of an nfsnode. 2148 */ 2149 int 2150 nfs_print(ap) 2151 struct vop_print_args /* { 2152 struct vnode *a_vp; 2153 } */ *ap; 2154 { 2155 register struct vnode *vp = ap->a_vp; 2156 register struct nfsnode *np = VTONFS(vp); 2157 2158 printf("tag VT_NFS, fileid %d fsid 0x%x", 2159 np->n_vattr.va_fileid, np->n_vattr.va_fsid); 2160 #ifdef FIFO 2161 if (vp->v_type == VFIFO) 2162 fifo_printinfo(vp); 2163 #endif /* FIFO */ 2164 printf("\n"); 2165 } 2166 2167 /* 2168 * NFS directory offset lookup. 2169 * Currently unsupported. 2170 */ 2171 int 2172 nfs_blkatoff(ap) 2173 struct vop_blkatoff_args /* { 2174 struct vnode *a_vp; 2175 off_t a_offset; 2176 char **a_res; 2177 struct buf **a_bpp; 2178 } */ *ap; 2179 { 2180 2181 return (EOPNOTSUPP); 2182 } 2183 2184 /* 2185 * NFS flat namespace allocation. 2186 * Currently unsupported. 2187 */ 2188 int 2189 nfs_valloc(ap) 2190 struct vop_valloc_args /* { 2191 struct vnode *a_pvp; 2192 int a_mode; 2193 struct ucred *a_cred; 2194 struct vnode **a_vpp; 2195 } */ *ap; 2196 { 2197 2198 return (EOPNOTSUPP); 2199 } 2200 2201 /* 2202 * NFS flat namespace free. 2203 * Currently unsupported. 2204 */ 2205 int 2206 nfs_vfree(ap) 2207 struct vop_vfree_args /* { 2208 struct vnode *a_pvp; 2209 ino_t a_ino; 2210 int a_mode; 2211 } */ *ap; 2212 { 2213 2214 return (EOPNOTSUPP); 2215 } 2216 2217 /* 2218 * NFS file truncation. 2219 */ 2220 int 2221 nfs_truncate(ap) 2222 struct vop_truncate_args /* { 2223 struct vnode *a_vp; 2224 off_t a_length; 2225 int a_flags; 2226 struct ucred *a_cred; 2227 struct proc *a_p; 2228 } */ *ap; 2229 { 2230 2231 /* Use nfs_setattr */ 2232 printf("nfs_truncate: need to implement!!"); 2233 return (EOPNOTSUPP); 2234 } 2235 2236 /* 2237 * NFS update. 2238 */ 2239 int 2240 nfs_update(ap) 2241 struct vop_update_args /* { 2242 struct vnode *a_vp; 2243 struct timeval *a_ta; 2244 struct timeval *a_tm; 2245 int a_waitfor; 2246 } */ *ap; 2247 { 2248 2249 /* Use nfs_setattr */ 2250 printf("nfs_update: need to implement!!"); 2251 return (EOPNOTSUPP); 2252 } 2253 2254 /* 2255 * nfs special file access vnode op. 2256 * Essentially just get vattr and then imitate iaccess() since the device is 2257 * local to the client. 2258 */ 2259 int 2260 nfsspec_access(ap) 2261 struct vop_access_args /* { 2262 struct vnode *a_vp; 2263 int a_mode; 2264 struct ucred *a_cred; 2265 struct proc *a_p; 2266 } */ *ap; 2267 { 2268 register struct vattr *vap; 2269 register gid_t *gp; 2270 register struct ucred *cred = ap->a_cred; 2271 mode_t mode = ap->a_mode; 2272 struct vattr vattr; 2273 register int i; 2274 int error; 2275 2276 /* 2277 * If you're the super-user, 2278 * you always get access. 2279 */ 2280 if (cred->cr_uid == 0) 2281 return (0); 2282 vap = &vattr; 2283 if (error = VOP_GETATTR(ap->a_vp, vap, cred, ap->a_p)) 2284 return (error); 2285 /* 2286 * Access check is based on only one of owner, group, public. 2287 * If not owner, then check group. If not a member of the 2288 * group, then check public access. 2289 */ 2290 if (cred->cr_uid != vap->va_uid) { 2291 mode >>= 3; 2292 gp = cred->cr_groups; 2293 for (i = 0; i < cred->cr_ngroups; i++, gp++) 2294 if (vap->va_gid == *gp) 2295 goto found; 2296 mode >>= 3; 2297 found: 2298 ; 2299 } 2300 return ((vap->va_mode & mode) == mode ? 0 : EACCES); 2301 } 2302 2303 /* 2304 * Read wrapper for special devices. 2305 */ 2306 int 2307 nfsspec_read(ap) 2308 struct vop_read_args /* { 2309 struct vnode *a_vp; 2310 struct uio *a_uio; 2311 int a_ioflag; 2312 struct ucred *a_cred; 2313 } */ *ap; 2314 { 2315 register struct nfsnode *np = VTONFS(ap->a_vp); 2316 2317 /* 2318 * Set access flag. 2319 */ 2320 np->n_flag |= NACC; 2321 np->n_atim = time; 2322 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap)); 2323 } 2324 2325 /* 2326 * Write wrapper for special devices. 2327 */ 2328 int 2329 nfsspec_write(ap) 2330 struct vop_write_args /* { 2331 struct vnode *a_vp; 2332 struct uio *a_uio; 2333 int a_ioflag; 2334 struct ucred *a_cred; 2335 } */ *ap; 2336 { 2337 register struct nfsnode *np = VTONFS(ap->a_vp); 2338 2339 /* 2340 * Set update flag. 2341 */ 2342 np->n_flag |= NUPD; 2343 np->n_mtim = time; 2344 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap)); 2345 } 2346 2347 /* 2348 * Close wrapper for special devices. 2349 * 2350 * Update the times on the nfsnode then do device close. 2351 */ 2352 int 2353 nfsspec_close(ap) 2354 struct vop_close_args /* { 2355 struct vnode *a_vp; 2356 int a_fflag; 2357 struct ucred *a_cred; 2358 struct proc *a_p; 2359 } */ *ap; 2360 { 2361 register struct vnode *vp = ap->a_vp; 2362 register struct nfsnode *np = VTONFS(vp); 2363 struct vattr vattr; 2364 2365 if (np->n_flag & (NACC | NUPD)) { 2366 np->n_flag |= NCHG; 2367 if (vp->v_usecount == 1 && 2368 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 2369 VATTR_NULL(&vattr); 2370 if (np->n_flag & NACC) { 2371 vattr.va_atime.ts_sec = np->n_atim.tv_sec; 2372 vattr.va_atime.ts_nsec = 2373 np->n_atim.tv_usec * 1000; 2374 } 2375 if (np->n_flag & NUPD) { 2376 vattr.va_mtime.ts_sec = np->n_mtim.tv_sec; 2377 vattr.va_mtime.ts_nsec = 2378 np->n_mtim.tv_usec * 1000; 2379 } 2380 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 2381 } 2382 } 2383 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 2384 } 2385 2386 #ifdef FIFO 2387 /* 2388 * Read wrapper for fifos. 2389 */ 2390 int 2391 nfsfifo_read(ap) 2392 struct vop_read_args /* { 2393 struct vnode *a_vp; 2394 struct uio *a_uio; 2395 int a_ioflag; 2396 struct ucred *a_cred; 2397 } */ *ap; 2398 { 2399 extern int (**fifo_vnodeop_p)(); 2400 register struct nfsnode *np = VTONFS(ap->a_vp); 2401 2402 /* 2403 * Set access flag. 2404 */ 2405 np->n_flag |= NACC; 2406 np->n_atim = time; 2407 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap)); 2408 } 2409 2410 /* 2411 * Write wrapper for fifos. 2412 */ 2413 int 2414 nfsfifo_write(ap) 2415 struct vop_write_args /* { 2416 struct vnode *a_vp; 2417 struct uio *a_uio; 2418 int a_ioflag; 2419 struct ucred *a_cred; 2420 } */ *ap; 2421 { 2422 extern int (**fifo_vnodeop_p)(); 2423 register struct nfsnode *np = VTONFS(ap->a_vp); 2424 2425 /* 2426 * Set update flag. 2427 */ 2428 np->n_flag |= NUPD; 2429 np->n_mtim = time; 2430 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap)); 2431 } 2432 2433 /* 2434 * Close wrapper for fifos. 2435 * 2436 * Update the times on the nfsnode then do fifo close. 2437 */ 2438 int 2439 nfsfifo_close(ap) 2440 struct vop_close_args /* { 2441 struct vnode *a_vp; 2442 int a_fflag; 2443 struct ucred *a_cred; 2444 struct proc *a_p; 2445 } */ *ap; 2446 { 2447 register struct vnode *vp = ap->a_vp; 2448 register struct nfsnode *np = VTONFS(vp); 2449 struct vattr vattr; 2450 extern int (**fifo_vnodeop_p)(); 2451 2452 if (np->n_flag & (NACC | NUPD)) { 2453 if (np->n_flag & NACC) 2454 np->n_atim = time; 2455 if (np->n_flag & NUPD) 2456 np->n_mtim = time; 2457 np->n_flag |= NCHG; 2458 if (vp->v_usecount == 1 && 2459 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 2460 VATTR_NULL(&vattr); 2461 if (np->n_flag & NACC) { 2462 vattr.va_atime.ts_sec = np->n_atim.tv_sec; 2463 vattr.va_atime.ts_nsec = 2464 np->n_atim.tv_usec * 1000; 2465 } 2466 if (np->n_flag & NUPD) { 2467 vattr.va_mtime.ts_sec = np->n_mtim.tv_sec; 2468 vattr.va_mtime.ts_nsec = 2469 np->n_mtim.tv_usec * 1000; 2470 } 2471 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 2472 } 2473 } 2474 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 2475 } 2476 #endif /* FIFO */ 2477