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