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