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