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.14 (Berkeley) 03/30/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 vnode *newvp; 700 register u_long *tl; 701 register caddr_t cp; 702 register long t1, t2; 703 struct nfsmount *nmp; 704 caddr_t bpos, dpos, cp2; 705 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 706 long len; 707 nfsfh_t *fhp; 708 struct nfsnode *np; 709 int lockparent, wantparent, error = 0, attrflag, fhsize; 710 int v3 = NFS_ISV3(dvp); 711 712 *vpp = NULLVP; 713 if (dvp->v_type != VDIR) 714 return (ENOTDIR); 715 lockparent = flags & LOCKPARENT; 716 wantparent = flags & (LOCKPARENT|WANTPARENT); 717 nmp = VFSTONFS(dvp->v_mount); 718 np = VTONFS(dvp); 719 if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) { 720 struct vattr vattr; 721 int vpid; 722 723 newvp = *vpp; 724 vpid = newvp->v_id; 725 /* 726 * See the comment starting `Step through' in ufs/ufs_lookup.c 727 * for an explanation of the locking protocol 728 */ 729 if (dvp == newvp) { 730 VREF(newvp); 731 error = 0; 732 } else 733 error = vget(newvp, 1); 734 if (!error) { 735 if (vpid == newvp->v_id) { 736 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_proc) 737 && vattr.va_ctime.ts_sec == VTONFS(newvp)->n_ctime) { 738 nfsstats.lookupcache_hits++; 739 if (cnp->cn_nameiop != LOOKUP && 740 (flags & ISLASTCN)) 741 cnp->cn_flags |= SAVENAME; 742 return (0); 743 } 744 cache_purge(newvp); 745 } 746 vrele(newvp); 747 } 748 *vpp = NULLVP; 749 } 750 error = 0; 751 newvp = NULLVP; 752 nfsstats.lookupcache_misses++; 753 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 754 len = cnp->cn_namelen; 755 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 756 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 757 nfsm_fhtom(dvp, v3); 758 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 759 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 760 if (error) { 761 nfsm_postop_attr(dvp, attrflag); 762 m_freem(mrep); 763 goto nfsmout; 764 } 765 nfsm_getfh(fhp, fhsize, v3); 766 767 /* 768 * Handle RENAME case... 769 */ 770 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { 771 if (NFS_CMPFH(np, fhp, fhsize)) { 772 m_freem(mrep); 773 return (EISDIR); 774 } 775 if (error = nfs_nget(dvp->v_mount, fhp, fhsize, &np)) { 776 m_freem(mrep); 777 return (error); 778 } 779 newvp = NFSTOV(np); 780 if (v3) { 781 nfsm_postop_attr(newvp, attrflag); 782 nfsm_postop_attr(dvp, attrflag); 783 } else 784 nfsm_loadattr(newvp, (struct vattr *)0); 785 *vpp = newvp; 786 m_freem(mrep); 787 cnp->cn_flags |= SAVENAME; 788 return (0); 789 } 790 791 if (NFS_CMPFH(np, fhp, fhsize)) { 792 VREF(dvp); 793 newvp = dvp; 794 } else { 795 if (error = nfs_nget(dvp->v_mount, fhp, fhsize, &np)) { 796 m_freem(mrep); 797 return (error); 798 } 799 newvp = NFSTOV(np); 800 } 801 if (v3) { 802 nfsm_postop_attr(newvp, attrflag); 803 nfsm_postop_attr(dvp, attrflag); 804 } else 805 nfsm_loadattr(newvp, (struct vattr *)0); 806 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 807 cnp->cn_flags |= SAVENAME; 808 if ((cnp->cn_flags & MAKEENTRY) && 809 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { 810 np->n_ctime = np->n_vattr.va_ctime.ts_sec; 811 cache_enter(dvp, newvp, cnp); 812 } 813 *vpp = newvp; 814 nfsm_reqdone; 815 if (error) { 816 if (newvp != NULLVP) 817 vrele(newvp); 818 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && 819 (flags & ISLASTCN) && error == ENOENT) 820 error = EJUSTRETURN; 821 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 822 cnp->cn_flags |= SAVENAME; 823 } 824 return (error); 825 } 826 827 /* 828 * nfs read call. 829 * Just call nfs_bioread() to do the work. 830 */ 831 int 832 nfs_read(ap) 833 struct vop_read_args /* { 834 struct vnode *a_vp; 835 struct uio *a_uio; 836 int a_ioflag; 837 struct ucred *a_cred; 838 } */ *ap; 839 { 840 register struct vnode *vp = ap->a_vp; 841 842 if (vp->v_type != VREG) 843 return (EPERM); 844 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); 845 } 846 847 /* 848 * nfs readlink call 849 */ 850 int 851 nfs_readlink(ap) 852 struct vop_readlink_args /* { 853 struct vnode *a_vp; 854 struct uio *a_uio; 855 struct ucred *a_cred; 856 } */ *ap; 857 { 858 register struct vnode *vp = ap->a_vp; 859 860 if (vp->v_type != VLNK) 861 return (EPERM); 862 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred)); 863 } 864 865 /* 866 * Do a readlink rpc. 867 * Called by nfs_doio() from below the buffer cache. 868 */ 869 int 870 nfs_readlinkrpc(vp, uiop, cred) 871 register struct vnode *vp; 872 struct uio *uiop; 873 struct ucred *cred; 874 { 875 register u_long *tl; 876 register caddr_t cp; 877 register long t1, t2; 878 caddr_t bpos, dpos, cp2; 879 int error = 0, len, attrflag; 880 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 881 int v3 = NFS_ISV3(vp); 882 883 nfsstats.rpccnt[NFSPROC_READLINK]++; 884 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3)); 885 nfsm_fhtom(vp, v3); 886 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred); 887 if (v3) 888 nfsm_postop_attr(vp, attrflag); 889 if (!error) { 890 nfsm_strsiz(len, NFS_MAXPATHLEN); 891 nfsm_mtouio(uiop, len); 892 } 893 nfsm_reqdone; 894 return (error); 895 } 896 897 /* 898 * nfs read rpc call 899 * Ditto above 900 */ 901 int 902 nfs_readrpc(vp, uiop, cred) 903 register struct vnode *vp; 904 struct uio *uiop; 905 struct ucred *cred; 906 { 907 register u_long *tl; 908 register caddr_t cp; 909 register long t1, t2; 910 caddr_t bpos, dpos, cp2; 911 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 912 struct nfsmount *nmp; 913 int error = 0, len, retlen, tsiz, eof, attrflag; 914 int v3 = NFS_ISV3(vp); 915 916 #ifndef nolint 917 eof = 0; 918 #endif 919 nmp = VFSTONFS(vp->v_mount); 920 tsiz = uiop->uio_resid; 921 if (uiop->uio_offset + tsiz > 0xffffffff && !v3) 922 return (EFBIG); 923 while (tsiz > 0) { 924 nfsstats.rpccnt[NFSPROC_READ]++; 925 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 926 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3); 927 nfsm_fhtom(vp, v3); 928 nfsm_build(tl, u_long *, NFSX_UNSIGNED * 3); 929 if (v3) { 930 txdr_hyper(&uiop->uio_offset, tl); 931 *(tl + 2) = txdr_unsigned(len); 932 } else { 933 *tl++ = txdr_unsigned(uiop->uio_offset); 934 *tl++ = txdr_unsigned(len); 935 *tl = 0; 936 } 937 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred); 938 if (v3) { 939 nfsm_postop_attr(vp, attrflag); 940 if (error) { 941 m_freem(mrep); 942 goto nfsmout; 943 } 944 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 945 eof = fxdr_unsigned(int, *(tl + 1)); 946 } else 947 nfsm_loadattr(vp, (struct vattr *)0); 948 nfsm_strsiz(retlen, nmp->nm_rsize); 949 nfsm_mtouio(uiop, retlen); 950 m_freem(mrep); 951 tsiz -= retlen; 952 if (v3) { 953 if (eof || retlen == 0) 954 tsiz = 0; 955 } else if (retlen < len) 956 tsiz = 0; 957 } 958 nfsmout: 959 return (error); 960 } 961 962 /* 963 * nfs write call 964 */ 965 int 966 nfs_writerpc(vp, uiop, cred, iomode, must_commit) 967 register struct vnode *vp; 968 register struct uio *uiop; 969 struct ucred *cred; 970 int *iomode, *must_commit; 971 { 972 register u_long *tl; 973 register caddr_t cp; 974 register int t1, t2, backup; 975 caddr_t bpos, dpos, cp2; 976 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 977 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 978 struct nfsnode *np = VTONFS(vp); 979 u_quad_t frev; 980 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit; 981 int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC; 982 983 #ifndef DIAGNOSTIC 984 if (uiop->uio_iovcnt != 1) 985 panic("nfs: writerpc iovcnt > 1"); 986 #endif 987 *must_commit = 0; 988 tsiz = uiop->uio_resid; 989 if (uiop->uio_offset + tsiz > 0xffffffff && !v3) 990 return (EFBIG); 991 while (tsiz > 0) { 992 nfsstats.rpccnt[NFSPROC_WRITE]++; 993 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 994 nfsm_reqhead(vp, NFSPROC_WRITE, 995 NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len)); 996 nfsm_fhtom(vp, v3); 997 if (v3) { 998 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 999 txdr_hyper(&uiop->uio_offset, tl); 1000 tl += 2; 1001 *tl++ = txdr_unsigned(len); 1002 *tl++ = txdr_unsigned(*iomode); 1003 } else { 1004 nfsm_build(tl, u_long *, 4 * NFSX_UNSIGNED); 1005 *++tl = txdr_unsigned(uiop->uio_offset); 1006 tl += 2; 1007 } 1008 *tl = txdr_unsigned(len); 1009 nfsm_uiotom(uiop, len); 1010 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred); 1011 if (v3) { 1012 wccflag = NFSV3_WCCCHK; 1013 nfsm_wcc_data(vp, wccflag); 1014 if (!error) { 1015 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED + 1016 NFSX_V3WRITEVERF); 1017 rlen = fxdr_unsigned(int, *tl++); 1018 if (rlen == 0) { 1019 error = NFSERR_IO; 1020 break; 1021 } else if (rlen < len) { 1022 backup = len - rlen; 1023 uiop->uio_iov->iov_base -= backup; 1024 uiop->uio_iov->iov_len += backup; 1025 uiop->uio_offset -= backup; 1026 uiop->uio_resid += backup; 1027 len = rlen; 1028 } 1029 commit = fxdr_unsigned(int, *tl++); 1030 1031 /* 1032 * Return the lowest committment level 1033 * obtained by any of the RPCs. 1034 */ 1035 if (committed == NFSV3WRITE_FILESYNC) 1036 committed = commit; 1037 else if (committed == NFSV3WRITE_DATASYNC && 1038 commit == NFSV3WRITE_UNSTABLE) 1039 committed = commit; 1040 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) { 1041 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1042 NFSX_V3WRITEVERF); 1043 nmp->nm_flag |= NFSMNT_HASWRITEVERF; 1044 } else if (bcmp((caddr_t)tl, 1045 (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) { 1046 *must_commit = 1; 1047 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1048 NFSX_V3WRITEVERF); 1049 } 1050 } 1051 } else 1052 nfsm_loadattr(vp, (struct vattr *)0); 1053 if (wccflag) 1054 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.ts_sec; 1055 m_freem(mrep); 1056 tsiz -= len; 1057 } 1058 nfsmout: 1059 *iomode = committed; 1060 if (error) 1061 uiop->uio_resid = tsiz; 1062 return (error); 1063 } 1064 1065 /* 1066 * nfs mknod rpc 1067 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the 1068 * mode set to specify the file type and the size field for rdev. 1069 */ 1070 int 1071 nfs_mknodrpc(dvp, vpp, cnp, vap) 1072 register struct vnode *dvp; 1073 register struct vnode **vpp; 1074 register struct componentname *cnp; 1075 register struct vattr *vap; 1076 { 1077 register struct nfsv2_sattr *sp; 1078 register struct nfsv3_sattr *sp3; 1079 register u_long *tl; 1080 register caddr_t cp; 1081 register long t1, t2; 1082 struct vnode *newvp = (struct vnode *)0; 1083 struct nfsnode *np; 1084 struct vattr vattr; 1085 char *cp2; 1086 caddr_t bpos, dpos; 1087 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0; 1088 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1089 u_long rdev; 1090 int v3 = NFS_ISV3(dvp); 1091 1092 if (vap->va_type == VCHR || vap->va_type == VBLK) 1093 rdev = txdr_unsigned(vap->va_rdev); 1094 else if (vap->va_type == VFIFO || vap->va_type == VSOCK) 1095 rdev = 0xffffffff; 1096 else { 1097 VOP_ABORTOP(dvp, cnp); 1098 vput(dvp); 1099 return (EOPNOTSUPP); 1100 } 1101 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1102 VOP_ABORTOP(dvp, cnp); 1103 vput(dvp); 1104 return (error); 1105 } 1106 nfsstats.rpccnt[NFSPROC_MKNOD]++; 1107 nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED + 1108 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1109 nfsm_fhtom(dvp, v3); 1110 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1111 if (v3) { 1112 nfsm_build(tl, u_long *, NFSX_UNSIGNED + NFSX_V3SRVSATTR); 1113 *tl++ = vtonfsv3_type(vap->va_type); 1114 sp3 = (struct nfsv3_sattr *)tl; 1115 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1116 if (vap->va_type == VCHR || vap->va_type == VBLK) { 1117 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 1118 *tl++ = txdr_unsigned(major(vap->va_rdev)); 1119 *tl = txdr_unsigned(minor(vap->va_rdev)); 1120 } 1121 } else { 1122 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1123 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1124 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1125 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1126 sp->sa_size = rdev; 1127 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1128 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1129 } 1130 nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred); 1131 if (!error) { 1132 nfsm_mtofh(dvp, newvp, v3, gotvp); 1133 if (!gotvp) { 1134 if (newvp) { 1135 vrele(newvp); 1136 newvp = (struct vnode *)0; 1137 } 1138 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1139 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1140 if (!error) 1141 newvp = NFSTOV(np); 1142 } 1143 } 1144 if (v3) 1145 nfsm_wcc_data(dvp, wccflag); 1146 nfsm_reqdone; 1147 if (error) { 1148 if (newvp) 1149 vrele(newvp); 1150 } else { 1151 if (cnp->cn_flags & MAKEENTRY) 1152 cache_enter(dvp, newvp, cnp); 1153 *vpp = newvp; 1154 } 1155 FREE(cnp->cn_pnbuf, M_NAMEI); 1156 VTONFS(dvp)->n_flag |= NMODIFIED; 1157 if (!wccflag) 1158 VTONFS(dvp)->n_attrstamp = 0; 1159 vrele(dvp); 1160 return (error); 1161 } 1162 1163 /* 1164 * nfs mknod vop 1165 * just call nfs_mknodrpc() to do the work. 1166 */ 1167 /* ARGSUSED */ 1168 int 1169 nfs_mknod(ap) 1170 struct vop_mknod_args /* { 1171 struct vnode *a_dvp; 1172 struct vnode **a_vpp; 1173 struct componentname *a_cnp; 1174 struct vattr *a_vap; 1175 } */ *ap; 1176 { 1177 struct vnode *newvp; 1178 int error; 1179 1180 error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap); 1181 if (!error) 1182 vrele(newvp); 1183 return (error); 1184 } 1185 1186 static u_long create_verf; 1187 /* 1188 * nfs file create call 1189 */ 1190 int 1191 nfs_create(ap) 1192 struct vop_create_args /* { 1193 struct vnode *a_dvp; 1194 struct vnode **a_vpp; 1195 struct componentname *a_cnp; 1196 struct vattr *a_vap; 1197 } */ *ap; 1198 { 1199 register struct vnode *dvp = ap->a_dvp; 1200 register struct vattr *vap = ap->a_vap; 1201 register struct componentname *cnp = ap->a_cnp; 1202 register struct nfsv2_sattr *sp; 1203 register struct nfsv3_sattr *sp3; 1204 register u_long *tl; 1205 register caddr_t cp; 1206 register long t1, t2; 1207 struct nfsnode *np = (struct nfsnode *)0; 1208 struct vnode *newvp = (struct vnode *)0; 1209 caddr_t bpos, dpos, cp2; 1210 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0; 1211 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1212 struct vattr vattr; 1213 int v3 = NFS_ISV3(dvp); 1214 1215 /* 1216 * Oops, not for me.. 1217 */ 1218 if (vap->va_type == VSOCK) 1219 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap)); 1220 1221 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1222 VOP_ABORTOP(dvp, cnp); 1223 vput(dvp); 1224 return (error); 1225 } 1226 if (vap->va_vaflags & VA_EXCLUSIVE) 1227 fmode |= O_EXCL; 1228 again: 1229 nfsstats.rpccnt[NFSPROC_CREATE]++; 1230 nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED + 1231 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1232 nfsm_fhtom(dvp, v3); 1233 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1234 if (v3) { 1235 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 1236 if (fmode & O_EXCL) { 1237 *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE); 1238 nfsm_build(tl, u_long *, NFSX_V3CREATEVERF); 1239 if (in_ifaddr) 1240 *tl++ = IA_SIN(in_ifaddr)->sin_addr.s_addr; 1241 else 1242 *tl++ = create_verf; 1243 *tl = ++create_verf; 1244 } else { 1245 *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED); 1246 nfsm_build(tl, u_long *, NFSX_V3SRVSATTR); 1247 sp3 = (struct nfsv3_sattr *)tl; 1248 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1249 } 1250 } else { 1251 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1252 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1253 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1254 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1255 sp->sa_size = 0; 1256 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1257 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1258 } 1259 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1260 if (!error) { 1261 nfsm_mtofh(dvp, newvp, v3, gotvp); 1262 if (!gotvp) { 1263 if (newvp) { 1264 vrele(newvp); 1265 newvp = (struct vnode *)0; 1266 } 1267 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1268 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1269 if (!error) 1270 newvp = NFSTOV(np); 1271 } 1272 } 1273 if (v3) 1274 nfsm_wcc_data(dvp, wccflag); 1275 nfsm_reqdone; 1276 if (error) { 1277 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) { 1278 fmode &= ~O_EXCL; 1279 goto again; 1280 } 1281 if (newvp) 1282 vrele(newvp); 1283 } else if (v3 && (fmode & O_EXCL)) 1284 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc); 1285 if (!error) { 1286 if (cnp->cn_flags & MAKEENTRY) 1287 cache_enter(dvp, newvp, cnp); 1288 *ap->a_vpp = newvp; 1289 } 1290 FREE(cnp->cn_pnbuf, M_NAMEI); 1291 VTONFS(dvp)->n_flag |= NMODIFIED; 1292 if (!wccflag) 1293 VTONFS(dvp)->n_attrstamp = 0; 1294 vrele(dvp); 1295 return (error); 1296 } 1297 1298 /* 1299 * nfs file remove call 1300 * To try and make nfs semantics closer to ufs semantics, a file that has 1301 * other processes using the vnode is renamed instead of removed and then 1302 * removed later on the last close. 1303 * - If v_usecount > 1 1304 * If a rename is not already in the works 1305 * call nfs_sillyrename() to set it up 1306 * else 1307 * do the remove rpc 1308 */ 1309 int 1310 nfs_remove(ap) 1311 struct vop_remove_args /* { 1312 struct vnodeop_desc *a_desc; 1313 struct vnode * a_dvp; 1314 struct vnode * a_vp; 1315 struct componentname * a_cnp; 1316 } */ *ap; 1317 { 1318 register struct vnode *vp = ap->a_vp; 1319 register struct vnode *dvp = ap->a_dvp; 1320 register struct componentname *cnp = ap->a_cnp; 1321 register struct nfsnode *np = VTONFS(vp); 1322 register u_long *tl; 1323 register caddr_t cp; 1324 register long t2; 1325 caddr_t bpos, dpos; 1326 int error = 0; 1327 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1328 struct vattr vattr; 1329 int v3 = NFS_ISV3(dvp); 1330 1331 #ifndef DIAGNOSTIC 1332 if ((cnp->cn_flags & HASBUF) == 0) 1333 panic("nfs_remove: no name"); 1334 if (vp->v_usecount < 1) 1335 panic("nfs_remove: bad v_usecount"); 1336 #endif 1337 if (vp->v_usecount == 1 || (np->n_sillyrename && 1338 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 && 1339 vattr.va_nlink > 1)) { 1340 /* 1341 * Purge the name cache so that the chance of a lookup for 1342 * the name succeeding while the remove is in progress is 1343 * minimized. Without node locking it can still happen, such 1344 * that an I/O op returns ESTALE, but since you get this if 1345 * another host removes the file.. 1346 */ 1347 cache_purge(vp); 1348 /* 1349 * throw away biocache buffers, mainly to avoid 1350 * unnecessary delayed writes later. 1351 */ 1352 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1); 1353 /* Do the rpc */ 1354 if (error != EINTR) 1355 error = nfs_removerpc(dvp, cnp->cn_nameptr, 1356 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc); 1357 /* 1358 * Kludge City: If the first reply to the remove rpc is lost.. 1359 * the reply to the retransmitted request will be ENOENT 1360 * since the file was in fact removed 1361 * Therefore, we cheat and return success. 1362 */ 1363 if (error == ENOENT) 1364 error = 0; 1365 } else if (!np->n_sillyrename) 1366 error = nfs_sillyrename(dvp, vp, cnp); 1367 FREE(cnp->cn_pnbuf, M_NAMEI); 1368 np->n_attrstamp = 0; 1369 vrele(dvp); 1370 vrele(vp); 1371 return (error); 1372 } 1373 1374 /* 1375 * nfs file remove rpc called from nfs_inactive 1376 */ 1377 int 1378 nfs_removeit(sp) 1379 register struct sillyrename *sp; 1380 { 1381 1382 return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred, 1383 (struct proc *)0)); 1384 } 1385 1386 /* 1387 * Nfs remove rpc, called from nfs_remove() and nfs_removeit(). 1388 */ 1389 int 1390 nfs_removerpc(dvp, name, namelen, cred, proc) 1391 register struct vnode *dvp; 1392 char *name; 1393 int namelen; 1394 struct ucred *cred; 1395 struct proc *proc; 1396 { 1397 register u_long *tl; 1398 register caddr_t cp; 1399 register long t1, t2; 1400 caddr_t bpos, dpos, cp2; 1401 int error = 0, wccflag = NFSV3_WCCRATTR; 1402 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1403 int v3 = NFS_ISV3(dvp); 1404 1405 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1406 nfsm_reqhead(dvp, NFSPROC_REMOVE, 1407 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen)); 1408 nfsm_fhtom(dvp, v3); 1409 nfsm_strtom(name, namelen, NFS_MAXNAMLEN); 1410 nfsm_request(dvp, NFSPROC_REMOVE, proc, cred); 1411 if (v3) 1412 nfsm_wcc_data(dvp, wccflag); 1413 nfsm_reqdone; 1414 VTONFS(dvp)->n_flag |= NMODIFIED; 1415 if (!wccflag) 1416 VTONFS(dvp)->n_attrstamp = 0; 1417 return (error); 1418 } 1419 1420 /* 1421 * nfs file rename call 1422 */ 1423 int 1424 nfs_rename(ap) 1425 struct vop_rename_args /* { 1426 struct vnode *a_fdvp; 1427 struct vnode *a_fvp; 1428 struct componentname *a_fcnp; 1429 struct vnode *a_tdvp; 1430 struct vnode *a_tvp; 1431 struct componentname *a_tcnp; 1432 } */ *ap; 1433 { 1434 register struct vnode *fvp = ap->a_fvp; 1435 register struct vnode *tvp = ap->a_tvp; 1436 register struct vnode *fdvp = ap->a_fdvp; 1437 register struct vnode *tdvp = ap->a_tdvp; 1438 register struct componentname *tcnp = ap->a_tcnp; 1439 register struct componentname *fcnp = ap->a_fcnp; 1440 int error; 1441 1442 #ifndef DIAGNOSTIC 1443 if ((tcnp->cn_flags & HASBUF) == 0 || 1444 (fcnp->cn_flags & HASBUF) == 0) 1445 panic("nfs_rename: no name"); 1446 #endif 1447 /* Check for cross-device rename */ 1448 if ((fvp->v_mount != tdvp->v_mount) || 1449 (tvp && (fvp->v_mount != tvp->v_mount))) { 1450 error = EXDEV; 1451 goto out; 1452 } 1453 1454 /* 1455 * If the tvp exists and is in use, sillyrename it before doing the 1456 * rename of the new file over it. 1457 */ 1458 if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename && 1459 !nfs_sillyrename(tdvp, tvp, tcnp)) { 1460 vrele(tvp); 1461 tvp = NULL; 1462 } 1463 1464 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen, 1465 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred, 1466 tcnp->cn_proc); 1467 1468 if (fvp->v_type == VDIR) { 1469 if (tvp != NULL && tvp->v_type == VDIR) 1470 cache_purge(tdvp); 1471 cache_purge(fdvp); 1472 } 1473 out: 1474 if (tdvp == tvp) 1475 vrele(tdvp); 1476 else 1477 vput(tdvp); 1478 if (tvp) 1479 vput(tvp); 1480 vrele(fdvp); 1481 vrele(fvp); 1482 /* 1483 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1484 */ 1485 if (error == ENOENT) 1486 error = 0; 1487 return (error); 1488 } 1489 1490 /* 1491 * nfs file rename rpc called from nfs_remove() above 1492 */ 1493 int 1494 nfs_renameit(sdvp, scnp, sp) 1495 struct vnode *sdvp; 1496 struct componentname *scnp; 1497 register struct sillyrename *sp; 1498 { 1499 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, 1500 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc)); 1501 } 1502 1503 /* 1504 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit(). 1505 */ 1506 int 1507 nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc) 1508 register struct vnode *fdvp; 1509 char *fnameptr; 1510 int fnamelen; 1511 register struct vnode *tdvp; 1512 char *tnameptr; 1513 int tnamelen; 1514 struct ucred *cred; 1515 struct proc *proc; 1516 { 1517 register u_long *tl; 1518 register caddr_t cp; 1519 register long t1, t2; 1520 caddr_t bpos, dpos, cp2; 1521 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR; 1522 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1523 int v3 = NFS_ISV3(fdvp); 1524 1525 nfsstats.rpccnt[NFSPROC_RENAME]++; 1526 nfsm_reqhead(fdvp, NFSPROC_RENAME, 1527 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) + 1528 nfsm_rndup(tnamelen)); 1529 nfsm_fhtom(fdvp, v3); 1530 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN); 1531 nfsm_fhtom(tdvp, v3); 1532 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN); 1533 nfsm_request(fdvp, NFSPROC_RENAME, proc, cred); 1534 if (v3) { 1535 nfsm_wcc_data(fdvp, fwccflag); 1536 nfsm_wcc_data(tdvp, twccflag); 1537 } 1538 nfsm_reqdone; 1539 VTONFS(fdvp)->n_flag |= NMODIFIED; 1540 VTONFS(tdvp)->n_flag |= NMODIFIED; 1541 if (!fwccflag) 1542 VTONFS(fdvp)->n_attrstamp = 0; 1543 if (!twccflag) 1544 VTONFS(tdvp)->n_attrstamp = 0; 1545 return (error); 1546 } 1547 1548 /* 1549 * nfs hard link create call 1550 */ 1551 int 1552 nfs_link(ap) 1553 struct vop_link_args /* { 1554 struct vnode *a_vp; 1555 struct vnode *a_tdvp; 1556 struct componentname *a_cnp; 1557 } */ *ap; 1558 { 1559 register struct vnode *vp = ap->a_vp; 1560 register struct vnode *tdvp = ap->a_tdvp; 1561 register struct componentname *cnp = ap->a_cnp; 1562 register u_long *tl; 1563 register caddr_t cp; 1564 register long t1, t2; 1565 caddr_t bpos, dpos, cp2; 1566 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0; 1567 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1568 int v3 = NFS_ISV3(vp); 1569 1570 if (vp->v_mount != tdvp->v_mount) { 1571 /*VOP_ABORTOP(vp, cnp);*/ 1572 if (tdvp == vp) 1573 vrele(tdvp); 1574 else 1575 vput(tdvp); 1576 return (EXDEV); 1577 } 1578 1579 /* 1580 * Push all writes to the server, so that the attribute cache 1581 * doesn't get "out of sync" with the server. 1582 * XXX There should be a better way! 1583 */ 1584 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc); 1585 1586 nfsstats.rpccnt[NFSPROC_LINK]++; 1587 nfsm_reqhead(vp, NFSPROC_LINK, 1588 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1589 nfsm_fhtom(vp, v3); 1590 nfsm_fhtom(tdvp, v3); 1591 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1592 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); 1593 if (v3) { 1594 nfsm_postop_attr(vp, attrflag); 1595 nfsm_wcc_data(tdvp, wccflag); 1596 } 1597 nfsm_reqdone; 1598 FREE(cnp->cn_pnbuf, M_NAMEI); 1599 VTONFS(tdvp)->n_flag |= NMODIFIED; 1600 if (!attrflag) 1601 VTONFS(vp)->n_attrstamp = 0; 1602 if (!wccflag) 1603 VTONFS(tdvp)->n_attrstamp = 0; 1604 vrele(tdvp); 1605 /* 1606 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1607 */ 1608 if (error == EEXIST) 1609 error = 0; 1610 return (error); 1611 } 1612 1613 /* 1614 * nfs symbolic link create call 1615 */ 1616 int 1617 nfs_symlink(ap) 1618 struct vop_symlink_args /* { 1619 struct vnode *a_dvp; 1620 struct vnode **a_vpp; 1621 struct componentname *a_cnp; 1622 struct vattr *a_vap; 1623 char *a_target; 1624 } */ *ap; 1625 { 1626 register struct vnode *dvp = ap->a_dvp; 1627 register struct vattr *vap = ap->a_vap; 1628 register struct componentname *cnp = ap->a_cnp; 1629 register struct nfsv2_sattr *sp; 1630 register struct nfsv3_sattr *sp3; 1631 register u_long *tl; 1632 register caddr_t cp; 1633 register long t1, t2; 1634 caddr_t bpos, dpos, cp2; 1635 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp; 1636 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1637 struct vnode *newvp = (struct vnode *)0; 1638 int v3 = NFS_ISV3(dvp); 1639 1640 nfsstats.rpccnt[NFSPROC_SYMLINK]++; 1641 slen = strlen(ap->a_target); 1642 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED + 1643 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3)); 1644 nfsm_fhtom(dvp, v3); 1645 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1646 if (v3) { 1647 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1648 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, 1649 cnp->cn_cred->cr_gid); 1650 } 1651 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN); 1652 if (!v3) { 1653 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1654 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode); 1655 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1656 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 1657 sp->sa_size = -1; 1658 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1659 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1660 } 1661 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred); 1662 if (v3) { 1663 if (!error) 1664 nfsm_mtofh(dvp, newvp, v3, gotvp); 1665 nfsm_wcc_data(dvp, wccflag); 1666 } 1667 nfsm_reqdone; 1668 if (newvp) 1669 vrele(newvp); 1670 FREE(cnp->cn_pnbuf, M_NAMEI); 1671 VTONFS(dvp)->n_flag |= NMODIFIED; 1672 if (!wccflag) 1673 VTONFS(dvp)->n_attrstamp = 0; 1674 vrele(dvp); 1675 /* 1676 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1677 */ 1678 if (error == EEXIST) 1679 error = 0; 1680 return (error); 1681 } 1682 1683 /* 1684 * nfs make dir call 1685 */ 1686 int 1687 nfs_mkdir(ap) 1688 struct vop_mkdir_args /* { 1689 struct vnode *a_dvp; 1690 struct vnode **a_vpp; 1691 struct componentname *a_cnp; 1692 struct vattr *a_vap; 1693 } */ *ap; 1694 { 1695 register struct vnode *dvp = ap->a_dvp; 1696 register struct vattr *vap = ap->a_vap; 1697 register struct componentname *cnp = ap->a_cnp; 1698 register struct nfsv2_sattr *sp; 1699 register struct nfsv3_sattr *sp3; 1700 register u_long *tl; 1701 register caddr_t cp; 1702 register long t1, t2; 1703 register int len; 1704 struct nfsnode *np = (struct nfsnode *)0; 1705 struct vnode *newvp = (struct vnode *)0; 1706 caddr_t bpos, dpos, cp2; 1707 nfsfh_t *fhp; 1708 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag; 1709 int fhsize, gotvp = 0; 1710 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1711 struct vattr vattr; 1712 int v3 = NFS_ISV3(dvp); 1713 1714 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1715 VOP_ABORTOP(dvp, cnp); 1716 vput(dvp); 1717 return (error); 1718 } 1719 len = cnp->cn_namelen; 1720 nfsstats.rpccnt[NFSPROC_MKDIR]++; 1721 nfsm_reqhead(dvp, NFSPROC_MKDIR, 1722 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3)); 1723 nfsm_fhtom(dvp, v3); 1724 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1725 if (v3) { 1726 nfsm_build(sp3, struct nfsv3_sattr *, NFSX_V3SRVSATTR); 1727 nfsm_v3sattr(sp3, vap, cnp->cn_cred->cr_uid, vattr.va_gid); 1728 } else { 1729 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1730 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode); 1731 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1732 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1733 sp->sa_size = -1; 1734 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1735 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1736 } 1737 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred); 1738 if (!error) 1739 nfsm_mtofh(dvp, newvp, v3, gotvp); 1740 if (v3) 1741 nfsm_wcc_data(dvp, wccflag); 1742 nfsm_reqdone; 1743 VTONFS(dvp)->n_flag |= NMODIFIED; 1744 if (!wccflag) 1745 VTONFS(dvp)->n_attrstamp = 0; 1746 /* 1747 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 1748 * if we can succeed in looking up the directory. 1749 */ 1750 if (error == EEXIST || (!error && !gotvp)) { 1751 if (newvp) { 1752 vrele(newvp); 1753 newvp = (struct vnode *)0; 1754 } 1755 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred, 1756 cnp->cn_proc, &np); 1757 if (!error) { 1758 newvp = NFSTOV(np); 1759 if (newvp->v_type != VDIR) 1760 error = EEXIST; 1761 } 1762 } 1763 if (error) { 1764 if (newvp) 1765 vrele(newvp); 1766 } else 1767 *ap->a_vpp = newvp; 1768 FREE(cnp->cn_pnbuf, M_NAMEI); 1769 vrele(dvp); 1770 return (error); 1771 } 1772 1773 /* 1774 * nfs remove directory call 1775 */ 1776 int 1777 nfs_rmdir(ap) 1778 struct vop_rmdir_args /* { 1779 struct vnode *a_dvp; 1780 struct vnode *a_vp; 1781 struct componentname *a_cnp; 1782 } */ *ap; 1783 { 1784 register struct vnode *vp = ap->a_vp; 1785 register struct vnode *dvp = ap->a_dvp; 1786 register struct componentname *cnp = ap->a_cnp; 1787 register u_long *tl; 1788 register caddr_t cp; 1789 register long t1, t2; 1790 caddr_t bpos, dpos, cp2; 1791 int error = 0, wccflag = NFSV3_WCCRATTR; 1792 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1793 int v3 = NFS_ISV3(dvp); 1794 1795 if (dvp == vp) { 1796 vrele(dvp); 1797 vrele(dvp); 1798 FREE(cnp->cn_pnbuf, M_NAMEI); 1799 return (EINVAL); 1800 } 1801 nfsstats.rpccnt[NFSPROC_RMDIR]++; 1802 nfsm_reqhead(dvp, NFSPROC_RMDIR, 1803 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1804 nfsm_fhtom(dvp, v3); 1805 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1806 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred); 1807 if (v3) 1808 nfsm_wcc_data(dvp, wccflag); 1809 nfsm_reqdone; 1810 FREE(cnp->cn_pnbuf, M_NAMEI); 1811 VTONFS(dvp)->n_flag |= NMODIFIED; 1812 if (!wccflag) 1813 VTONFS(dvp)->n_attrstamp = 0; 1814 cache_purge(dvp); 1815 cache_purge(vp); 1816 vrele(vp); 1817 vrele(dvp); 1818 /* 1819 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 1820 */ 1821 if (error == ENOENT) 1822 error = 0; 1823 return (error); 1824 } 1825 1826 /* 1827 * nfs readdir call 1828 */ 1829 int 1830 nfs_readdir(ap) 1831 struct vop_readdir_args /* { 1832 struct vnode *a_vp; 1833 struct uio *a_uio; 1834 struct ucred *a_cred; 1835 } */ *ap; 1836 { 1837 register struct vnode *vp = ap->a_vp; 1838 register struct nfsnode *np = VTONFS(vp); 1839 register struct uio *uio = ap->a_uio; 1840 int tresid, error; 1841 struct vattr vattr; 1842 1843 if (vp->v_type != VDIR) 1844 return (EPERM); 1845 /* 1846 * First, check for hit on the EOF offset cache 1847 */ 1848 if (np->n_direofoffset > 0 && uio->uio_offset >= np->n_direofoffset && 1849 (np->n_flag & NMODIFIED) == 0) { 1850 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { 1851 if (NQNFS_CKCACHABLE(vp, ND_READ)) { 1852 nfsstats.direofcache_hits++; 1853 return (0); 1854 } 1855 } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 && 1856 np->n_mtime == vattr.va_mtime.ts_sec) { 1857 nfsstats.direofcache_hits++; 1858 return (0); 1859 } 1860 } 1861 1862 /* 1863 * Call nfs_bioread() to do the real work. 1864 */ 1865 tresid = uio->uio_resid; 1866 error = nfs_bioread(vp, uio, 0, ap->a_cred); 1867 1868 if (!error && uio->uio_resid == tresid) 1869 nfsstats.direofcache_misses++; 1870 return (error); 1871 } 1872 1873 /* 1874 * Readdir rpc call. 1875 * Called from below the buffer cache by nfs_doio(). 1876 */ 1877 int 1878 nfs_readdirrpc(vp, uiop, cred) 1879 struct vnode *vp; 1880 register struct uio *uiop; 1881 struct ucred *cred; 1882 { 1883 register int len, left; 1884 register struct dirent *dp; 1885 register u_long *tl; 1886 register caddr_t cp; 1887 register long t1, t2; 1888 register nfsuint64 *cookiep; 1889 caddr_t bpos, dpos, cp2; 1890 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1891 nfsuint64 cookie; 1892 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1893 struct nfsnode *dnp = VTONFS(vp); 1894 nfsfh_t *fhp; 1895 u_quad_t frev, fileno; 1896 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1, i; 1897 int cachable, attrflag, fhsize; 1898 int v3 = NFS_ISV3(vp); 1899 1900 #ifndef nolint 1901 dp = (struct dirent *)0; 1902 #endif 1903 #ifndef DIAGNOSTIC 1904 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (NFS_DIRBLKSIZ - 1)) || 1905 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1))) 1906 panic("nfs readdirrpc bad uio"); 1907 #endif 1908 1909 /* 1910 * If there is no cookie, assume end of directory. 1911 */ 1912 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 1913 if (cookiep) 1914 cookie = *cookiep; 1915 else 1916 return (0); 1917 /* 1918 * Loop around doing readdir rpc's of size nm_readdirsize 1919 * truncated to a multiple of DIRBLKSIZ. 1920 * The stopping criteria is EOF or buffer full. 1921 */ 1922 while (more_dirs && bigenough) { 1923 nfsstats.rpccnt[NFSPROC_READDIR]++; 1924 nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) + 1925 NFSX_READDIR(v3)); 1926 nfsm_fhtom(vp, v3); 1927 if (v3) { 1928 nfsm_build(tl, u_long *, 5 * NFSX_UNSIGNED); 1929 *tl++ = cookie.nfsuquad[0]; 1930 *tl++ = cookie.nfsuquad[1]; 1931 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 1932 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 1933 } else { 1934 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 1935 *tl++ = cookie.nfsuquad[0]; 1936 } 1937 *tl = txdr_unsigned(nmp->nm_readdirsize); 1938 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred); 1939 if (v3) { 1940 nfsm_postop_attr(vp, attrflag); 1941 if (!error) { 1942 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1943 dnp->n_cookieverf.nfsuquad[0] = *tl++; 1944 dnp->n_cookieverf.nfsuquad[1] = *tl; 1945 } else { 1946 m_freem(mrep); 1947 goto nfsmout; 1948 } 1949 } 1950 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1951 more_dirs = fxdr_unsigned(int, *tl); 1952 1953 /* loop thru the dir entries, doctoring them to 4bsd form */ 1954 while (more_dirs && bigenough) { 1955 if (v3) { 1956 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 1957 fxdr_hyper(tl, &fileno); 1958 len = fxdr_unsigned(int, *(tl + 2)); 1959 } else { 1960 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1961 fileno = fxdr_unsigned(u_quad_t, *tl++); 1962 len = fxdr_unsigned(int, *tl); 1963 } 1964 if (len <= 0 || len > NFS_MAXNAMLEN) { 1965 error = EBADRPC; 1966 m_freem(mrep); 1967 goto nfsmout; 1968 } 1969 tlen = nfsm_rndup(len); 1970 if (tlen == len) 1971 tlen += 4; /* To ensure null termination */ 1972 left = DIRBLKSIZ - blksiz; 1973 if ((tlen + DIRHDSIZ) > left) { 1974 dp->d_reclen += left; 1975 uiop->uio_iov->iov_base += left; 1976 uiop->uio_iov->iov_len -= left; 1977 uiop->uio_offset += left; 1978 uiop->uio_resid -= left; 1979 blksiz = 0; 1980 } 1981 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 1982 bigenough = 0; 1983 if (bigenough) { 1984 dp = (struct dirent *)uiop->uio_iov->iov_base; 1985 dp->d_fileno = (int)fileno; 1986 dp->d_namlen = len; 1987 dp->d_reclen = tlen + DIRHDSIZ; 1988 dp->d_type = DT_UNKNOWN; 1989 blksiz += dp->d_reclen; 1990 if (blksiz == DIRBLKSIZ) 1991 blksiz = 0; 1992 uiop->uio_offset += DIRHDSIZ; 1993 uiop->uio_resid -= DIRHDSIZ; 1994 uiop->uio_iov->iov_base += DIRHDSIZ; 1995 uiop->uio_iov->iov_len -= DIRHDSIZ; 1996 nfsm_mtouio(uiop, len); 1997 cp = uiop->uio_iov->iov_base; 1998 tlen -= len; 1999 *cp = '\0'; /* null terminate */ 2000 uiop->uio_iov->iov_base += tlen; 2001 uiop->uio_iov->iov_len -= tlen; 2002 uiop->uio_offset += tlen; 2003 uiop->uio_resid -= tlen; 2004 } else 2005 nfsm_adv(nfsm_rndup(len)); 2006 if (v3) { 2007 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2008 } else { 2009 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 2010 } 2011 if (bigenough) { 2012 cookie.nfsuquad[0] = *tl++; 2013 if (v3) 2014 cookie.nfsuquad[1] = *tl++; 2015 } else if (v3) 2016 tl += 2; 2017 else 2018 tl++; 2019 more_dirs = fxdr_unsigned(int, *tl); 2020 } 2021 /* 2022 * If at end of rpc data, get the eof boolean 2023 */ 2024 if (!more_dirs) { 2025 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2026 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2027 } 2028 m_freem(mrep); 2029 } 2030 /* 2031 * Fill last record, iff any, out to a multiple of DIRBLKSIZ 2032 * by increasing d_reclen for the last record. 2033 */ 2034 if (blksiz > 0) { 2035 left = DIRBLKSIZ - blksiz; 2036 dp->d_reclen += left; 2037 uiop->uio_iov->iov_base += left; 2038 uiop->uio_iov->iov_len -= left; 2039 uiop->uio_offset += left; 2040 uiop->uio_resid -= left; 2041 } 2042 2043 /* 2044 * We are now either at the end of the directory or have filled the 2045 * block. 2046 */ 2047 if (bigenough) 2048 dnp->n_direofoffset = uiop->uio_offset; 2049 else { 2050 if (uiop->uio_resid > 0) 2051 printf("EEK! readdirrpc resid > 0\n"); 2052 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2053 *cookiep = cookie; 2054 } 2055 nfsmout: 2056 return (error); 2057 } 2058 2059 /* 2060 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc(). 2061 */ 2062 int 2063 nfs_readdirplusrpc(vp, uiop, cred) 2064 struct vnode *vp; 2065 register struct uio *uiop; 2066 struct ucred *cred; 2067 { 2068 register int len, left; 2069 register struct dirent *dp; 2070 register u_long *tl; 2071 register caddr_t cp; 2072 register long t1, t2; 2073 register struct vnode *newvp; 2074 register nfsuint64 *cookiep; 2075 caddr_t bpos, dpos, cp2, dpossav1, dpossav2; 2076 struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2; 2077 struct nameidata nami, *ndp = &nami; 2078 struct componentname *cnp = &ndp->ni_cnd; 2079 nfsuint64 cookie; 2080 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2081 struct nfsnode *dnp = VTONFS(vp), *np; 2082 nfsfh_t *fhp; 2083 u_quad_t frev, fileno; 2084 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i; 2085 int cachable, attrflag, fhsize; 2086 2087 #ifndef nolint 2088 dp = (struct dirent *)0; 2089 #endif 2090 #ifndef DIAGNOSTIC 2091 if (uiop->uio_iovcnt != 1 || (uiop->uio_offset & (DIRBLKSIZ - 1)) || 2092 (uiop->uio_resid & (DIRBLKSIZ - 1))) 2093 panic("nfs readdirplusrpc bad uio"); 2094 #endif 2095 ndp->ni_dvp = vp; 2096 newvp = NULLVP; 2097 2098 /* 2099 * If there is no cookie, assume end of directory. 2100 */ 2101 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 0); 2102 if (cookiep) 2103 cookie = *cookiep; 2104 else 2105 return (0); 2106 /* 2107 * Loop around doing readdir rpc's of size nm_readdirsize 2108 * truncated to a multiple of DIRBLKSIZ. 2109 * The stopping criteria is EOF or buffer full. 2110 */ 2111 while (more_dirs && bigenough) { 2112 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++; 2113 nfsm_reqhead(vp, NFSPROC_READDIRPLUS, 2114 NFSX_FH(1) + 6 * NFSX_UNSIGNED); 2115 nfsm_fhtom(vp, 1); 2116 nfsm_build(tl, u_long *, 6 * NFSX_UNSIGNED); 2117 *tl++ = cookie.nfsuquad[0]; 2118 *tl++ = cookie.nfsuquad[1]; 2119 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2120 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2121 *tl++ = txdr_unsigned(nmp->nm_readdirsize); 2122 *tl = txdr_unsigned(nmp->nm_rsize); 2123 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred); 2124 nfsm_postop_attr(vp, attrflag); 2125 if (error) { 2126 m_freem(mrep); 2127 goto nfsmout; 2128 } 2129 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2130 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2131 dnp->n_cookieverf.nfsuquad[1] = *tl++; 2132 more_dirs = fxdr_unsigned(int, *tl); 2133 2134 /* loop thru the dir entries, doctoring them to 4bsd form */ 2135 while (more_dirs && bigenough) { 2136 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2137 fxdr_hyper(tl, &fileno); 2138 len = fxdr_unsigned(int, *(tl + 2)); 2139 if (len <= 0 || len > NFS_MAXNAMLEN) { 2140 error = EBADRPC; 2141 m_freem(mrep); 2142 goto nfsmout; 2143 } 2144 tlen = nfsm_rndup(len); 2145 if (tlen == len) 2146 tlen += 4; /* To ensure null termination*/ 2147 left = DIRBLKSIZ - blksiz; 2148 if ((tlen + DIRHDSIZ) > left) { 2149 dp->d_reclen += left; 2150 uiop->uio_iov->iov_base += left; 2151 uiop->uio_iov->iov_len -= left; 2152 uiop->uio_offset += left; 2153 uiop->uio_resid -= left; 2154 blksiz = 0; 2155 } 2156 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 2157 bigenough = 0; 2158 if (bigenough) { 2159 dp = (struct dirent *)uiop->uio_iov->iov_base; 2160 dp->d_fileno = (int)fileno; 2161 dp->d_namlen = len; 2162 dp->d_reclen = tlen + DIRHDSIZ; 2163 dp->d_type = DT_UNKNOWN; 2164 blksiz += dp->d_reclen; 2165 if (blksiz == DIRBLKSIZ) 2166 blksiz = 0; 2167 uiop->uio_offset += DIRHDSIZ; 2168 uiop->uio_resid -= DIRHDSIZ; 2169 uiop->uio_iov->iov_base += DIRHDSIZ; 2170 uiop->uio_iov->iov_len -= DIRHDSIZ; 2171 cnp->cn_nameptr = uiop->uio_iov->iov_base; 2172 cnp->cn_namelen = len; 2173 nfsm_mtouio(uiop, len); 2174 cp = uiop->uio_iov->iov_base; 2175 tlen -= len; 2176 *cp = '\0'; 2177 uiop->uio_iov->iov_base += tlen; 2178 uiop->uio_iov->iov_len -= tlen; 2179 uiop->uio_offset += tlen; 2180 uiop->uio_resid -= tlen; 2181 } else 2182 nfsm_adv(nfsm_rndup(len)); 2183 nfsm_dissect(tl, u_long *, 3 * NFSX_UNSIGNED); 2184 if (bigenough) { 2185 cookie.nfsuquad[0] = *tl++; 2186 cookie.nfsuquad[1] = *tl++; 2187 } else 2188 tl += 2; 2189 2190 /* 2191 * Since the attributes are before the file handle 2192 * (sigh), we must skip over the attributes and then 2193 * come back and get them. 2194 */ 2195 attrflag = fxdr_unsigned(int, *tl); 2196 if (attrflag) { 2197 dpossav1 = dpos; 2198 mdsav1 = md; 2199 nfsm_adv(NFSX_V3FATTR); 2200 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2201 doit = fxdr_unsigned(int, *tl); 2202 if (doit) { 2203 nfsm_getfh(fhp, fhsize, 1); 2204 if (NFS_CMPFH(dnp, fhp, fhsize)) { 2205 VREF(vp); 2206 newvp = vp; 2207 np = dnp; 2208 } else { 2209 if (error = nfs_nget(vp->v_mount, fhp, 2210 fhsize, &np)) 2211 doit = 0; 2212 else 2213 newvp = NFSTOV(np); 2214 } 2215 } 2216 if (doit) { 2217 dpossav2 = dpos; 2218 dpos = dpossav1; 2219 mdsav2 = md; 2220 md = mdsav1; 2221 nfsm_loadattr(newvp, (struct vattr *)0); 2222 dpos = dpossav2; 2223 md = mdsav2; 2224 dp->d_type = 2225 IFTODT(VTTOIF(np->n_vattr.va_type)); 2226 ndp->ni_vp = newvp; 2227 cnp->cn_hash = 0; 2228 for (cp = cnp->cn_nameptr, i = 1; i <= len; 2229 i++, cp++) 2230 cnp->cn_hash += (unsigned char)*cp * i; 2231 if (cnp->cn_namelen <= NCHNAMLEN) 2232 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp); 2233 } 2234 } else { 2235 /* Just skip over the file handle */ 2236 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2237 i = fxdr_unsigned(int, *tl); 2238 nfsm_adv(nfsm_rndup(i)); 2239 } 2240 if (newvp != NULLVP) { 2241 vrele(newvp); 2242 newvp = NULLVP; 2243 } 2244 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2245 more_dirs = fxdr_unsigned(int, *tl); 2246 } 2247 /* 2248 * If at end of rpc data, get the eof boolean 2249 */ 2250 if (!more_dirs) { 2251 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2252 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2253 } 2254 m_freem(mrep); 2255 } 2256 /* 2257 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 2258 * by increasing d_reclen for the last record. 2259 */ 2260 if (blksiz > 0) { 2261 left = DIRBLKSIZ - blksiz; 2262 dp->d_reclen += left; 2263 uiop->uio_iov->iov_base += left; 2264 uiop->uio_iov->iov_len -= left; 2265 uiop->uio_offset += left; 2266 uiop->uio_resid -= left; 2267 } 2268 2269 /* 2270 * We are now either at the end of the directory or have filled the 2271 * block. 2272 */ 2273 if (bigenough) 2274 dnp->n_direofoffset = uiop->uio_offset; 2275 else { 2276 if (uiop->uio_resid > 0) 2277 printf("EEK! readdirplusrpc resid > 0\n"); 2278 cookiep = nfs_getcookie(dnp, uiop->uio_offset, 1); 2279 *cookiep = cookie; 2280 } 2281 nfsmout: 2282 if (newvp != NULLVP) 2283 vrele(newvp); 2284 return (error); 2285 } 2286 static char hextoasc[] = "0123456789abcdef"; 2287 2288 /* 2289 * Silly rename. To make the NFS filesystem that is stateless look a little 2290 * more like the "ufs" a remove of an active vnode is translated to a rename 2291 * to a funny looking filename that is removed by nfs_inactive on the 2292 * nfsnode. There is the potential for another process on a different client 2293 * to create the same funny name between the nfs_lookitup() fails and the 2294 * nfs_rename() completes, but... 2295 */ 2296 int 2297 nfs_sillyrename(dvp, vp, cnp) 2298 struct vnode *dvp, *vp; 2299 struct componentname *cnp; 2300 { 2301 register struct sillyrename *sp; 2302 struct nfsnode *np; 2303 int error; 2304 short pid; 2305 2306 cache_purge(dvp); 2307 np = VTONFS(vp); 2308 #ifndef DIAGNOSTIC 2309 if (vp->v_type == VDIR) 2310 panic("nfs: sillyrename dir"); 2311 #endif 2312 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 2313 M_NFSREQ, M_WAITOK); 2314 sp->s_cred = crdup(cnp->cn_cred); 2315 sp->s_dvp = dvp; 2316 VREF(dvp); 2317 2318 /* Fudge together a funny name */ 2319 pid = cnp->cn_proc->p_pid; 2320 bcopy(".nfsAxxxx4.4", sp->s_name, 13); 2321 sp->s_namlen = 12; 2322 sp->s_name[8] = hextoasc[pid & 0xf]; 2323 sp->s_name[7] = hextoasc[(pid >> 4) & 0xf]; 2324 sp->s_name[6] = hextoasc[(pid >> 8) & 0xf]; 2325 sp->s_name[5] = hextoasc[(pid >> 12) & 0xf]; 2326 2327 /* Try lookitups until we get one that isn't there */ 2328 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2329 cnp->cn_proc, (struct nfsnode **)0) == 0) { 2330 sp->s_name[4]++; 2331 if (sp->s_name[4] > 'z') { 2332 error = EINVAL; 2333 goto bad; 2334 } 2335 } 2336 if (error = nfs_renameit(dvp, cnp, sp)) 2337 goto bad; 2338 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2339 cnp->cn_proc, &np); 2340 np->n_sillyrename = sp; 2341 return (0); 2342 bad: 2343 vrele(sp->s_dvp); 2344 crfree(sp->s_cred); 2345 free((caddr_t)sp, M_NFSREQ); 2346 return (error); 2347 } 2348 2349 /* 2350 * Look up a file name and optionally either update the file handle or 2351 * allocate an nfsnode, depending on the value of npp. 2352 * npp == NULL --> just do the lookup 2353 * *npp == NULL --> allocate a new nfsnode and make sure attributes are 2354 * handled too 2355 * *npp != NULL --> update the file handle in the vnode 2356 */ 2357 int 2358 nfs_lookitup(dvp, name, len, cred, procp, npp) 2359 register struct vnode *dvp; 2360 char *name; 2361 int len; 2362 struct ucred *cred; 2363 struct proc *procp; 2364 struct nfsnode **npp; 2365 { 2366 register u_long *tl; 2367 register caddr_t cp; 2368 register long t1, t2; 2369 struct vnode *newvp = (struct vnode *)0; 2370 struct nfsnode *np, *dnp = VTONFS(dvp); 2371 caddr_t bpos, dpos, cp2; 2372 int error = 0, fhlen, attrflag; 2373 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2374 nfsfh_t *nfhp; 2375 int v3 = NFS_ISV3(dvp); 2376 2377 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 2378 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 2379 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 2380 nfsm_fhtom(dvp, v3); 2381 nfsm_strtom(name, len, NFS_MAXNAMLEN); 2382 nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred); 2383 if (npp && !error) { 2384 nfsm_getfh(nfhp, fhlen, v3); 2385 if (*npp) { 2386 np = *npp; 2387 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) { 2388 free((caddr_t)np->n_fhp, M_NFSBIGFH); 2389 np->n_fhp = &np->n_fh; 2390 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH) 2391 np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK); 2392 bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen); 2393 np->n_fhsize = fhlen; 2394 newvp = NFSTOV(np); 2395 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) { 2396 VREF(dvp); 2397 newvp = dvp; 2398 } else { 2399 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np); 2400 if (error) { 2401 m_freem(mrep); 2402 return (error); 2403 } 2404 newvp = NFSTOV(np); 2405 } 2406 if (v3) { 2407 nfsm_postop_attr(newvp, attrflag); 2408 if (!attrflag && *npp == NULL) { 2409 m_freem(mrep); 2410 vrele(newvp); 2411 return (ENOENT); 2412 } 2413 } else 2414 nfsm_loadattr(newvp, (struct vattr *)0); 2415 } 2416 nfsm_reqdone; 2417 if (npp && *npp == NULL) { 2418 if (error) { 2419 if (newvp) 2420 vrele(newvp); 2421 } else 2422 *npp = np; 2423 } 2424 return (error); 2425 } 2426 2427 /* 2428 * Nfs Version 3 commit rpc 2429 */ 2430 int 2431 nfs_commit(vp, offset, cnt, cred, procp) 2432 register struct vnode *vp; 2433 u_quad_t offset; 2434 int cnt; 2435 struct ucred *cred; 2436 struct proc *procp; 2437 { 2438 register caddr_t cp; 2439 register u_long *tl; 2440 register int t1, t2; 2441 register struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2442 caddr_t bpos, dpos, cp2; 2443 int error = 0, wccflag = NFSV3_WCCRATTR; 2444 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2445 2446 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) 2447 return (0); 2448 nfsstats.rpccnt[NFSPROC_COMMIT]++; 2449 nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1)); 2450 nfsm_fhtom(vp, 1); 2451 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 2452 txdr_hyper(&offset, tl); 2453 tl += 2; 2454 *tl = txdr_unsigned(cnt); 2455 nfsm_request(vp, NFSPROC_COMMIT, procp, cred); 2456 nfsm_wcc_data(vp, wccflag); 2457 if (!error) { 2458 nfsm_dissect(tl, u_long *, NFSX_V3WRITEVERF); 2459 if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl, 2460 NFSX_V3WRITEVERF)) { 2461 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 2462 NFSX_V3WRITEVERF); 2463 error = NFSERR_STALEWRITEVERF; 2464 } 2465 } 2466 nfsm_reqdone; 2467 return (error); 2468 } 2469 2470 /* 2471 * Kludge City.. 2472 * - make nfs_bmap() essentially a no-op that does no translation 2473 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc 2474 * (Maybe I could use the process's page mapping, but I was concerned that 2475 * Kernel Write might not be enabled and also figured copyout() would do 2476 * a lot more work than bcopy() and also it currently happens in the 2477 * context of the swapper process (2). 2478 */ 2479 int 2480 nfs_bmap(ap) 2481 struct vop_bmap_args /* { 2482 struct vnode *a_vp; 2483 daddr_t a_bn; 2484 struct vnode **a_vpp; 2485 daddr_t *a_bnp; 2486 int *a_runp; 2487 } */ *ap; 2488 { 2489 register struct vnode *vp = ap->a_vp; 2490 2491 if (ap->a_vpp != NULL) 2492 *ap->a_vpp = vp; 2493 if (ap->a_bnp != NULL) 2494 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize); 2495 return (0); 2496 } 2497 2498 /* 2499 * Strategy routine. 2500 * For async requests when nfsiod(s) are running, queue the request by 2501 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the 2502 * request. 2503 */ 2504 int 2505 nfs_strategy(ap) 2506 struct vop_strategy_args *ap; 2507 { 2508 register struct buf *bp = ap->a_bp; 2509 struct ucred *cr; 2510 struct proc *p; 2511 int error = 0; 2512 2513 if (bp->b_flags & B_PHYS) 2514 panic("nfs physio"); 2515 if (bp->b_flags & B_ASYNC) 2516 p = (struct proc *)0; 2517 else 2518 p = curproc; /* XXX */ 2519 if (bp->b_flags & B_READ) 2520 cr = bp->b_rcred; 2521 else 2522 cr = bp->b_wcred; 2523 /* 2524 * If the op is asynchronous and an i/o daemon is waiting 2525 * queue the request, wake it up and wait for completion 2526 * otherwise just do it ourselves. 2527 */ 2528 if ((bp->b_flags & B_ASYNC) == 0 || 2529 nfs_asyncio(bp, NOCRED)) 2530 error = nfs_doio(bp, cr, p); 2531 return (error); 2532 } 2533 2534 /* 2535 * Mmap a file 2536 * 2537 * NB Currently unsupported. 2538 */ 2539 /* ARGSUSED */ 2540 int 2541 nfs_mmap(ap) 2542 struct vop_mmap_args /* { 2543 struct vnode *a_vp; 2544 int a_fflags; 2545 struct ucred *a_cred; 2546 struct proc *a_p; 2547 } */ *ap; 2548 { 2549 2550 return (EINVAL); 2551 } 2552 2553 /* 2554 * fsync vnode op. Just call nfs_flush() with commit == 1. 2555 */ 2556 /* ARGSUSED */ 2557 int 2558 nfs_fsync(ap) 2559 struct vop_fsync_args /* { 2560 struct vnodeop_desc *a_desc; 2561 struct vnode * a_vp; 2562 struct ucred * a_cred; 2563 int a_waitfor; 2564 struct proc * a_p; 2565 } */ *ap; 2566 { 2567 2568 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1)); 2569 } 2570 2571 /* 2572 * Flush all the blocks associated with a vnode. 2573 * Walk through the buffer pool and push any dirty pages 2574 * associated with the vnode. 2575 */ 2576 int 2577 nfs_flush(vp, cred, waitfor, p, commit) 2578 register struct vnode *vp; 2579 struct ucred *cred; 2580 int waitfor; 2581 struct proc *p; 2582 int commit; 2583 { 2584 register struct nfsnode *np = VTONFS(vp); 2585 register struct buf *bp; 2586 register int i; 2587 struct buf *nbp; 2588 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2589 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos; 2590 int passone = 1; 2591 u_quad_t off = (u_quad_t)-1, endoff = 0, toff; 2592 #ifndef NFS_COMMITBVECSIZ 2593 #define NFS_COMMITBVECSIZ 20 2594 #endif 2595 struct buf *bvec[NFS_COMMITBVECSIZ]; 2596 2597 if (nmp->nm_flag & NFSMNT_INT) 2598 slpflag = PCATCH; 2599 if (!commit) 2600 passone = 0; 2601 /* 2602 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the 2603 * server, but nas not been committed to stable storage on the server 2604 * yet. On the first pass, the byte range is worked out and the commit 2605 * rpc is done. On the second pass, nfs_writebp() is called to do the 2606 * job. 2607 */ 2608 again: 2609 bvecpos = 0; 2610 if (NFS_ISV3(vp) && commit) { 2611 s = splbio(); 2612 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2613 nbp = bp->b_vnbufs.le_next; 2614 if (bvecpos >= NFS_COMMITBVECSIZ) 2615 break; 2616 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2617 != (B_DELWRI | B_NEEDCOMMIT)) 2618 continue; 2619 bremfree(bp); 2620 bp->b_flags |= (B_BUSY | B_WRITEINPROG); 2621 /* 2622 * A list of these buffers is kept so that the 2623 * second loop knows which buffers have actually 2624 * been committed. This is necessary, since there 2625 * may be a race between the commit rpc and new 2626 * uncommitted writes on the file. 2627 */ 2628 bvec[bvecpos++] = bp; 2629 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2630 bp->b_dirtyoff; 2631 if (toff < off) 2632 off = toff; 2633 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff); 2634 if (toff > endoff) 2635 endoff = toff; 2636 } 2637 splx(s); 2638 } 2639 if (bvecpos > 0) { 2640 /* 2641 * Commit data on the server, as required. 2642 */ 2643 retv = nfs_commit(vp, off, (int)(endoff - off), cred, p); 2644 if (retv == NFSERR_STALEWRITEVERF) 2645 nfs_clearcommit(vp->v_mount); 2646 /* 2647 * Now, either mark the blocks I/O done or mark the 2648 * blocks dirty, depending on whether the commit 2649 * succeeded. 2650 */ 2651 for (i = 0; i < bvecpos; i++) { 2652 bp = bvec[i]; 2653 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG); 2654 if (retv) { 2655 brelse(bp); 2656 } else { 2657 vp->v_numoutput++; 2658 bp->b_flags |= B_ASYNC; 2659 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 2660 bp->b_dirtyoff = bp->b_dirtyend = 0; 2661 reassignbuf(bp, vp); 2662 biodone(bp); 2663 } 2664 } 2665 } 2666 2667 /* 2668 * Start/do any write(s) that are required. 2669 */ 2670 loop: 2671 s = splbio(); 2672 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2673 nbp = bp->b_vnbufs.le_next; 2674 if (bp->b_flags & B_BUSY) { 2675 if (waitfor != MNT_WAIT || passone) 2676 continue; 2677 bp->b_flags |= B_WANTED; 2678 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), 2679 "nfsfsync", slptimeo); 2680 splx(s); 2681 if (error) { 2682 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) 2683 return (EINTR); 2684 if (slpflag == PCATCH) { 2685 slpflag = 0; 2686 slptimeo = 2 * hz; 2687 } 2688 } 2689 goto loop; 2690 } 2691 if ((bp->b_flags & B_DELWRI) == 0) 2692 panic("nfs_fsync: not dirty"); 2693 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) 2694 continue; 2695 bremfree(bp); 2696 if (passone || !commit) 2697 bp->b_flags |= (B_BUSY|B_ASYNC); 2698 else 2699 bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT); 2700 splx(s); 2701 VOP_BWRITE(bp); 2702 goto loop; 2703 } 2704 splx(s); 2705 if (passone) { 2706 passone = 0; 2707 goto again; 2708 } 2709 if (waitfor == MNT_WAIT) { 2710 while (vp->v_numoutput) { 2711 vp->v_flag |= VBWAIT; 2712 error = tsleep((caddr_t)&vp->v_numoutput, 2713 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); 2714 if (error) { 2715 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) 2716 return (EINTR); 2717 if (slpflag == PCATCH) { 2718 slpflag = 0; 2719 slptimeo = 2 * hz; 2720 } 2721 } 2722 } 2723 if (vp->v_dirtyblkhd.lh_first && commit) { 2724 #ifndef DIAGNOSTIC 2725 vprint("nfs_fsync: dirty", vp); 2726 #endif 2727 goto loop; 2728 } 2729 } 2730 if (np->n_flag & NWRITEERR) { 2731 error = np->n_error; 2732 np->n_flag &= ~NWRITEERR; 2733 } 2734 return (error); 2735 } 2736 2737 /* 2738 * Return POSIX pathconf information applicable to nfs. 2739 * 2740 * The NFS V2 protocol doesn't support this, so just return EINVAL 2741 * for V2. 2742 */ 2743 /* ARGSUSED */ 2744 int 2745 nfs_pathconf(ap) 2746 struct vop_pathconf_args /* { 2747 struct vnode *a_vp; 2748 int a_name; 2749 int *a_retval; 2750 } */ *ap; 2751 { 2752 2753 return (EINVAL); 2754 } 2755 2756 /* 2757 * NFS advisory byte-level locks. 2758 * Currently unsupported. 2759 */ 2760 int 2761 nfs_advlock(ap) 2762 struct vop_advlock_args /* { 2763 struct vnode *a_vp; 2764 caddr_t a_id; 2765 int a_op; 2766 struct flock *a_fl; 2767 int a_flags; 2768 } */ *ap; 2769 { 2770 2771 return (EOPNOTSUPP); 2772 } 2773 2774 /* 2775 * Print out the contents of an nfsnode. 2776 */ 2777 int 2778 nfs_print(ap) 2779 struct vop_print_args /* { 2780 struct vnode *a_vp; 2781 } */ *ap; 2782 { 2783 register struct vnode *vp = ap->a_vp; 2784 register struct nfsnode *np = VTONFS(vp); 2785 2786 printf("tag VT_NFS, fileid %ld fsid 0x%lx", 2787 np->n_vattr.va_fileid, np->n_vattr.va_fsid); 2788 if (vp->v_type == VFIFO) 2789 fifo_printinfo(vp); 2790 printf("\n"); 2791 return (0); 2792 } 2793 2794 /* 2795 * NFS directory offset lookup. 2796 * Currently unsupported. 2797 */ 2798 int 2799 nfs_blkatoff(ap) 2800 struct vop_blkatoff_args /* { 2801 struct vnode *a_vp; 2802 off_t a_offset; 2803 char **a_res; 2804 struct buf **a_bpp; 2805 } */ *ap; 2806 { 2807 2808 return (EOPNOTSUPP); 2809 } 2810 2811 /* 2812 * NFS flat namespace allocation. 2813 * Currently unsupported. 2814 */ 2815 int 2816 nfs_valloc(ap) 2817 struct vop_valloc_args /* { 2818 struct vnode *a_pvp; 2819 int a_mode; 2820 struct ucred *a_cred; 2821 struct vnode **a_vpp; 2822 } */ *ap; 2823 { 2824 2825 return (EOPNOTSUPP); 2826 } 2827 2828 /* 2829 * NFS flat namespace free. 2830 * Currently unsupported. 2831 */ 2832 int 2833 nfs_vfree(ap) 2834 struct vop_vfree_args /* { 2835 struct vnode *a_pvp; 2836 ino_t a_ino; 2837 int a_mode; 2838 } */ *ap; 2839 { 2840 2841 return (EOPNOTSUPP); 2842 } 2843 2844 /* 2845 * NFS file truncation. 2846 */ 2847 int 2848 nfs_truncate(ap) 2849 struct vop_truncate_args /* { 2850 struct vnode *a_vp; 2851 off_t a_length; 2852 int a_flags; 2853 struct ucred *a_cred; 2854 struct proc *a_p; 2855 } */ *ap; 2856 { 2857 2858 /* Use nfs_setattr */ 2859 printf("nfs_truncate: need to implement!!"); 2860 return (EOPNOTSUPP); 2861 } 2862 2863 /* 2864 * NFS update. 2865 */ 2866 int 2867 nfs_update(ap) 2868 struct vop_update_args /* { 2869 struct vnode *a_vp; 2870 struct timeval *a_ta; 2871 struct timeval *a_tm; 2872 int a_waitfor; 2873 } */ *ap; 2874 { 2875 2876 /* Use nfs_setattr */ 2877 printf("nfs_update: need to implement!!"); 2878 return (EOPNOTSUPP); 2879 } 2880 2881 /* 2882 * Just call nfs_writebp() with the force argument set to 1. 2883 */ 2884 int 2885 nfs_bwrite(ap) 2886 struct vop_bwrite_args /* { 2887 struct vnode *a_bp; 2888 } */ *ap; 2889 { 2890 2891 return (nfs_writebp(ap->a_bp, 1)); 2892 } 2893 2894 /* 2895 * This is a clone of vn_bwrite(), except that B_WRITEINPROG isn't set unless 2896 * the force flag is one and it also handles the B_NEEDCOMMIT flag. 2897 */ 2898 int 2899 nfs_writebp(bp, force) 2900 register struct buf *bp; 2901 int force; 2902 { 2903 register int oldflags = bp->b_flags, retv = 1; 2904 register struct proc *p = curproc; /* XXX */ 2905 off_t off; 2906 2907 if(!(bp->b_flags & B_BUSY)) 2908 panic("bwrite: buffer is not busy???"); 2909 2910 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR|B_DELWRI); 2911 2912 if (oldflags & B_ASYNC) { 2913 if (oldflags & B_DELWRI) { 2914 reassignbuf(bp, bp->b_vp); 2915 } else if (p) { 2916 ++p->p_stats->p_ru.ru_oublock; 2917 } 2918 } 2919 bp->b_vp->v_numoutput++; 2920 2921 /* 2922 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not 2923 * an actual write will have to be scheduled via. VOP_STRATEGY(). 2924 * If B_WRITEINPROG is already set, then push it with a write anyhow. 2925 */ 2926 if (oldflags & (B_NEEDCOMMIT | B_WRITEINPROG) == B_NEEDCOMMIT) { 2927 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff; 2928 bp->b_flags |= B_WRITEINPROG; 2929 retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff, 2930 bp->b_wcred, bp->b_proc); 2931 bp->b_flags &= ~B_WRITEINPROG; 2932 if (!retv) { 2933 bp->b_dirtyoff = bp->b_dirtyend = 0; 2934 bp->b_flags &= ~B_NEEDCOMMIT; 2935 biodone(bp); 2936 } else if (retv == NFSERR_STALEWRITEVERF) 2937 nfs_clearcommit(bp->b_vp->v_mount); 2938 } 2939 if (retv) { 2940 if (force) 2941 bp->b_flags |= B_WRITEINPROG; 2942 VOP_STRATEGY(bp); 2943 } 2944 2945 if( (oldflags & B_ASYNC) == 0) { 2946 int rtval = biowait(bp); 2947 if (oldflags & B_DELWRI) { 2948 reassignbuf(bp, bp->b_vp); 2949 } else if (p) { 2950 ++p->p_stats->p_ru.ru_oublock; 2951 } 2952 brelse(bp); 2953 return (rtval); 2954 } 2955 2956 return (0); 2957 } 2958 2959 /* 2960 * nfs special file access vnode op. 2961 * Essentially just get vattr and then imitate iaccess() since the device is 2962 * local to the client. 2963 */ 2964 int 2965 nfsspec_access(ap) 2966 struct vop_access_args /* { 2967 struct vnode *a_vp; 2968 int a_mode; 2969 struct ucred *a_cred; 2970 struct proc *a_p; 2971 } */ *ap; 2972 { 2973 register struct vattr *vap; 2974 register gid_t *gp; 2975 register struct ucred *cred = ap->a_cred; 2976 mode_t mode = ap->a_mode; 2977 struct vattr vattr; 2978 register int i; 2979 int error; 2980 2981 /* 2982 * If you're the super-user, 2983 * you always get access. 2984 */ 2985 if (cred->cr_uid == 0) 2986 return (0); 2987 vap = &vattr; 2988 error = VOP_GETATTR(ap->a_vp, vap, cred, ap->a_p); 2989 if (error) 2990 return (error); 2991 /* 2992 * Access check is based on only one of owner, group, public. 2993 * If not owner, then check group. If not a member of the 2994 * group, then check public access. 2995 */ 2996 if (cred->cr_uid != vap->va_uid) { 2997 mode >>= 3; 2998 gp = cred->cr_groups; 2999 for (i = 0; i < cred->cr_ngroups; i++, gp++) 3000 if (vap->va_gid == *gp) 3001 goto found; 3002 mode >>= 3; 3003 found: 3004 ; 3005 } 3006 error = (vap->va_mode & mode) == mode ? 0 : EACCES; 3007 return (error); 3008 } 3009 3010 /* 3011 * Read wrapper for special devices. 3012 */ 3013 int 3014 nfsspec_read(ap) 3015 struct vop_read_args /* { 3016 struct vnode *a_vp; 3017 struct uio *a_uio; 3018 int a_ioflag; 3019 struct ucred *a_cred; 3020 } */ *ap; 3021 { 3022 register struct nfsnode *np = VTONFS(ap->a_vp); 3023 3024 /* 3025 * Set access flag. 3026 */ 3027 np->n_flag |= NACC; 3028 np->n_atim.ts_sec = time.tv_sec; 3029 np->n_atim.ts_nsec = time.tv_usec * 1000; 3030 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap)); 3031 } 3032 3033 /* 3034 * Write wrapper for special devices. 3035 */ 3036 int 3037 nfsspec_write(ap) 3038 struct vop_write_args /* { 3039 struct vnode *a_vp; 3040 struct uio *a_uio; 3041 int a_ioflag; 3042 struct ucred *a_cred; 3043 } */ *ap; 3044 { 3045 register struct nfsnode *np = VTONFS(ap->a_vp); 3046 3047 /* 3048 * Set update flag. 3049 */ 3050 np->n_flag |= NUPD; 3051 np->n_mtim.ts_sec = time.tv_sec; 3052 np->n_mtim.ts_nsec = time.tv_usec * 1000; 3053 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap)); 3054 } 3055 3056 /* 3057 * Close wrapper for special devices. 3058 * 3059 * Update the times on the nfsnode then do device close. 3060 */ 3061 int 3062 nfsspec_close(ap) 3063 struct vop_close_args /* { 3064 struct vnode *a_vp; 3065 int a_fflag; 3066 struct ucred *a_cred; 3067 struct proc *a_p; 3068 } */ *ap; 3069 { 3070 register struct vnode *vp = ap->a_vp; 3071 register struct nfsnode *np = VTONFS(vp); 3072 struct vattr vattr; 3073 3074 if (np->n_flag & (NACC | NUPD)) { 3075 np->n_flag |= NCHG; 3076 if (vp->v_usecount == 1 && 3077 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3078 VATTR_NULL(&vattr); 3079 if (np->n_flag & NACC) 3080 vattr.va_atime = np->n_atim; 3081 if (np->n_flag & NUPD) 3082 vattr.va_mtime = np->n_mtim; 3083 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3084 } 3085 } 3086 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 3087 } 3088 3089 /* 3090 * Read wrapper for fifos. 3091 */ 3092 int 3093 nfsfifo_read(ap) 3094 struct vop_read_args /* { 3095 struct vnode *a_vp; 3096 struct uio *a_uio; 3097 int a_ioflag; 3098 struct ucred *a_cred; 3099 } */ *ap; 3100 { 3101 extern int (**fifo_vnodeop_p)(); 3102 register struct nfsnode *np = VTONFS(ap->a_vp); 3103 3104 /* 3105 * Set access flag. 3106 */ 3107 np->n_flag |= NACC; 3108 np->n_atim.ts_sec = time.tv_sec; 3109 np->n_atim.ts_nsec = time.tv_usec * 1000; 3110 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap)); 3111 } 3112 3113 /* 3114 * Write wrapper for fifos. 3115 */ 3116 int 3117 nfsfifo_write(ap) 3118 struct vop_write_args /* { 3119 struct vnode *a_vp; 3120 struct uio *a_uio; 3121 int a_ioflag; 3122 struct ucred *a_cred; 3123 } */ *ap; 3124 { 3125 extern int (**fifo_vnodeop_p)(); 3126 register struct nfsnode *np = VTONFS(ap->a_vp); 3127 3128 /* 3129 * Set update flag. 3130 */ 3131 np->n_flag |= NUPD; 3132 np->n_mtim.ts_sec = time.tv_sec; 3133 np->n_mtim.ts_nsec = time.tv_usec * 1000; 3134 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap)); 3135 } 3136 3137 /* 3138 * Close wrapper for fifos. 3139 * 3140 * Update the times on the nfsnode then do fifo close. 3141 */ 3142 int 3143 nfsfifo_close(ap) 3144 struct vop_close_args /* { 3145 struct vnode *a_vp; 3146 int a_fflag; 3147 struct ucred *a_cred; 3148 struct proc *a_p; 3149 } */ *ap; 3150 { 3151 register struct vnode *vp = ap->a_vp; 3152 register struct nfsnode *np = VTONFS(vp); 3153 struct vattr vattr; 3154 extern int (**fifo_vnodeop_p)(); 3155 3156 if (np->n_flag & (NACC | NUPD)) { 3157 if (np->n_flag & NACC) { 3158 np->n_atim.ts_sec = time.tv_sec; 3159 np->n_atim.ts_nsec = time.tv_usec * 1000; 3160 } 3161 if (np->n_flag & NUPD) { 3162 np->n_mtim.ts_sec = time.tv_sec; 3163 np->n_mtim.ts_nsec = time.tv_usec * 1000; 3164 } 3165 np->n_flag |= NCHG; 3166 if (vp->v_usecount == 1 && 3167 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3168 VATTR_NULL(&vattr); 3169 if (np->n_flag & NACC) 3170 vattr.va_atime = np->n_atim; 3171 if (np->n_flag & NUPD) 3172 vattr.va_mtime = np->n_mtim; 3173 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3174 } 3175 } 3176 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 3177 } 3178