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