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