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