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