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