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