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