1 /* $OpenBSD: nfs_vnops.c,v 1.164 2015/05/03 02:02:15 guenther 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, 0, 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, 0, 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, 0, 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, 0, 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, 0, 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); 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 = uiomovei(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) 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 ndp->ni_dvp = vp; 2291 newvp = NULLVP; 2292 2293 txdr_hyper(uiop->uio_offset, &cookie.nfsuquad[0]); 2294 2295 /* 2296 * Loop around doing readdir rpc's of size nm_readdirsize 2297 * truncated to a multiple of NFS_READDIRBLKSIZ. 2298 * The stopping criteria is EOF or buffer full. 2299 */ 2300 while (more_dirs && bigenough) { 2301 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++; 2302 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(1) + 6 * NFSX_UNSIGNED); 2303 nfsm_fhtom(&info, vp, 1); 2304 tl = nfsm_build(&info.nmi_mb, 6 * NFSX_UNSIGNED); 2305 *tl++ = cookie.nfsuquad[0]; 2306 *tl++ = cookie.nfsuquad[1]; 2307 if (cookie.nfsuquad[0] == 0 && 2308 cookie.nfsuquad[1] == 0) { 2309 *tl++ = 0; 2310 *tl++ = 0; 2311 } else { 2312 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2313 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2314 } 2315 *tl++ = txdr_unsigned(nmp->nm_readdirsize); 2316 *tl = txdr_unsigned(nmp->nm_rsize); 2317 2318 info.nmi_procp = uiop->uio_procp; 2319 info.nmi_cred = cred; 2320 error = nfs_request(vp, NFSPROC_READDIRPLUS, &info); 2321 nfsm_postop_attr(vp, attrflag); 2322 if (error) { 2323 m_freem(info.nmi_mrep); 2324 goto nfsmout; 2325 } 2326 2327 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2328 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2329 dnp->n_cookieverf.nfsuquad[1] = *tl++; 2330 more_dirs = fxdr_unsigned(int, *tl); 2331 2332 /* loop thru the dir entries, doctoring them to 4bsd form */ 2333 while (more_dirs && bigenough) { 2334 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2335 fileno = fxdr_hyper(tl); 2336 len = fxdr_unsigned(int, *(tl + 2)); 2337 if (len <= 0 || len > NFS_MAXNAMLEN) { 2338 error = EBADRPC; 2339 m_freem(info.nmi_mrep); 2340 goto nfsmout; 2341 } 2342 tlen = DIRENT_RECSIZE(len) + NFS_DIRENT_OVERHEAD; 2343 left = NFS_READDIRBLKSIZ - blksiz; 2344 if (tlen > left) { 2345 dp->d_reclen += left; 2346 uiop->uio_iov->iov_base = 2347 (char *)uiop->uio_iov->iov_base + left; 2348 uiop->uio_iov->iov_len -= left; 2349 uiop->uio_resid -= left; 2350 blksiz = 0; 2351 } 2352 if (tlen > uiop->uio_resid) 2353 bigenough = 0; 2354 if (bigenough) { 2355 ndirp = (struct nfs_dirent *) 2356 uiop->uio_iov->iov_base; 2357 dp = &ndirp->dirent; 2358 dp->d_fileno = fileno; 2359 dp->d_namlen = len; 2360 dp->d_reclen = tlen; 2361 dp->d_type = DT_UNKNOWN; 2362 blksiz += tlen; 2363 if (blksiz == NFS_READDIRBLKSIZ) 2364 blksiz = 0; 2365 uiop->uio_resid -= NFS_DIRHDSIZ; 2366 uiop->uio_iov->iov_base = 2367 (char *)uiop->uio_iov->iov_base + 2368 NFS_DIRHDSIZ; 2369 uiop->uio_iov->iov_len -= NFS_DIRHDSIZ; 2370 cnp->cn_nameptr = uiop->uio_iov->iov_base; 2371 cnp->cn_namelen = len; 2372 nfsm_mtouio(uiop, len); 2373 cp = uiop->uio_iov->iov_base; 2374 tlen -= NFS_DIRHDSIZ + len; 2375 *cp = '\0'; 2376 uiop->uio_iov->iov_base += tlen; 2377 uiop->uio_iov->iov_len -= tlen; 2378 uiop->uio_resid -= tlen; 2379 } else 2380 nfsm_adv(nfsm_rndup(len)); 2381 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2382 if (bigenough) { 2383 ndirp->cookie[0] = cookie.nfsuquad[0] = *tl++; 2384 ndirp->cookie[1] = cookie.nfsuquad[1] = *tl++; 2385 } else 2386 tl += 2; 2387 2388 /* 2389 * Since the attributes are before the file handle 2390 * (sigh), we must skip over the attributes and then 2391 * come back and get them. 2392 */ 2393 attrflag = fxdr_unsigned(int, *tl); 2394 if (attrflag) { 2395 dpossav1 = info.nmi_dpos; 2396 mdsav1 = info.nmi_md; 2397 nfsm_adv(NFSX_V3FATTR); 2398 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2399 doit = fxdr_unsigned(int, *tl); 2400 if (doit) { 2401 nfsm_getfh(fhp, fhsize, 1); 2402 if (NFS_CMPFH(dnp, fhp, fhsize)) { 2403 vref(vp); 2404 newvp = vp; 2405 np = dnp; 2406 } else { 2407 error = nfs_nget(vp->v_mount, 2408 fhp, fhsize, &np); 2409 if (error) 2410 doit = 0; 2411 else 2412 newvp = NFSTOV(np); 2413 } 2414 } 2415 if (doit && bigenough) { 2416 dpossav2 = info.nmi_dpos; 2417 info.nmi_dpos = dpossav1; 2418 mdsav2 = info.nmi_md; 2419 info.nmi_md = mdsav1; 2420 nfsm_loadattr(newvp, NULL); 2421 info.nmi_dpos = dpossav2; 2422 info.nmi_md = mdsav2; 2423 dp->d_type = IFTODT( 2424 VTTOIF(np->n_vattr.va_type)); 2425 if (cnp->cn_namelen <= 2426 NAMECACHE_MAXLEN) { 2427 ndp->ni_vp = newvp; 2428 cache_purge(ndp->ni_dvp); 2429 nfs_cache_enter(ndp->ni_dvp, 2430 ndp->ni_vp, cnp); 2431 } 2432 } 2433 } else { 2434 /* Just skip over the file handle */ 2435 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2436 i = fxdr_unsigned(int, *tl); 2437 nfsm_adv(nfsm_rndup(i)); 2438 } 2439 if (newvp != NULLVP) { 2440 vrele(newvp); 2441 newvp = NULLVP; 2442 } 2443 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2444 more_dirs = fxdr_unsigned(int, *tl); 2445 } 2446 /* 2447 * If at end of rpc data, get the eof boolean 2448 */ 2449 if (!more_dirs) { 2450 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2451 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2452 } 2453 m_freem(info.nmi_mrep); 2454 } 2455 /* 2456 * Fill last record, iff any, out to a multiple of NFS_READDIRBLKSIZ 2457 * by increasing d_reclen for the last record. 2458 */ 2459 if (blksiz > 0) { 2460 left = NFS_READDIRBLKSIZ - blksiz; 2461 dp->d_reclen += left; 2462 uiop->uio_iov->iov_base = (char *)uiop->uio_iov->iov_base + 2463 left; 2464 uiop->uio_iov->iov_len -= left; 2465 uiop->uio_resid -= left; 2466 } 2467 2468 /* 2469 * We are now either at the end of the directory or have filled the 2470 * block. 2471 */ 2472 if (bigenough) { 2473 dnp->n_direofoffset = fxdr_hyper(&cookie.nfsuquad[0]); 2474 if (end_of_directory) *end_of_directory = 1; 2475 } else { 2476 if (uiop->uio_resid > 0) 2477 printf("EEK! readdirplusrpc resid > 0\n"); 2478 } 2479 2480 nfsmout: 2481 if (newvp != NULLVP) 2482 vrele(newvp); 2483 return (error); 2484 } 2485 2486 /* 2487 * Silly rename. To make the NFS filesystem that is stateless look a little 2488 * more like the "ufs" a remove of an active vnode is translated to a rename 2489 * to a funny looking filename that is removed by nfs_inactive on the 2490 * nfsnode. There is the potential for another process on a different client 2491 * to create the same funny name between the nfs_lookitup() fails and the 2492 * nfs_rename() completes, but... 2493 */ 2494 int 2495 nfs_sillyrename(struct vnode *dvp, struct vnode *vp, struct componentname *cnp) 2496 { 2497 struct sillyrename *sp; 2498 struct nfsnode *np; 2499 int error; 2500 2501 cache_purge(dvp); 2502 np = VTONFS(vp); 2503 sp = malloc(sizeof(*sp), M_NFSREQ, M_WAITOK); 2504 sp->s_cred = crdup(cnp->cn_cred); 2505 sp->s_dvp = dvp; 2506 vref(dvp); 2507 2508 if (vp->v_type == VDIR) { 2509 #ifdef DIAGNOSTIC 2510 printf("nfs: sillyrename dir\n"); 2511 #endif 2512 error = EINVAL; 2513 goto bad; 2514 } 2515 2516 /* Try lookitups until we get one that isn't there */ 2517 while (1) { 2518 /* Fudge together a funny name */ 2519 u_int32_t rnd[2]; 2520 2521 arc4random_buf(&rnd, sizeof rnd); 2522 sp->s_namlen = snprintf(sp->s_name, sizeof sp->s_name, 2523 ".nfs%08X%08X", rnd[0], rnd[1]); 2524 if (sp->s_namlen > sizeof sp->s_name) 2525 sp->s_namlen = strlen(sp->s_name); 2526 2527 if (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2528 cnp->cn_proc, NULL)) 2529 break; 2530 } 2531 2532 error = nfs_renameit(dvp, cnp, sp); 2533 if (error) 2534 goto bad; 2535 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2536 cnp->cn_proc, &np); 2537 np->n_sillyrename = sp; 2538 return (0); 2539 bad: 2540 vrele(sp->s_dvp); 2541 crfree(sp->s_cred); 2542 free(sp, M_NFSREQ, sizeof(*sp)); 2543 return (error); 2544 } 2545 2546 /* 2547 * Look up a file name and optionally either update the file handle or 2548 * allocate an nfsnode, depending on the value of npp. 2549 * npp == NULL --> just do the lookup 2550 * *npp == NULL --> allocate a new nfsnode and make sure attributes are 2551 * handled too 2552 * *npp != NULL --> update the file handle in the vnode 2553 */ 2554 int 2555 nfs_lookitup(struct vnode *dvp, char *name, int len, struct ucred *cred, 2556 struct proc *procp, struct nfsnode **npp) 2557 { 2558 struct nfsm_info info; 2559 u_int32_t *tl; 2560 int32_t t1; 2561 struct vnode *newvp = NULL; 2562 struct nfsnode *np, *dnp = VTONFS(dvp); 2563 caddr_t cp2; 2564 int error = 0, fhlen, attrflag; 2565 nfsfh_t *nfhp; 2566 2567 info.nmi_v3 = NFS_ISV3(dvp); 2568 2569 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 2570 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(info.nmi_v3) + NFSX_UNSIGNED + 2571 nfsm_rndup(len)); 2572 nfsm_fhtom(&info, dvp, info.nmi_v3); 2573 nfsm_strtom(name, len, NFS_MAXNAMLEN); 2574 2575 info.nmi_procp = procp; 2576 info.nmi_cred = cred; 2577 error = nfs_request(dvp, NFSPROC_LOOKUP, &info); 2578 if (error && !info.nmi_v3) { 2579 m_freem(info.nmi_mrep); 2580 goto nfsmout; 2581 } 2582 2583 if (npp && !error) { 2584 nfsm_getfh(nfhp, fhlen, info.nmi_v3); 2585 if (*npp) { 2586 np = *npp; 2587 np->n_fhp = &np->n_fh; 2588 bcopy(nfhp, np->n_fhp, fhlen); 2589 np->n_fhsize = fhlen; 2590 newvp = NFSTOV(np); 2591 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) { 2592 vref(dvp); 2593 newvp = dvp; 2594 np = dnp; 2595 } else { 2596 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np); 2597 if (error) { 2598 m_freem(info.nmi_mrep); 2599 return (error); 2600 } 2601 newvp = NFSTOV(np); 2602 } 2603 if (info.nmi_v3) { 2604 nfsm_postop_attr(newvp, attrflag); 2605 if (!attrflag && *npp == NULL) { 2606 m_freem(info.nmi_mrep); 2607 vrele(newvp); 2608 return (ENOENT); 2609 } 2610 } else 2611 nfsm_loadattr(newvp, NULL); 2612 } 2613 m_freem(info.nmi_mrep); 2614 nfsmout: 2615 if (npp && *npp == NULL) { 2616 if (error) { 2617 if (newvp) 2618 vrele(newvp); 2619 } else 2620 *npp = np; 2621 } 2622 return (error); 2623 } 2624 2625 /* 2626 * Nfs Version 3 commit rpc 2627 */ 2628 int 2629 nfs_commit(struct vnode *vp, u_quad_t offset, int cnt, struct proc *procp) 2630 { 2631 struct nfsm_info info; 2632 u_int32_t *tl; 2633 int32_t t1; 2634 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2635 caddr_t cp2; 2636 int error = 0, wccflag = NFSV3_WCCRATTR; 2637 2638 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) 2639 return (0); 2640 nfsstats.rpccnt[NFSPROC_COMMIT]++; 2641 info.nmi_mb = info.nmi_mreq = nfsm_reqhead(NFSX_FH(1)); 2642 nfsm_fhtom(&info, vp, 1); 2643 2644 tl = nfsm_build(&info.nmi_mb, 3 * NFSX_UNSIGNED); 2645 txdr_hyper(offset, tl); 2646 tl += 2; 2647 *tl = txdr_unsigned(cnt); 2648 2649 info.nmi_procp = procp; 2650 info.nmi_cred = VTONFS(vp)->n_wcred; 2651 error = nfs_request(vp, NFSPROC_COMMIT, &info); 2652 nfsm_wcc_data(vp, wccflag); 2653 2654 if (!error) { 2655 nfsm_dissect(tl, u_int32_t *, NFSX_V3WRITEVERF); 2656 if (bcmp(nmp->nm_verf, tl, 2657 NFSX_V3WRITEVERF)) { 2658 bcopy(tl, nmp->nm_verf, 2659 NFSX_V3WRITEVERF); 2660 error = NFSERR_STALEWRITEVERF; 2661 } 2662 } 2663 m_freem(info.nmi_mrep); 2664 2665 nfsmout: 2666 return (error); 2667 } 2668 2669 /* 2670 * Kludge City.. 2671 * - make nfs_bmap() essentially a no-op that does no translation 2672 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc 2673 * (Maybe I could use the process's page mapping, but I was concerned that 2674 * Kernel Write might not be enabled and also figured copyout() would do 2675 * a lot more work than bcopy() and also it currently happens in the 2676 * context of the swapper process (2). 2677 */ 2678 int 2679 nfs_bmap(void *v) 2680 { 2681 struct vop_bmap_args *ap = v; 2682 struct vnode *vp = ap->a_vp; 2683 2684 if (ap->a_vpp != NULL) 2685 *ap->a_vpp = vp; 2686 if (ap->a_bnp != NULL) 2687 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize); 2688 return (0); 2689 } 2690 2691 /* 2692 * Strategy routine. 2693 * For async requests when nfsiod(s) are running, queue the request by 2694 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the 2695 * request. 2696 */ 2697 int 2698 nfs_strategy(void *v) 2699 { 2700 struct vop_strategy_args *ap = v; 2701 struct buf *bp = ap->a_bp; 2702 struct proc *p; 2703 int error = 0; 2704 2705 if ((bp->b_flags & (B_PHYS|B_ASYNC)) == (B_PHYS|B_ASYNC)) 2706 panic("nfs physio/async"); 2707 if (bp->b_flags & B_ASYNC) 2708 p = NULL; 2709 else 2710 p = curproc; /* XXX */ 2711 /* 2712 * If the op is asynchronous and an i/o daemon is waiting 2713 * queue the request, wake it up and wait for completion 2714 * otherwise just do it ourselves. 2715 */ 2716 if ((bp->b_flags & B_ASYNC) == 0 || nfs_asyncio(bp, 0)) 2717 error = nfs_doio(bp, p); 2718 return (error); 2719 } 2720 2721 /* 2722 * fsync vnode op. Just call nfs_flush() with commit == 1. 2723 */ 2724 int 2725 nfs_fsync(void *v) 2726 { 2727 struct vop_fsync_args *ap = v; 2728 2729 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1)); 2730 } 2731 2732 /* 2733 * Flush all the blocks associated with a vnode. 2734 * Walk through the buffer pool and push any dirty pages 2735 * associated with the vnode. 2736 */ 2737 int 2738 nfs_flush(struct vnode *vp, struct ucred *cred, int waitfor, struct proc *p, 2739 int commit) 2740 { 2741 struct nfsnode *np = VTONFS(vp); 2742 struct buf *bp; 2743 int i; 2744 struct buf *nbp; 2745 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2746 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos; 2747 int passone = 1; 2748 u_quad_t off = (u_quad_t)-1, endoff = 0, toff; 2749 #ifndef NFS_COMMITBVECSIZ 2750 #define NFS_COMMITBVECSIZ 20 2751 #endif 2752 struct buf *bvec[NFS_COMMITBVECSIZ]; 2753 2754 if (nmp->nm_flag & NFSMNT_INT) 2755 slpflag = PCATCH; 2756 if (!commit) 2757 passone = 0; 2758 /* 2759 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the 2760 * server, but nas not been committed to stable storage on the server 2761 * yet. On the first pass, the byte range is worked out and the commit 2762 * rpc is done. On the second pass, nfs_writebp() is called to do the 2763 * job. 2764 */ 2765 again: 2766 bvecpos = 0; 2767 if (NFS_ISV3(vp) && commit) { 2768 s = splbio(); 2769 for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) { 2770 if (bvecpos >= NFS_COMMITBVECSIZ) 2771 break; 2772 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2773 != (B_DELWRI | B_NEEDCOMMIT)) { 2774 nbp = LIST_NEXT(bp, b_vnbufs); 2775 continue; 2776 } 2777 bremfree(bp); 2778 bp->b_flags |= B_WRITEINPROG; 2779 buf_acquire(bp); 2780 nbp = LIST_NEXT(bp, b_vnbufs); 2781 2782 /* 2783 * A list of these buffers is kept so that the 2784 * second loop knows which buffers have actually 2785 * been committed. This is necessary, since there 2786 * may be a race between the commit rpc and new 2787 * uncommitted writes on the file. 2788 */ 2789 bvec[bvecpos++] = bp; 2790 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2791 bp->b_dirtyoff; 2792 if (toff < off) 2793 off = toff; 2794 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff); 2795 if (toff > endoff) 2796 endoff = toff; 2797 } 2798 splx(s); 2799 } 2800 if (bvecpos > 0) { 2801 /* 2802 * Commit data on the server, as required. 2803 */ 2804 bcstats.pendingwrites++; 2805 bcstats.numwrites++; 2806 retv = nfs_commit(vp, off, (int)(endoff - off), p); 2807 if (retv == NFSERR_STALEWRITEVERF) 2808 nfs_clearcommit(vp->v_mount); 2809 /* 2810 * Now, either mark the blocks I/O done or mark the 2811 * blocks dirty, depending on whether the commit 2812 * succeeded. 2813 */ 2814 for (i = 0; i < bvecpos; i++) { 2815 bp = bvec[i]; 2816 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG); 2817 if (retv) { 2818 if (i == 0) 2819 bcstats.pendingwrites--; 2820 brelse(bp); 2821 } else { 2822 if (i > 0) 2823 bcstats.pendingwrites++; 2824 s = splbio(); 2825 buf_undirty(bp); 2826 vp->v_numoutput++; 2827 bp->b_flags |= B_ASYNC; 2828 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR); 2829 bp->b_dirtyoff = bp->b_dirtyend = 0; 2830 biodone(bp); 2831 splx(s); 2832 } 2833 } 2834 } 2835 2836 /* 2837 * Start/do any write(s) that are required. 2838 */ 2839 loop: 2840 s = splbio(); 2841 for (bp = LIST_FIRST(&vp->v_dirtyblkhd); bp != NULL; bp = nbp) { 2842 nbp = LIST_NEXT(bp, b_vnbufs); 2843 if (bp->b_flags & B_BUSY) { 2844 if (waitfor != MNT_WAIT || passone) 2845 continue; 2846 bp->b_flags |= B_WANTED; 2847 error = tsleep(bp, slpflag | (PRIBIO + 1), 2848 "nfsfsync", slptimeo); 2849 splx(s); 2850 if (error) { 2851 if (nfs_sigintr(nmp, NULL, p)) 2852 return (EINTR); 2853 if (slpflag == PCATCH) { 2854 slpflag = 0; 2855 slptimeo = 2 * hz; 2856 } 2857 } 2858 goto loop; 2859 } 2860 if ((bp->b_flags & B_DELWRI) == 0) 2861 panic("nfs_fsync: not dirty"); 2862 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) 2863 continue; 2864 bremfree(bp); 2865 if (passone || !commit) { 2866 bp->b_flags |= B_ASYNC; 2867 } else { 2868 bp->b_flags |= (B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT); 2869 } 2870 buf_acquire(bp); 2871 splx(s); 2872 VOP_BWRITE(bp); 2873 goto loop; 2874 } 2875 splx(s); 2876 if (passone) { 2877 passone = 0; 2878 goto again; 2879 } 2880 if (waitfor == MNT_WAIT) { 2881 loop2: 2882 s = splbio(); 2883 error = vwaitforio(vp, slpflag, "nfs_fsync", slptimeo); 2884 splx(s); 2885 if (error) { 2886 if (nfs_sigintr(nmp, NULL, p)) 2887 return (EINTR); 2888 if (slpflag == PCATCH) { 2889 slpflag = 0; 2890 slptimeo = 2 * hz; 2891 } 2892 goto loop2; 2893 } 2894 2895 if (LIST_FIRST(&vp->v_dirtyblkhd) && commit) { 2896 #if 0 2897 vprint("nfs_fsync: dirty", vp); 2898 #endif 2899 goto loop; 2900 } 2901 } 2902 if (np->n_flag & NWRITEERR) { 2903 error = np->n_error; 2904 np->n_flag &= ~NWRITEERR; 2905 } 2906 return (error); 2907 } 2908 2909 /* 2910 * Return POSIX pathconf information applicable to nfs. 2911 * Fake it. For v3 we could ask the server, but such code 2912 * hasn't been written yet. 2913 */ 2914 /* ARGSUSED */ 2915 int 2916 nfs_pathconf(void *v) 2917 { 2918 struct vop_pathconf_args *ap = v; 2919 struct nfsmount *nmp = VFSTONFS(ap->a_vp->v_mount); 2920 int error = 0; 2921 2922 switch (ap->a_name) { 2923 case _PC_LINK_MAX: 2924 *ap->a_retval = LINK_MAX; 2925 break; 2926 case _PC_NAME_MAX: 2927 *ap->a_retval = NAME_MAX; 2928 break; 2929 case _PC_CHOWN_RESTRICTED: 2930 *ap->a_retval = 1; 2931 break; 2932 case _PC_NO_TRUNC: 2933 *ap->a_retval = 1; 2934 break; 2935 case _PC_ALLOC_SIZE_MIN: 2936 *ap->a_retval = NFS_FABLKSIZE; 2937 break; 2938 case _PC_FILESIZEBITS: 2939 *ap->a_retval = 64; 2940 break; 2941 case _PC_REC_INCR_XFER_SIZE: 2942 *ap->a_retval = min(nmp->nm_rsize, nmp->nm_wsize); 2943 break; 2944 case _PC_REC_MAX_XFER_SIZE: 2945 *ap->a_retval = -1; /* means ``unlimited'' */ 2946 break; 2947 case _PC_REC_MIN_XFER_SIZE: 2948 *ap->a_retval = min(nmp->nm_rsize, nmp->nm_wsize); 2949 break; 2950 case _PC_REC_XFER_ALIGN: 2951 *ap->a_retval = PAGE_SIZE; 2952 break; 2953 case _PC_SYMLINK_MAX: 2954 *ap->a_retval = MAXPATHLEN; 2955 break; 2956 case _PC_2_SYMLINKS: 2957 *ap->a_retval = 1; 2958 break; 2959 case _PC_TIMESTAMP_RESOLUTION: 2960 *ap->a_retval = NFS_ISV3(ap->a_vp) ? 1 : 1000; 2961 break; 2962 default: 2963 error = EINVAL; 2964 break; 2965 } 2966 2967 return (error); 2968 } 2969 2970 /* 2971 * NFS advisory byte-level locks. 2972 */ 2973 int 2974 nfs_advlock(void *v) 2975 { 2976 struct vop_advlock_args *ap = v; 2977 struct nfsnode *np = VTONFS(ap->a_vp); 2978 2979 return (lf_advlock(&np->n_lockf, np->n_size, ap->a_id, ap->a_op, 2980 ap->a_fl, ap->a_flags)); 2981 } 2982 2983 /* 2984 * Print out the contents of an nfsnode. 2985 */ 2986 int 2987 nfs_print(void *v) 2988 { 2989 struct vop_print_args *ap = v; 2990 struct vnode *vp = ap->a_vp; 2991 struct nfsnode *np = VTONFS(vp); 2992 2993 printf("tag VT_NFS, fileid %lld fsid 0x%lx", 2994 np->n_vattr.va_fileid, np->n_vattr.va_fsid); 2995 #ifdef FIFO 2996 if (vp->v_type == VFIFO) 2997 fifo_printinfo(vp); 2998 #endif 2999 printf("\n"); 3000 return (0); 3001 } 3002 3003 /* 3004 * Just call nfs_writebp() with the force argument set to 1. 3005 */ 3006 int 3007 nfs_bwrite(void *v) 3008 { 3009 struct vop_bwrite_args *ap = v; 3010 3011 return (nfs_writebp(ap->a_bp, 1)); 3012 } 3013 3014 /* 3015 * This is a clone of vop_generic_bwrite(), except that B_WRITEINPROG isn't set unless 3016 * the force flag is one and it also handles the B_NEEDCOMMIT flag. 3017 */ 3018 int 3019 nfs_writebp(struct buf *bp, int force) 3020 { 3021 int oldflags = bp->b_flags, retv = 1; 3022 struct proc *p = curproc; /* XXX */ 3023 off_t off; 3024 size_t cnt; 3025 int s; 3026 struct vnode *vp; 3027 struct nfsnode *np; 3028 3029 if(!(bp->b_flags & B_BUSY)) 3030 panic("bwrite: buffer is not busy???"); 3031 3032 vp = bp->b_vp; 3033 np = VTONFS(vp); 3034 3035 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR); 3036 3037 s = splbio(); 3038 buf_undirty(bp); 3039 3040 if ((oldflags & B_ASYNC) && !(oldflags & B_DELWRI) && p) 3041 ++p->p_ru.ru_oublock; 3042 3043 bp->b_vp->v_numoutput++; 3044 splx(s); 3045 3046 /* 3047 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not 3048 * an actual write will have to be scheduled via. VOP_STRATEGY(). 3049 * If B_WRITEINPROG is already set, then push it with a write anyhow. 3050 */ 3051 if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) { 3052 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff; 3053 cnt = bp->b_dirtyend - bp->b_dirtyoff; 3054 3055 rw_enter_write(&np->n_commitlock); 3056 if (!(bp->b_flags & B_NEEDCOMMIT)) { 3057 rw_exit_write(&np->n_commitlock); 3058 return (0); 3059 } 3060 3061 /* 3062 * If it's already been commited by somebody else, 3063 * bail. 3064 */ 3065 if (!nfs_in_committed_range(vp, bp)) { 3066 int pushedrange = 0; 3067 /* 3068 * Since we're going to do this, push as much 3069 * as we can. 3070 */ 3071 3072 if (nfs_in_tobecommitted_range(vp, bp)) { 3073 pushedrange = 1; 3074 off = np->n_pushlo; 3075 cnt = np->n_pushhi - np->n_pushlo; 3076 } 3077 3078 bp->b_flags |= B_WRITEINPROG; 3079 bcstats.pendingwrites++; 3080 bcstats.numwrites++; 3081 retv = nfs_commit(bp->b_vp, off, cnt, curproc); 3082 bp->b_flags &= ~B_WRITEINPROG; 3083 3084 if (retv == 0) { 3085 if (pushedrange) 3086 nfs_merge_commit_ranges(vp); 3087 else 3088 nfs_add_committed_range(vp, bp); 3089 } else 3090 bcstats.pendingwrites--; 3091 } else 3092 retv = 0; /* It has already been commited. */ 3093 3094 rw_exit_write(&np->n_commitlock); 3095 if (!retv) { 3096 bp->b_dirtyoff = bp->b_dirtyend = 0; 3097 bp->b_flags &= ~B_NEEDCOMMIT; 3098 s = splbio(); 3099 biodone(bp); 3100 splx(s); 3101 } else if (retv == NFSERR_STALEWRITEVERF) 3102 nfs_clearcommit(bp->b_vp->v_mount); 3103 } 3104 if (retv) { 3105 if (force) 3106 bp->b_flags |= B_WRITEINPROG; 3107 VOP_STRATEGY(bp); 3108 } 3109 3110 if( (oldflags & B_ASYNC) == 0) { 3111 int rtval; 3112 3113 bp->b_flags |= B_RAW; 3114 rtval = biowait(bp); 3115 if (!(oldflags & B_DELWRI) && p) { 3116 ++p->p_ru.ru_oublock; 3117 } 3118 brelse(bp); 3119 return (rtval); 3120 } 3121 3122 return (0); 3123 } 3124 3125 /* 3126 * nfs special file access vnode op. 3127 * Essentially just get vattr and then imitate iaccess() since the device is 3128 * local to the client. 3129 */ 3130 int 3131 nfsspec_access(void *v) 3132 { 3133 struct vop_access_args *ap = v; 3134 struct vattr va; 3135 struct vnode *vp = ap->a_vp; 3136 int error; 3137 3138 /* 3139 * Disallow write attempts on filesystems mounted read-only; 3140 * unless the file is a socket, fifo, or a block or character 3141 * device resident on the filesystem. 3142 */ 3143 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3144 switch (vp->v_type) { 3145 case VREG: 3146 case VDIR: 3147 case VLNK: 3148 return (EROFS); 3149 default: 3150 break; 3151 } 3152 } 3153 3154 error = VOP_GETATTR(vp, &va, ap->a_cred, ap->a_p); 3155 if (error) 3156 return (error); 3157 3158 return (vaccess(vp->v_type, va.va_mode, va.va_uid, va.va_gid, 3159 ap->a_mode, ap->a_cred)); 3160 } 3161 3162 int 3163 nfs_poll(void *v) 3164 { 3165 struct vop_poll_args *ap = v; 3166 3167 /* 3168 * We should really check to see if I/O is possible. 3169 */ 3170 return (ap->a_events & (POLLIN | POLLOUT | POLLRDNORM | POLLWRNORM)); 3171 } 3172 3173 /* 3174 * Read wrapper for special devices. 3175 */ 3176 int 3177 nfsspec_read(void *v) 3178 { 3179 struct vop_read_args *ap = v; 3180 struct nfsnode *np = VTONFS(ap->a_vp); 3181 3182 /* 3183 * Set access flag. 3184 */ 3185 np->n_flag |= NACC; 3186 getnanotime(&np->n_atim); 3187 return (spec_read(ap)); 3188 } 3189 3190 /* 3191 * Write wrapper for special devices. 3192 */ 3193 int 3194 nfsspec_write(void *v) 3195 { 3196 struct vop_write_args *ap = v; 3197 struct nfsnode *np = VTONFS(ap->a_vp); 3198 3199 /* 3200 * Set update flag. 3201 */ 3202 np->n_flag |= NUPD; 3203 getnanotime(&np->n_mtim); 3204 return (spec_write(ap)); 3205 } 3206 3207 /* 3208 * Close wrapper for special devices. 3209 * 3210 * Update the times on the nfsnode then do device close. 3211 */ 3212 int 3213 nfsspec_close(void *v) 3214 { 3215 struct vop_close_args *ap = v; 3216 struct vnode *vp = ap->a_vp; 3217 struct nfsnode *np = VTONFS(vp); 3218 struct vattr vattr; 3219 3220 if (np->n_flag & (NACC | NUPD)) { 3221 np->n_flag |= NCHG; 3222 if (vp->v_usecount == 1 && 3223 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3224 VATTR_NULL(&vattr); 3225 if (np->n_flag & NACC) 3226 vattr.va_atime = np->n_atim; 3227 if (np->n_flag & NUPD) 3228 vattr.va_mtime = np->n_mtim; 3229 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3230 } 3231 } 3232 return (spec_close(ap)); 3233 } 3234 3235 #ifdef FIFO 3236 /* 3237 * Read wrapper for fifos. 3238 */ 3239 int 3240 nfsfifo_read(void *v) 3241 { 3242 struct vop_read_args *ap = v; 3243 struct nfsnode *np = VTONFS(ap->a_vp); 3244 3245 /* 3246 * Set access flag. 3247 */ 3248 np->n_flag |= NACC; 3249 getnanotime(&np->n_atim); 3250 return (fifo_read(ap)); 3251 } 3252 3253 /* 3254 * Write wrapper for fifos. 3255 */ 3256 int 3257 nfsfifo_write(void *v) 3258 { 3259 struct vop_write_args *ap = v; 3260 struct nfsnode *np = VTONFS(ap->a_vp); 3261 3262 /* 3263 * Set update flag. 3264 */ 3265 np->n_flag |= NUPD; 3266 getnanotime(&np->n_mtim); 3267 return (fifo_write(ap)); 3268 } 3269 3270 /* 3271 * Close wrapper for fifos. 3272 * 3273 * Update the times on the nfsnode then do fifo close. 3274 */ 3275 int 3276 nfsfifo_close(void *v) 3277 { 3278 struct vop_close_args *ap = v; 3279 struct vnode *vp = ap->a_vp; 3280 struct nfsnode *np = VTONFS(vp); 3281 struct vattr vattr; 3282 3283 if (np->n_flag & (NACC | NUPD)) { 3284 if (np->n_flag & NACC) { 3285 getnanotime(&np->n_atim); 3286 } 3287 if (np->n_flag & NUPD) { 3288 getnanotime(&np->n_mtim); 3289 } 3290 np->n_flag |= NCHG; 3291 if (vp->v_usecount == 1 && 3292 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3293 VATTR_NULL(&vattr); 3294 if (np->n_flag & NACC) 3295 vattr.va_atime = np->n_atim; 3296 if (np->n_flag & NUPD) 3297 vattr.va_mtime = np->n_mtim; 3298 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3299 } 3300 } 3301 return (fifo_close(ap)); 3302 } 3303 3304 int 3305 nfsfifo_reclaim(void *v) 3306 { 3307 fifo_reclaim(v); 3308 return (nfs_reclaim(v)); 3309 } 3310 #endif /* ! FIFO */ 3311