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