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