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