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