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