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