1 /* $NetBSD: nfs_vnops.c,v 1.231 2006/03/01 12:38:32 yamt Exp $ */ 2 3 /* 4 * Copyright (c) 1989, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This code is derived from software contributed to Berkeley by 8 * Rick Macklem at The University of Guelph. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. Neither the name of the University nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * @(#)nfs_vnops.c 8.19 (Berkeley) 7/31/95 35 */ 36 37 /* 38 * vnode op calls for Sun NFS version 2 and 3 39 */ 40 41 #include <sys/cdefs.h> 42 __KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.231 2006/03/01 12:38:32 yamt Exp $"); 43 44 #include "opt_inet.h" 45 #include "opt_nfs.h" 46 #include "opt_uvmhist.h" 47 48 #include <sys/param.h> 49 #include <sys/proc.h> 50 #include <sys/kernel.h> 51 #include <sys/systm.h> 52 #include <sys/resourcevar.h> 53 #include <sys/proc.h> 54 #include <sys/mount.h> 55 #include <sys/buf.h> 56 #include <sys/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, curlwp, 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, curlwp, 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, curlwp, 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 (!VMSPACE_IS_KERNEL_P(uio->uio_vmspace) || 2496 uio->uio_iovcnt != 1) 2497 panic("nfs_readdir: lost in space"); 2498 for (nc = 0; ncookies-- && 2499 base < (char *)uio->uio_iov->iov_base; nc++){ 2500 dp = (struct dirent *) base; 2501 if (dp->d_reclen == 0) 2502 break; 2503 if (nmp->nm_flag & NFSMNT_XLATECOOKIE) 2504 *(cookies++) = (off_t)NFS_GETCOOKIE32(dp); 2505 else 2506 *(cookies++) = NFS_GETCOOKIE(dp); 2507 base += dp->d_reclen; 2508 } 2509 uio->uio_resid += 2510 ((caddr_t)uio->uio_iov->iov_base - base); 2511 uio->uio_iov->iov_len += 2512 ((caddr_t)uio->uio_iov->iov_base - base); 2513 uio->uio_iov->iov_base = base; 2514 *ap->a_ncookies = nc; 2515 } 2516 2517 uio->uio_resid += lost; 2518 *ap->a_eofflag = 0; 2519 return (error); 2520 } 2521 2522 /* 2523 * Readdir rpc call. 2524 * Called from below the buffer cache by nfs_doio(). 2525 */ 2526 int 2527 nfs_readdirrpc(vp, uiop, cred) 2528 struct vnode *vp; 2529 struct uio *uiop; 2530 struct ucred *cred; 2531 { 2532 int len, left; 2533 struct dirent *dp = NULL; 2534 u_int32_t *tl; 2535 caddr_t cp; 2536 int32_t t1, t2; 2537 caddr_t bpos, dpos, cp2; 2538 struct mbuf *mreq, *mrep, *md, *mb; 2539 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2540 struct nfsnode *dnp = VTONFS(vp); 2541 u_quad_t fileno; 2542 int error = 0, more_dirs = 1, blksiz = 0, bigenough = 1; 2543 #ifndef NFS_V2_ONLY 2544 int attrflag; 2545 #endif 2546 int nrpcs = 0, reclen; 2547 const int v3 = NFS_ISV3(vp); 2548 2549 #ifdef DIAGNOSTIC 2550 /* 2551 * Should be called from buffer cache, so only amount of 2552 * NFS_DIRBLKSIZ will be requested. 2553 */ 2554 if (uiop->uio_iovcnt != 1 || uiop->uio_resid != NFS_DIRBLKSIZ) 2555 panic("nfs readdirrpc bad uio"); 2556 #endif 2557 2558 /* 2559 * Loop around doing readdir rpc's of size nm_readdirsize 2560 * truncated to a multiple of NFS_DIRFRAGSIZ. 2561 * The stopping criteria is EOF or buffer full. 2562 */ 2563 while (more_dirs && bigenough) { 2564 /* 2565 * Heuristic: don't bother to do another RPC to further 2566 * fill up this block if there is not much room left. (< 50% 2567 * of the readdir RPC size). This wastes some buffer space 2568 * but can save up to 50% in RPC calls. 2569 */ 2570 if (nrpcs > 0 && uiop->uio_resid < (nmp->nm_readdirsize / 2)) { 2571 bigenough = 0; 2572 break; 2573 } 2574 nfsstats.rpccnt[NFSPROC_READDIR]++; 2575 nfsm_reqhead(dnp, NFSPROC_READDIR, NFSX_FH(v3) + 2576 NFSX_READDIR(v3)); 2577 nfsm_fhtom(dnp, v3); 2578 #ifndef NFS_V2_ONLY 2579 if (v3) { 2580 nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 2581 if (nmp->nm_iflag & NFSMNT_SWAPCOOKIE) { 2582 txdr_swapcookie3(uiop->uio_offset, tl); 2583 } else { 2584 txdr_cookie3(uiop->uio_offset, tl); 2585 } 2586 tl += 2; 2587 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2588 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2589 } else 2590 #endif 2591 { 2592 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2593 *tl++ = txdr_unsigned(uiop->uio_offset); 2594 } 2595 *tl = txdr_unsigned(nmp->nm_readdirsize); 2596 nfsm_request(dnp, NFSPROC_READDIR, curlwp, cred); 2597 nrpcs++; 2598 #ifndef NFS_V2_ONLY 2599 if (v3) { 2600 nfsm_postop_attr(vp, attrflag, 0); 2601 if (!error) { 2602 nfsm_dissect(tl, u_int32_t *, 2603 2 * NFSX_UNSIGNED); 2604 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2605 dnp->n_cookieverf.nfsuquad[1] = *tl; 2606 } else { 2607 m_freem(mrep); 2608 goto nfsmout; 2609 } 2610 } 2611 #endif 2612 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2613 more_dirs = fxdr_unsigned(int, *tl); 2614 2615 /* loop thru the dir entries, doctoring them to 4bsd form */ 2616 while (more_dirs && bigenough) { 2617 #ifndef NFS_V2_ONLY 2618 if (v3) { 2619 nfsm_dissect(tl, u_int32_t *, 2620 3 * NFSX_UNSIGNED); 2621 fileno = fxdr_hyper(tl); 2622 len = fxdr_unsigned(int, *(tl + 2)); 2623 } else 2624 #endif 2625 { 2626 nfsm_dissect(tl, u_int32_t *, 2627 2 * NFSX_UNSIGNED); 2628 fileno = fxdr_unsigned(u_quad_t, *tl++); 2629 len = fxdr_unsigned(int, *tl); 2630 } 2631 if (len <= 0 || len > NFS_MAXNAMLEN) { 2632 error = EBADRPC; 2633 m_freem(mrep); 2634 goto nfsmout; 2635 } 2636 /* for cookie stashing */ 2637 reclen = _DIRENT_RECLEN(dp, len) + 2 * sizeof(off_t); 2638 left = NFS_DIRFRAGSIZ - blksiz; 2639 if (reclen > left) { 2640 memset(uiop->uio_iov->iov_base, 0, left); 2641 dp->d_reclen += left; 2642 UIO_ADVANCE(uiop, left); 2643 blksiz = 0; 2644 NFS_STASHCOOKIE(dp, uiop->uio_offset); 2645 } 2646 if (reclen > uiop->uio_resid) 2647 bigenough = 0; 2648 if (bigenough) { 2649 int tlen; 2650 2651 dp = (struct dirent *)uiop->uio_iov->iov_base; 2652 dp->d_fileno = fileno; 2653 dp->d_namlen = len; 2654 dp->d_reclen = reclen; 2655 dp->d_type = DT_UNKNOWN; 2656 blksiz += reclen; 2657 if (blksiz == NFS_DIRFRAGSIZ) 2658 blksiz = 0; 2659 UIO_ADVANCE(uiop, DIRHDSIZ); 2660 nfsm_mtouio(uiop, len); 2661 tlen = reclen - (DIRHDSIZ + len); 2662 (void)memset(uiop->uio_iov->iov_base, 0, tlen); 2663 UIO_ADVANCE(uiop, tlen); 2664 } else 2665 nfsm_adv(nfsm_rndup(len)); 2666 #ifndef NFS_V2_ONLY 2667 if (v3) { 2668 nfsm_dissect(tl, u_int32_t *, 2669 3 * NFSX_UNSIGNED); 2670 } else 2671 #endif 2672 { 2673 nfsm_dissect(tl, u_int32_t *, 2674 2 * NFSX_UNSIGNED); 2675 } 2676 if (bigenough) { 2677 #ifndef NFS_V2_ONLY 2678 if (v3) { 2679 if (nmp->nm_iflag & NFSMNT_SWAPCOOKIE) 2680 uiop->uio_offset = 2681 fxdr_swapcookie3(tl); 2682 else 2683 uiop->uio_offset = 2684 fxdr_cookie3(tl); 2685 } 2686 else 2687 #endif 2688 { 2689 uiop->uio_offset = 2690 fxdr_unsigned(off_t, *tl); 2691 } 2692 NFS_STASHCOOKIE(dp, uiop->uio_offset); 2693 } 2694 if (v3) 2695 tl += 2; 2696 else 2697 tl++; 2698 more_dirs = fxdr_unsigned(int, *tl); 2699 } 2700 /* 2701 * If at end of rpc data, get the eof boolean 2702 */ 2703 if (!more_dirs) { 2704 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2705 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2706 2707 /* 2708 * kludge: if we got no entries, treat it as EOF. 2709 * some server sometimes send a reply without any 2710 * entries or EOF. 2711 * although it might mean the server has very long name, 2712 * we can't handle such entries anyway. 2713 */ 2714 2715 if (uiop->uio_resid >= NFS_DIRBLKSIZ) 2716 more_dirs = 0; 2717 } 2718 m_freem(mrep); 2719 } 2720 /* 2721 * Fill last record, iff any, out to a multiple of NFS_DIRFRAGSIZ 2722 * by increasing d_reclen for the last record. 2723 */ 2724 if (blksiz > 0) { 2725 left = NFS_DIRFRAGSIZ - blksiz; 2726 memset(uiop->uio_iov->iov_base, 0, left); 2727 dp->d_reclen += left; 2728 NFS_STASHCOOKIE(dp, uiop->uio_offset); 2729 UIO_ADVANCE(uiop, left); 2730 } 2731 2732 /* 2733 * We are now either at the end of the directory or have filled the 2734 * block. 2735 */ 2736 if (bigenough) { 2737 dnp->n_direofoffset = uiop->uio_offset; 2738 dnp->n_flag |= NEOFVALID; 2739 } 2740 nfsmout: 2741 return (error); 2742 } 2743 2744 #ifndef NFS_V2_ONLY 2745 /* 2746 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc(). 2747 */ 2748 int 2749 nfs_readdirplusrpc(vp, uiop, cred) 2750 struct vnode *vp; 2751 struct uio *uiop; 2752 struct ucred *cred; 2753 { 2754 int len, left; 2755 struct dirent *dp = NULL; 2756 u_int32_t *tl; 2757 caddr_t cp; 2758 int32_t t1, t2; 2759 struct vnode *newvp; 2760 caddr_t bpos, dpos, cp2; 2761 struct mbuf *mreq, *mrep, *md, *mb; 2762 struct nameidata nami, *ndp = &nami; 2763 struct componentname *cnp = &ndp->ni_cnd; 2764 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2765 struct nfsnode *dnp = VTONFS(vp), *np; 2766 nfsfh_t *fhp; 2767 u_quad_t fileno; 2768 int error = 0, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i; 2769 int attrflag, fhsize, nrpcs = 0, reclen; 2770 struct nfs_fattr fattr, *fp; 2771 2772 #ifdef DIAGNOSTIC 2773 if (uiop->uio_iovcnt != 1 || uiop->uio_resid != NFS_DIRBLKSIZ) 2774 panic("nfs readdirplusrpc bad uio"); 2775 #endif 2776 ndp->ni_dvp = vp; 2777 newvp = NULLVP; 2778 2779 /* 2780 * Loop around doing readdir rpc's of size nm_readdirsize 2781 * truncated to a multiple of NFS_DIRFRAGSIZ. 2782 * The stopping criteria is EOF or buffer full. 2783 */ 2784 while (more_dirs && bigenough) { 2785 if (nrpcs > 0 && uiop->uio_resid < (nmp->nm_readdirsize / 2)) { 2786 bigenough = 0; 2787 break; 2788 } 2789 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++; 2790 nfsm_reqhead(dnp, NFSPROC_READDIRPLUS, 2791 NFSX_FH(1) + 6 * NFSX_UNSIGNED); 2792 nfsm_fhtom(dnp, 1); 2793 nfsm_build(tl, u_int32_t *, 6 * NFSX_UNSIGNED); 2794 if (nmp->nm_iflag & NFSMNT_SWAPCOOKIE) { 2795 txdr_swapcookie3(uiop->uio_offset, tl); 2796 } else { 2797 txdr_cookie3(uiop->uio_offset, tl); 2798 } 2799 tl += 2; 2800 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2801 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2802 *tl++ = txdr_unsigned(nmp->nm_readdirsize); 2803 *tl = txdr_unsigned(nmp->nm_rsize); 2804 nfsm_request(dnp, NFSPROC_READDIRPLUS, curlwp, cred); 2805 nfsm_postop_attr(vp, attrflag, 0); 2806 if (error) { 2807 m_freem(mrep); 2808 goto nfsmout; 2809 } 2810 nrpcs++; 2811 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2812 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2813 dnp->n_cookieverf.nfsuquad[1] = *tl++; 2814 more_dirs = fxdr_unsigned(int, *tl); 2815 2816 /* loop thru the dir entries, doctoring them to 4bsd form */ 2817 while (more_dirs && bigenough) { 2818 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2819 fileno = fxdr_hyper(tl); 2820 len = fxdr_unsigned(int, *(tl + 2)); 2821 if (len <= 0 || len > NFS_MAXNAMLEN) { 2822 error = EBADRPC; 2823 m_freem(mrep); 2824 goto nfsmout; 2825 } 2826 /* for cookie stashing */ 2827 reclen = _DIRENT_RECLEN(dp, len) + 2 * sizeof(off_t); 2828 left = NFS_DIRFRAGSIZ - blksiz; 2829 if (reclen > left) { 2830 /* 2831 * DIRFRAGSIZ is aligned, no need to align 2832 * again here. 2833 */ 2834 memset(uiop->uio_iov->iov_base, 0, left); 2835 dp->d_reclen += left; 2836 UIO_ADVANCE(uiop, left); 2837 NFS_STASHCOOKIE(dp, uiop->uio_offset); 2838 blksiz = 0; 2839 } 2840 if (reclen > uiop->uio_resid) 2841 bigenough = 0; 2842 if (bigenough) { 2843 int tlen; 2844 2845 dp = (struct dirent *)uiop->uio_iov->iov_base; 2846 dp->d_fileno = fileno; 2847 dp->d_namlen = len; 2848 dp->d_reclen = reclen; 2849 dp->d_type = DT_UNKNOWN; 2850 blksiz += reclen; 2851 if (blksiz == NFS_DIRFRAGSIZ) 2852 blksiz = 0; 2853 UIO_ADVANCE(uiop, DIRHDSIZ); 2854 nfsm_mtouio(uiop, len); 2855 tlen = reclen - (DIRHDSIZ + len); 2856 (void)memset(uiop->uio_iov->iov_base, 0, tlen); 2857 UIO_ADVANCE(uiop, tlen); 2858 cnp->cn_nameptr = dp->d_name; 2859 cnp->cn_namelen = dp->d_namlen; 2860 } else 2861 nfsm_adv(nfsm_rndup(len)); 2862 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2863 if (bigenough) { 2864 if (nmp->nm_iflag & NFSMNT_SWAPCOOKIE) 2865 uiop->uio_offset = 2866 fxdr_swapcookie3(tl); 2867 else 2868 uiop->uio_offset = 2869 fxdr_cookie3(tl); 2870 NFS_STASHCOOKIE(dp, uiop->uio_offset); 2871 } 2872 tl += 2; 2873 2874 /* 2875 * Since the attributes are before the file handle 2876 * (sigh), we must skip over the attributes and then 2877 * come back and get them. 2878 */ 2879 attrflag = fxdr_unsigned(int, *tl); 2880 if (attrflag) { 2881 nfsm_dissect(fp, struct nfs_fattr *, NFSX_V3FATTR); 2882 memcpy(&fattr, fp, NFSX_V3FATTR); 2883 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2884 doit = fxdr_unsigned(int, *tl); 2885 if (doit) { 2886 nfsm_getfh(fhp, fhsize, 1); 2887 if (NFS_CMPFH(dnp, fhp, fhsize)) { 2888 VREF(vp); 2889 newvp = vp; 2890 np = dnp; 2891 } else { 2892 error = nfs_nget1(vp->v_mount, fhp, 2893 fhsize, &np, LK_NOWAIT); 2894 if (!error) 2895 newvp = NFSTOV(np); 2896 } 2897 if (!error) { 2898 const char *xcp; 2899 2900 nfs_loadattrcache(&newvp, &fattr, 0, 0); 2901 if (bigenough) { 2902 dp->d_type = 2903 IFTODT(VTTOIF(np->n_vattr->va_type)); 2904 if (cnp->cn_namelen <= NCHNAMLEN) { 2905 ndp->ni_vp = newvp; 2906 xcp = cnp->cn_nameptr + 2907 cnp->cn_namelen; 2908 cnp->cn_hash = 2909 namei_hash(cnp->cn_nameptr, &xcp); 2910 nfs_cache_enter(ndp->ni_dvp, 2911 ndp->ni_vp, cnp); 2912 } 2913 } 2914 } 2915 error = 0; 2916 } 2917 } else { 2918 /* Just skip over the file handle */ 2919 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2920 i = fxdr_unsigned(int, *tl); 2921 nfsm_adv(nfsm_rndup(i)); 2922 } 2923 if (newvp != NULLVP) { 2924 if (newvp == vp) 2925 vrele(newvp); 2926 else 2927 vput(newvp); 2928 newvp = NULLVP; 2929 } 2930 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2931 more_dirs = fxdr_unsigned(int, *tl); 2932 } 2933 /* 2934 * If at end of rpc data, get the eof boolean 2935 */ 2936 if (!more_dirs) { 2937 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2938 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2939 2940 /* 2941 * kludge: see a comment in nfs_readdirrpc. 2942 */ 2943 2944 if (uiop->uio_resid >= NFS_DIRBLKSIZ) 2945 more_dirs = 0; 2946 } 2947 m_freem(mrep); 2948 } 2949 /* 2950 * Fill last record, iff any, out to a multiple of NFS_DIRFRAGSIZ 2951 * by increasing d_reclen for the last record. 2952 */ 2953 if (blksiz > 0) { 2954 left = NFS_DIRFRAGSIZ - blksiz; 2955 memset(uiop->uio_iov->iov_base, 0, left); 2956 dp->d_reclen += left; 2957 NFS_STASHCOOKIE(dp, uiop->uio_offset); 2958 UIO_ADVANCE(uiop, left); 2959 } 2960 2961 /* 2962 * We are now either at the end of the directory or have filled the 2963 * block. 2964 */ 2965 if (bigenough) { 2966 dnp->n_direofoffset = uiop->uio_offset; 2967 dnp->n_flag |= NEOFVALID; 2968 } 2969 nfsmout: 2970 if (newvp != NULLVP) { 2971 if(newvp == vp) 2972 vrele(newvp); 2973 else 2974 vput(newvp); 2975 } 2976 return (error); 2977 } 2978 #endif 2979 2980 /* 2981 * Silly rename. To make the NFS filesystem that is stateless look a little 2982 * more like the "ufs" a remove of an active vnode is translated to a rename 2983 * to a funny looking filename that is removed by nfs_inactive on the 2984 * nfsnode. There is the potential for another process on a different client 2985 * to create the same funny name between the nfs_lookitup() fails and the 2986 * nfs_rename() completes, but... 2987 */ 2988 int 2989 nfs_sillyrename(dvp, vp, cnp) 2990 struct vnode *dvp, *vp; 2991 struct componentname *cnp; 2992 { 2993 struct sillyrename *sp; 2994 struct nfsnode *np; 2995 int error; 2996 short pid; 2997 2998 cache_purge(dvp); 2999 np = VTONFS(vp); 3000 #ifndef DIAGNOSTIC 3001 if (vp->v_type == VDIR) 3002 panic("nfs: sillyrename dir"); 3003 #endif 3004 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 3005 M_NFSREQ, M_WAITOK); 3006 sp->s_cred = crdup(cnp->cn_cred); 3007 sp->s_dvp = dvp; 3008 VREF(dvp); 3009 3010 /* Fudge together a funny name */ 3011 pid = cnp->cn_lwp->l_proc->p_pid; 3012 memcpy(sp->s_name, ".nfsAxxxx4.4", 13); 3013 sp->s_namlen = 12; 3014 sp->s_name[8] = hexdigits[pid & 0xf]; 3015 sp->s_name[7] = hexdigits[(pid >> 4) & 0xf]; 3016 sp->s_name[6] = hexdigits[(pid >> 8) & 0xf]; 3017 sp->s_name[5] = hexdigits[(pid >> 12) & 0xf]; 3018 3019 /* Try lookitups until we get one that isn't there */ 3020 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 3021 cnp->cn_lwp, (struct nfsnode **)0) == 0) { 3022 sp->s_name[4]++; 3023 if (sp->s_name[4] > 'z') { 3024 error = EINVAL; 3025 goto bad; 3026 } 3027 } 3028 error = nfs_renameit(dvp, cnp, sp); 3029 if (error) 3030 goto bad; 3031 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 3032 cnp->cn_lwp, &np); 3033 np->n_sillyrename = sp; 3034 return (0); 3035 bad: 3036 vrele(sp->s_dvp); 3037 crfree(sp->s_cred); 3038 free((caddr_t)sp, M_NFSREQ); 3039 return (error); 3040 } 3041 3042 /* 3043 * Look up a file name and optionally either update the file handle or 3044 * allocate an nfsnode, depending on the value of npp. 3045 * npp == NULL --> just do the lookup 3046 * *npp == NULL --> allocate a new nfsnode and make sure attributes are 3047 * handled too 3048 * *npp != NULL --> update the file handle in the vnode 3049 */ 3050 int 3051 nfs_lookitup(dvp, name, len, cred, l, npp) 3052 struct vnode *dvp; 3053 const char *name; 3054 int len; 3055 struct ucred *cred; 3056 struct lwp *l; 3057 struct nfsnode **npp; 3058 { 3059 u_int32_t *tl; 3060 caddr_t cp; 3061 int32_t t1, t2; 3062 struct vnode *newvp = (struct vnode *)0; 3063 struct nfsnode *np, *dnp = VTONFS(dvp); 3064 caddr_t bpos, dpos, cp2; 3065 int error = 0, fhlen; 3066 #ifndef NFS_V2_ONLY 3067 int attrflag; 3068 #endif 3069 struct mbuf *mreq, *mrep, *md, *mb; 3070 nfsfh_t *nfhp; 3071 const int v3 = NFS_ISV3(dvp); 3072 3073 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 3074 nfsm_reqhead(dnp, NFSPROC_LOOKUP, 3075 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 3076 nfsm_fhtom(dnp, v3); 3077 nfsm_strtom(name, len, NFS_MAXNAMLEN); 3078 nfsm_request(dnp, NFSPROC_LOOKUP, l, cred); 3079 if (npp && !error) { 3080 nfsm_getfh(nfhp, fhlen, v3); 3081 if (*npp) { 3082 np = *npp; 3083 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) { 3084 free((caddr_t)np->n_fhp, M_NFSBIGFH); 3085 np->n_fhp = &np->n_fh; 3086 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH) 3087 np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK); 3088 memcpy((caddr_t)np->n_fhp, (caddr_t)nfhp, fhlen); 3089 np->n_fhsize = fhlen; 3090 newvp = NFSTOV(np); 3091 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) { 3092 VREF(dvp); 3093 newvp = dvp; 3094 np = dnp; 3095 } else { 3096 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np); 3097 if (error) { 3098 m_freem(mrep); 3099 return (error); 3100 } 3101 newvp = NFSTOV(np); 3102 } 3103 #ifndef NFS_V2_ONLY 3104 if (v3) { 3105 nfsm_postop_attr(newvp, attrflag, 0); 3106 if (!attrflag && *npp == NULL) { 3107 m_freem(mrep); 3108 vput(newvp); 3109 return (ENOENT); 3110 } 3111 } else 3112 #endif 3113 nfsm_loadattr(newvp, (struct vattr *)0, 0); 3114 } 3115 nfsm_reqdone; 3116 if (npp && *npp == NULL) { 3117 if (error) { 3118 if (newvp) 3119 vput(newvp); 3120 } else 3121 *npp = np; 3122 } 3123 return (error); 3124 } 3125 3126 #ifndef NFS_V2_ONLY 3127 /* 3128 * Nfs Version 3 commit rpc 3129 */ 3130 int 3131 nfs_commit(vp, offset, cnt, l) 3132 struct vnode *vp; 3133 off_t offset; 3134 uint32_t cnt; 3135 struct lwp *l; 3136 { 3137 caddr_t cp; 3138 u_int32_t *tl; 3139 int32_t t1, t2; 3140 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 3141 caddr_t bpos, dpos, cp2; 3142 int error = 0, wccflag = NFSV3_WCCRATTR; 3143 struct mbuf *mreq, *mrep, *md, *mb; 3144 struct nfsnode *np; 3145 3146 KASSERT(NFS_ISV3(vp)); 3147 3148 #ifdef NFS_DEBUG_COMMIT 3149 printf("commit %lu - %lu\n", (unsigned long)offset, 3150 (unsigned long)(offset + cnt)); 3151 #endif 3152 3153 simple_lock(&nmp->nm_slock); 3154 if ((nmp->nm_iflag & NFSMNT_HASWRITEVERF) == 0) { 3155 simple_unlock(&nmp->nm_slock); 3156 return (0); 3157 } 3158 simple_unlock(&nmp->nm_slock); 3159 nfsstats.rpccnt[NFSPROC_COMMIT]++; 3160 np = VTONFS(vp); 3161 nfsm_reqhead(np, NFSPROC_COMMIT, NFSX_FH(1)); 3162 nfsm_fhtom(np, 1); 3163 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 3164 txdr_hyper(offset, tl); 3165 tl += 2; 3166 *tl = txdr_unsigned(cnt); 3167 nfsm_request(np, NFSPROC_COMMIT, l, np->n_wcred); 3168 nfsm_wcc_data(vp, wccflag, NAC_NOTRUNC, FALSE); 3169 if (!error) { 3170 nfsm_dissect(tl, u_int32_t *, NFSX_V3WRITEVERF); 3171 simple_lock(&nmp->nm_slock); 3172 if ((nmp->nm_iflag & NFSMNT_STALEWRITEVERF) || 3173 memcmp(nmp->nm_writeverf, tl, NFSX_V3WRITEVERF)) { 3174 memcpy(nmp->nm_writeverf, tl, NFSX_V3WRITEVERF); 3175 error = NFSERR_STALEWRITEVERF; 3176 nmp->nm_iflag |= NFSMNT_STALEWRITEVERF; 3177 } 3178 simple_unlock(&nmp->nm_slock); 3179 } 3180 nfsm_reqdone; 3181 return (error); 3182 } 3183 #endif 3184 3185 /* 3186 * Kludge City.. 3187 * - make nfs_bmap() essentially a no-op that does no translation 3188 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc 3189 * (Maybe I could use the process's page mapping, but I was concerned that 3190 * Kernel Write might not be enabled and also figured copyout() would do 3191 * a lot more work than memcpy() and also it currently happens in the 3192 * context of the swapper process (2). 3193 */ 3194 int 3195 nfs_bmap(v) 3196 void *v; 3197 { 3198 struct vop_bmap_args /* { 3199 struct vnode *a_vp; 3200 daddr_t a_bn; 3201 struct vnode **a_vpp; 3202 daddr_t *a_bnp; 3203 int *a_runp; 3204 } */ *ap = v; 3205 struct vnode *vp = ap->a_vp; 3206 int bshift = vp->v_mount->mnt_fs_bshift - vp->v_mount->mnt_dev_bshift; 3207 3208 if (ap->a_vpp != NULL) 3209 *ap->a_vpp = vp; 3210 if (ap->a_bnp != NULL) 3211 *ap->a_bnp = ap->a_bn << bshift; 3212 if (ap->a_runp != NULL) 3213 *ap->a_runp = 1024 * 1024; /* XXX */ 3214 return (0); 3215 } 3216 3217 /* 3218 * Strategy routine. 3219 * For async requests when nfsiod(s) are running, queue the request by 3220 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the 3221 * request. 3222 */ 3223 int 3224 nfs_strategy(v) 3225 void *v; 3226 { 3227 struct vop_strategy_args *ap = v; 3228 struct buf *bp = ap->a_bp; 3229 int error = 0; 3230 3231 if ((bp->b_flags & (B_PHYS|B_ASYNC)) == (B_PHYS|B_ASYNC)) 3232 panic("nfs physio/async"); 3233 3234 /* 3235 * If the op is asynchronous and an i/o daemon is waiting 3236 * queue the request, wake it up and wait for completion 3237 * otherwise just do it ourselves. 3238 */ 3239 if ((bp->b_flags & B_ASYNC) == 0 || nfs_asyncio(bp)) 3240 error = nfs_doio(bp); 3241 return (error); 3242 } 3243 3244 /* 3245 * fsync vnode op. Just call nfs_flush() with commit == 1. 3246 */ 3247 /* ARGSUSED */ 3248 int 3249 nfs_fsync(v) 3250 void *v; 3251 { 3252 struct vop_fsync_args /* { 3253 struct vnodeop_desc *a_desc; 3254 struct vnode * a_vp; 3255 struct ucred * a_cred; 3256 int a_flags; 3257 off_t offlo; 3258 off_t offhi; 3259 struct lwp * a_l; 3260 } */ *ap = v; 3261 3262 struct vnode *vp = ap->a_vp; 3263 3264 if (vp->v_type != VREG) 3265 return 0; 3266 3267 return (nfs_flush(vp, ap->a_cred, 3268 (ap->a_flags & FSYNC_WAIT) != 0 ? MNT_WAIT : 0, ap->a_l, 1)); 3269 } 3270 3271 /* 3272 * Flush all the data associated with a vnode. 3273 */ 3274 int 3275 nfs_flush(vp, cred, waitfor, l, commit) 3276 struct vnode *vp; 3277 struct ucred *cred; 3278 int waitfor; 3279 struct lwp *l; 3280 int commit; 3281 { 3282 struct nfsnode *np = VTONFS(vp); 3283 int error; 3284 int flushflags = PGO_ALLPAGES|PGO_CLEANIT|PGO_SYNCIO; 3285 UVMHIST_FUNC("nfs_flush"); UVMHIST_CALLED(ubchist); 3286 3287 simple_lock(&vp->v_interlock); 3288 error = VOP_PUTPAGES(vp, 0, 0, flushflags); 3289 if (np->n_flag & NWRITEERR) { 3290 error = np->n_error; 3291 np->n_flag &= ~NWRITEERR; 3292 } 3293 UVMHIST_LOG(ubchist, "returning %d", error,0,0,0); 3294 return (error); 3295 } 3296 3297 /* 3298 * Return POSIX pathconf information applicable to nfs. 3299 * 3300 * N.B. The NFS V2 protocol doesn't support this RPC. 3301 */ 3302 /* ARGSUSED */ 3303 int 3304 nfs_pathconf(v) 3305 void *v; 3306 { 3307 struct vop_pathconf_args /* { 3308 struct vnode *a_vp; 3309 int a_name; 3310 register_t *a_retval; 3311 } */ *ap = v; 3312 struct nfsv3_pathconf *pcp; 3313 struct vnode *vp = ap->a_vp; 3314 struct mbuf *mreq, *mrep, *md, *mb; 3315 int32_t t1, t2; 3316 u_int32_t *tl; 3317 caddr_t bpos, dpos, cp, cp2; 3318 int error = 0, attrflag; 3319 #ifndef NFS_V2_ONLY 3320 struct nfsmount *nmp; 3321 unsigned int l; 3322 u_int64_t maxsize; 3323 #endif 3324 const int v3 = NFS_ISV3(vp); 3325 struct nfsnode *np = VTONFS(vp); 3326 3327 switch (ap->a_name) { 3328 /* Names that can be resolved locally. */ 3329 case _PC_PIPE_BUF: 3330 *ap->a_retval = PIPE_BUF; 3331 break; 3332 case _PC_SYNC_IO: 3333 *ap->a_retval = 1; 3334 break; 3335 /* Names that cannot be resolved locally; do an RPC, if possible. */ 3336 case _PC_LINK_MAX: 3337 case _PC_NAME_MAX: 3338 case _PC_CHOWN_RESTRICTED: 3339 case _PC_NO_TRUNC: 3340 if (!v3) { 3341 error = EINVAL; 3342 break; 3343 } 3344 nfsstats.rpccnt[NFSPROC_PATHCONF]++; 3345 nfsm_reqhead(np, NFSPROC_PATHCONF, NFSX_FH(1)); 3346 nfsm_fhtom(np, 1); 3347 nfsm_request(np, NFSPROC_PATHCONF, 3348 curlwp, curlwp->l_proc->p_ucred); /* XXX */ 3349 nfsm_postop_attr(vp, attrflag, 0); 3350 if (!error) { 3351 nfsm_dissect(pcp, struct nfsv3_pathconf *, 3352 NFSX_V3PATHCONF); 3353 switch (ap->a_name) { 3354 case _PC_LINK_MAX: 3355 *ap->a_retval = 3356 fxdr_unsigned(register_t, pcp->pc_linkmax); 3357 break; 3358 case _PC_NAME_MAX: 3359 *ap->a_retval = 3360 fxdr_unsigned(register_t, pcp->pc_namemax); 3361 break; 3362 case _PC_CHOWN_RESTRICTED: 3363 *ap->a_retval = 3364 (pcp->pc_chownrestricted == nfs_true); 3365 break; 3366 case _PC_NO_TRUNC: 3367 *ap->a_retval = 3368 (pcp->pc_notrunc == nfs_true); 3369 break; 3370 } 3371 } 3372 nfsm_reqdone; 3373 break; 3374 case _PC_FILESIZEBITS: 3375 #ifndef NFS_V2_ONLY 3376 if (v3) { 3377 nmp = VFSTONFS(vp->v_mount); 3378 if ((nmp->nm_iflag & NFSMNT_GOTFSINFO) == 0) 3379 if ((error = nfs_fsinfo(nmp, vp, 3380 curproc->p_ucred, curlwp)) != 0) /* XXX */ 3381 break; 3382 for (l = 0, maxsize = nmp->nm_maxfilesize; 3383 (maxsize >> l) > 0; l++) 3384 ; 3385 *ap->a_retval = l + 1; 3386 } else 3387 #endif 3388 { 3389 *ap->a_retval = 32; /* NFS V2 limitation */ 3390 } 3391 break; 3392 default: 3393 error = EINVAL; 3394 break; 3395 } 3396 3397 return (error); 3398 } 3399 3400 /* 3401 * NFS advisory byte-level locks. 3402 */ 3403 int 3404 nfs_advlock(v) 3405 void *v; 3406 { 3407 struct vop_advlock_args /* { 3408 struct vnode *a_vp; 3409 caddr_t a_id; 3410 int a_op; 3411 struct flock *a_fl; 3412 int a_flags; 3413 } */ *ap = v; 3414 struct nfsnode *np = VTONFS(ap->a_vp); 3415 3416 return lf_advlock(ap, &np->n_lockf, np->n_size); 3417 } 3418 3419 /* 3420 * Print out the contents of an nfsnode. 3421 */ 3422 int 3423 nfs_print(v) 3424 void *v; 3425 { 3426 struct vop_print_args /* { 3427 struct vnode *a_vp; 3428 } */ *ap = v; 3429 struct vnode *vp = ap->a_vp; 3430 struct nfsnode *np = VTONFS(vp); 3431 3432 printf("tag VT_NFS, fileid %lld fsid 0x%lx", 3433 (unsigned long long)np->n_vattr->va_fileid, np->n_vattr->va_fsid); 3434 if (vp->v_type == VFIFO) 3435 fifo_printinfo(vp); 3436 printf("\n"); 3437 return (0); 3438 } 3439 3440 /* 3441 * nfs unlock wrapper. 3442 */ 3443 int 3444 nfs_unlock(void *v) 3445 { 3446 struct vop_unlock_args /* { 3447 struct vnode *a_vp; 3448 int a_flags; 3449 } */ *ap = v; 3450 struct vnode *vp = ap->a_vp; 3451 3452 /* 3453 * VOP_UNLOCK can be called by nfs_loadattrcache 3454 * with v_data == 0. 3455 */ 3456 if (VTONFS(vp)) { 3457 nfs_delayedtruncate(vp); 3458 } 3459 3460 return genfs_unlock(v); 3461 } 3462 3463 /* 3464 * nfs special file access vnode op. 3465 * Essentially just get vattr and then imitate iaccess() since the device is 3466 * local to the client. 3467 */ 3468 int 3469 nfsspec_access(v) 3470 void *v; 3471 { 3472 struct vop_access_args /* { 3473 struct vnode *a_vp; 3474 int a_mode; 3475 struct ucred *a_cred; 3476 struct lwp *a_l; 3477 } */ *ap = v; 3478 struct vattr va; 3479 struct vnode *vp = ap->a_vp; 3480 int error; 3481 3482 error = VOP_GETATTR(vp, &va, ap->a_cred, ap->a_l); 3483 if (error) 3484 return (error); 3485 3486 /* 3487 * Disallow write attempts on filesystems mounted read-only; 3488 * unless the file is a socket, fifo, or a block or character 3489 * device resident on the filesystem. 3490 */ 3491 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 3492 switch (vp->v_type) { 3493 case VREG: 3494 case VDIR: 3495 case VLNK: 3496 return (EROFS); 3497 default: 3498 break; 3499 } 3500 } 3501 3502 return (vaccess(va.va_type, va.va_mode, 3503 va.va_uid, va.va_gid, ap->a_mode, ap->a_cred)); 3504 } 3505 3506 /* 3507 * Read wrapper for special devices. 3508 */ 3509 int 3510 nfsspec_read(v) 3511 void *v; 3512 { 3513 struct vop_read_args /* { 3514 struct vnode *a_vp; 3515 struct uio *a_uio; 3516 int a_ioflag; 3517 struct ucred *a_cred; 3518 } */ *ap = v; 3519 struct nfsnode *np = VTONFS(ap->a_vp); 3520 3521 /* 3522 * Set access flag. 3523 */ 3524 np->n_flag |= NACC; 3525 np->n_atim.tv_sec = time.tv_sec; 3526 np->n_atim.tv_nsec = time.tv_usec * 1000; 3527 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap)); 3528 } 3529 3530 /* 3531 * Write wrapper for special devices. 3532 */ 3533 int 3534 nfsspec_write(v) 3535 void *v; 3536 { 3537 struct vop_write_args /* { 3538 struct vnode *a_vp; 3539 struct uio *a_uio; 3540 int a_ioflag; 3541 struct ucred *a_cred; 3542 } */ *ap = v; 3543 struct nfsnode *np = VTONFS(ap->a_vp); 3544 3545 /* 3546 * Set update flag. 3547 */ 3548 np->n_flag |= NUPD; 3549 np->n_mtim.tv_sec = time.tv_sec; 3550 np->n_mtim.tv_nsec = time.tv_usec * 1000; 3551 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap)); 3552 } 3553 3554 /* 3555 * Close wrapper for special devices. 3556 * 3557 * Update the times on the nfsnode then do device close. 3558 */ 3559 int 3560 nfsspec_close(v) 3561 void *v; 3562 { 3563 struct vop_close_args /* { 3564 struct vnode *a_vp; 3565 int a_fflag; 3566 struct ucred *a_cred; 3567 struct lwp *a_l; 3568 } */ *ap = v; 3569 struct vnode *vp = ap->a_vp; 3570 struct nfsnode *np = VTONFS(vp); 3571 struct vattr vattr; 3572 3573 if (np->n_flag & (NACC | NUPD)) { 3574 np->n_flag |= NCHG; 3575 if (vp->v_usecount == 1 && 3576 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3577 VATTR_NULL(&vattr); 3578 if (np->n_flag & NACC) 3579 vattr.va_atime = np->n_atim; 3580 if (np->n_flag & NUPD) 3581 vattr.va_mtime = np->n_mtim; 3582 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_l); 3583 } 3584 } 3585 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 3586 } 3587 3588 /* 3589 * Read wrapper for fifos. 3590 */ 3591 int 3592 nfsfifo_read(v) 3593 void *v; 3594 { 3595 struct vop_read_args /* { 3596 struct vnode *a_vp; 3597 struct uio *a_uio; 3598 int a_ioflag; 3599 struct ucred *a_cred; 3600 } */ *ap = v; 3601 struct nfsnode *np = VTONFS(ap->a_vp); 3602 3603 /* 3604 * Set access flag. 3605 */ 3606 np->n_flag |= NACC; 3607 np->n_atim.tv_sec = time.tv_sec; 3608 np->n_atim.tv_nsec = time.tv_usec * 1000; 3609 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap)); 3610 } 3611 3612 /* 3613 * Write wrapper for fifos. 3614 */ 3615 int 3616 nfsfifo_write(v) 3617 void *v; 3618 { 3619 struct vop_write_args /* { 3620 struct vnode *a_vp; 3621 struct uio *a_uio; 3622 int a_ioflag; 3623 struct ucred *a_cred; 3624 } */ *ap = v; 3625 struct nfsnode *np = VTONFS(ap->a_vp); 3626 3627 /* 3628 * Set update flag. 3629 */ 3630 np->n_flag |= NUPD; 3631 np->n_mtim.tv_sec = time.tv_sec; 3632 np->n_mtim.tv_nsec = time.tv_usec * 1000; 3633 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap)); 3634 } 3635 3636 /* 3637 * Close wrapper for fifos. 3638 * 3639 * Update the times on the nfsnode then do fifo close. 3640 */ 3641 int 3642 nfsfifo_close(v) 3643 void *v; 3644 { 3645 struct vop_close_args /* { 3646 struct vnode *a_vp; 3647 int a_fflag; 3648 struct ucred *a_cred; 3649 struct lwp *a_l; 3650 } */ *ap = v; 3651 struct vnode *vp = ap->a_vp; 3652 struct nfsnode *np = VTONFS(vp); 3653 struct vattr vattr; 3654 3655 if (np->n_flag & (NACC | NUPD)) { 3656 if (np->n_flag & NACC) { 3657 np->n_atim.tv_sec = time.tv_sec; 3658 np->n_atim.tv_nsec = time.tv_usec * 1000; 3659 } 3660 if (np->n_flag & NUPD) { 3661 np->n_mtim.tv_sec = time.tv_sec; 3662 np->n_mtim.tv_nsec = time.tv_usec * 1000; 3663 } 3664 np->n_flag |= NCHG; 3665 if (vp->v_usecount == 1 && 3666 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3667 VATTR_NULL(&vattr); 3668 if (np->n_flag & NACC) 3669 vattr.va_atime = np->n_atim; 3670 if (np->n_flag & NUPD) 3671 vattr.va_mtime = np->n_mtim; 3672 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_l); 3673 } 3674 } 3675 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 3676 } 3677