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