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.13 (Berkeley) 03/19/95 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_revoke_desc, nfs_revoke }, /* revoke */ 69 { &vop_mmap_desc, nfs_mmap }, /* mmap */ 70 { &vop_fsync_desc, nfs_fsync }, /* fsync */ 71 { &vop_seek_desc, nfs_seek }, /* seek */ 72 { &vop_remove_desc, nfs_remove }, /* remove */ 73 { &vop_link_desc, nfs_link }, /* link */ 74 { &vop_rename_desc, nfs_rename }, /* rename */ 75 { &vop_mkdir_desc, nfs_mkdir }, /* mkdir */ 76 { &vop_rmdir_desc, nfs_rmdir }, /* rmdir */ 77 { &vop_symlink_desc, nfs_symlink }, /* symlink */ 78 { &vop_readdir_desc, nfs_readdir }, /* readdir */ 79 { &vop_readlink_desc, nfs_readlink }, /* readlink */ 80 { &vop_abortop_desc, nfs_abortop }, /* abortop */ 81 { &vop_inactive_desc, nfs_inactive }, /* inactive */ 82 { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ 83 { &vop_lock_desc, nfs_lock }, /* lock */ 84 { &vop_unlock_desc, nfs_unlock }, /* unlock */ 85 { &vop_bmap_desc, nfs_bmap }, /* bmap */ 86 { &vop_strategy_desc, nfs_strategy }, /* strategy */ 87 { &vop_print_desc, nfs_print }, /* print */ 88 { &vop_islocked_desc, nfs_islocked }, /* islocked */ 89 { &vop_pathconf_desc, nfs_pathconf }, /* pathconf */ 90 { &vop_advlock_desc, nfs_advlock }, /* advlock */ 91 { &vop_blkatoff_desc, nfs_blkatoff }, /* blkatoff */ 92 { &vop_valloc_desc, nfs_valloc }, /* valloc */ 93 { &vop_reallocblks_desc, nfs_reallocblks }, /* reallocblks */ 94 { &vop_vfree_desc, nfs_vfree }, /* vfree */ 95 { &vop_truncate_desc, nfs_truncate }, /* truncate */ 96 { &vop_update_desc, nfs_update }, /* update */ 97 { &vop_bwrite_desc, vn_bwrite }, 98 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 99 }; 100 struct vnodeopv_desc nfsv2_vnodeop_opv_desc = 101 { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries }; 102 103 /* 104 * Special device vnode ops 105 */ 106 int (**spec_nfsv2nodeop_p)(); 107 struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = { 108 { &vop_default_desc, vn_default_error }, 109 { &vop_lookup_desc, spec_lookup }, /* lookup */ 110 { &vop_create_desc, spec_create }, /* create */ 111 { &vop_mknod_desc, spec_mknod }, /* mknod */ 112 { &vop_open_desc, spec_open }, /* open */ 113 { &vop_close_desc, nfsspec_close }, /* close */ 114 { &vop_access_desc, nfsspec_access }, /* access */ 115 { &vop_getattr_desc, nfs_getattr }, /* getattr */ 116 { &vop_setattr_desc, nfs_setattr }, /* setattr */ 117 { &vop_read_desc, nfsspec_read }, /* read */ 118 { &vop_write_desc, nfsspec_write }, /* write */ 119 { &vop_lease_desc, spec_lease_check }, /* lease */ 120 { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 121 { &vop_select_desc, spec_select }, /* select */ 122 { &vop_revoke_desc, spec_revoke }, /* revoke */ 123 { &vop_mmap_desc, spec_mmap }, /* mmap */ 124 { &vop_fsync_desc, nfs_fsync }, /* fsync */ 125 { &vop_seek_desc, spec_seek }, /* seek */ 126 { &vop_remove_desc, spec_remove }, /* remove */ 127 { &vop_link_desc, spec_link }, /* link */ 128 { &vop_rename_desc, spec_rename }, /* rename */ 129 { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 130 { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 131 { &vop_symlink_desc, spec_symlink }, /* symlink */ 132 { &vop_readdir_desc, spec_readdir }, /* readdir */ 133 { &vop_readlink_desc, spec_readlink }, /* readlink */ 134 { &vop_abortop_desc, spec_abortop }, /* abortop */ 135 { &vop_inactive_desc, nfs_inactive }, /* inactive */ 136 { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ 137 { &vop_lock_desc, nfs_lock }, /* lock */ 138 { &vop_unlock_desc, nfs_unlock }, /* unlock */ 139 { &vop_bmap_desc, spec_bmap }, /* bmap */ 140 { &vop_strategy_desc, spec_strategy }, /* strategy */ 141 { &vop_print_desc, nfs_print }, /* print */ 142 { &vop_islocked_desc, nfs_islocked }, /* islocked */ 143 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ 144 { &vop_advlock_desc, spec_advlock }, /* advlock */ 145 { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ 146 { &vop_valloc_desc, spec_valloc }, /* valloc */ 147 { &vop_reallocblks_desc, spec_reallocblks }, /* reallocblks */ 148 { &vop_vfree_desc, spec_vfree }, /* vfree */ 149 { &vop_truncate_desc, spec_truncate }, /* truncate */ 150 { &vop_update_desc, nfs_update }, /* update */ 151 { &vop_bwrite_desc, vn_bwrite }, 152 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 153 }; 154 struct vnodeopv_desc spec_nfsv2nodeop_opv_desc = 155 { &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries }; 156 157 #ifdef FIFO 158 int (**fifo_nfsv2nodeop_p)(); 159 struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = { 160 { &vop_default_desc, vn_default_error }, 161 { &vop_lookup_desc, fifo_lookup }, /* lookup */ 162 { &vop_create_desc, fifo_create }, /* create */ 163 { &vop_mknod_desc, fifo_mknod }, /* mknod */ 164 { &vop_open_desc, fifo_open }, /* open */ 165 { &vop_close_desc, nfsfifo_close }, /* close */ 166 { &vop_access_desc, nfsspec_access }, /* access */ 167 { &vop_getattr_desc, nfs_getattr }, /* getattr */ 168 { &vop_setattr_desc, nfs_setattr }, /* setattr */ 169 { &vop_read_desc, nfsfifo_read }, /* read */ 170 { &vop_write_desc, nfsfifo_write }, /* write */ 171 { &vop_lease_desc, fifo_lease_check }, /* lease */ 172 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 173 { &vop_select_desc, fifo_select }, /* select */ 174 { &vop_revoke_desc, fifo_revoke }, /* revoke */ 175 { &vop_mmap_desc, fifo_mmap }, /* mmap */ 176 { &vop_fsync_desc, nfs_fsync }, /* fsync */ 177 { &vop_seek_desc, fifo_seek }, /* seek */ 178 { &vop_remove_desc, fifo_remove }, /* remove */ 179 { &vop_link_desc, fifo_link }, /* link */ 180 { &vop_rename_desc, fifo_rename }, /* rename */ 181 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 182 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 183 { &vop_symlink_desc, fifo_symlink }, /* symlink */ 184 { &vop_readdir_desc, fifo_readdir }, /* readdir */ 185 { &vop_readlink_desc, fifo_readlink }, /* readlink */ 186 { &vop_abortop_desc, fifo_abortop }, /* abortop */ 187 { &vop_inactive_desc, nfs_inactive }, /* inactive */ 188 { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ 189 { &vop_lock_desc, nfs_lock }, /* lock */ 190 { &vop_unlock_desc, nfs_unlock }, /* unlock */ 191 { &vop_bmap_desc, fifo_bmap }, /* bmap */ 192 { &vop_strategy_desc, fifo_badop }, /* strategy */ 193 { &vop_print_desc, nfs_print }, /* print */ 194 { &vop_islocked_desc, nfs_islocked }, /* islocked */ 195 { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ 196 { &vop_advlock_desc, fifo_advlock }, /* advlock */ 197 { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 198 { &vop_valloc_desc, fifo_valloc }, /* valloc */ 199 { &vop_reallocblks_desc, fifo_reallocblks }, /* reallocblks */ 200 { &vop_vfree_desc, fifo_vfree }, /* vfree */ 201 { &vop_truncate_desc, fifo_truncate }, /* truncate */ 202 { &vop_update_desc, nfs_update }, /* update */ 203 { &vop_bwrite_desc, vn_bwrite }, 204 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 205 }; 206 struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc = 207 { &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries }; 208 #endif /* FIFO */ 209 210 void nqnfs_clientlease(); 211 212 /* 213 * Global variables 214 */ 215 extern u_long nfs_procids[NFS_NPROCS]; 216 extern u_long nfs_prog, nfs_vers, nfs_true, nfs_false; 217 extern char nfsiobuf[MAXPHYS+NBPG]; 218 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 219 int nfs_numasync = 0; 220 #define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) 221 222 /* 223 * nfs null call from vfs. 224 */ 225 int 226 nfs_null(vp, cred, procp) 227 struct vnode *vp; 228 struct ucred *cred; 229 struct proc *procp; 230 { 231 caddr_t bpos, dpos; 232 int error = 0; 233 struct mbuf *mreq, *mrep, *md, *mb; 234 235 nfsm_reqhead(vp, NFSPROC_NULL, 0); 236 nfsm_request(vp, NFSPROC_NULL, procp, cred); 237 nfsm_reqdone; 238 return (error); 239 } 240 241 /* 242 * nfs access vnode op. 243 * For nfs, just return ok. File accesses may fail later. 244 * For nqnfs, use the access rpc to check accessibility. If file modes are 245 * changed on the server, accesses might still fail later. 246 */ 247 int 248 nfs_access(ap) 249 struct vop_access_args /* { 250 struct vnode *a_vp; 251 int a_mode; 252 struct ucred *a_cred; 253 struct proc *a_p; 254 } */ *ap; 255 { 256 register struct vnode *vp = ap->a_vp; 257 register u_long *tl; 258 register caddr_t cp; 259 caddr_t bpos, dpos; 260 int error = 0; 261 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 262 263 /* 264 * For nqnfs, do an access rpc, otherwise you are stuck emulating 265 * ufs_access() locally using the vattr. This may not be correct, 266 * since the server may apply other access criteria such as 267 * client uid-->server uid mapping that we do not know about, but 268 * this is better than just returning anything that is lying about 269 * in the cache. 270 */ 271 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { 272 nfsstats.rpccnt[NQNFSPROC_ACCESS]++; 273 nfsm_reqhead(vp, NQNFSPROC_ACCESS, NFSX_FH + 3 * NFSX_UNSIGNED); 274 nfsm_fhtom(vp); 275 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 276 if (ap->a_mode & VREAD) 277 *tl++ = nfs_true; 278 else 279 *tl++ = nfs_false; 280 if (ap->a_mode & VWRITE) 281 *tl++ = nfs_true; 282 else 283 *tl++ = nfs_false; 284 if (ap->a_mode & VEXEC) 285 *tl = nfs_true; 286 else 287 *tl = nfs_false; 288 nfsm_request(vp, NQNFSPROC_ACCESS, ap->a_p, ap->a_cred); 289 nfsm_reqdone; 290 return (error); 291 } else 292 return (nfsspec_access(ap)); 293 } 294 295 /* 296 * nfs open vnode op 297 * Check to see if the type is ok 298 * and that deletion is not in progress. 299 * For paged in text files, you will need to flush the page cache 300 * if consistency is lost. 301 */ 302 /* ARGSUSED */ 303 int 304 nfs_open(ap) 305 struct vop_open_args /* { 306 struct vnode *a_vp; 307 int a_mode; 308 struct ucred *a_cred; 309 struct proc *a_p; 310 } */ *ap; 311 { 312 register struct vnode *vp = ap->a_vp; 313 struct nfsnode *np = VTONFS(vp); 314 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 315 struct vattr vattr; 316 int error; 317 318 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) 319 return (EACCES); 320 if (vp->v_flag & VTEXT) { 321 /* 322 * Get a valid lease. If cached data is stale, flush it. 323 */ 324 if (nmp->nm_flag & NFSMNT_NQNFS) { 325 if (NQNFS_CKINVALID(vp, np, NQL_READ)) { 326 do { 327 error = nqnfs_getlease(vp, NQL_READ, ap->a_cred, ap->a_p); 328 } while (error == NQNFS_EXPIRED); 329 if (error) 330 return (error); 331 if (np->n_lrev != np->n_brev || 332 (np->n_flag & NQNFSNONCACHE)) { 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_brev = np->n_lrev; 338 } 339 } 340 } else { 341 if (np->n_flag & NMODIFIED) { 342 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 343 ap->a_p, 1)) == EINTR) 344 return (error); 345 (void) vnode_pager_uncache(vp); 346 np->n_attrstamp = 0; 347 np->n_direofoffset = 0; 348 if (error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p)) 349 return (error); 350 np->n_mtime = vattr.va_mtime.ts_sec; 351 } else { 352 if (error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p)) 353 return (error); 354 if (np->n_mtime != vattr.va_mtime.ts_sec) { 355 np->n_direofoffset = 0; 356 if ((error = nfs_vinvalbuf(vp, V_SAVE, 357 ap->a_cred, ap->a_p, 1)) == EINTR) 358 return (error); 359 (void) vnode_pager_uncache(vp); 360 np->n_mtime = vattr.va_mtime.ts_sec; 361 } 362 } 363 } 364 } else if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) 365 np->n_attrstamp = 0; /* For Open/Close consistency */ 366 return (0); 367 } 368 369 /* 370 * nfs close vnode op 371 * For reg files, invalidate any buffer cache entries. 372 */ 373 /* ARGSUSED */ 374 int 375 nfs_close(ap) 376 struct vop_close_args /* { 377 struct vnodeop_desc *a_desc; 378 struct vnode *a_vp; 379 int a_fflag; 380 struct ucred *a_cred; 381 struct proc *a_p; 382 } */ *ap; 383 { 384 register struct vnode *vp = ap->a_vp; 385 register struct nfsnode *np = VTONFS(vp); 386 int error = 0; 387 388 if (vp->v_type == VREG) { 389 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 && 390 (np->n_flag & NMODIFIED)) { 391 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1); 392 np->n_attrstamp = 0; 393 } 394 if (np->n_flag & NWRITEERR) { 395 np->n_flag &= ~NWRITEERR; 396 error = np->n_error; 397 } 398 } 399 return (error); 400 } 401 402 /* 403 * nfs getattr call from vfs. 404 */ 405 int 406 nfs_getattr(ap) 407 struct vop_getattr_args /* { 408 struct vnode *a_vp; 409 struct vattr *a_vap; 410 struct ucred *a_cred; 411 struct proc *a_p; 412 } */ *ap; 413 { 414 register struct vnode *vp = ap->a_vp; 415 register struct nfsnode *np = VTONFS(vp); 416 register caddr_t cp; 417 caddr_t bpos, dpos; 418 int error = 0; 419 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 420 421 /* 422 * Update local times for special files. 423 */ 424 if (np->n_flag & (NACC | NUPD)) 425 np->n_flag |= NCHG; 426 /* 427 * First look in the cache. 428 */ 429 if (nfs_getattrcache(vp, ap->a_vap) == 0) 430 return (0); 431 nfsstats.rpccnt[NFSPROC_GETATTR]++; 432 nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH); 433 nfsm_fhtom(vp); 434 nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred); 435 nfsm_loadattr(vp, ap->a_vap); 436 nfsm_reqdone; 437 return (error); 438 } 439 440 /* 441 * nfs setattr call. 442 */ 443 int 444 nfs_setattr(ap) 445 struct vop_setattr_args /* { 446 struct vnodeop_desc *a_desc; 447 struct vnode *a_vp; 448 struct vattr *a_vap; 449 struct ucred *a_cred; 450 struct proc *a_p; 451 } */ *ap; 452 { 453 register struct nfsv2_sattr *sp; 454 register caddr_t cp; 455 register long t1; 456 caddr_t bpos, dpos, cp2; 457 u_long *tl; 458 int error = 0, isnq; 459 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 460 register struct vnode *vp = ap->a_vp; 461 register struct nfsnode *np = VTONFS(vp); 462 register struct vattr *vap = ap->a_vap; 463 u_quad_t frev, tsize; 464 465 if (vap->va_size != VNOVAL || vap->va_mtime.ts_sec != VNOVAL || 466 vap->va_atime.ts_sec != VNOVAL) { 467 if (vap->va_size != VNOVAL) { 468 switch (vp->v_type) { 469 case VDIR: 470 return (EISDIR); 471 case VCHR: 472 case VBLK: 473 vap->va_size = VNOVAL; 474 break; 475 default: 476 if (np->n_flag & NMODIFIED) { 477 if (vap->va_size == 0) 478 error = nfs_vinvalbuf(vp, 0, 479 ap->a_cred, ap->a_p, 1); 480 else 481 error = nfs_vinvalbuf(vp, V_SAVE, 482 ap->a_cred, ap->a_p, 1); 483 if (error) 484 return (error); 485 } 486 tsize = np->n_size; 487 np->n_size = np->n_vattr.va_size = vap->va_size; 488 vnode_pager_setsize(vp, (u_long)np->n_size); 489 } 490 } else if ((np->n_flag & NMODIFIED) && 491 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 492 ap->a_p, 1)) == EINTR) 493 return (error); 494 } 495 nfsstats.rpccnt[NFSPROC_SETATTR]++; 496 isnq = (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS); 497 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH+NFSX_SATTR(isnq)); 498 nfsm_fhtom(vp); 499 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 500 if (vap->va_mode == (u_short)-1) 501 sp->sa_mode = VNOVAL; 502 else 503 sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode); 504 if (vap->va_uid == (uid_t)-1) 505 sp->sa_uid = VNOVAL; 506 else 507 sp->sa_uid = txdr_unsigned(vap->va_uid); 508 if (vap->va_gid == (gid_t)-1) 509 sp->sa_gid = VNOVAL; 510 else 511 sp->sa_gid = txdr_unsigned(vap->va_gid); 512 if (isnq) { 513 txdr_hyper(&vap->va_size, &sp->sa_nqsize); 514 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 515 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 516 sp->sa_nqflags = txdr_unsigned(vap->va_flags); 517 sp->sa_nqrdev = VNOVAL; 518 } else { 519 sp->sa_nfssize = txdr_unsigned(vap->va_size); 520 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 521 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 522 } 523 nfsm_request(vp, NFSPROC_SETATTR, ap->a_p, ap->a_cred); 524 nfsm_loadattr(vp, (struct vattr *)0); 525 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) && 526 NQNFS_CKCACHABLE(vp, NQL_WRITE)) { 527 nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED); 528 fxdr_hyper(tl, &frev); 529 if (frev > np->n_brev) 530 np->n_brev = frev; 531 } 532 nfsm_reqdone; 533 if (error) { 534 np->n_size = np->n_vattr.va_size = tsize; 535 vnode_pager_setsize(vp, (u_long)np->n_size); 536 } 537 return (error); 538 } 539 540 /* 541 * nfs lookup call, one step at a time... 542 * First look in cache 543 * If not found, unlock the directory nfsnode and do the rpc 544 */ 545 int 546 nfs_lookup(ap) 547 struct vop_lookup_args /* { 548 struct vnodeop_desc *a_desc; 549 struct vnode *a_dvp; 550 struct vnode **a_vpp; 551 struct componentname *a_cnp; 552 } */ *ap; 553 { 554 register struct componentname *cnp = ap->a_cnp; 555 register struct vnode *dvp = ap->a_dvp; 556 register struct vnode **vpp = ap->a_vpp; 557 register int flags = cnp->cn_flags; 558 register struct vnode *vdp; 559 register u_long *tl; 560 register caddr_t cp; 561 register long t1, t2; 562 struct nfsmount *nmp; 563 caddr_t bpos, dpos, cp2; 564 time_t reqtime; 565 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 566 struct vnode *newvp; 567 long len; 568 nfsv2fh_t *fhp; 569 struct nfsnode *np; 570 int lockparent, wantparent, error = 0; 571 int nqlflag, cachable; 572 u_quad_t frev; 573 574 *vpp = NULL; 575 if (dvp->v_type != VDIR) 576 return (ENOTDIR); 577 lockparent = flags & LOCKPARENT; 578 wantparent = flags & (LOCKPARENT|WANTPARENT); 579 nmp = VFSTONFS(dvp->v_mount); 580 np = VTONFS(dvp); 581 if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) { 582 struct vattr vattr; 583 int vpid; 584 585 vdp = *vpp; 586 vpid = vdp->v_id; 587 /* 588 * See the comment starting `Step through' in ufs/ufs_lookup.c 589 * for an explanation of the locking protocol 590 */ 591 if (dvp == vdp) { 592 VREF(vdp); 593 error = 0; 594 } else 595 error = vget(vdp, 1); 596 if (!error) { 597 if (vpid == vdp->v_id) { 598 if (nmp->nm_flag & NFSMNT_NQNFS) { 599 if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) == 0) { 600 nfsstats.lookupcache_hits++; 601 if (cnp->cn_nameiop != LOOKUP && 602 (flags & ISLASTCN)) 603 cnp->cn_flags |= SAVENAME; 604 return (0); 605 } else if (NQNFS_CKCACHABLE(dvp, NQL_READ)) { 606 if (np->n_lrev != np->n_brev || 607 (np->n_flag & NMODIFIED)) { 608 np->n_direofoffset = 0; 609 cache_purge(dvp); 610 error = nfs_vinvalbuf(dvp, 0, 611 cnp->cn_cred, cnp->cn_proc, 612 1); 613 if (error == EINTR) 614 return (error); 615 np->n_brev = np->n_lrev; 616 } else { 617 nfsstats.lookupcache_hits++; 618 if (cnp->cn_nameiop != LOOKUP && 619 (flags & ISLASTCN)) 620 cnp->cn_flags |= SAVENAME; 621 return (0); 622 } 623 } 624 } else if (!VOP_GETATTR(vdp, &vattr, cnp->cn_cred, cnp->cn_proc) && 625 vattr.va_ctime.ts_sec == VTONFS(vdp)->n_ctime) { 626 nfsstats.lookupcache_hits++; 627 if (cnp->cn_nameiop != LOOKUP && 628 (flags & ISLASTCN)) 629 cnp->cn_flags |= SAVENAME; 630 return (0); 631 } 632 cache_purge(vdp); 633 } 634 vrele(vdp); 635 } 636 *vpp = NULLVP; 637 } 638 error = 0; 639 nfsstats.lookupcache_misses++; 640 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 641 len = cnp->cn_namelen; 642 nfsm_reqhead(dvp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 643 644 /* 645 * For nqnfs optionally piggyback a getlease request for the name 646 * being looked up. 647 */ 648 if (nmp->nm_flag & NFSMNT_NQNFS) { 649 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 650 if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) && 651 ((cnp->cn_flags & MAKEENTRY) && 652 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)))) 653 *tl = txdr_unsigned(nmp->nm_leaseterm); 654 else 655 *tl = 0; 656 } 657 nfsm_fhtom(dvp); 658 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 659 reqtime = time.tv_sec; 660 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 661 nfsmout: 662 if (error) { 663 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && 664 (flags & ISLASTCN) && error == ENOENT) 665 error = EJUSTRETURN; 666 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 667 cnp->cn_flags |= SAVENAME; 668 return (error); 669 } 670 if (nmp->nm_flag & NFSMNT_NQNFS) { 671 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 672 if (*tl) { 673 nqlflag = fxdr_unsigned(int, *tl); 674 nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED); 675 cachable = fxdr_unsigned(int, *tl++); 676 reqtime += fxdr_unsigned(int, *tl++); 677 fxdr_hyper(tl, &frev); 678 } else 679 nqlflag = 0; 680 } 681 nfsm_dissect(fhp, nfsv2fh_t *, NFSX_FH); 682 683 /* 684 * Handle RENAME case... 685 */ 686 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { 687 if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 688 m_freem(mrep); 689 return (EISDIR); 690 } 691 if (error = nfs_nget(dvp->v_mount, fhp, &np)) { 692 m_freem(mrep); 693 return (error); 694 } 695 newvp = NFSTOV(np); 696 if (error = 697 nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 698 vrele(newvp); 699 m_freem(mrep); 700 return (error); 701 } 702 *vpp = newvp; 703 m_freem(mrep); 704 cnp->cn_flags |= SAVENAME; 705 return (0); 706 } 707 708 if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 709 VREF(dvp); 710 newvp = dvp; 711 } else { 712 if (error = nfs_nget(dvp->v_mount, fhp, &np)) { 713 m_freem(mrep); 714 return (error); 715 } 716 newvp = NFSTOV(np); 717 } 718 if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 719 vrele(newvp); 720 m_freem(mrep); 721 return (error); 722 } 723 m_freem(mrep); 724 *vpp = newvp; 725 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 726 cnp->cn_flags |= SAVENAME; 727 if ((cnp->cn_flags & MAKEENTRY) && 728 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { 729 if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) 730 np->n_ctime = np->n_vattr.va_ctime.ts_sec; 731 else if (nqlflag && reqtime > time.tv_sec) 732 nqnfs_clientlease(nmp, np, nqlflag, cachable, reqtime, 733 frev); 734 cache_enter(dvp, *vpp, cnp); 735 } 736 return (0); 737 } 738 739 /* 740 * nfs read call. 741 * Just call nfs_bioread() to do the work. 742 */ 743 int 744 nfs_read(ap) 745 struct vop_read_args /* { 746 struct vnode *a_vp; 747 struct uio *a_uio; 748 int a_ioflag; 749 struct ucred *a_cred; 750 } */ *ap; 751 { 752 register struct vnode *vp = ap->a_vp; 753 754 if (vp->v_type != VREG) 755 return (EPERM); 756 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); 757 } 758 759 /* 760 * nfs readlink call 761 */ 762 int 763 nfs_readlink(ap) 764 struct vop_readlink_args /* { 765 struct vnode *a_vp; 766 struct uio *a_uio; 767 struct ucred *a_cred; 768 } */ *ap; 769 { 770 register struct vnode *vp = ap->a_vp; 771 772 if (vp->v_type != VLNK) 773 return (EPERM); 774 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred)); 775 } 776 777 /* 778 * Do a readlink rpc. 779 * Called by nfs_doio() from below the buffer cache. 780 */ 781 int 782 nfs_readlinkrpc(vp, uiop, cred) 783 register struct vnode *vp; 784 struct uio *uiop; 785 struct ucred *cred; 786 { 787 register u_long *tl; 788 register caddr_t cp; 789 register long t1; 790 caddr_t bpos, dpos, cp2; 791 int error = 0; 792 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 793 long len; 794 795 nfsstats.rpccnt[NFSPROC_READLINK]++; 796 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH); 797 nfsm_fhtom(vp); 798 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred); 799 nfsm_strsiz(len, NFS_MAXPATHLEN); 800 nfsm_mtouio(uiop, len); 801 nfsm_reqdone; 802 return (error); 803 } 804 805 /* 806 * nfs read rpc call 807 * Ditto above 808 */ 809 int 810 nfs_readrpc(vp, uiop, cred) 811 register struct vnode *vp; 812 struct uio *uiop; 813 struct ucred *cred; 814 { 815 register u_long *tl; 816 register caddr_t cp; 817 register long t1; 818 caddr_t bpos, dpos, cp2; 819 int error = 0; 820 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 821 struct nfsmount *nmp; 822 long len, retlen, tsiz; 823 824 nmp = VFSTONFS(vp->v_mount); 825 tsiz = uiop->uio_resid; 826 if (uiop->uio_offset + tsiz > 0xffffffff && 827 (nmp->nm_flag & NFSMNT_NQNFS) == 0) 828 return (EFBIG); 829 while (tsiz > 0) { 830 nfsstats.rpccnt[NFSPROC_READ]++; 831 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 832 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH+NFSX_UNSIGNED*3); 833 nfsm_fhtom(vp); 834 nfsm_build(tl, u_long *, NFSX_UNSIGNED*3); 835 if (nmp->nm_flag & NFSMNT_NQNFS) { 836 txdr_hyper(&uiop->uio_offset, tl); 837 *(tl + 2) = txdr_unsigned(len); 838 } else { 839 *tl++ = txdr_unsigned(uiop->uio_offset); 840 *tl++ = txdr_unsigned(len); 841 *tl = 0; 842 } 843 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred); 844 nfsm_loadattr(vp, (struct vattr *)0); 845 nfsm_strsiz(retlen, nmp->nm_rsize); 846 nfsm_mtouio(uiop, retlen); 847 m_freem(mrep); 848 if (retlen < len) 849 tsiz = 0; 850 else 851 tsiz -= len; 852 } 853 nfsmout: 854 return (error); 855 } 856 857 /* 858 * nfs write call 859 */ 860 int 861 nfs_writerpc(vp, uiop, cred, ioflags) 862 register struct vnode *vp; 863 struct uio *uiop; 864 struct ucred *cred; 865 int ioflags; 866 { 867 register u_long *tl; 868 register caddr_t cp; 869 register long t1; 870 caddr_t bpos, dpos, cp2; 871 int error = 0; 872 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 873 struct nfsmount *nmp; 874 struct nfsnode *np = VTONFS(vp); 875 u_quad_t frev; 876 long len, tsiz; 877 878 nmp = VFSTONFS(vp->v_mount); 879 tsiz = uiop->uio_resid; 880 if (uiop->uio_offset + tsiz > 0xffffffff && 881 (nmp->nm_flag & NFSMNT_NQNFS) == 0) 882 return (EFBIG); 883 while (tsiz > 0) { 884 nfsstats.rpccnt[NFSPROC_WRITE]++; 885 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 886 nfsm_reqhead(vp, NFSPROC_WRITE, 887 NFSX_FH+NFSX_UNSIGNED*4+nfsm_rndup(len)); 888 nfsm_fhtom(vp); 889 nfsm_build(tl, u_long *, NFSX_UNSIGNED * 4); 890 if (nmp->nm_flag & NFSMNT_NQNFS) { 891 txdr_hyper(&uiop->uio_offset, tl); 892 tl += 2; 893 *tl++ = 0; 894 } else { 895 *++tl = txdr_unsigned(uiop->uio_offset); 896 tl += 2; 897 } 898 *tl = txdr_unsigned(len); 899 nfsm_uiotom(uiop, len); 900 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred); 901 nfsm_loadattr(vp, (struct vattr *)0); 902 if (nmp->nm_flag & NFSMNT_MYWRITE) 903 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.ts_sec; 904 else if ((nmp->nm_flag & NFSMNT_NQNFS) && 905 NQNFS_CKCACHABLE(vp, NQL_WRITE)) { 906 nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED); 907 fxdr_hyper(tl, &frev); 908 if (frev > np->n_brev) 909 np->n_brev = frev; 910 } 911 m_freem(mrep); 912 tsiz -= len; 913 } 914 nfsmout: 915 if (error) 916 uiop->uio_resid = tsiz; 917 return (error); 918 } 919 920 /* 921 * nfs mknod call 922 * This is a kludge. Use a create rpc but with the IFMT bits of the mode 923 * set to specify the file type and the size field for rdev. 924 */ 925 /* ARGSUSED */ 926 int 927 nfs_mknod(ap) 928 struct vop_mknod_args /* { 929 struct vnode *a_dvp; 930 struct vnode **a_vpp; 931 struct componentname *a_cnp; 932 struct vattr *a_vap; 933 } */ *ap; 934 { 935 register struct vnode *dvp = ap->a_dvp; 936 register struct vattr *vap = ap->a_vap; 937 register struct componentname *cnp = ap->a_cnp; 938 register struct nfsv2_sattr *sp; 939 register u_long *tl; 940 register caddr_t cp; 941 register long t1, t2; 942 struct vnode *newvp; 943 struct vattr vattr; 944 char *cp2; 945 caddr_t bpos, dpos; 946 int error = 0, isnq; 947 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 948 u_long rdev; 949 950 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 951 if (vap->va_type == VCHR || vap->va_type == VBLK) 952 rdev = txdr_unsigned(vap->va_rdev); 953 #ifdef FIFO 954 else if (vap->va_type == VFIFO) 955 rdev = 0xffffffff; 956 #endif /* FIFO */ 957 else { 958 VOP_ABORTOP(dvp, cnp); 959 vput(dvp); 960 return (EOPNOTSUPP); 961 } 962 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 963 VOP_ABORTOP(dvp, cnp); 964 vput(dvp); 965 return (error); 966 } 967 nfsstats.rpccnt[NFSPROC_CREATE]++; 968 nfsm_reqhead(dvp, NFSPROC_CREATE, 969 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR(isnq)); 970 nfsm_fhtom(dvp); 971 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 972 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 973 sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 974 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 975 sp->sa_gid = txdr_unsigned(vattr.va_gid); 976 if (isnq) { 977 sp->sa_nqrdev = rdev; 978 sp->sa_nqflags = 0; 979 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 980 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 981 } else { 982 sp->sa_nfssize = rdev; 983 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 984 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 985 } 986 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 987 nfsm_mtofh(dvp, newvp); 988 nfsm_reqdone; 989 if (!error && (cnp->cn_flags & MAKEENTRY)) 990 cache_enter(dvp, newvp, cnp); 991 FREE(cnp->cn_pnbuf, M_NAMEI); 992 VTONFS(dvp)->n_flag |= NMODIFIED; 993 VTONFS(dvp)->n_attrstamp = 0; 994 vrele(dvp); 995 return (error); 996 } 997 998 /* 999 * nfs file create call 1000 */ 1001 int 1002 nfs_create(ap) 1003 struct vop_create_args /* { 1004 struct vnode *a_dvp; 1005 struct vnode **a_vpp; 1006 struct componentname *a_cnp; 1007 struct vattr *a_vap; 1008 } */ *ap; 1009 { 1010 register struct vnode *dvp = ap->a_dvp; 1011 register struct vattr *vap = ap->a_vap; 1012 register struct componentname *cnp = ap->a_cnp; 1013 register struct nfsv2_sattr *sp; 1014 register u_long *tl; 1015 register caddr_t cp; 1016 register long t1, t2; 1017 caddr_t bpos, dpos, cp2; 1018 int error = 0, isnq; 1019 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1020 struct vattr vattr; 1021 1022 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1023 VOP_ABORTOP(dvp, cnp); 1024 vput(dvp); 1025 return (error); 1026 } 1027 nfsstats.rpccnt[NFSPROC_CREATE]++; 1028 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 1029 nfsm_reqhead(dvp, NFSPROC_CREATE, 1030 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR(isnq)); 1031 nfsm_fhtom(dvp); 1032 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1033 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 1034 sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 1035 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1036 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1037 if (isnq) { 1038 u_quad_t qval = 0; 1039 1040 txdr_hyper(&qval, &sp->sa_nqsize); 1041 sp->sa_nqflags = 0; 1042 sp->sa_nqrdev = -1; 1043 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 1044 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 1045 } else { 1046 sp->sa_nfssize = 0; 1047 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 1048 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 1049 } 1050 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1051 nfsm_mtofh(dvp, *ap->a_vpp); 1052 nfsm_reqdone; 1053 if (!error && (cnp->cn_flags & MAKEENTRY)) 1054 cache_enter(dvp, *ap->a_vpp, cnp); 1055 FREE(cnp->cn_pnbuf, M_NAMEI); 1056 VTONFS(dvp)->n_flag |= NMODIFIED; 1057 VTONFS(dvp)->n_attrstamp = 0; 1058 vrele(dvp); 1059 return (error); 1060 } 1061 1062 /* 1063 * nfs file remove call 1064 * To try and make nfs semantics closer to ufs semantics, a file that has 1065 * other processes using the vnode is renamed instead of removed and then 1066 * removed later on the last close. 1067 * - If v_usecount > 1 1068 * If a rename is not already in the works 1069 * call nfs_sillyrename() to set it up 1070 * else 1071 * do the remove rpc 1072 */ 1073 int 1074 nfs_remove(ap) 1075 struct vop_remove_args /* { 1076 struct vnodeop_desc *a_desc; 1077 struct vnode * a_dvp; 1078 struct vnode * a_vp; 1079 struct componentname * a_cnp; 1080 } */ *ap; 1081 { 1082 register struct vnode *vp = ap->a_vp; 1083 register struct vnode *dvp = ap->a_dvp; 1084 register struct componentname *cnp = ap->a_cnp; 1085 register struct nfsnode *np = VTONFS(vp); 1086 register u_long *tl; 1087 register caddr_t cp; 1088 register long t2; 1089 caddr_t bpos, dpos; 1090 int error = 0; 1091 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1092 1093 if (vp->v_usecount > 1) { 1094 if (!np->n_sillyrename) 1095 error = nfs_sillyrename(dvp, vp, cnp); 1096 } else { 1097 /* 1098 * Purge the name cache so that the chance of a lookup for 1099 * the name succeeding while the remove is in progress is 1100 * minimized. Without node locking it can still happen, such 1101 * that an I/O op returns ESTALE, but since you get this if 1102 * another host removes the file.. 1103 */ 1104 cache_purge(vp); 1105 /* 1106 * Throw away biocache buffers. Mainly to avoid 1107 * unnecessary delayed writes. 1108 */ 1109 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1); 1110 if (error == EINTR) 1111 return (error); 1112 /* Do the rpc */ 1113 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1114 nfsm_reqhead(dvp, NFSPROC_REMOVE, 1115 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 1116 nfsm_fhtom(dvp); 1117 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1118 nfsm_request(dvp, NFSPROC_REMOVE, cnp->cn_proc, cnp->cn_cred); 1119 nfsm_reqdone; 1120 FREE(cnp->cn_pnbuf, M_NAMEI); 1121 VTONFS(dvp)->n_flag |= NMODIFIED; 1122 VTONFS(dvp)->n_attrstamp = 0; 1123 /* 1124 * Kludge City: If the first reply to the remove rpc is lost.. 1125 * the reply to the retransmitted request will be ENOENT 1126 * since the file was in fact removed 1127 * Therefore, we cheat and return success. 1128 */ 1129 if (error == ENOENT) 1130 error = 0; 1131 } 1132 np->n_attrstamp = 0; 1133 vrele(dvp); 1134 vrele(vp); 1135 return (error); 1136 } 1137 1138 /* 1139 * nfs file remove rpc called from nfs_inactive 1140 */ 1141 int 1142 nfs_removeit(sp) 1143 register struct sillyrename *sp; 1144 { 1145 register u_long *tl; 1146 register caddr_t cp; 1147 register long t2; 1148 caddr_t bpos, dpos; 1149 int error = 0; 1150 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1151 1152 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1153 nfsm_reqhead(sp->s_dvp, NFSPROC_REMOVE, 1154 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(sp->s_namlen)); 1155 nfsm_fhtom(sp->s_dvp); 1156 nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN); 1157 nfsm_request(sp->s_dvp, NFSPROC_REMOVE, NULL, sp->s_cred); 1158 nfsm_reqdone; 1159 VTONFS(sp->s_dvp)->n_flag |= NMODIFIED; 1160 VTONFS(sp->s_dvp)->n_attrstamp = 0; 1161 return (error); 1162 } 1163 1164 /* 1165 * nfs file rename call 1166 */ 1167 int 1168 nfs_rename(ap) 1169 struct vop_rename_args /* { 1170 struct vnode *a_fdvp; 1171 struct vnode *a_fvp; 1172 struct componentname *a_fcnp; 1173 struct vnode *a_tdvp; 1174 struct vnode *a_tvp; 1175 struct componentname *a_tcnp; 1176 } */ *ap; 1177 { 1178 register struct vnode *fvp = ap->a_fvp; 1179 register struct vnode *tvp = ap->a_tvp; 1180 register struct vnode *fdvp = ap->a_fdvp; 1181 register struct vnode *tdvp = ap->a_tdvp; 1182 register struct componentname *tcnp = ap->a_tcnp; 1183 register struct componentname *fcnp = ap->a_fcnp; 1184 register u_long *tl; 1185 register caddr_t cp; 1186 register long t2; 1187 caddr_t bpos, dpos; 1188 int error = 0; 1189 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1190 1191 /* Check for cross-device rename */ 1192 if ((fvp->v_mount != tdvp->v_mount) || 1193 (tvp && (fvp->v_mount != tvp->v_mount))) { 1194 error = EXDEV; 1195 goto out; 1196 } 1197 1198 1199 nfsstats.rpccnt[NFSPROC_RENAME]++; 1200 nfsm_reqhead(fdvp, NFSPROC_RENAME, 1201 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(fcnp->cn_namelen)+ 1202 nfsm_rndup(fcnp->cn_namelen)); /* or fcnp->cn_cred?*/ 1203 nfsm_fhtom(fdvp); 1204 nfsm_strtom(fcnp->cn_nameptr, fcnp->cn_namelen, NFS_MAXNAMLEN); 1205 nfsm_fhtom(tdvp); 1206 nfsm_strtom(tcnp->cn_nameptr, tcnp->cn_namelen, NFS_MAXNAMLEN); 1207 nfsm_request(fdvp, NFSPROC_RENAME, tcnp->cn_proc, tcnp->cn_cred); 1208 nfsm_reqdone; 1209 VTONFS(fdvp)->n_flag |= NMODIFIED; 1210 VTONFS(fdvp)->n_attrstamp = 0; 1211 VTONFS(tdvp)->n_flag |= NMODIFIED; 1212 VTONFS(tdvp)->n_attrstamp = 0; 1213 if (fvp->v_type == VDIR) { 1214 if (tvp != NULL && tvp->v_type == VDIR) 1215 cache_purge(tdvp); 1216 cache_purge(fdvp); 1217 } 1218 out: 1219 if (tdvp == tvp) 1220 vrele(tdvp); 1221 else 1222 vput(tdvp); 1223 if (tvp) 1224 vput(tvp); 1225 vrele(fdvp); 1226 vrele(fvp); 1227 /* 1228 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1229 */ 1230 if (error == ENOENT) 1231 error = 0; 1232 return (error); 1233 } 1234 1235 /* 1236 * nfs file rename rpc called from nfs_remove() above 1237 */ 1238 int 1239 nfs_renameit(sdvp, scnp, sp) 1240 struct vnode *sdvp; 1241 struct componentname *scnp; 1242 register struct sillyrename *sp; 1243 { 1244 register u_long *tl; 1245 register caddr_t cp; 1246 register long t2; 1247 caddr_t bpos, dpos; 1248 int error = 0; 1249 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1250 1251 nfsstats.rpccnt[NFSPROC_RENAME]++; 1252 nfsm_reqhead(sdvp, NFSPROC_RENAME, 1253 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(scnp->cn_namelen)+ 1254 nfsm_rndup(sp->s_namlen)); 1255 nfsm_fhtom(sdvp); 1256 nfsm_strtom(scnp->cn_nameptr, scnp->cn_namelen, NFS_MAXNAMLEN); 1257 nfsm_fhtom(sdvp); 1258 nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN); 1259 nfsm_request(sdvp, NFSPROC_RENAME, scnp->cn_proc, scnp->cn_cred); 1260 nfsm_reqdone; 1261 FREE(scnp->cn_pnbuf, M_NAMEI); 1262 VTONFS(sdvp)->n_flag |= NMODIFIED; 1263 VTONFS(sdvp)->n_attrstamp = 0; 1264 return (error); 1265 } 1266 1267 /* 1268 * nfs hard link create call 1269 */ 1270 int 1271 nfs_link(ap) 1272 struct vop_link_args /* { 1273 struct vnode *a_vp; 1274 struct vnode *a_tdvp; 1275 struct componentname *a_cnp; 1276 } */ *ap; 1277 { 1278 register struct vnode *vp = ap->a_vp; 1279 register struct vnode *tdvp = ap->a_tdvp; 1280 register struct componentname *cnp = ap->a_cnp; 1281 register u_long *tl; 1282 register caddr_t cp; 1283 register long t2; 1284 caddr_t bpos, dpos; 1285 int error = 0; 1286 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1287 1288 if (tdvp->v_mount != vp->v_mount) { 1289 VOP_ABORTOP(tdvp, cnp); 1290 vput(tdvp); 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(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc); 1300 1301 nfsstats.rpccnt[NFSPROC_LINK]++; 1302 nfsm_reqhead(vp, NFSPROC_LINK, 1303 NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 1304 nfsm_fhtom(vp); 1305 nfsm_fhtom(tdvp); 1306 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1307 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); 1308 nfsm_reqdone; 1309 FREE(cnp->cn_pnbuf, M_NAMEI); 1310 VTONFS(vp)->n_attrstamp = 0; 1311 VTONFS(vp)->n_flag |= NMODIFIED; 1312 VTONFS(tdvp)->n_attrstamp = 0; 1313 vput(tdvp); 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 if (ap->a_runp != NULL) 2031 *ap->a_runp = 0; 2032 return (0); 2033 } 2034 2035 /* 2036 * Strategy routine. 2037 * For async requests when nfsiod(s) are running, queue the request by 2038 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the 2039 * request. 2040 */ 2041 int 2042 nfs_strategy(ap) 2043 struct vop_strategy_args *ap; 2044 { 2045 register struct buf *bp = ap->a_bp; 2046 struct ucred *cr; 2047 struct proc *p; 2048 int error = 0; 2049 2050 if (bp->b_flags & B_PHYS) 2051 panic("nfs physio"); 2052 if (bp->b_flags & B_ASYNC) 2053 p = (struct proc *)0; 2054 else 2055 p = curproc; /* XXX */ 2056 if (bp->b_flags & B_READ) 2057 cr = bp->b_rcred; 2058 else 2059 cr = bp->b_wcred; 2060 /* 2061 * If the op is asynchronous and an i/o daemon is waiting 2062 * queue the request, wake it up and wait for completion 2063 * otherwise just do it ourselves. 2064 */ 2065 if ((bp->b_flags & B_ASYNC) == 0 || 2066 nfs_asyncio(bp, NOCRED)) 2067 error = nfs_doio(bp, cr, p); 2068 return (error); 2069 } 2070 2071 /* 2072 * Mmap a file 2073 * 2074 * NB Currently unsupported. 2075 */ 2076 /* ARGSUSED */ 2077 int 2078 nfs_mmap(ap) 2079 struct vop_mmap_args /* { 2080 struct vnode *a_vp; 2081 int a_fflags; 2082 struct ucred *a_cred; 2083 struct proc *a_p; 2084 } */ *ap; 2085 { 2086 2087 return (EINVAL); 2088 } 2089 2090 /* 2091 * Flush all the blocks associated with a vnode. 2092 * Walk through the buffer pool and push any dirty pages 2093 * associated with the vnode. 2094 */ 2095 /* ARGSUSED */ 2096 int 2097 nfs_fsync(ap) 2098 struct vop_fsync_args /* { 2099 struct vnodeop_desc *a_desc; 2100 struct vnode * a_vp; 2101 struct ucred * a_cred; 2102 int a_waitfor; 2103 struct proc * a_p; 2104 } */ *ap; 2105 { 2106 register struct vnode *vp = ap->a_vp; 2107 register struct nfsnode *np = VTONFS(vp); 2108 register struct buf *bp; 2109 struct buf *nbp; 2110 struct nfsmount *nmp; 2111 int s, error = 0, slptimeo = 0, slpflag = 0; 2112 2113 nmp = VFSTONFS(vp->v_mount); 2114 if (nmp->nm_flag & NFSMNT_INT) 2115 slpflag = PCATCH; 2116 loop: 2117 s = splbio(); 2118 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2119 nbp = bp->b_vnbufs.le_next; 2120 if (bp->b_flags & B_BUSY) { 2121 if (ap->a_waitfor != MNT_WAIT) 2122 continue; 2123 bp->b_flags |= B_WANTED; 2124 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), 2125 "nfsfsync", slptimeo); 2126 splx(s); 2127 if (error) { 2128 if (nfs_sigintr(nmp, (struct nfsreq *)0, ap->a_p)) 2129 return (EINTR); 2130 if (slpflag == PCATCH) { 2131 slpflag = 0; 2132 slptimeo = 2 * hz; 2133 } 2134 } 2135 goto loop; 2136 } 2137 if ((bp->b_flags & B_DELWRI) == 0) 2138 panic("nfs_fsync: not dirty"); 2139 bremfree(bp); 2140 bp->b_flags |= B_BUSY; 2141 splx(s); 2142 bp->b_flags |= B_ASYNC; 2143 VOP_BWRITE(bp); 2144 goto loop; 2145 } 2146 splx(s); 2147 if (ap->a_waitfor == MNT_WAIT) { 2148 while (vp->v_numoutput) { 2149 vp->v_flag |= VBWAIT; 2150 error = tsleep((caddr_t)&vp->v_numoutput, 2151 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); 2152 if (error) { 2153 if (nfs_sigintr(nmp, (struct nfsreq *)0, ap->a_p)) 2154 return (EINTR); 2155 if (slpflag == PCATCH) { 2156 slpflag = 0; 2157 slptimeo = 2 * hz; 2158 } 2159 } 2160 } 2161 if (vp->v_dirtyblkhd.lh_first) { 2162 #ifdef DIAGNOSTIC 2163 vprint("nfs_fsync: dirty", vp); 2164 #endif 2165 goto loop; 2166 } 2167 } 2168 if (np->n_flag & NWRITEERR) { 2169 error = np->n_error; 2170 np->n_flag &= ~NWRITEERR; 2171 } 2172 return (error); 2173 } 2174 2175 /* 2176 * Return POSIX pathconf information applicable to nfs. 2177 * 2178 * Currently the NFS protocol does not support getting such 2179 * information from the remote server. 2180 */ 2181 /* ARGSUSED */ 2182 nfs_pathconf(ap) 2183 struct vop_pathconf_args /* { 2184 struct vnode *a_vp; 2185 int a_name; 2186 int *a_retval; 2187 } */ *ap; 2188 { 2189 2190 return (EINVAL); 2191 } 2192 2193 /* 2194 * NFS advisory byte-level locks. 2195 * Currently unsupported. 2196 */ 2197 int 2198 nfs_advlock(ap) 2199 struct vop_advlock_args /* { 2200 struct vnode *a_vp; 2201 caddr_t a_id; 2202 int a_op; 2203 struct flock *a_fl; 2204 int a_flags; 2205 } */ *ap; 2206 { 2207 2208 return (EOPNOTSUPP); 2209 } 2210 2211 /* 2212 * Print out the contents of an nfsnode. 2213 */ 2214 int 2215 nfs_print(ap) 2216 struct vop_print_args /* { 2217 struct vnode *a_vp; 2218 } */ *ap; 2219 { 2220 register struct vnode *vp = ap->a_vp; 2221 register struct nfsnode *np = VTONFS(vp); 2222 2223 printf("tag VT_NFS, fileid %d fsid 0x%x", 2224 np->n_vattr.va_fileid, np->n_vattr.va_fsid); 2225 #ifdef FIFO 2226 if (vp->v_type == VFIFO) 2227 fifo_printinfo(vp); 2228 #endif /* FIFO */ 2229 printf("\n"); 2230 } 2231 2232 /* 2233 * NFS directory offset lookup. 2234 * Currently unsupported. 2235 */ 2236 int 2237 nfs_blkatoff(ap) 2238 struct vop_blkatoff_args /* { 2239 struct vnode *a_vp; 2240 off_t a_offset; 2241 char **a_res; 2242 struct buf **a_bpp; 2243 } */ *ap; 2244 { 2245 2246 return (EOPNOTSUPP); 2247 } 2248 2249 /* 2250 * NFS flat namespace allocation. 2251 * Currently unsupported. 2252 */ 2253 int 2254 nfs_valloc(ap) 2255 struct vop_valloc_args /* { 2256 struct vnode *a_pvp; 2257 int a_mode; 2258 struct ucred *a_cred; 2259 struct vnode **a_vpp; 2260 } */ *ap; 2261 { 2262 2263 return (EOPNOTSUPP); 2264 } 2265 2266 /* 2267 * NFS flat namespace free. 2268 * Currently unsupported. 2269 */ 2270 int 2271 nfs_vfree(ap) 2272 struct vop_vfree_args /* { 2273 struct vnode *a_pvp; 2274 ino_t a_ino; 2275 int a_mode; 2276 } */ *ap; 2277 { 2278 2279 return (EOPNOTSUPP); 2280 } 2281 2282 /* 2283 * NFS file truncation. 2284 */ 2285 int 2286 nfs_truncate(ap) 2287 struct vop_truncate_args /* { 2288 struct vnode *a_vp; 2289 off_t a_length; 2290 int a_flags; 2291 struct ucred *a_cred; 2292 struct proc *a_p; 2293 } */ *ap; 2294 { 2295 2296 /* Use nfs_setattr */ 2297 printf("nfs_truncate: need to implement!!"); 2298 return (EOPNOTSUPP); 2299 } 2300 2301 /* 2302 * NFS update. 2303 */ 2304 int 2305 nfs_update(ap) 2306 struct vop_update_args /* { 2307 struct vnode *a_vp; 2308 struct timeval *a_ta; 2309 struct timeval *a_tm; 2310 int a_waitfor; 2311 } */ *ap; 2312 { 2313 2314 /* Use nfs_setattr */ 2315 printf("nfs_update: need to implement!!"); 2316 return (EOPNOTSUPP); 2317 } 2318 2319 /* 2320 * nfs special file access vnode op. 2321 * Essentially just get vattr and then imitate iaccess() since the device is 2322 * local to the client. 2323 */ 2324 int 2325 nfsspec_access(ap) 2326 struct vop_access_args /* { 2327 struct vnode *a_vp; 2328 int a_mode; 2329 struct ucred *a_cred; 2330 struct proc *a_p; 2331 } */ *ap; 2332 { 2333 register struct vattr *vap; 2334 register gid_t *gp; 2335 register struct ucred *cred = ap->a_cred; 2336 mode_t mode = ap->a_mode; 2337 struct vattr vattr; 2338 register int i; 2339 int error; 2340 2341 /* 2342 * If you're the super-user, 2343 * you always get access. 2344 */ 2345 if (cred->cr_uid == 0) 2346 return (0); 2347 vap = &vattr; 2348 if (error = VOP_GETATTR(ap->a_vp, vap, cred, ap->a_p)) 2349 return (error); 2350 /* 2351 * Access check is based on only one of owner, group, public. 2352 * If not owner, then check group. If not a member of the 2353 * group, then check public access. 2354 */ 2355 if (cred->cr_uid != vap->va_uid) { 2356 mode >>= 3; 2357 gp = cred->cr_groups; 2358 for (i = 0; i < cred->cr_ngroups; i++, gp++) 2359 if (vap->va_gid == *gp) 2360 goto found; 2361 mode >>= 3; 2362 found: 2363 ; 2364 } 2365 return ((vap->va_mode & mode) == mode ? 0 : EACCES); 2366 } 2367 2368 /* 2369 * Read wrapper for special devices. 2370 */ 2371 int 2372 nfsspec_read(ap) 2373 struct vop_read_args /* { 2374 struct vnode *a_vp; 2375 struct uio *a_uio; 2376 int a_ioflag; 2377 struct ucred *a_cred; 2378 } */ *ap; 2379 { 2380 register struct nfsnode *np = VTONFS(ap->a_vp); 2381 2382 /* 2383 * Set access flag. 2384 */ 2385 np->n_flag |= NACC; 2386 np->n_atim = time; 2387 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap)); 2388 } 2389 2390 /* 2391 * Write wrapper for special devices. 2392 */ 2393 int 2394 nfsspec_write(ap) 2395 struct vop_write_args /* { 2396 struct vnode *a_vp; 2397 struct uio *a_uio; 2398 int a_ioflag; 2399 struct ucred *a_cred; 2400 } */ *ap; 2401 { 2402 register struct nfsnode *np = VTONFS(ap->a_vp); 2403 2404 /* 2405 * Set update flag. 2406 */ 2407 np->n_flag |= NUPD; 2408 np->n_mtim = time; 2409 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap)); 2410 } 2411 2412 /* 2413 * Close wrapper for special devices. 2414 * 2415 * Update the times on the nfsnode then do device close. 2416 */ 2417 int 2418 nfsspec_close(ap) 2419 struct vop_close_args /* { 2420 struct vnode *a_vp; 2421 int a_fflag; 2422 struct ucred *a_cred; 2423 struct proc *a_p; 2424 } */ *ap; 2425 { 2426 register struct vnode *vp = ap->a_vp; 2427 register struct nfsnode *np = VTONFS(vp); 2428 struct vattr vattr; 2429 2430 if (np->n_flag & (NACC | NUPD)) { 2431 np->n_flag |= NCHG; 2432 if (vp->v_usecount == 1 && 2433 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 2434 VATTR_NULL(&vattr); 2435 if (np->n_flag & NACC) { 2436 vattr.va_atime.ts_sec = np->n_atim.tv_sec; 2437 vattr.va_atime.ts_nsec = 2438 np->n_atim.tv_usec * 1000; 2439 } 2440 if (np->n_flag & NUPD) { 2441 vattr.va_mtime.ts_sec = np->n_mtim.tv_sec; 2442 vattr.va_mtime.ts_nsec = 2443 np->n_mtim.tv_usec * 1000; 2444 } 2445 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 2446 } 2447 } 2448 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 2449 } 2450 2451 #ifdef FIFO 2452 /* 2453 * Read wrapper for fifos. 2454 */ 2455 int 2456 nfsfifo_read(ap) 2457 struct vop_read_args /* { 2458 struct vnode *a_vp; 2459 struct uio *a_uio; 2460 int a_ioflag; 2461 struct ucred *a_cred; 2462 } */ *ap; 2463 { 2464 extern int (**fifo_vnodeop_p)(); 2465 register struct nfsnode *np = VTONFS(ap->a_vp); 2466 2467 /* 2468 * Set access flag. 2469 */ 2470 np->n_flag |= NACC; 2471 np->n_atim = time; 2472 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap)); 2473 } 2474 2475 /* 2476 * Write wrapper for fifos. 2477 */ 2478 int 2479 nfsfifo_write(ap) 2480 struct vop_write_args /* { 2481 struct vnode *a_vp; 2482 struct uio *a_uio; 2483 int a_ioflag; 2484 struct ucred *a_cred; 2485 } */ *ap; 2486 { 2487 extern int (**fifo_vnodeop_p)(); 2488 register struct nfsnode *np = VTONFS(ap->a_vp); 2489 2490 /* 2491 * Set update flag. 2492 */ 2493 np->n_flag |= NUPD; 2494 np->n_mtim = time; 2495 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap)); 2496 } 2497 2498 /* 2499 * Close wrapper for fifos. 2500 * 2501 * Update the times on the nfsnode then do fifo close. 2502 */ 2503 int 2504 nfsfifo_close(ap) 2505 struct vop_close_args /* { 2506 struct vnode *a_vp; 2507 int a_fflag; 2508 struct ucred *a_cred; 2509 struct proc *a_p; 2510 } */ *ap; 2511 { 2512 register struct vnode *vp = ap->a_vp; 2513 register struct nfsnode *np = VTONFS(vp); 2514 struct vattr vattr; 2515 extern int (**fifo_vnodeop_p)(); 2516 2517 if (np->n_flag & (NACC | NUPD)) { 2518 if (np->n_flag & NACC) 2519 np->n_atim = time; 2520 if (np->n_flag & NUPD) 2521 np->n_mtim = time; 2522 np->n_flag |= NCHG; 2523 if (vp->v_usecount == 1 && 2524 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 2525 VATTR_NULL(&vattr); 2526 if (np->n_flag & NACC) { 2527 vattr.va_atime.ts_sec = np->n_atim.tv_sec; 2528 vattr.va_atime.ts_nsec = 2529 np->n_atim.tv_usec * 1000; 2530 } 2531 if (np->n_flag & NUPD) { 2532 vattr.va_mtime.ts_sec = np->n_mtim.tv_sec; 2533 vattr.va_mtime.ts_nsec = 2534 np->n_mtim.tv_usec * 1000; 2535 } 2536 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 2537 } 2538 } 2539 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 2540 } 2541 #endif /* FIFO */ 2542