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