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