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