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