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