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.15 (Berkeley) 05/14/95 11 */ 12 13 14 /* 15 * vnode op calls for Sun NFS version 2 and 3 16 */ 17 18 #include <sys/param.h> 19 #include <sys/kernel.h> 20 #include <sys/systm.h> 21 #include <sys/resourcevar.h> 22 #include <sys/proc.h> 23 #include <sys/mount.h> 24 #include <sys/buf.h> 25 #include <sys/malloc.h> 26 #include <sys/mbuf.h> 27 #include <sys/conf.h> 28 #include <sys/namei.h> 29 #include <sys/vnode.h> 30 #include <sys/dirent.h> 31 #include <sys/fcntl.h> 32 #include <ufs/ufs/dir.h> 33 34 #include <vm/vm.h> 35 36 #include <miscfs/specfs/specdev.h> 37 #include <miscfs/fifofs/fifo.h> 38 39 #include <nfs/rpcv2.h> 40 #include <nfs/nfsproto.h> 41 #include <nfs/nfs.h> 42 #include <nfs/nfsnode.h> 43 #include <nfs/nfsmount.h> 44 #include <nfs/xdr_subs.h> 45 #include <nfs/nfsm_subs.h> 46 #include <nfs/nqnfs.h> 47 48 #include <net/if.h> 49 #include <netinet/in.h> 50 #include <netinet/in_var.h> 51 52 /* Defs */ 53 #define TRUE 1 54 #define FALSE 0 55 56 /* 57 * Global vfs data structures for nfs 58 */ 59 int (**nfsv2_vnodeop_p)(); 60 struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = { 61 { &vop_default_desc, vn_default_error }, 62 { &vop_lookup_desc, nfs_lookup }, /* lookup */ 63 { &vop_create_desc, nfs_create }, /* create */ 64 { &vop_mknod_desc, nfs_mknod }, /* mknod */ 65 { &vop_open_desc, nfs_open }, /* open */ 66 { &vop_close_desc, nfs_close }, /* close */ 67 { &vop_access_desc, nfs_access }, /* access */ 68 { &vop_getattr_desc, nfs_getattr }, /* getattr */ 69 { &vop_setattr_desc, nfs_setattr }, /* setattr */ 70 { &vop_read_desc, nfs_read }, /* read */ 71 { &vop_write_desc, nfs_write }, /* write */ 72 { &vop_lease_desc, nfs_lease_check }, /* lease */ 73 { &vop_ioctl_desc, nfs_ioctl }, /* ioctl */ 74 { &vop_select_desc, nfs_select }, /* select */ 75 { &vop_revoke_desc, nfs_revoke }, /* revoke */ 76 { &vop_mmap_desc, nfs_mmap }, /* mmap */ 77 { &vop_fsync_desc, nfs_fsync }, /* fsync */ 78 { &vop_seek_desc, nfs_seek }, /* seek */ 79 { &vop_remove_desc, nfs_remove }, /* remove */ 80 { &vop_link_desc, nfs_link }, /* link */ 81 { &vop_rename_desc, nfs_rename }, /* rename */ 82 { &vop_mkdir_desc, nfs_mkdir }, /* mkdir */ 83 { &vop_rmdir_desc, nfs_rmdir }, /* rmdir */ 84 { &vop_symlink_desc, nfs_symlink }, /* symlink */ 85 { &vop_readdir_desc, nfs_readdir }, /* readdir */ 86 { &vop_readlink_desc, nfs_readlink }, /* readlink */ 87 { &vop_abortop_desc, nfs_abortop }, /* abortop */ 88 { &vop_inactive_desc, nfs_inactive }, /* inactive */ 89 { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ 90 { &vop_lock_desc, nfs_lock }, /* lock */ 91 { &vop_unlock_desc, nfs_unlock }, /* unlock */ 92 { &vop_bmap_desc, nfs_bmap }, /* bmap */ 93 { &vop_strategy_desc, nfs_strategy }, /* strategy */ 94 { &vop_print_desc, nfs_print }, /* print */ 95 { &vop_islocked_desc, nfs_islocked }, /* islocked */ 96 { &vop_pathconf_desc, nfs_pathconf }, /* pathconf */ 97 { &vop_advlock_desc, nfs_advlock }, /* advlock */ 98 { &vop_blkatoff_desc, nfs_blkatoff }, /* blkatoff */ 99 { &vop_valloc_desc, nfs_valloc }, /* valloc */ 100 { &vop_reallocblks_desc, nfs_reallocblks }, /* reallocblks */ 101 { &vop_vfree_desc, nfs_vfree }, /* vfree */ 102 { &vop_truncate_desc, nfs_truncate }, /* truncate */ 103 { &vop_update_desc, nfs_update }, /* update */ 104 { &vop_bwrite_desc, nfs_bwrite }, 105 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 106 }; 107 struct vnodeopv_desc nfsv2_vnodeop_opv_desc = 108 { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries }; 109 110 /* 111 * Special device vnode ops 112 */ 113 int (**spec_nfsv2nodeop_p)(); 114 struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = { 115 { &vop_default_desc, vn_default_error }, 116 { &vop_lookup_desc, spec_lookup }, /* lookup */ 117 { &vop_create_desc, spec_create }, /* create */ 118 { &vop_mknod_desc, spec_mknod }, /* mknod */ 119 { &vop_open_desc, spec_open }, /* open */ 120 { &vop_close_desc, nfsspec_close }, /* close */ 121 { &vop_access_desc, nfsspec_access }, /* access */ 122 { &vop_getattr_desc, nfs_getattr }, /* getattr */ 123 { &vop_setattr_desc, nfs_setattr }, /* setattr */ 124 { &vop_read_desc, nfsspec_read }, /* read */ 125 { &vop_write_desc, nfsspec_write }, /* write */ 126 { &vop_lease_desc, spec_lease_check }, /* lease */ 127 { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 128 { &vop_select_desc, spec_select }, /* select */ 129 { &vop_revoke_desc, spec_revoke }, /* revoke */ 130 { &vop_mmap_desc, spec_mmap }, /* mmap */ 131 { &vop_fsync_desc, nfs_fsync }, /* fsync */ 132 { &vop_seek_desc, spec_seek }, /* seek */ 133 { &vop_remove_desc, spec_remove }, /* remove */ 134 { &vop_link_desc, spec_link }, /* link */ 135 { &vop_rename_desc, spec_rename }, /* rename */ 136 { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 137 { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 138 { &vop_symlink_desc, spec_symlink }, /* symlink */ 139 { &vop_readdir_desc, spec_readdir }, /* readdir */ 140 { &vop_readlink_desc, spec_readlink }, /* readlink */ 141 { &vop_abortop_desc, spec_abortop }, /* abortop */ 142 { &vop_inactive_desc, nfs_inactive }, /* inactive */ 143 { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ 144 { &vop_lock_desc, nfs_lock }, /* lock */ 145 { &vop_unlock_desc, nfs_unlock }, /* unlock */ 146 { &vop_bmap_desc, spec_bmap }, /* bmap */ 147 { &vop_strategy_desc, spec_strategy }, /* strategy */ 148 { &vop_print_desc, nfs_print }, /* print */ 149 { &vop_islocked_desc, nfs_islocked }, /* islocked */ 150 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ 151 { &vop_advlock_desc, spec_advlock }, /* advlock */ 152 { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ 153 { &vop_valloc_desc, spec_valloc }, /* valloc */ 154 { &vop_reallocblks_desc, spec_reallocblks }, /* reallocblks */ 155 { &vop_vfree_desc, spec_vfree }, /* vfree */ 156 { &vop_truncate_desc, spec_truncate }, /* truncate */ 157 { &vop_update_desc, nfs_update }, /* update */ 158 { &vop_bwrite_desc, vn_bwrite }, 159 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 160 }; 161 struct vnodeopv_desc spec_nfsv2nodeop_opv_desc = 162 { &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries }; 163 164 int (**fifo_nfsv2nodeop_p)(); 165 struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = { 166 { &vop_default_desc, vn_default_error }, 167 { &vop_lookup_desc, fifo_lookup }, /* lookup */ 168 { &vop_create_desc, fifo_create }, /* create */ 169 { &vop_mknod_desc, fifo_mknod }, /* mknod */ 170 { &vop_open_desc, fifo_open }, /* open */ 171 { &vop_close_desc, nfsfifo_close }, /* close */ 172 { &vop_access_desc, nfsspec_access }, /* access */ 173 { &vop_getattr_desc, nfs_getattr }, /* getattr */ 174 { &vop_setattr_desc, nfs_setattr }, /* setattr */ 175 { &vop_read_desc, nfsfifo_read }, /* read */ 176 { &vop_write_desc, nfsfifo_write }, /* write */ 177 { &vop_lease_desc, fifo_lease_check }, /* lease */ 178 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 179 { &vop_select_desc, fifo_select }, /* select */ 180 { &vop_revoke_desc, fifo_revoke }, /* revoke */ 181 { &vop_mmap_desc, fifo_mmap }, /* mmap */ 182 { &vop_fsync_desc, nfs_fsync }, /* fsync */ 183 { &vop_seek_desc, fifo_seek }, /* seek */ 184 { &vop_remove_desc, fifo_remove }, /* remove */ 185 { &vop_link_desc, fifo_link }, /* link */ 186 { &vop_rename_desc, fifo_rename }, /* rename */ 187 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 188 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 189 { &vop_symlink_desc, fifo_symlink }, /* symlink */ 190 { &vop_readdir_desc, fifo_readdir }, /* readdir */ 191 { &vop_readlink_desc, fifo_readlink }, /* readlink */ 192 { &vop_abortop_desc, fifo_abortop }, /* abortop */ 193 { &vop_inactive_desc, nfs_inactive }, /* inactive */ 194 { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ 195 { &vop_lock_desc, nfs_lock }, /* lock */ 196 { &vop_unlock_desc, nfs_unlock }, /* unlock */ 197 { &vop_bmap_desc, fifo_bmap }, /* bmap */ 198 { &vop_strategy_desc, fifo_badop }, /* strategy */ 199 { &vop_print_desc, nfs_print }, /* print */ 200 { &vop_islocked_desc, nfs_islocked }, /* islocked */ 201 { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ 202 { &vop_advlock_desc, fifo_advlock }, /* advlock */ 203 { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 204 { &vop_valloc_desc, fifo_valloc }, /* valloc */ 205 { &vop_reallocblks_desc, fifo_reallocblks }, /* reallocblks */ 206 { &vop_vfree_desc, fifo_vfree }, /* vfree */ 207 { &vop_truncate_desc, fifo_truncate }, /* truncate */ 208 { &vop_update_desc, nfs_update }, /* update */ 209 { &vop_bwrite_desc, vn_bwrite }, 210 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 211 }; 212 struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc = 213 { &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries }; 214 215 void nqnfs_clientlease(); 216 int nfs_commit(); 217 218 /* 219 * Global variables 220 */ 221 extern u_long nfs_true, nfs_false; 222 extern struct nfsstats nfsstats; 223 extern nfstype nfsv3_type[9]; 224 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 225 int nfs_numasync = 0; 226 #define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) 227 228 /* 229 * nfs null call from vfs. 230 */ 231 int 232 nfs_null(vp, cred, procp) 233 struct vnode *vp; 234 struct ucred *cred; 235 struct proc *procp; 236 { 237 caddr_t bpos, dpos; 238 int error = 0; 239 struct mbuf *mreq, *mrep, *md, *mb; 240 241 nfsm_reqhead(vp, NFSPROC_NULL, 0); 242 nfsm_request(vp, NFSPROC_NULL, procp, cred); 243 nfsm_reqdone; 244 return (error); 245 } 246 247 /* 248 * nfs access vnode op. 249 * For nfs version 2, just return ok. File accesses may fail later. 250 * For nfs version 3, use the access rpc to check accessibility. If file modes 251 * are changed on the server, accesses might still fail later. 252 */ 253 int 254 nfs_access(ap) 255 struct vop_access_args /* { 256 struct vnode *a_vp; 257 int a_mode; 258 struct ucred *a_cred; 259 struct proc *a_p; 260 } */ *ap; 261 { 262 register struct vnode *vp = ap->a_vp; 263 register u_long *tl; 264 register caddr_t cp; 265 register int t1, t2; 266 caddr_t bpos, dpos, cp2; 267 int error = 0, attrflag; 268 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 269 u_long mode, rmode; 270 int v3 = NFS_ISV3(vp); 271 272 /* 273 * For nfs v3, do an access rpc, otherwise you are stuck emulating 274 * ufs_access() locally using the vattr. This may not be correct, 275 * since the server may apply other access criteria such as 276 * client uid-->server uid mapping that we do not know about, but 277 * this is better than just returning anything that is lying about 278 * in the cache. 279 */ 280 if (v3) { 281 nfsstats.rpccnt[NFSPROC_ACCESS]++; 282 nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED); 283 nfsm_fhtom(vp, v3); 284 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 285 if (ap->a_mode & VREAD) 286 mode = NFSV3ACCESS_READ; 287 else 288 mode = 0; 289 if (vp->v_type == VDIR) { 290 if (ap->a_mode & VWRITE) 291 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND | 292 NFSV3ACCESS_DELETE); 293 if (ap->a_mode & VEXEC) 294 mode |= NFSV3ACCESS_LOOKUP; 295 } else { 296 if (ap->a_mode & VWRITE) 297 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND); 298 if (ap->a_mode & VEXEC) 299 mode |= NFSV3ACCESS_EXECUTE; 300 } 301 *tl = txdr_unsigned(mode); 302 nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred); 303 nfsm_postop_attr(vp, attrflag); 304 if (!error) { 305 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 306 rmode = fxdr_unsigned(u_long, *tl); 307 /* 308 * The NFS V3 spec does not clarify whether or not 309 * the returned access bits can be a superset of 310 * the ones requested, so... 311 */ 312 if ((rmode & mode) != mode) 313 error = EACCES; 314 } 315 nfsm_reqdone; 316 return (error); 317 } else 318 return (nfsspec_access(ap)); 319 } 320 321 /* 322 * nfs open vnode op 323 * Check to see if the type is ok 324 * and that deletion is not in progress. 325 * For paged in text files, you will need to flush the page cache 326 * if consistency is lost. 327 */ 328 /* ARGSUSED */ 329 int 330 nfs_open(ap) 331 struct vop_open_args /* { 332 struct vnode *a_vp; 333 int a_mode; 334 struct ucred *a_cred; 335 struct proc *a_p; 336 } */ *ap; 337 { 338 register struct vnode *vp = ap->a_vp; 339 struct nfsnode *np = VTONFS(vp); 340 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 341 struct vattr vattr; 342 int error; 343 344 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) 345 { printf("open eacces vtyp=%d\n",vp->v_type); 346 return (EACCES); 347 } 348 /* 349 * Get a valid lease. If cached data is stale, flush it. 350 */ 351 if (nmp->nm_flag & NFSMNT_NQNFS) { 352 if (NQNFS_CKINVALID(vp, np, ND_READ)) { 353 do { 354 error = nqnfs_getlease(vp, ND_READ, ap->a_cred, 355 ap->a_p); 356 } while (error == NQNFS_EXPIRED); 357 if (error) 358 return (error); 359 if (np->n_lrev != np->n_brev || 360 (np->n_flag & NQNFSNONCACHE)) { 361 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 362 ap->a_p, 1)) == EINTR) 363 return (error); 364 (void) vnode_pager_uncache(vp); 365 np->n_brev = np->n_lrev; 366 } 367 } 368 } else { 369 if (np->n_flag & NMODIFIED) { 370 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 371 ap->a_p, 1)) == EINTR) 372 return (error); 373 (void) vnode_pager_uncache(vp); 374 np->n_attrstamp = 0; 375 if (vp->v_type == VDIR) 376 np->n_direofoffset = 0; 377 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 378 if (error) 379 return (error); 380 np->n_mtime = vattr.va_mtime.ts_sec; 381 } else { 382 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 383 if (error) 384 return (error); 385 if (np->n_mtime != vattr.va_mtime.ts_sec) { 386 if (vp->v_type == VDIR) 387 np->n_direofoffset = 0; 388 if ((error = nfs_vinvalbuf(vp, V_SAVE, 389 ap->a_cred, ap->a_p, 1)) == EINTR) 390 return (error); 391 (void) vnode_pager_uncache(vp); 392 np->n_mtime = vattr.va_mtime.ts_sec; 393 } 394 } 395 } 396 if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) 397 np->n_attrstamp = 0; /* For Open/Close consistency */ 398 return (0); 399 } 400 401 /* 402 * nfs close vnode op 403 * What an NFS client should do upon close after writing is a debatable issue. 404 * Most NFS clients push delayed writes to the server upon close, basically for 405 * two reasons: 406 * 1 - So that any write errors may be reported back to the client process 407 * doing the close system call. By far the two most likely errors are 408 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure. 409 * 2 - To put a worst case upper bound on cache inconsistency between 410 * multiple clients for the file. 411 * There is also a consistency problem for Version 2 of the protocol w.r.t. 412 * not being able to tell if other clients are writing a file concurrently, 413 * since there is no way of knowing if the changed modify time in the reply 414 * is only due to the write for this client. 415 * (NFS Version 3 provides weak cache consistency data in the reply that 416 * should be sufficient to detect and handle this case.) 417 * 418 * The current code does the following: 419 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers 420 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate 421 * or commit them (this satisfies 1 and 2 except for the 422 * case where the server crashes after this close but 423 * before the commit RPC, which is felt to be "good 424 * enough". Changing the last argument to nfs_flush() to 425 * a 1 would force a commit operation, if it is felt a 426 * commit is necessary now. 427 * for NQNFS - do nothing now, since 2 is dealt with via leases and 428 * 1 should be dealt with via an fsync() system call for 429 * cases where write errors are important. 430 */ 431 /* ARGSUSED */ 432 int 433 nfs_close(ap) 434 struct vop_close_args /* { 435 struct vnodeop_desc *a_desc; 436 struct vnode *a_vp; 437 int a_fflag; 438 struct ucred *a_cred; 439 struct proc *a_p; 440 } */ *ap; 441 { 442 register struct vnode *vp = ap->a_vp; 443 register struct nfsnode *np = VTONFS(vp); 444 int error = 0; 445 446 if (vp->v_type == VREG) { 447 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 && 448 (np->n_flag & NMODIFIED)) { 449 if (NFS_ISV3(vp)) 450 error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0); 451 else 452 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1); 453 np->n_attrstamp = 0; 454 } 455 if (np->n_flag & NWRITEERR) { 456 np->n_flag &= ~NWRITEERR; 457 error = np->n_error; 458 } 459 } 460 return (error); 461 } 462 463 /* 464 * nfs getattr call from vfs. 465 */ 466 int 467 nfs_getattr(ap) 468 struct vop_getattr_args /* { 469 struct vnode *a_vp; 470 struct vattr *a_vap; 471 struct ucred *a_cred; 472 struct proc *a_p; 473 } */ *ap; 474 { 475 register struct vnode *vp = ap->a_vp; 476 register struct nfsnode *np = VTONFS(vp); 477 register caddr_t cp; 478 register u_long *tl; 479 register int t1, t2; 480 caddr_t bpos, dpos; 481 int error = 0; 482 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 483 int v3 = NFS_ISV3(vp); 484 485 /* 486 * Update local times for special files. 487 */ 488 if (np->n_flag & (NACC | NUPD)) 489 np->n_flag |= NCHG; 490 /* 491 * First look in the cache. 492 */ 493 if (nfs_getattrcache(vp, ap->a_vap) == 0) 494 return (0); 495 nfsstats.rpccnt[NFSPROC_GETATTR]++; 496 nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3)); 497 nfsm_fhtom(vp, v3); 498 nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred); 499 if (!error) 500 nfsm_loadattr(vp, ap->a_vap); 501 nfsm_reqdone; 502 return (error); 503 } 504 505 /* 506 * nfs setattr call. 507 */ 508 int 509 nfs_setattr(ap) 510 struct vop_setattr_args /* { 511 struct vnodeop_desc *a_desc; 512 struct vnode *a_vp; 513 struct vattr *a_vap; 514 struct ucred *a_cred; 515 struct proc *a_p; 516 } */ *ap; 517 { 518 register struct vnode *vp = ap->a_vp; 519 register struct nfsnode *np = VTONFS(vp); 520 register struct vattr *vap = ap->a_vap; 521 int error = 0; 522 u_quad_t tsize; 523 524 #ifndef nolint 525 tsize = (u_quad_t)0; 526 #endif 527 if (vap->va_size != VNOVAL) { 528 switch (vp->v_type) { 529 case VDIR: 530 return (EISDIR); 531 case VCHR: 532 case VBLK: 533 if (vap->va_mtime.ts_sec == VNOVAL && 534 vap->va_atime.ts_sec == VNOVAL && 535 vap->va_mode == (u_short)VNOVAL && 536 vap->va_uid == (uid_t)VNOVAL && 537 vap->va_gid == (gid_t)VNOVAL) 538 return (0); 539 vap->va_size = VNOVAL; 540 break; 541 default: 542 if (np->n_flag & NMODIFIED) { 543 if (vap->va_size == 0) 544 error = nfs_vinvalbuf(vp, 0, 545 ap->a_cred, ap->a_p, 1); 546 else 547 error = nfs_vinvalbuf(vp, V_SAVE, 548 ap->a_cred, ap->a_p, 1); 549 if (error) 550 return (error); 551 } 552 tsize = np->n_size; 553 np->n_size = np->n_vattr.va_size = vap->va_size; 554 vnode_pager_setsize(vp, (u_long)np->n_size); 555 }; 556 } else if ((vap->va_mtime.ts_sec != VNOVAL || 557 vap->va_atime.ts_sec != VNOVAL) && (np->n_flag & NMODIFIED) && 558 vp->v_type == VREG && 559 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 560 ap->a_p, 1)) == EINTR) 561 return (error); 562 error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p); 563 if (error) { 564 np->n_size = np->n_vattr.va_size = tsize; 565 vnode_pager_setsize(vp, (u_long)np->n_size); 566 } 567 return (error); 568 } 569 570 /* 571 * Do an nfs setattr rpc. 572 */ 573 int 574 nfs_setattrrpc(vp, vap, cred, procp) 575 register struct vnode *vp; 576 register struct vattr *vap; 577 struct ucred *cred; 578 struct proc *procp; 579 { 580 register struct nfsv2_sattr *sp; 581 register caddr_t cp; 582 register long t1, t2; 583 caddr_t bpos, dpos, cp2; 584 u_long *tl; 585 int error = 0, wccflag = NFSV3_WCCRATTR; 586 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 587 u_quad_t frev; 588 int v3 = NFS_ISV3(vp); 589 590 nfsstats.rpccnt[NFSPROC_SETATTR]++; 591 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3)); 592 nfsm_fhtom(vp, v3); 593 if (v3) { 594 if (vap->va_mode != (u_short)VNOVAL) { 595 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 596 *tl++ = nfs_true; 597 *tl = txdr_unsigned(vap->va_mode); 598 } else { 599 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 600 *tl = nfs_false; 601 } 602 if (vap->va_uid != (uid_t)VNOVAL) { 603 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 604 *tl++ = nfs_true; 605 *tl = txdr_unsigned(vap->va_uid); 606 } else { 607 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 608 *tl = nfs_false; 609 } 610 if (vap->va_gid != (gid_t)VNOVAL) { 611 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 612 *tl++ = nfs_true; 613 *tl = txdr_unsigned(vap->va_gid); 614 } else { 615 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 616 *tl = nfs_false; 617 } 618 if (vap->va_size != VNOVAL) { 619 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 620 *tl++ = nfs_true; 621 txdr_hyper(&vap->va_size, tl); 622 } else { 623 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 624 *tl = nfs_false; 625 } 626 if (vap->va_atime.ts_sec != VNOVAL) { 627 if (vap->va_atime.ts_sec != time.tv_sec) { 628 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 629 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 630 txdr_nfsv3time(&vap->va_atime, tl); 631 } else { 632 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 633 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 634 } 635 } else { 636 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 637 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 638 } 639 if (vap->va_mtime.ts_sec != VNOVAL) { 640 if (vap->va_mtime.ts_sec != time.tv_sec) { 641 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 642 *tl++ = txdr_unsigned(NFSV3SATTRTIME_TOCLIENT); 643 txdr_nfsv3time(&vap->va_atime, tl); 644 } else { 645 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 646 *tl = txdr_unsigned(NFSV3SATTRTIME_TOSERVER); 647 } 648 } else { 649 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 650 *tl = txdr_unsigned(NFSV3SATTRTIME_DONTCHANGE); 651 } 652 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 653 *tl = nfs_false; 654 } else { 655 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 656 if (vap->va_mode == (u_short)VNOVAL) 657 sp->sa_mode = VNOVAL; 658 else 659 sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode); 660 if (vap->va_uid == (uid_t)VNOVAL) 661 sp->sa_uid = VNOVAL; 662 else 663 sp->sa_uid = txdr_unsigned(vap->va_uid); 664 if (vap->va_gid == (gid_t)VNOVAL) 665 sp->sa_gid = VNOVAL; 666 else 667 sp->sa_gid = txdr_unsigned(vap->va_gid); 668 sp->sa_size = txdr_unsigned(vap->va_size); 669 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 670 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 671 } 672 nfsm_request(vp, NFSPROC_SETATTR, procp, cred); 673 if (v3) { 674 nfsm_wcc_data(vp, wccflag); 675 } else 676 nfsm_loadattr(vp, (struct vattr *)0); 677 nfsm_reqdone; 678 return (error); 679 } 680 681 /* 682 * nfs lookup call, one step at a time... 683 * First look in cache 684 * If not found, unlock the directory nfsnode and do the rpc 685 */ 686 int 687 nfs_lookup(ap) 688 struct vop_lookup_args /* { 689 struct vnodeop_desc *a_desc; 690 struct vnode *a_dvp; 691 struct vnode **a_vpp; 692 struct componentname *a_cnp; 693 } */ *ap; 694 { 695 register struct componentname *cnp = ap->a_cnp; 696 register struct vnode *dvp = ap->a_dvp; 697 register struct vnode **vpp = ap->a_vpp; 698 register int flags = cnp->cn_flags; 699 register struct proc *p = cnp->cn_proc; 700 register struct vnode *newvp; 701 register u_long *tl; 702 register caddr_t cp; 703 register long t1, t2; 704 struct nfsmount *nmp; 705 caddr_t bpos, dpos, cp2; 706 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 707 long len; 708 nfsfh_t *fhp; 709 struct nfsnode *np; 710 int lockparent, wantparent, error = 0, attrflag, fhsize; 711 int v3 = NFS_ISV3(dvp); 712 713 *vpp = NULLVP; 714 if (dvp->v_type != VDIR) 715 return (ENOTDIR); 716 lockparent = flags & LOCKPARENT; 717 wantparent = flags & (LOCKPARENT|WANTPARENT); 718 nmp = VFSTONFS(dvp->v_mount); 719 np = VTONFS(dvp); 720 if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) { 721 struct vattr vattr; 722 int vpid; 723 724 newvp = *vpp; 725 vpid = newvp->v_id; 726 /* 727 * See the comment starting `Step through' in ufs/ufs_lookup.c 728 * for an explanation of the locking protocol 729 */ 730 if (dvp == newvp) { 731 VREF(newvp); 732 error = 0; 733 } else 734 error = vget(newvp, LK_EXCLUSIVE, p); 735 if (!error) { 736 if (vpid == newvp->v_id) { 737 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_proc) 738 && vattr.va_ctime.ts_sec == VTONFS(newvp)->n_ctime) { 739 nfsstats.lookupcache_hits++; 740 if (cnp->cn_nameiop != LOOKUP && 741 (flags & ISLASTCN)) 742 cnp->cn_flags |= SAVENAME; 743 return (0); 744 } 745 cache_purge(newvp); 746 } 747 vrele(newvp); 748 } 749 *vpp = NULLVP; 750 } 751 error = 0; 752 newvp = NULLVP; 753 nfsstats.lookupcache_misses++; 754 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 755 len = cnp->cn_namelen; 756 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 757 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 758 nfsm_fhtom(dvp, v3); 759 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 760 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 761 if (error) { 762 nfsm_postop_attr(dvp, attrflag); 763 m_freem(mrep); 764 goto nfsmout; 765 } 766 nfsm_getfh(fhp, fhsize, v3); 767 768 /* 769 * Handle RENAME case... 770 */ 771 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { 772 if (NFS_CMPFH(np, fhp, fhsize)) { 773 m_freem(mrep); 774 return (EISDIR); 775 } 776 if (error = nfs_nget(dvp->v_mount, fhp, fhsize, &np)) { 777 m_freem(mrep); 778 return (error); 779 } 780 newvp = NFSTOV(np); 781 if (v3) { 782 nfsm_postop_attr(newvp, attrflag); 783 nfsm_postop_attr(dvp, attrflag); 784 } else 785 nfsm_loadattr(newvp, (struct vattr *)0); 786 *vpp = newvp; 787 m_freem(mrep); 788 cnp->cn_flags |= SAVENAME; 789 return (0); 790 } 791 792 if (NFS_CMPFH(np, fhp, fhsize)) { 793 VREF(dvp); 794 newvp = dvp; 795 } else { 796 if (error = nfs_nget(dvp->v_mount, fhp, fhsize, &np)) { 797 m_freem(mrep); 798 return (error); 799 } 800 newvp = NFSTOV(np); 801 } 802 if (v3) { 803 nfsm_postop_attr(newvp, attrflag); 804 nfsm_postop_attr(dvp, attrflag); 805 } else 806 nfsm_loadattr(newvp, (struct vattr *)0); 807 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 808 cnp->cn_flags |= SAVENAME; 809 if ((cnp->cn_flags & MAKEENTRY) && 810 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { 811 np->n_ctime = np->n_vattr.va_ctime.ts_sec; 812 cache_enter(dvp, newvp, cnp); 813 } 814 *vpp = newvp; 815 nfsm_reqdone; 816 if (error) { 817 if (newvp != NULLVP) 818 vrele(newvp); 819 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && 820 (flags & ISLASTCN) && error == ENOENT) 821 error = EJUSTRETURN; 822 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 823 cnp->cn_flags |= SAVENAME; 824 } 825 return (error); 826 } 827 828 /* 829 * nfs read call. 830 * Just call nfs_bioread() to do the work. 831 */ 832 int 833 nfs_read(ap) 834 struct vop_read_args /* { 835 struct vnode *a_vp; 836 struct uio *a_uio; 837 int a_ioflag; 838 struct ucred *a_cred; 839 } */ *ap; 840 { 841 register struct vnode *vp = ap->a_vp; 842 843 if (vp->v_type != VREG) 844 return (EPERM); 845 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); 846 } 847 848 /* 849 * nfs readlink call 850 */ 851 int 852 nfs_readlink(ap) 853 struct vop_readlink_args /* { 854 struct vnode *a_vp; 855 struct uio *a_uio; 856 struct ucred *a_cred; 857 } */ *ap; 858 { 859 register struct vnode *vp = ap->a_vp; 860 861 if (vp->v_type != VLNK) 862 return (EPERM); 863 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred)); 864 } 865 866 /* 867 * Do a readlink rpc. 868 * Called by nfs_doio() from below the buffer cache. 869 */ 870 int 871 nfs_readlinkrpc(vp, uiop, cred) 872 register struct vnode *vp; 873 struct uio *uiop; 874 struct ucred *cred; 875 { 876 register u_long *tl; 877 register caddr_t cp; 878 register long t1, t2; 879 caddr_t bpos, dpos, cp2; 880 int error = 0, len, attrflag; 881 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 882 int v3 = NFS_ISV3(vp); 883 884 nfsstats.rpccnt[NFSPROC_READLINK]++; 885 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3)); 886 nfsm_fhtom(vp, v3); 887 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred); 888 if (v3) 889 nfsm_postop_attr(vp, attrflag); 890 if (!error) { 891 nfsm_strsiz(len, NFS_MAXPATHLEN); 892 nfsm_mtouio(uiop, len); 893 } 894 nfsm_reqdone; 895 return (error); 896 } 897 898 /* 899 * nfs read rpc call 900 * Ditto above 901 */ 902 int 903 nfs_readrpc(vp, uiop, cred) 904 register struct vnode *vp; 905 struct uio *uiop; 906 struct ucred *cred; 907 { 908 register u_long *tl; 909 register caddr_t cp; 910 register long t1, t2; 911 caddr_t bpos, dpos, cp2; 912 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 913 struct nfsmount *nmp; 914 int error = 0, len, retlen, tsiz, eof, attrflag; 915 int v3 = NFS_ISV3(vp); 916 917 #ifndef nolint 918 eof = 0; 919 #endif 920 nmp = VFSTONFS(vp->v_mount); 921 tsiz = uiop->uio_resid; 922 if (uiop->uio_offset + tsiz > 0xffffffff && !v3) 923 return (EFBIG); 924 while (tsiz > 0) { 925 nfsstats.rpccnt[NFSPROC_READ]++; 926 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 927 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3); 928 nfsm_fhtom(vp, v3); 929 nfsm_build(tl, u_long *, NFSX_UNSIGNED * 3); 930 if (v3) { 931 txdr_hyper(&uiop->uio_offset, tl); 932 *(tl + 2) = txdr_unsigned(len); 933 } else { 934 *tl++ = txdr_unsigned(uiop->uio_offset); 935 *tl++ = txdr_unsigned(len); 936 *tl = 0; 937 } 938 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred); 939 if (v3) { 940 nfsm_postop_attr(vp, attrflag); 941 if (error) { 942 m_freem(mrep); 943 goto nfsmout; 944 } 945 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 946 eof = fxdr_unsigned(int, *(tl + 1)); 947 } else 948 nfsm_loadattr(vp, (struct vattr *)0); 949 nfsm_strsiz(retlen, nmp->nm_rsize); 950 nfsm_mtouio(uiop, retlen); 951 m_freem(mrep); 952 tsiz -= retlen; 953 if (v3) { 954 if (eof || retlen == 0) 955 tsiz = 0; 956 } else if (retlen < len) 957 tsiz = 0; 958 } 959 nfsmout: 960 return (error); 961 } 962 963 /* 964 * nfs write call 965 */ 966 int 967 nfs_writerpc(vp, uiop, cred, iomode, must_commit) 968 register struct vnode *vp; 969 register struct uio *uiop; 970 struct ucred *cred; 971 int *iomode, *must_commit; 972 { 973 register u_long *tl; 974 register caddr_t cp; 975 register int t1, t2, backup; 976 caddr_t bpos, dpos, cp2; 977 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 978 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 979 struct nfsnode *np = VTONFS(vp); 980 u_quad_t frev; 981 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit; 982 int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC; 983 984 #ifndef DIAGNOSTIC 985 if (uiop->uio_iovcnt != 1) 986 panic("nfs: writerpc iovcnt > 1"); 987 #endif 988 *must_commit = 0; 989 tsiz = uiop->uio_resid; 990 if (uiop->uio_offset + tsiz > 0xffffffff && !v3) 991 return (EFBIG); 992 while (tsiz > 0) { 993 nfsstats.rpccnt[NFSPROC_WRITE]++; 994 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 995 nfsm_reqhead(vp, NFSPROC_WRITE, 996 NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len)); 997 nfsm_fhtom(vp, v3); 998 if (v3) { 999 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 1000 txdr_hyper(&uiop->uio_offset, tl); 1001 tl += 2; 1002 *tl++ = txdr_unsigned(len); 1003 *tl++ = txdr_unsigned(*iomode); 1004 } else { 1005 nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED); 1006 *++tl = txdr_unsigned(uiop->uio_offset); 1007 tl += 2; 1008 } 1009 *tl = txdr_unsigned(len); 1010 nfsm_uiotom(uiop, len); 1011 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred); 1012 if (v3) { 1013 wccflag = NFSV3_WCCCHK; 1014 nfsm_wcc_data(vp, wccflag); 1015 if (!error) { 1016 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED + 1017 NFSX_V3WRITEVERF); 1018 rlen = fxdr_unsigned(int, *tl++); 1019 if (rlen == 0) { 1020 error = NFSERR_IO; 1021 break; 1022 } else if (rlen < len) { 1023 backup = len - rlen; 1024 uiop->uio_iov->iov_base -= backup; 1025 uiop->uio_iov->iov_len += backup; 1026 uiop->uio_offset -= backup; 1027 uiop->uio_resid += backup; 1028 len = rlen; 1029 } 1030 commit = fxdr_unsigned(int, *tl++); 1031 1032 /* 1033 * Return the lowest committment level 1034 * obtained by any of the RPCs. 1035 */ 1036 if (committed == NFSV3WRITE_FILESYNC) 1037 committed = commit; 1038 else if (committed == NFSV3WRITE_DATASYNC && 1039 commit == NFSV3WRITE_UNSTABLE) 1040 committed = commit; 1041 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) { 1042 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1043 NFSX_V3WRITEVERF); 1044 nmp->nm_flag |= NFSMNT_HASWRITEVERF; 1045 } else if (bcmp((caddr_t)tl, 1046 (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) { 1047 *must_commit = 1; 1048 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1049 NFSX_V3WRITEVERF); 1050 } 1051 } 1052 } else 1053 nfsm_loadattr(vp, (struct vattr *)0); 1054 if (wccflag) 1055 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.ts_sec; 1056 m_freem(mrep); 1057 tsiz -= len; 1058 } 1059 nfsmout: 1060 *iomode = committed; 1061 if (error) 1062 uiop->uio_resid = tsiz; 1063 return (error); 1064 } 1065 1066 /* 1067 * nfs mknod rpc 1068 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the 1069 * mode set to specify the file type and the size field for rdev. 1070 */ 1071 int 1072 nfs_mknodrpc(dvp, vpp, cnp, vap) 1073 register struct vnode *dvp; 1074 register struct vnode **vpp; 1075 register struct componentname *cnp; 1076 register struct vattr *vap; 1077 { 1078 register struct nfsv2_sattr *sp; 1079 register struct nfsv3_sattr *sp3; 1080 register u_long *tl; 1081 register caddr_t cp; 1082 register long t1, t2; 1083 struct vnode *newvp = (struct vnode *)0; 1084 struct nfsnode *np; 1085 struct vattr vattr; 1086 char *cp2; 1087 caddr_t bpos, dpos; 1088 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0; 1089 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1090 u_long rdev; 1091 int v3 = NFS_ISV3(dvp); 1092 1093 if (vap->va_type == VCHR || vap->va_type == VBLK) 1094 rdev = txdr_unsigned(vap->va_rdev); 1095 else if (vap->va_type == VFIFO || vap->va_type == VSOCK) 1096 rdev = 0xffffffff; 1097 else { 1098 VOP_ABORTOP(dvp, cnp); 1099 vput(dvp); 1100 return (EOPNOTSUPP); 1101 } 1102 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1103 VOP_ABORTOP(dvp, cnp); 1104 vput(dvp); 1105 return (error); 1106 } 1107 nfsstats.rpccnt[NFSPROC_MKNOD]++; 1108 nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED + 1109 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1110 nfsm_fhtom(dvp, v3); 1111 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1112 if (v3) { 1113 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3SRVSATTR); 1114 *tl++ = vtonfsv3_type(vap->va_type); 1115 sp3 = (struct nfsv3_sattr *)tl; 1116 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1117 if (vap->va_type == VCHR || vap->va_type == VBLK) { 1118 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 1119 *tl++ = txdr_unsigned(major(vap->va_rdev)); 1120 *tl = txdr_unsigned(minor(vap->va_rdev)); 1121 } 1122 } else { 1123 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1124 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1125 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1126 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1127 sp->sa_size = rdev; 1128 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1129 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1130 } 1131 nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred); 1132 if (!error) { 1133 nfsm_mtofh(dvp, newvp, v3, gotvp); 1134 if (!gotvp) { 1135 if (newvp) { 1136 vrele(newvp); 1137 newvp = (struct vnode *)0; 1138 } 1139 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1140 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1141 if (!error) 1142 newvp = NFSTOV(np); 1143 } 1144 } 1145 if (v3) 1146 nfsm_wcc_data(dvp, wccflag); 1147 nfsm_reqdone; 1148 if (error) { 1149 if (newvp) 1150 vrele(newvp); 1151 } else { 1152 if (cnp->cn_flags & MAKEENTRY) 1153 cache_enter(dvp, newvp, cnp); 1154 *vpp = newvp; 1155 } 1156 FREE(cnp->cn_pnbuf, M_NAMEI); 1157 VTONFS(dvp)->n_flag |= NMODIFIED; 1158 if (!wccflag) 1159 VTONFS(dvp)->n_attrstamp = 0; 1160 vrele(dvp); 1161 return (error); 1162 } 1163 1164 /* 1165 * nfs mknod vop 1166 * just call nfs_mknodrpc() to do the work. 1167 */ 1168 /* ARGSUSED */ 1169 int 1170 nfs_mknod(ap) 1171 struct vop_mknod_args /* { 1172 struct vnode *a_dvp; 1173 struct vnode **a_vpp; 1174 struct componentname *a_cnp; 1175 struct vattr *a_vap; 1176 } */ *ap; 1177 { 1178 struct vnode *newvp; 1179 int error; 1180 1181 error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap); 1182 if (!error) 1183 vrele(newvp); 1184 return (error); 1185 } 1186 1187 static u_long create_verf; 1188 /* 1189 * nfs file create call 1190 */ 1191 int 1192 nfs_create(ap) 1193 struct vop_create_args /* { 1194 struct vnode *a_dvp; 1195 struct vnode **a_vpp; 1196 struct componentname *a_cnp; 1197 struct vattr *a_vap; 1198 } */ *ap; 1199 { 1200 register struct vnode *dvp = ap->a_dvp; 1201 register struct vattr *vap = ap->a_vap; 1202 register struct componentname *cnp = ap->a_cnp; 1203 register struct nfsv2_sattr *sp; 1204 register struct nfsv3_sattr *sp3; 1205 register u_long *tl; 1206 register caddr_t cp; 1207 register long t1, t2; 1208 struct nfsnode *np = (struct nfsnode *)0; 1209 struct vnode *newvp = (struct vnode *)0; 1210 caddr_t bpos, dpos, cp2; 1211 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0; 1212 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1213 struct vattr vattr; 1214 int v3 = NFS_ISV3(dvp); 1215 1216 /* 1217 * Oops, not for me.. 1218 */ 1219 if (vap->va_type == VSOCK) 1220 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap)); 1221 1222 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1223 VOP_ABORTOP(dvp, cnp); 1224 vput(dvp); 1225 return (error); 1226 } 1227 if (vap->va_vaflags & VA_EXCLUSIVE) 1228 fmode |= O_EXCL; 1229 again: 1230 nfsstats.rpccnt[NFSPROC_CREATE]++; 1231 nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED + 1232 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1233 nfsm_fhtom(dvp, v3); 1234 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1235 if (v3) { 1236 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 1237 if (fmode & O_EXCL) { 1238 *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE); 1239 nfsm_build(tl, u_long *, NFSX_V3CREATEVERF); 1240 if (in_ifaddr) 1241 *tl++ = IA_SIN(in_ifaddr)->sin_addr.s_addr; 1242 else 1243 *tl++ = create_verf; 1244 *tl = ++create_verf; 1245 } else { 1246 *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED); 1247 nfsm_build(tl, u_long *, NFSX_V3SRVSATTR); 1248 sp3 = (struct nfsv3_sattr *)tl; 1249 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1250 } 1251 } else { 1252 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1253 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1254 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1255 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1256 sp->sa_size = 0; 1257 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1258 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1259 } 1260 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1261 if (!error) { 1262 nfsm_mtofh(dvp, newvp, v3, gotvp); 1263 if (!gotvp) { 1264 if (newvp) { 1265 vrele(newvp); 1266 newvp = (struct vnode *)0; 1267 } 1268 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1269 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1270 if (!error) 1271 newvp = NFSTOV(np); 1272 } 1273 } 1274 if (v3) 1275 nfsm_wcc_data(dvp, wccflag); 1276 nfsm_reqdone; 1277 if (error) { 1278 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) { 1279 fmode &= ~O_EXCL; 1280 goto again; 1281 } 1282 if (newvp) 1283 vrele(newvp); 1284 } else if (v3 && (fmode & O_EXCL)) 1285 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc); 1286 if (!error) { 1287 if (cnp->cn_flags & MAKEENTRY) 1288 cache_enter(dvp, newvp, cnp); 1289 *ap->a_vpp = newvp; 1290 } 1291 FREE(cnp->cn_pnbuf, M_NAMEI); 1292 VTONFS(dvp)->n_flag |= NMODIFIED; 1293 if (!wccflag) 1294 VTONFS(dvp)->n_attrstamp = 0; 1295 vrele(dvp); 1296 return (error); 1297 } 1298 1299 /* 1300 * nfs file remove call 1301 * To try and make nfs semantics closer to ufs semantics, a file that has 1302 * other processes using the vnode is renamed instead of removed and then 1303 * removed later on the last close. 1304 * - If v_usecount > 1 1305 * If a rename is not already in the works 1306 * call nfs_sillyrename() to set it up 1307 * else 1308 * do the remove rpc 1309 */ 1310 int 1311 nfs_remove(ap) 1312 struct vop_remove_args /* { 1313 struct vnodeop_desc *a_desc; 1314 struct vnode * a_dvp; 1315 struct vnode * a_vp; 1316 struct componentname * a_cnp; 1317 } */ *ap; 1318 { 1319 register struct vnode *vp = ap->a_vp; 1320 register struct vnode *dvp = ap->a_dvp; 1321 register struct componentname *cnp = ap->a_cnp; 1322 register struct nfsnode *np = VTONFS(vp); 1323 register u_long *tl; 1324 register caddr_t cp; 1325 register long t2; 1326 caddr_t bpos, dpos; 1327 int error = 0; 1328 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1329 struct vattr vattr; 1330 int v3 = NFS_ISV3(dvp); 1331 1332 #ifndef DIAGNOSTIC 1333 if ((cnp->cn_flags & HASBUF) == 0) 1334 panic("nfs_remove: no name"); 1335 if (vp->v_usecount < 1) 1336 panic("nfs_remove: bad v_usecount"); 1337 #endif 1338 if (vp->v_usecount == 1 || (np->n_sillyrename && 1339 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 && 1340 vattr.va_nlink > 1)) { 1341 /* 1342 * Purge the name cache so that the chance of a lookup for 1343 * the name succeeding while the remove is in progress is 1344 * minimized. Without node locking it can still happen, such 1345 * that an I/O op returns ESTALE, but since you get this if 1346 * another host removes the file.. 1347 */ 1348 cache_purge(vp); 1349 /* 1350 * throw away biocache buffers, mainly to avoid 1351 * unnecessary delayed writes later. 1352 */ 1353 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1); 1354 /* Do the rpc */ 1355 if (error != EINTR) 1356 error = nfs_removerpc(dvp, cnp->cn_nameptr, 1357 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc); 1358 /* 1359 * Kludge City: If the first reply to the remove rpc is lost.. 1360 * the reply to the retransmitted request will be ENOENT 1361 * since the file was in fact removed 1362 * Therefore, we cheat and return success. 1363 */ 1364 if (error == ENOENT) 1365 error = 0; 1366 } else if (!np->n_sillyrename) 1367 error = nfs_sillyrename(dvp, vp, cnp); 1368 FREE(cnp->cn_pnbuf, M_NAMEI); 1369 np->n_attrstamp = 0; 1370 vrele(dvp); 1371 vrele(vp); 1372 return (error); 1373 } 1374 1375 /* 1376 * nfs file remove rpc called from nfs_inactive 1377 */ 1378 int 1379 nfs_removeit(sp) 1380 register struct sillyrename *sp; 1381 { 1382 1383 return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred, 1384 (struct proc *)0)); 1385 } 1386 1387 /* 1388 * Nfs remove rpc, called from nfs_remove() and nfs_removeit(). 1389 */ 1390 int 1391 nfs_removerpc(dvp, name, namelen, cred, proc) 1392 register struct vnode *dvp; 1393 char *name; 1394 int namelen; 1395 struct ucred *cred; 1396 struct proc *proc; 1397 { 1398 register u_long *tl; 1399 register caddr_t cp; 1400 register long t1, t2; 1401 caddr_t bpos, dpos, cp2; 1402 int error = 0, wccflag = NFSV3_WCCRATTR; 1403 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1404 int v3 = NFS_ISV3(dvp); 1405 1406 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1407 nfsm_reqhead(dvp, NFSPROC_REMOVE, 1408 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen)); 1409 nfsm_fhtom(dvp, v3); 1410 nfsm_strtom(name, namelen, NFS_MAXNAMLEN); 1411 nfsm_request(dvp, NFSPROC_REMOVE, proc, cred); 1412 if (v3) 1413 nfsm_wcc_data(dvp, wccflag); 1414 nfsm_reqdone; 1415 VTONFS(dvp)->n_flag |= NMODIFIED; 1416 if (!wccflag) 1417 VTONFS(dvp)->n_attrstamp = 0; 1418 return (error); 1419 } 1420 1421 /* 1422 * nfs file rename call 1423 */ 1424 int 1425 nfs_rename(ap) 1426 struct vop_rename_args /* { 1427 struct vnode *a_fdvp; 1428 struct vnode *a_fvp; 1429 struct componentname *a_fcnp; 1430 struct vnode *a_tdvp; 1431 struct vnode *a_tvp; 1432 struct componentname *a_tcnp; 1433 } */ *ap; 1434 { 1435 register struct vnode *fvp = ap->a_fvp; 1436 register struct vnode *tvp = ap->a_tvp; 1437 register struct vnode *fdvp = ap->a_fdvp; 1438 register struct vnode *tdvp = ap->a_tdvp; 1439 register struct componentname *tcnp = ap->a_tcnp; 1440 register struct componentname *fcnp = ap->a_fcnp; 1441 int error; 1442 1443 #ifndef DIAGNOSTIC 1444 if ((tcnp->cn_flags & HASBUF) == 0 || 1445 (fcnp->cn_flags & HASBUF) == 0) 1446 panic("nfs_rename: no name"); 1447 #endif 1448 /* Check for cross-device rename */ 1449 if ((fvp->v_mount != tdvp->v_mount) || 1450 (tvp && (fvp->v_mount != tvp->v_mount))) { 1451 error = EXDEV; 1452 goto out; 1453 } 1454 1455 /* 1456 * If the tvp exists and is in use, sillyrename it before doing the 1457 * rename of the new file over it. 1458 */ 1459 if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename && 1460 !nfs_sillyrename(tdvp, tvp, tcnp)) { 1461 vrele(tvp); 1462 tvp = NULL; 1463 } 1464 1465 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen, 1466 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred, 1467 tcnp->cn_proc); 1468 1469 if (fvp->v_type == VDIR) { 1470 if (tvp != NULL && tvp->v_type == VDIR) 1471 cache_purge(tdvp); 1472 cache_purge(fdvp); 1473 } 1474 out: 1475 if (tdvp == tvp) 1476 vrele(tdvp); 1477 else 1478 vput(tdvp); 1479 if (tvp) 1480 vput(tvp); 1481 vrele(fdvp); 1482 vrele(fvp); 1483 /* 1484 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1485 */ 1486 if (error == ENOENT) 1487 error = 0; 1488 return (error); 1489 } 1490 1491 /* 1492 * nfs file rename rpc called from nfs_remove() above 1493 */ 1494 int 1495 nfs_renameit(sdvp, scnp, sp) 1496 struct vnode *sdvp; 1497 struct componentname *scnp; 1498 register struct sillyrename *sp; 1499 { 1500 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, 1501 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc)); 1502 } 1503 1504 /* 1505 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit(). 1506 */ 1507 int 1508 nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc) 1509 register struct vnode *fdvp; 1510 char *fnameptr; 1511 int fnamelen; 1512 register struct vnode *tdvp; 1513 char *tnameptr; 1514 int tnamelen; 1515 struct ucred *cred; 1516 struct proc *proc; 1517 { 1518 register u_long *tl; 1519 register caddr_t cp; 1520 register long t1, t2; 1521 caddr_t bpos, dpos, cp2; 1522 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR; 1523 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1524 int v3 = NFS_ISV3(fdvp); 1525 1526 nfsstats.rpccnt[NFSPROC_RENAME]++; 1527 nfsm_reqhead(fdvp, NFSPROC_RENAME, 1528 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) + 1529 nfsm_rndup(tnamelen)); 1530 nfsm_fhtom(fdvp, v3); 1531 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN); 1532 nfsm_fhtom(tdvp, v3); 1533 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN); 1534 nfsm_request(fdvp, NFSPROC_RENAME, proc, cred); 1535 if (v3) { 1536 nfsm_wcc_data(fdvp, fwccflag); 1537 nfsm_wcc_data(tdvp, twccflag); 1538 } 1539 nfsm_reqdone; 1540 VTONFS(fdvp)->n_flag |= NMODIFIED; 1541 VTONFS(tdvp)->n_flag |= NMODIFIED; 1542 if (!fwccflag) 1543 VTONFS(fdvp)->n_attrstamp = 0; 1544 if (!twccflag) 1545 VTONFS(tdvp)->n_attrstamp = 0; 1546 return (error); 1547 } 1548 1549 /* 1550 * nfs hard link create call 1551 */ 1552 int 1553 nfs_link(ap) 1554 struct vop_link_args /* { 1555 struct vnode *a_vp; 1556 struct vnode *a_tdvp; 1557 struct componentname *a_cnp; 1558 } */ *ap; 1559 { 1560 register struct vnode *vp = ap->a_vp; 1561 register struct vnode *tdvp = ap->a_tdvp; 1562 register struct componentname *cnp = ap->a_cnp; 1563 register u_long *tl; 1564 register caddr_t cp; 1565 register long t1, t2; 1566 caddr_t bpos, dpos, cp2; 1567 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0; 1568 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1569 int v3 = NFS_ISV3(vp); 1570 1571 if (vp->v_mount != tdvp->v_mount) { 1572 /*VOP_ABORTOP(vp, cnp);*/ 1573 if (tdvp == vp) 1574 vrele(tdvp); 1575 else 1576 vput(tdvp); 1577 return (EXDEV); 1578 } 1579 1580 /* 1581 * Push all writes to the server, so that the attribute cache 1582 * doesn't get "out of sync" with the server. 1583 * XXX There should be a better way! 1584 */ 1585 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc); 1586 1587 nfsstats.rpccnt[NFSPROC_LINK]++; 1588 nfsm_reqhead(vp, NFSPROC_LINK, 1589 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1590 nfsm_fhtom(vp, v3); 1591 nfsm_fhtom(tdvp, v3); 1592 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1593 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); 1594 if (v3) { 1595 nfsm_postop_attr(vp, attrflag); 1596 nfsm_wcc_data(tdvp, wccflag); 1597 } 1598 nfsm_reqdone; 1599 FREE(cnp->cn_pnbuf, M_NAMEI); 1600 VTONFS(tdvp)->n_flag |= NMODIFIED; 1601 if (!attrflag) 1602 VTONFS(vp)->n_attrstamp = 0; 1603 if (!wccflag) 1604 VTONFS(tdvp)->n_attrstamp = 0; 1605 vrele(tdvp); 1606 /* 1607 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1608 */ 1609 if (error == EEXIST) 1610 error = 0; 1611 return (error); 1612 } 1613 1614 /* 1615 * nfs symbolic link create call 1616 */ 1617 int 1618 nfs_symlink(ap) 1619 struct vop_symlink_args /* { 1620 struct vnode *a_dvp; 1621 struct vnode **a_vpp; 1622 struct componentname *a_cnp; 1623 struct vattr *a_vap; 1624 char *a_target; 1625 } */ *ap; 1626 { 1627 register struct vnode *dvp = ap->a_dvp; 1628 register struct vattr *vap = ap->a_vap; 1629 register struct componentname *cnp = ap->a_cnp; 1630 register struct nfsv2_sattr *sp; 1631 register struct nfsv3_sattr *sp3; 1632 register u_long *tl; 1633 register caddr_t cp; 1634 register long t1, t2; 1635 caddr_t bpos, dpos, cp2; 1636 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp; 1637 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1638 struct vnode *newvp = (struct vnode *)0; 1639 int v3 = NFS_ISV3(dvp); 1640 1641 nfsstats.rpccnt[NFSPROC_SYMLINK]++; 1642 slen = strlen(ap->a_target); 1643 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED + 1644 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3)); 1645 nfsm_fhtom(dvp, v3); 1646 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1647 if (v3) { 1648 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1649 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, 1650 cnp->cn_cred->cr_gid); 1651 } 1652 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN); 1653 if (!v3) { 1654 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1655 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode); 1656 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1657 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 1658 sp->sa_size = -1; 1659 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1660 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1661 } 1662 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred); 1663 if (v3) { 1664 if (!error) 1665 nfsm_mtofh(dvp, newvp, v3, gotvp); 1666 nfsm_wcc_data(dvp, wccflag); 1667 } 1668 nfsm_reqdone; 1669 if (newvp) 1670 vrele(newvp); 1671 FREE(cnp->cn_pnbuf, M_NAMEI); 1672 VTONFS(dvp)->n_flag |= NMODIFIED; 1673 if (!wccflag) 1674 VTONFS(dvp)->n_attrstamp = 0; 1675 vrele(dvp); 1676 /* 1677 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1678 */ 1679 if (error == EEXIST) 1680 error = 0; 1681 return (error); 1682 } 1683 1684 /* 1685 * nfs make dir call 1686 */ 1687 int 1688 nfs_mkdir(ap) 1689 struct vop_mkdir_args /* { 1690 struct vnode *a_dvp; 1691 struct vnode **a_vpp; 1692 struct componentname *a_cnp; 1693 struct vattr *a_vap; 1694 } */ *ap; 1695 { 1696 register struct vnode *dvp = ap->a_dvp; 1697 register struct vattr *vap = ap->a_vap; 1698 register struct componentname *cnp = ap->a_cnp; 1699 register struct nfsv2_sattr *sp; 1700 register struct nfsv3_sattr *sp3; 1701 register u_long *tl; 1702 register caddr_t cp; 1703 register long t1, t2; 1704 register int len; 1705 struct nfsnode *np = (struct nfsnode *)0; 1706 struct vnode *newvp = (struct vnode *)0; 1707 caddr_t bpos, dpos, cp2; 1708 nfsfh_t *fhp; 1709 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag; 1710 int fhsize, gotvp = 0; 1711 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1712 struct vattr vattr; 1713 int v3 = NFS_ISV3(dvp); 1714 1715 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1716 VOP_ABORTOP(dvp, cnp); 1717 vput(dvp); 1718 return (error); 1719 } 1720 len = cnp->cn_namelen; 1721 nfsstats.rpccnt[NFSPROC_MKDIR]++; 1722 nfsm_reqhead(dvp, NFSPROC_MKDIR, 1723 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3)); 1724 nfsm_fhtom(dvp, v3); 1725 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1726 if (v3) { 1727 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1728 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1729 } else { 1730 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1731 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode); 1732 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1733 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1734 sp->sa_size = -1; 1735 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1736 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1737 } 1738 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred); 1739 if (!error) 1740 nfsm_mtofh(dvp, newvp, v3, gotvp); 1741 if (v3) 1742 nfsm_wcc_data(dvp, wccflag); 1743 nfsm_reqdone; 1744 VTONFS(dvp)->n_flag |= NMODIFIED; 1745 if (!wccflag) 1746 VTONFS(dvp)->n_attrstamp = 0; 1747 /* 1748 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 1749 * if we can succeed in looking up the directory. 1750 */ 1751 if (error == EEXIST || (!error && !gotvp)) { 1752 if (newvp) { 1753 vrele(newvp); 1754 newvp = (struct vnode *)0; 1755 } 1756 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred, 1757 cnp->cn_proc, &np); 1758 if (!error) { 1759 newvp = NFSTOV(np); 1760 if (newvp->v_type != VDIR) 1761 error = EEXIST; 1762 } 1763 } 1764 if (error) { 1765 if (newvp) 1766 vrele(newvp); 1767 } else 1768 *ap->a_vpp = newvp; 1769 FREE(cnp->cn_pnbuf, M_NAMEI); 1770 vrele(dvp); 1771 return (error); 1772 } 1773 1774 /* 1775 * nfs remove directory call 1776 */ 1777 int 1778 nfs_rmdir(ap) 1779 struct vop_rmdir_args /* { 1780 struct vnode *a_dvp; 1781 struct vnode *a_vp; 1782 struct componentname *a_cnp; 1783 } */ *ap; 1784 { 1785 register struct vnode *vp = ap->a_vp; 1786 register struct vnode *dvp = ap->a_dvp; 1787 register struct componentname *cnp = ap->a_cnp; 1788 register u_long *tl; 1789 register caddr_t cp; 1790 register long t1, t2; 1791 caddr_t bpos, dpos, cp2; 1792 int error = 0, wccflag = NFSV3_WCCRATTR; 1793 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1794 int v3 = NFS_ISV3(dvp); 1795 1796 if (dvp == vp) { 1797 vrele(dvp); 1798 vrele(dvp); 1799 FREE(cnp->cn_pnbuf, M_NAMEI); 1800 return (EINVAL); 1801 } 1802 nfsstats.rpccnt[NFSPROC_RMDIR]++; 1803 nfsm_reqhead(dvp, NFSPROC_RMDIR, 1804 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1805 nfsm_fhtom(dvp, v3); 1806 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1807 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred); 1808 if (v3) 1809 nfsm_wcc_data(dvp, wccflag); 1810 nfsm_reqdone; 1811 FREE(cnp->cn_pnbuf, M_NAMEI); 1812 VTONFS(dvp)->n_flag |= NMODIFIED; 1813 if (!wccflag) 1814 VTONFS(dvp)->n_attrstamp = 0; 1815 cache_purge(dvp); 1816 cache_purge(vp); 1817 vrele(vp); 1818 vrele(dvp); 1819 /* 1820 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 1821 */ 1822 if (error == ENOENT) 1823 error = 0; 1824 return (error); 1825 } 1826 1827 /* 1828 * nfs readdir call 1829 */ 1830 int 1831 nfs_readdir(ap) 1832 struct vop_readdir_args /* { 1833 struct vnode *a_vp; 1834 struct uio *a_uio; 1835 struct ucred *a_cred; 1836 } */ *ap; 1837 { 1838 register struct vnode *vp = ap->a_vp; 1839 register struct nfsnode *np = VTONFS(vp); 1840 register struct uio *uio = ap->a_uio; 1841 int tresid, error; 1842 struct vattr vattr; 1843 1844 if (vp->v_type != VDIR) 1845 return (EPERM); 1846 /* 1847 * First, check for hit on the EOF offset cache 1848 */ 1849 if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset && 1850 (np->n_flag & NMODIFIED) == 0) { 1851 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { 1852 if (NQNFS_CKCACHABLE(vp, ND_READ)) { 1853 nfsstats.direofcache_hits++; 1854 return (0); 1855 } 1856 } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 && 1857 np->n_mtime == vattr.va_mtime.ts_sec) { 1858 nfsstats.direofcache_hits++; 1859 return (0); 1860 } 1861 } 1862 1863 /* 1864 * Call nfs_bioread() to do the real work. 1865 */ 1866 tresid = uio->uio_resid; 1867 error = nfs_bioread(vp, uio, 0, ap->a_cred); 1868 1869 if (!error && uio->uio_resid == tresid) 1870 nfsstats.direofcache_misses++; 1871 return (error); 1872 } 1873 1874 /* 1875 * Readdir rpc call. 1876 * Called from below the buffer cache by nfs_doio(). 1877 */ 1878 int 1879 nfs_readdirrpc(vp, uiop, cred) 1880 struct vnode *vp; 1881 register struct uio *uiop; 1882 struct ucred *cred; 1883 { 1884 register int len, left; 1885 register struct dirent *dp; 1886 register u_long *tl; 1887 register caddr_t cp; 1888 register long t1, t2; 1889 register nfsuint64 *cookiep; 1890 caddr_t bpos, dpos, cp2; 1891 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1892 nfsuint64 cookie; 1893 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1894 struct nfsnode *dnp = VTONFS(vp); 1895 nfsfh_t *fhp; 1896 u_quad_t frev, fileno; 1897 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1, i; 1898 int cachable, attrflag, fhsize; 1899 int v3 = NFS_ISV3(vp); 1900 1901 #ifndef nolint 1902 dp = (struct dirent *)0; 1903 #endif 1904 #ifndef DIAGNOSTIC 1905 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (NFS_DIRBLKSIZ - 1)) || 1906 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1))) 1907 panic("nfs readdirrpc bad uio"); 1908 #endif 1909 1910 /* 1911 * If there is no cookie, assume end of directory. 1912 */ 1913 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 1914 if (cookiep) 1915 cookie = *cookiep; 1916 else 1917 return (0); 1918 /* 1919 * Loop around doing readdir rpc's of size nm_readdirsize 1920 * truncated to a multiple of DIRBLKSIZ. 1921 * The stopping criteria is EOF or buffer full. 1922 */ 1923 while (more_dirs && bigenough) { 1924 nfsstats.rpccnt[NFSPROC_READDIR]++; 1925 nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) + 1926 NFSX_READDIR(v3)); 1927 nfsm_fhtom(vp, v3); 1928 if (v3) { 1929 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 1930 *tl++ = cookie.nfsuquad[0]; 1931 *tl++ = cookie.nfsuquad[1]; 1932 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 1933 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 1934 } else { 1935 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 1936 *tl++ = cookie.nfsuquad[0]; 1937 } 1938 *tl = txdr_unsigned(nmp->nm_readdirsize); 1939 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred); 1940 if (v3) { 1941 nfsm_postop_attr(vp, attrflag); 1942 if (!error) { 1943 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1944 dnp->n_cookieverf.nfsuquad[0] = *tl++; 1945 dnp->n_cookieverf.nfsuquad[1] = *tl; 1946 } else { 1947 m_freem(mrep); 1948 goto nfsmout; 1949 } 1950 } 1951 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1952 more_dirs = fxdr_unsigned(int, *tl); 1953 1954 /* loop thru the dir entries, doctoring them to 4bsd form */ 1955 while (more_dirs && bigenough) { 1956 if (v3) { 1957 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 1958 fxdr_hyper(tl, &fileno); 1959 len = fxdr_unsigned(int, *(tl + 2)); 1960 } else { 1961 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1962 fileno = fxdr_unsigned(u_quad_t, *tl++); 1963 len = fxdr_unsigned(int, *tl); 1964 } 1965 if (len <= 0 || len > NFS_MAXNAMLEN) { 1966 error = EBADRPC; 1967 m_freem(mrep); 1968 goto nfsmout; 1969 } 1970 tlen = nfsm_rndup(len); 1971 if (tlen == len) 1972 tlen += 4; /* To ensure null termination */ 1973 left = DIRBLKSIZ - blksiz; 1974 if ((tlen + DIRHDSIZ) > left) { 1975 dp->d_reclen += left; 1976 uiop->uio_iov->iov_base += left; 1977 uiop->uio_iov->iov_len -= left; 1978 uiop->uio_offset += left; 1979 uiop->uio_resid -= left; 1980 blksiz = 0; 1981 } 1982 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 1983 bigenough = 0; 1984 if (bigenough) { 1985 dp = (struct dirent *)uiop->uio_iov->iov_base; 1986 dp->d_fileno = (int)fileno; 1987 dp->d_namlen = len; 1988 dp->d_reclen = tlen + DIRHDSIZ; 1989 dp->d_type = DT_UNKNOWN; 1990 blksiz += dp->d_reclen; 1991 if (blksiz == DIRBLKSIZ) 1992 blksiz = 0; 1993 uiop->uio_offset += DIRHDSIZ; 1994 uiop->uio_resid -= DIRHDSIZ; 1995 uiop->uio_iov->iov_base += DIRHDSIZ; 1996 uiop->uio_iov->iov_len -= DIRHDSIZ; 1997 nfsm_mtouio(uiop, len); 1998 cp = uiop->uio_iov->iov_base; 1999 tlen -= len; 2000 *cp = '\0'; /* null terminate */ 2001 uiop->uio_iov->iov_base += tlen; 2002 uiop->uio_iov->iov_len -= tlen; 2003 uiop->uio_offset += tlen; 2004 uiop->uio_resid -= tlen; 2005 } else 2006 nfsm_adv(nfsm_rndup(len)); 2007 if (v3) { 2008 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2009 } else { 2010 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2011 } 2012 if (bigenough) { 2013 cookie.nfsuquad[0] = *tl++; 2014 if (v3) 2015 cookie.nfsuquad[1] = *tl++; 2016 } else if (v3) 2017 tl += 2; 2018 else 2019 tl++; 2020 more_dirs = fxdr_unsigned(int, *tl); 2021 } 2022 /* 2023 * If at end of rpc data, get the eof boolean 2024 */ 2025 if (!more_dirs) { 2026 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2027 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2028 } 2029 m_freem(mrep); 2030 } 2031 /* 2032 * Fill last record, iff any, out to a multiple of DIRBLKSIZ 2033 * by increasing d_reclen for the last record. 2034 */ 2035 if (blksiz > 0) { 2036 left = DIRBLKSIZ - blksiz; 2037 dp->d_reclen += left; 2038 uiop->uio_iov->iov_base += left; 2039 uiop->uio_iov->iov_len -= left; 2040 uiop->uio_offset += left; 2041 uiop->uio_resid -= left; 2042 } 2043 2044 /* 2045 * We are now either at the end of the directory or have filled the 2046 * block. 2047 */ 2048 if (bigenough) 2049 dnp->n_direofoffset = uiop->uio_offset; 2050 else { 2051 if (uiop->uio_resid > 0) 2052 printf("EEK! readdirrpc resid > 0\n"); 2053 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2054 *cookiep = cookie; 2055 } 2056 nfsmout: 2057 return (error); 2058 } 2059 2060 /* 2061 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc(). 2062 */ 2063 int 2064 nfs_readdirplusrpc(vp, uiop, cred) 2065 struct vnode *vp; 2066 register struct uio *uiop; 2067 struct ucred *cred; 2068 { 2069 register int len, left; 2070 register struct dirent *dp; 2071 register u_long *tl; 2072 register caddr_t cp; 2073 register long t1, t2; 2074 register struct vnode *newvp; 2075 register nfsuint64 *cookiep; 2076 caddr_t bpos, dpos, cp2, dpossav1, dpossav2; 2077 struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2; 2078 struct nameidata nami, *ndp = &nami; 2079 struct componentname *cnp = &ndp->ni_cnd; 2080 nfsuint64 cookie; 2081 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2082 struct nfsnode *dnp = VTONFS(vp), *np; 2083 nfsfh_t *fhp; 2084 u_quad_t frev, fileno; 2085 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i; 2086 int cachable, attrflag, fhsize; 2087 2088 #ifndef nolint 2089 dp = (struct dirent *)0; 2090 #endif 2091 #ifndef DIAGNOSTIC 2092 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) || 2093 (uiop->uio_resid & (DIRBLKSIZ - 1))) 2094 panic("nfs readdirplusrpc bad uio"); 2095 #endif 2096 ndp->ni_dvp = vp; 2097 newvp = NULLVP; 2098 2099 /* 2100 * If there is no cookie, assume end of directory. 2101 */ 2102 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 2103 if (cookiep) 2104 cookie = *cookiep; 2105 else 2106 return (0); 2107 /* 2108 * Loop around doing readdir rpc's of size nm_readdirsize 2109 * truncated to a multiple of DIRBLKSIZ. 2110 * The stopping criteria is EOF or buffer full. 2111 */ 2112 while (more_dirs && bigenough) { 2113 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++; 2114 nfsm_reqhead(vp, NFSPROC_READDIRPLUS, 2115 NFSX_FH(1) + 6 * NFSX_UNSIGNED); 2116 nfsm_fhtom(vp, 1); 2117 nfsm_build(tl, u_long *, 6 * NFSX_UNSIGNED); 2118 *tl++ = cookie.nfsuquad[0]; 2119 *tl++ = cookie.nfsuquad[1]; 2120 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2121 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2122 *tl++ = txdr_unsigned(nmp->nm_readdirsize); 2123 *tl = txdr_unsigned(nmp->nm_rsize); 2124 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred); 2125 nfsm_postop_attr(vp, attrflag); 2126 if (error) { 2127 m_freem(mrep); 2128 goto nfsmout; 2129 } 2130 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2131 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2132 dnp->n_cookieverf.nfsuquad[1] = *tl++; 2133 more_dirs = fxdr_unsigned(int, *tl); 2134 2135 /* loop thru the dir entries, doctoring them to 4bsd form */ 2136 while (more_dirs && bigenough) { 2137 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2138 fxdr_hyper(tl, &fileno); 2139 len = fxdr_unsigned(int, *(tl + 2)); 2140 if (len <= 0 || len > NFS_MAXNAMLEN) { 2141 error = EBADRPC; 2142 m_freem(mrep); 2143 goto nfsmout; 2144 } 2145 tlen = nfsm_rndup(len); 2146 if (tlen == len) 2147 tlen += 4; /* To ensure null termination*/ 2148 left = DIRBLKSIZ - blksiz; 2149 if ((tlen + DIRHDSIZ) > left) { 2150 dp->d_reclen += left; 2151 uiop->uio_iov->iov_base += left; 2152 uiop->uio_iov->iov_len -= left; 2153 uiop->uio_offset += left; 2154 uiop->uio_resid -= left; 2155 blksiz = 0; 2156 } 2157 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 2158 bigenough = 0; 2159 if (bigenough) { 2160 dp = (struct dirent *)uiop->uio_iov->iov_base; 2161 dp->d_fileno = (int)fileno; 2162 dp->d_namlen = len; 2163 dp->d_reclen = tlen + DIRHDSIZ; 2164 dp->d_type = DT_UNKNOWN; 2165 blksiz += dp->d_reclen; 2166 if (blksiz == DIRBLKSIZ) 2167 blksiz = 0; 2168 uiop->uio_offset += DIRHDSIZ; 2169 uiop->uio_resid -= DIRHDSIZ; 2170 uiop->uio_iov->iov_base += DIRHDSIZ; 2171 uiop->uio_iov->iov_len -= DIRHDSIZ; 2172 cnp->cn_nameptr = uiop->uio_iov->iov_base; 2173 cnp->cn_namelen = len; 2174 nfsm_mtouio(uiop, len); 2175 cp = uiop->uio_iov->iov_base; 2176 tlen -= len; 2177 *cp = '\0'; 2178 uiop->uio_iov->iov_base += tlen; 2179 uiop->uio_iov->iov_len -= tlen; 2180 uiop->uio_offset += tlen; 2181 uiop->uio_resid -= tlen; 2182 } else 2183 nfsm_adv(nfsm_rndup(len)); 2184 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2185 if (bigenough) { 2186 cookie.nfsuquad[0] = *tl++; 2187 cookie.nfsuquad[1] = *tl++; 2188 } else 2189 tl += 2; 2190 2191 /* 2192 * Since the attributes are before the file handle 2193 * (sigh), we must skip over the attributes and then 2194 * come back and get them. 2195 */ 2196 attrflag = fxdr_unsigned(int, *tl); 2197 if (attrflag) { 2198 dpossav1 = dpos; 2199 mdsav1 = md; 2200 nfsm_adv(NFSX_V3FATTR); 2201 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2202 doit = fxdr_unsigned(int, *tl); 2203 if (doit) { 2204 nfsm_getfh(fhp, fhsize, 1); 2205 if (NFS_CMPFH(dnp, fhp, fhsize)) { 2206 VREF(vp); 2207 newvp = vp; 2208 np = dnp; 2209 } else { 2210 if (error = nfs_nget(vp->v_mount, fhp, 2211 fhsize, &np)) 2212 doit = 0; 2213 else 2214 newvp = NFSTOV(np); 2215 } 2216 } 2217 if (doit) { 2218 dpossav2 = dpos; 2219 dpos = dpossav1; 2220 mdsav2 = md; 2221 md = mdsav1; 2222 nfsm_loadattr(newvp, (struct vattr *)0); 2223 dpos = dpossav2; 2224 md = mdsav2; 2225 dp->d_type = 2226 IFTODT(VTTOIF(np->n_vattr.va_type)); 2227 ndp->ni_vp = newvp; 2228 cnp->cn_hash = 0; 2229 for (cp = cnp->cn_nameptr, i = 1; i <= len; 2230 i++, cp++) 2231 cnp->cn_hash += (unsigned char)*cp * i; 2232 if (cnp->cn_namelen <= NCHNAMLEN) 2233 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp); 2234 } 2235 } else { 2236 /* Just skip over the file handle */ 2237 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2238 i = fxdr_unsigned(int, *tl); 2239 nfsm_adv(nfsm_rndup(i)); 2240 } 2241 if (newvp != NULLVP) { 2242 vrele(newvp); 2243 newvp = NULLVP; 2244 } 2245 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2246 more_dirs = fxdr_unsigned(int, *tl); 2247 } 2248 /* 2249 * If at end of rpc data, get the eof boolean 2250 */ 2251 if (!more_dirs) { 2252 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2253 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2254 } 2255 m_freem(mrep); 2256 } 2257 /* 2258 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 2259 * by increasing d_reclen for the last record. 2260 */ 2261 if (blksiz > 0) { 2262 left = DIRBLKSIZ - blksiz; 2263 dp->d_reclen += left; 2264 uiop->uio_iov->iov_base += left; 2265 uiop->uio_iov->iov_len -= left; 2266 uiop->uio_offset += left; 2267 uiop->uio_resid -= left; 2268 } 2269 2270 /* 2271 * We are now either at the end of the directory or have filled the 2272 * block. 2273 */ 2274 if (bigenough) 2275 dnp->n_direofoffset = uiop->uio_offset; 2276 else { 2277 if (uiop->uio_resid > 0) 2278 printf("EEK! readdirplusrpc resid > 0\n"); 2279 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2280 *cookiep = cookie; 2281 } 2282 nfsmout: 2283 if (newvp != NULLVP) 2284 vrele(newvp); 2285 return (error); 2286 } 2287 static char hextoasc[] = "0123456789abcdef"; 2288 2289 /* 2290 * Silly rename. To make the NFS filesystem that is stateless look a little 2291 * more like the "ufs" a remove of an active vnode is translated to a rename 2292 * to a funny looking filename that is removed by nfs_inactive on the 2293 * nfsnode. There is the potential for another process on a different client 2294 * to create the same funny name between the nfs_lookitup() fails and the 2295 * nfs_rename() completes, but... 2296 */ 2297 int 2298 nfs_sillyrename(dvp, vp, cnp) 2299 struct vnode *dvp, *vp; 2300 struct componentname *cnp; 2301 { 2302 register struct sillyrename *sp; 2303 struct nfsnode *np; 2304 int error; 2305 short pid; 2306 2307 cache_purge(dvp); 2308 np = VTONFS(vp); 2309 #ifndef DIAGNOSTIC 2310 if (vp->v_type == VDIR) 2311 panic("nfs: sillyrename dir"); 2312 #endif 2313 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 2314 M_NFSREQ, M_WAITOK); 2315 sp->s_cred = crdup(cnp->cn_cred); 2316 sp->s_dvp = dvp; 2317 VREF(dvp); 2318 2319 /* Fudge together a funny name */ 2320 pid = cnp->cn_proc->p_pid; 2321 bcopy(".nfsAxxxx4.4", sp->s_name, 13); 2322 sp->s_namlen = 12; 2323 sp->s_name[8] = hextoasc[pid & 0xf]; 2324 sp->s_name[7] = hextoasc[(pid >> 4) & 0xf]; 2325 sp->s_name[6] = hextoasc[(pid >> 8) & 0xf]; 2326 sp->s_name[5] = hextoasc[(pid >> 12) & 0xf]; 2327 2328 /* Try lookitups until we get one that isn't there */ 2329 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2330 cnp->cn_proc, (struct nfsnode **)0) == 0) { 2331 sp->s_name[4]++; 2332 if (sp->s_name[4] > 'z') { 2333 error = EINVAL; 2334 goto bad; 2335 } 2336 } 2337 if (error = nfs_renameit(dvp, cnp, sp)) 2338 goto bad; 2339 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2340 cnp->cn_proc, &np); 2341 np->n_sillyrename = sp; 2342 return (0); 2343 bad: 2344 vrele(sp->s_dvp); 2345 crfree(sp->s_cred); 2346 free((caddr_t)sp, M_NFSREQ); 2347 return (error); 2348 } 2349 2350 /* 2351 * Look up a file name and optionally either update the file handle or 2352 * allocate an nfsnode, depending on the value of npp. 2353 * npp == NULL --> just do the lookup 2354 * *npp == NULL --> allocate a new nfsnode and make sure attributes are 2355 * handled too 2356 * *npp != NULL --> update the file handle in the vnode 2357 */ 2358 int 2359 nfs_lookitup(dvp, name, len, cred, procp, npp) 2360 register struct vnode *dvp; 2361 char *name; 2362 int len; 2363 struct ucred *cred; 2364 struct proc *procp; 2365 struct nfsnode **npp; 2366 { 2367 register u_long *tl; 2368 register caddr_t cp; 2369 register long t1, t2; 2370 struct vnode *newvp = (struct vnode *)0; 2371 struct nfsnode *np, *dnp = VTONFS(dvp); 2372 caddr_t bpos, dpos, cp2; 2373 int error = 0, fhlen, attrflag; 2374 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2375 nfsfh_t *nfhp; 2376 int v3 = NFS_ISV3(dvp); 2377 2378 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 2379 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 2380 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 2381 nfsm_fhtom(dvp, v3); 2382 nfsm_strtom(name, len, NFS_MAXNAMLEN); 2383 nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred); 2384 if (npp && !error) { 2385 nfsm_getfh(nfhp, fhlen, v3); 2386 if (*npp) { 2387 np = *npp; 2388 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) { 2389 free((caddr_t)np->n_fhp, M_NFSBIGFH); 2390 np->n_fhp = &np->n_fh; 2391 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH) 2392 np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK); 2393 bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen); 2394 np->n_fhsize = fhlen; 2395 newvp = NFSTOV(np); 2396 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) { 2397 VREF(dvp); 2398 newvp = dvp; 2399 } else { 2400 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np); 2401 if (error) { 2402 m_freem(mrep); 2403 return (error); 2404 } 2405 newvp = NFSTOV(np); 2406 } 2407 if (v3) { 2408 nfsm_postop_attr(newvp, attrflag); 2409 if (!attrflag && *npp == NULL) { 2410 m_freem(mrep); 2411 vrele(newvp); 2412 return (ENOENT); 2413 } 2414 } else 2415 nfsm_loadattr(newvp, (struct vattr *)0); 2416 } 2417 nfsm_reqdone; 2418 if (npp && *npp == NULL) { 2419 if (error) { 2420 if (newvp) 2421 vrele(newvp); 2422 } else 2423 *npp = np; 2424 } 2425 return (error); 2426 } 2427 2428 /* 2429 * Nfs Version 3 commit rpc 2430 */ 2431 int 2432 nfs_commit(vp, offset, cnt, cred, procp) 2433 register struct vnode *vp; 2434 u_quad_t offset; 2435 int cnt; 2436 struct ucred *cred; 2437 struct proc *procp; 2438 { 2439 register caddr_t cp; 2440 register u_long *tl; 2441 register int t1, t2; 2442 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2443 caddr_t bpos, dpos, cp2; 2444 int error = 0, wccflag = NFSV3_WCCRATTR; 2445 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2446 2447 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) 2448 return (0); 2449 nfsstats.rpccnt[NFSPROC_COMMIT]++; 2450 nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1)); 2451 nfsm_fhtom(vp, 1); 2452 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 2453 txdr_hyper(&offset, tl); 2454 tl += 2; 2455 *tl = txdr_unsigned(cnt); 2456 nfsm_request(vp, NFSPROC_COMMIT, procp, cred); 2457 nfsm_wcc_data(vp, wccflag); 2458 if (!error) { 2459 nfsm_dissect(tl, u_long *, NFSX_V3WRITEVERF); 2460 if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl, 2461 NFSX_V3WRITEVERF)) { 2462 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 2463 NFSX_V3WRITEVERF); 2464 error = NFSERR_STALEWRITEVERF; 2465 } 2466 } 2467 nfsm_reqdone; 2468 return (error); 2469 } 2470 2471 /* 2472 * Kludge City.. 2473 * - make nfs_bmap() essentially a no-op that does no translation 2474 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc 2475 * (Maybe I could use the process's page mapping, but I was concerned that 2476 * Kernel Write might not be enabled and also figured copyout() would do 2477 * a lot more work than bcopy() and also it currently happens in the 2478 * context of the swapper process (2). 2479 */ 2480 int 2481 nfs_bmap(ap) 2482 struct vop_bmap_args /* { 2483 struct vnode *a_vp; 2484 daddr_t a_bn; 2485 struct vnode **a_vpp; 2486 daddr_t *a_bnp; 2487 int *a_runp; 2488 } */ *ap; 2489 { 2490 register struct vnode *vp = ap->a_vp; 2491 2492 if (ap->a_vpp != NULL) 2493 *ap->a_vpp = vp; 2494 if (ap->a_bnp != NULL) 2495 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize); 2496 return (0); 2497 } 2498 2499 /* 2500 * Strategy routine. 2501 * For async requests when nfsiod(s) are running, queue the request by 2502 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the 2503 * request. 2504 */ 2505 int 2506 nfs_strategy(ap) 2507 struct vop_strategy_args *ap; 2508 { 2509 register struct buf *bp = ap->a_bp; 2510 struct ucred *cr; 2511 struct proc *p; 2512 int error = 0; 2513 2514 if (bp->b_flags & B_PHYS) 2515 panic("nfs physio"); 2516 if (bp->b_flags & B_ASYNC) 2517 p = (struct proc *)0; 2518 else 2519 p = curproc; /* XXX */ 2520 if (bp->b_flags & B_READ) 2521 cr = bp->b_rcred; 2522 else 2523 cr = bp->b_wcred; 2524 /* 2525 * If the op is asynchronous and an i/o daemon is waiting 2526 * queue the request, wake it up and wait for completion 2527 * otherwise just do it ourselves. 2528 */ 2529 if ((bp->b_flags & B_ASYNC) == 0 || 2530 nfs_asyncio(bp, NOCRED)) 2531 error = nfs_doio(bp, cr, p); 2532 return (error); 2533 } 2534 2535 /* 2536 * Mmap a file 2537 * 2538 * NB Currently unsupported. 2539 */ 2540 /* ARGSUSED */ 2541 int 2542 nfs_mmap(ap) 2543 struct vop_mmap_args /* { 2544 struct vnode *a_vp; 2545 int a_fflags; 2546 struct ucred *a_cred; 2547 struct proc *a_p; 2548 } */ *ap; 2549 { 2550 2551 return (EINVAL); 2552 } 2553 2554 /* 2555 * fsync vnode op. Just call nfs_flush() with commit == 1. 2556 */ 2557 /* ARGSUSED */ 2558 int 2559 nfs_fsync(ap) 2560 struct vop_fsync_args /* { 2561 struct vnodeop_desc *a_desc; 2562 struct vnode * a_vp; 2563 struct ucred * a_cred; 2564 int a_waitfor; 2565 struct proc * a_p; 2566 } */ *ap; 2567 { 2568 2569 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1)); 2570 } 2571 2572 /* 2573 * Flush all the blocks associated with a vnode. 2574 * Walk through the buffer pool and push any dirty pages 2575 * associated with the vnode. 2576 */ 2577 int 2578 nfs_flush(vp, cred, waitfor, p, commit) 2579 register struct vnode *vp; 2580 struct ucred *cred; 2581 int waitfor; 2582 struct proc *p; 2583 int commit; 2584 { 2585 register struct nfsnode *np = VTONFS(vp); 2586 register struct buf *bp; 2587 register int i; 2588 struct buf *nbp; 2589 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2590 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos; 2591 int passone = 1; 2592 u_quad_t off = (u_quad_t)-1, endoff = 0, toff; 2593 #ifndef NFS_COMMITBVECSIZ 2594 #define NFS_COMMITBVECSIZ 20 2595 #endif 2596 struct buf *bvec[NFS_COMMITBVECSIZ]; 2597 2598 if (nmp->nm_flag & NFSMNT_INT) 2599 slpflag = PCATCH; 2600 if (!commit) 2601 passone = 0; 2602 /* 2603 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the 2604 * server, but nas not been committed to stable storage on the server 2605 * yet. On the first pass, the byte range is worked out and the commit 2606 * rpc is done. On the second pass, nfs_writebp() is called to do the 2607 * job. 2608 */ 2609 again: 2610 bvecpos = 0; 2611 if (NFS_ISV3(vp) && commit) { 2612 s = splbio(); 2613 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2614 nbp = bp->b_vnbufs.le_next; 2615 if (bvecpos >= NFS_COMMITBVECSIZ) 2616 break; 2617 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2618 != (B_DELWRI | B_NEEDCOMMIT)) 2619 continue; 2620 bremfree(bp); 2621 bp->b_flags |= (B_BUSY | B_WRITEINPROG); 2622 /* 2623 * A list of these buffers is kept so that the 2624 * second loop knows which buffers have actually 2625 * been committed. This is necessary, since there 2626 * may be a race between the commit rpc and new 2627 * uncommitted writes on the file. 2628 */ 2629 bvec[bvecpos++] = bp; 2630 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2631 bp->b_dirtyoff; 2632 if (toff < off) 2633 off = toff; 2634 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff); 2635 if (toff > endoff) 2636 endoff = toff; 2637 } 2638 splx(s); 2639 } 2640 if (bvecpos > 0) { 2641 /* 2642 * Commit data on the server, as required. 2643 */ 2644 retv = nfs_commit(vp, off, (int)(endoff - off), cred, p); 2645 if (retv == NFSERR_STALEWRITEVERF) 2646 nfs_clearcommit(vp->v_mount); 2647 /* 2648 * Now, either mark the blocks I/O done or mark the 2649 * blocks dirty, depending on whether the commit 2650 * succeeded. 2651 */ 2652 for (i = 0; i < bvecpos; i++) { 2653 bp = bvec[i]; 2654 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG); 2655 if (retv) { 2656 brelse(bp); 2657 } else { 2658 vp->v_numoutput++; 2659 bp->b_flags |= B_ASYNC; 2660 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 2661 bp->b_dirtyoff = bp->b_dirtyend = 0; 2662 reassignbuf(bp, vp); 2663 biodone(bp); 2664 } 2665 } 2666 } 2667 2668 /* 2669 * Start/do any write(s) that are required. 2670 */ 2671 loop: 2672 s = splbio(); 2673 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2674 nbp = bp->b_vnbufs.le_next; 2675 if (bp->b_flags & B_BUSY) { 2676 if (waitfor != MNT_WAIT || passone) 2677 continue; 2678 bp->b_flags |= B_WANTED; 2679 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), 2680 "nfsfsync", slptimeo); 2681 splx(s); 2682 if (error) { 2683 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) 2684 return (EINTR); 2685 if (slpflag == PCATCH) { 2686 slpflag = 0; 2687 slptimeo = 2 * hz; 2688 } 2689 } 2690 goto loop; 2691 } 2692 if ((bp->b_flags & B_DELWRI) == 0) 2693 panic("nfs_fsync: not dirty"); 2694 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) 2695 continue; 2696 bremfree(bp); 2697 if (passone || !commit) 2698 bp->b_flags |= (B_BUSY|B_ASYNC); 2699 else 2700 bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT); 2701 splx(s); 2702 VOP_BWRITE(bp); 2703 goto loop; 2704 } 2705 splx(s); 2706 if (passone) { 2707 passone = 0; 2708 goto again; 2709 } 2710 if (waitfor == MNT_WAIT) { 2711 while (vp->v_numoutput) { 2712 vp->v_flag |= VBWAIT; 2713 error = tsleep((caddr_t)&vp->v_numoutput, 2714 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); 2715 if (error) { 2716 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) 2717 return (EINTR); 2718 if (slpflag == PCATCH) { 2719 slpflag = 0; 2720 slptimeo = 2 * hz; 2721 } 2722 } 2723 } 2724 if (vp->v_dirtyblkhd.lh_first && commit) { 2725 #ifndef DIAGNOSTIC 2726 vprint("nfs_fsync: dirty", vp); 2727 #endif 2728 goto loop; 2729 } 2730 } 2731 if (np->n_flag & NWRITEERR) { 2732 error = np->n_error; 2733 np->n_flag &= ~NWRITEERR; 2734 } 2735 return (error); 2736 } 2737 2738 /* 2739 * Return POSIX pathconf information applicable to nfs. 2740 * 2741 * The NFS V2 protocol doesn't support this, so just return EINVAL 2742 * for V2. 2743 */ 2744 /* ARGSUSED */ 2745 int 2746 nfs_pathconf(ap) 2747 struct vop_pathconf_args /* { 2748 struct vnode *a_vp; 2749 int a_name; 2750 int *a_retval; 2751 } */ *ap; 2752 { 2753 2754 return (EINVAL); 2755 } 2756 2757 /* 2758 * NFS advisory byte-level locks. 2759 * Currently unsupported. 2760 */ 2761 int 2762 nfs_advlock(ap) 2763 struct vop_advlock_args /* { 2764 struct vnode *a_vp; 2765 caddr_t a_id; 2766 int a_op; 2767 struct flock *a_fl; 2768 int a_flags; 2769 } */ *ap; 2770 { 2771 2772 return (EOPNOTSUPP); 2773 } 2774 2775 /* 2776 * Print out the contents of an nfsnode. 2777 */ 2778 int 2779 nfs_print(ap) 2780 struct vop_print_args /* { 2781 struct vnode *a_vp; 2782 } */ *ap; 2783 { 2784 register struct vnode *vp = ap->a_vp; 2785 register struct nfsnode *np = VTONFS(vp); 2786 2787 printf("tag VT_NFS, fileid %ld fsid 0x%lx", 2788 np->n_vattr.va_fileid, np->n_vattr.va_fsid); 2789 if (vp->v_type == VFIFO) 2790 fifo_printinfo(vp); 2791 printf("\n"); 2792 return (0); 2793 } 2794 2795 /* 2796 * NFS directory offset lookup. 2797 * Currently unsupported. 2798 */ 2799 int 2800 nfs_blkatoff(ap) 2801 struct vop_blkatoff_args /* { 2802 struct vnode *a_vp; 2803 off_t a_offset; 2804 char **a_res; 2805 struct buf **a_bpp; 2806 } */ *ap; 2807 { 2808 2809 return (EOPNOTSUPP); 2810 } 2811 2812 /* 2813 * NFS flat namespace allocation. 2814 * Currently unsupported. 2815 */ 2816 int 2817 nfs_valloc(ap) 2818 struct vop_valloc_args /* { 2819 struct vnode *a_pvp; 2820 int a_mode; 2821 struct ucred *a_cred; 2822 struct vnode **a_vpp; 2823 } */ *ap; 2824 { 2825 2826 return (EOPNOTSUPP); 2827 } 2828 2829 /* 2830 * NFS flat namespace free. 2831 * Currently unsupported. 2832 */ 2833 int 2834 nfs_vfree(ap) 2835 struct vop_vfree_args /* { 2836 struct vnode *a_pvp; 2837 ino_t a_ino; 2838 int a_mode; 2839 } */ *ap; 2840 { 2841 2842 return (EOPNOTSUPP); 2843 } 2844 2845 /* 2846 * NFS file truncation. 2847 */ 2848 int 2849 nfs_truncate(ap) 2850 struct vop_truncate_args /* { 2851 struct vnode *a_vp; 2852 off_t a_length; 2853 int a_flags; 2854 struct ucred *a_cred; 2855 struct proc *a_p; 2856 } */ *ap; 2857 { 2858 2859 /* Use nfs_setattr */ 2860 printf("nfs_truncate: need to implement!!"); 2861 return (EOPNOTSUPP); 2862 } 2863 2864 /* 2865 * NFS update. 2866 */ 2867 int 2868 nfs_update(ap) 2869 struct vop_update_args /* { 2870 struct vnode *a_vp; 2871 struct timeval *a_ta; 2872 struct timeval *a_tm; 2873 int a_waitfor; 2874 } */ *ap; 2875 { 2876 2877 /* Use nfs_setattr */ 2878 printf("nfs_update: need to implement!!"); 2879 return (EOPNOTSUPP); 2880 } 2881 2882 /* 2883 * Just call nfs_writebp() with the force argument set to 1. 2884 */ 2885 int 2886 nfs_bwrite(ap) 2887 struct vop_bwrite_args /* { 2888 struct vnode *a_bp; 2889 } */ *ap; 2890 { 2891 2892 return (nfs_writebp(ap->a_bp, 1)); 2893 } 2894 2895 /* 2896 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless 2897 * the force flag is one and it also handles the B_NEEDCOMMIT flag. 2898 */ 2899 int 2900 nfs_writebp(bp, force) 2901 register struct buf *bp; 2902 int force; 2903 { 2904 register int oldflags = bp->b_flags, retv = 1; 2905 register struct proc *p = curproc; /* XXX */ 2906 off_t off; 2907 2908 if(!(bp->b_flags & B_BUSY)) 2909 panic("bwrite: buffer is not busy???"); 2910 2911 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 2912 2913 if (oldflags & B_ASYNC) { 2914 if (oldflags & B_DELWRI) { 2915 reassignbuf(bp, bp->b_vp); 2916 } else if (p) { 2917 ++p->p_stats->p_ru.ru_oublock; 2918 } 2919 } 2920 bp->b_vp->v_numoutput++; 2921 2922 /* 2923 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not 2924 * an actual write will have to be scheduled via. VOP_STRATEGY(). 2925 * If B_WRITEINPROG is already set, then push it with a write anyhow. 2926 */ 2927 if (oldflags & (B_NEEDCOMMIT | B_WRITEINPROG) == B_NEEDCOMMIT) { 2928 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff; 2929 bp->b_flags |= B_WRITEINPROG; 2930 retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff, 2931 bp->b_wcred, bp->b_proc); 2932 bp->b_flags &= ~B_WRITEINPROG; 2933 if (!retv) { 2934 bp->b_dirtyoff = bp->b_dirtyend = 0; 2935 bp->b_flags &= ~B_NEEDCOMMIT; 2936 biodone(bp); 2937 } else if (retv == NFSERR_STALEWRITEVERF) 2938 nfs_clearcommit(bp->b_vp->v_mount); 2939 } 2940 if (retv) { 2941 if (force) 2942 bp->b_flags |= B_WRITEINPROG; 2943 VOP_STRATEGY(bp); 2944 } 2945 2946 if( (oldflags & B_ASYNC) == 0) { 2947 int rtval = biowait(bp); 2948 if (oldflags & B_DELWRI) { 2949 reassignbuf(bp, bp->b_vp); 2950 } else if (p) { 2951 ++p->p_stats->p_ru.ru_oublock; 2952 } 2953 brelse(bp); 2954 return (rtval); 2955 } 2956 2957 return (0); 2958 } 2959 2960 /* 2961 * nfs special file access vnode op. 2962 * Essentially just get vattr and then imitate iaccess() since the device is 2963 * local to the client. 2964 */ 2965 int 2966 nfsspec_access(ap) 2967 struct vop_access_args /* { 2968 struct vnode *a_vp; 2969 int a_mode; 2970 struct ucred *a_cred; 2971 struct proc *a_p; 2972 } */ *ap; 2973 { 2974 register struct vattr *vap; 2975 register gid_t *gp; 2976 register struct ucred *cred = ap->a_cred; 2977 mode_t mode = ap->a_mode; 2978 struct vattr vattr; 2979 register int i; 2980 int error; 2981 2982 /* 2983 * If you're the super-user, 2984 * you always get access. 2985 */ 2986 if (cred->cr_uid == 0) 2987 return (0); 2988 vap = &vattr; 2989 error = VOP_GETATTR(ap->a_vp, vap, cred, ap->a_p); 2990 if (error) 2991 return (error); 2992 /* 2993 * Access check is based on only one of owner, group, public. 2994 * If not owner, then check group. If not a member of the 2995 * group, then check public access. 2996 */ 2997 if (cred->cr_uid != vap->va_uid) { 2998 mode >>= 3; 2999 gp = cred->cr_groups; 3000 for (i = 0; i < cred->cr_ngroups; i++, gp++) 3001 if (vap->va_gid == *gp) 3002 goto found; 3003 mode >>= 3; 3004 found: 3005 ; 3006 } 3007 error = (vap->va_mode & mode) == mode ? 0 : EACCES; 3008 return (error); 3009 } 3010 3011 /* 3012 * Read wrapper for special devices. 3013 */ 3014 int 3015 nfsspec_read(ap) 3016 struct vop_read_args /* { 3017 struct vnode *a_vp; 3018 struct uio *a_uio; 3019 int a_ioflag; 3020 struct ucred *a_cred; 3021 } */ *ap; 3022 { 3023 register struct nfsnode *np = VTONFS(ap->a_vp); 3024 3025 /* 3026 * Set access flag. 3027 */ 3028 np->n_flag |= NACC; 3029 np->n_atim.ts_sec = time.tv_sec; 3030 np->n_atim.ts_nsec = time.tv_usec * 1000; 3031 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap)); 3032 } 3033 3034 /* 3035 * Write wrapper for special devices. 3036 */ 3037 int 3038 nfsspec_write(ap) 3039 struct vop_write_args /* { 3040 struct vnode *a_vp; 3041 struct uio *a_uio; 3042 int a_ioflag; 3043 struct ucred *a_cred; 3044 } */ *ap; 3045 { 3046 register struct nfsnode *np = VTONFS(ap->a_vp); 3047 3048 /* 3049 * Set update flag. 3050 */ 3051 np->n_flag |= NUPD; 3052 np->n_mtim.ts_sec = time.tv_sec; 3053 np->n_mtim.ts_nsec = time.tv_usec * 1000; 3054 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap)); 3055 } 3056 3057 /* 3058 * Close wrapper for special devices. 3059 * 3060 * Update the times on the nfsnode then do device close. 3061 */ 3062 int 3063 nfsspec_close(ap) 3064 struct vop_close_args /* { 3065 struct vnode *a_vp; 3066 int a_fflag; 3067 struct ucred *a_cred; 3068 struct proc *a_p; 3069 } */ *ap; 3070 { 3071 register struct vnode *vp = ap->a_vp; 3072 register struct nfsnode *np = VTONFS(vp); 3073 struct vattr vattr; 3074 3075 if (np->n_flag & (NACC | NUPD)) { 3076 np->n_flag |= NCHG; 3077 if (vp->v_usecount == 1 && 3078 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3079 VATTR_NULL(&vattr); 3080 if (np->n_flag & NACC) 3081 vattr.va_atime = np->n_atim; 3082 if (np->n_flag & NUPD) 3083 vattr.va_mtime = np->n_mtim; 3084 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3085 } 3086 } 3087 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 3088 } 3089 3090 /* 3091 * Read wrapper for fifos. 3092 */ 3093 int 3094 nfsfifo_read(ap) 3095 struct vop_read_args /* { 3096 struct vnode *a_vp; 3097 struct uio *a_uio; 3098 int a_ioflag; 3099 struct ucred *a_cred; 3100 } */ *ap; 3101 { 3102 extern int (**fifo_vnodeop_p)(); 3103 register struct nfsnode *np = VTONFS(ap->a_vp); 3104 3105 /* 3106 * Set access flag. 3107 */ 3108 np->n_flag |= NACC; 3109 np->n_atim.ts_sec = time.tv_sec; 3110 np->n_atim.ts_nsec = time.tv_usec * 1000; 3111 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap)); 3112 } 3113 3114 /* 3115 * Write wrapper for fifos. 3116 */ 3117 int 3118 nfsfifo_write(ap) 3119 struct vop_write_args /* { 3120 struct vnode *a_vp; 3121 struct uio *a_uio; 3122 int a_ioflag; 3123 struct ucred *a_cred; 3124 } */ *ap; 3125 { 3126 extern int (**fifo_vnodeop_p)(); 3127 register struct nfsnode *np = VTONFS(ap->a_vp); 3128 3129 /* 3130 * Set update flag. 3131 */ 3132 np->n_flag |= NUPD; 3133 np->n_mtim.ts_sec = time.tv_sec; 3134 np->n_mtim.ts_nsec = time.tv_usec * 1000; 3135 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap)); 3136 } 3137 3138 /* 3139 * Close wrapper for fifos. 3140 * 3141 * Update the times on the nfsnode then do fifo close. 3142 */ 3143 int 3144 nfsfifo_close(ap) 3145 struct vop_close_args /* { 3146 struct vnode *a_vp; 3147 int a_fflag; 3148 struct ucred *a_cred; 3149 struct proc *a_p; 3150 } */ *ap; 3151 { 3152 register struct vnode *vp = ap->a_vp; 3153 register struct nfsnode *np = VTONFS(vp); 3154 struct vattr vattr; 3155 extern int (**fifo_vnodeop_p)(); 3156 3157 if (np->n_flag & (NACC | NUPD)) { 3158 if (np->n_flag & NACC) { 3159 np->n_atim.ts_sec = time.tv_sec; 3160 np->n_atim.ts_nsec = time.tv_usec * 1000; 3161 } 3162 if (np->n_flag & NUPD) { 3163 np->n_mtim.ts_sec = time.tv_sec; 3164 np->n_mtim.ts_nsec = time.tv_usec * 1000; 3165 } 3166 np->n_flag |= NCHG; 3167 if (vp->v_usecount == 1 && 3168 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3169 VATTR_NULL(&vattr); 3170 if (np->n_flag & NACC) 3171 vattr.va_atime = np->n_atim; 3172 if (np->n_flag & NUPD) 3173 vattr.va_mtime = np->n_mtim; 3174 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3175 } 3176 } 3177 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 3178 } 3179