1 /* $OpenBSD: nfs_vnops.c,v 1.46 2001/12/22 09:58:04 art Exp $ */ 2 /* $NetBSD: nfs_vnops.c,v 1.62.4.1 1996/07/08 20:26:52 jtc Exp $ */ 3 4 /* 5 * Copyright (c) 1989, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Rick Macklem at The University of Guelph. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * @(#)nfs_vnops.c 8.16 (Berkeley) 5/27/95 40 */ 41 42 43 /* 44 * vnode op calls for Sun NFS version 2 and 3 45 */ 46 47 #include <sys/param.h> 48 #include <sys/proc.h> 49 #include <sys/kernel.h> 50 #include <sys/systm.h> 51 #include <sys/resourcevar.h> 52 #include <sys/proc.h> 53 #include <sys/mount.h> 54 #include <sys/buf.h> 55 #include <sys/malloc.h> 56 #include <sys/mbuf.h> 57 #include <sys/conf.h> 58 #include <sys/namei.h> 59 #include <sys/vnode.h> 60 #include <sys/dirent.h> 61 #include <sys/fcntl.h> 62 #include <sys/lockf.h> 63 64 #include <uvm/uvm_extern.h> 65 66 #include <miscfs/specfs/specdev.h> 67 #include <miscfs/fifofs/fifo.h> 68 69 #include <nfs/rpcv2.h> 70 #include <nfs/nfsproto.h> 71 #include <nfs/nfs.h> 72 #include <nfs/nfsnode.h> 73 #include <nfs/nfsmount.h> 74 #include <nfs/xdr_subs.h> 75 #include <nfs/nfsm_subs.h> 76 #include <nfs/nfs_var.h> 77 78 #include <net/if.h> 79 #include <netinet/in.h> 80 #include <netinet/in_var.h> 81 82 /* Defs */ 83 #define TRUE 1 84 #define FALSE 0 85 86 /* 87 * Global vfs data structures for nfs 88 */ 89 int (**nfsv2_vnodeop_p) __P((void *)); 90 struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = { 91 { &vop_default_desc, vn_default_error }, 92 { &vop_lookup_desc, nfs_lookup }, /* lookup */ 93 { &vop_create_desc, nfs_create }, /* create */ 94 { &vop_mknod_desc, nfs_mknod }, /* mknod */ 95 { &vop_open_desc, nfs_open }, /* open */ 96 { &vop_close_desc, nfs_close }, /* close */ 97 { &vop_access_desc, nfs_access }, /* access */ 98 { &vop_getattr_desc, nfs_getattr }, /* getattr */ 99 { &vop_setattr_desc, nfs_setattr }, /* setattr */ 100 { &vop_read_desc, nfs_read }, /* read */ 101 { &vop_write_desc, nfs_write }, /* write */ 102 { &vop_lease_desc, nfs_lease_check }, /* lease */ 103 { &vop_ioctl_desc, nfs_ioctl }, /* ioctl */ 104 { &vop_select_desc, nfs_select }, /* select */ 105 { &vop_kqfilter_desc, vop_generic_kqfilter }, /* kqfilter */ 106 { &vop_revoke_desc, nfs_revoke }, /* revoke */ 107 { &vop_fsync_desc, nfs_fsync }, /* fsync */ 108 { &vop_remove_desc, nfs_remove }, /* remove */ 109 { &vop_link_desc, nfs_link }, /* link */ 110 { &vop_rename_desc, nfs_rename }, /* rename */ 111 { &vop_mkdir_desc, nfs_mkdir }, /* mkdir */ 112 { &vop_rmdir_desc, nfs_rmdir }, /* rmdir */ 113 { &vop_symlink_desc, nfs_symlink }, /* symlink */ 114 { &vop_readdir_desc, nfs_readdir }, /* readdir */ 115 { &vop_readlink_desc, nfs_readlink }, /* readlink */ 116 { &vop_abortop_desc, vop_generic_abortop }, /* abortop */ 117 { &vop_inactive_desc, nfs_inactive }, /* inactive */ 118 { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ 119 { &vop_lock_desc, nfs_lock }, /* lock */ 120 { &vop_unlock_desc, nfs_unlock }, /* unlock */ 121 { &vop_bmap_desc, nfs_bmap }, /* bmap */ 122 { &vop_strategy_desc, nfs_strategy }, /* strategy */ 123 { &vop_print_desc, nfs_print }, /* print */ 124 { &vop_islocked_desc, nfs_islocked }, /* islocked */ 125 { &vop_pathconf_desc, nfs_pathconf }, /* pathconf */ 126 { &vop_advlock_desc, nfs_advlock }, /* advlock */ 127 { &vop_reallocblks_desc, nfs_reallocblks }, /* reallocblks */ 128 { &vop_bwrite_desc, nfs_bwrite }, 129 { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } 130 }; 131 struct vnodeopv_desc nfsv2_vnodeop_opv_desc = 132 { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries }; 133 134 /* 135 * Special device vnode ops 136 */ 137 int (**spec_nfsv2nodeop_p) __P((void *)); 138 struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = { 139 { &vop_default_desc, vn_default_error }, 140 { &vop_lookup_desc, spec_lookup }, /* lookup */ 141 { &vop_create_desc, spec_create }, /* create */ 142 { &vop_mknod_desc, spec_mknod }, /* mknod */ 143 { &vop_open_desc, spec_open }, /* open */ 144 { &vop_close_desc, nfsspec_close }, /* close */ 145 { &vop_access_desc, nfsspec_access }, /* access */ 146 { &vop_getattr_desc, nfs_getattr }, /* getattr */ 147 { &vop_setattr_desc, nfs_setattr }, /* setattr */ 148 { &vop_read_desc, nfsspec_read }, /* read */ 149 { &vop_write_desc, nfsspec_write }, /* write */ 150 { &vop_lease_desc, spec_lease_check }, /* lease */ 151 { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 152 { &vop_select_desc, spec_select }, /* select */ 153 { &vop_revoke_desc, spec_revoke }, /* revoke */ 154 { &vop_fsync_desc, nfs_fsync }, /* fsync */ 155 { &vop_remove_desc, spec_remove }, /* remove */ 156 { &vop_link_desc, spec_link }, /* link */ 157 { &vop_rename_desc, spec_rename }, /* rename */ 158 { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 159 { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 160 { &vop_symlink_desc, spec_symlink }, /* symlink */ 161 { &vop_readdir_desc, spec_readdir }, /* readdir */ 162 { &vop_readlink_desc, spec_readlink }, /* readlink */ 163 { &vop_abortop_desc, spec_abortop }, /* abortop */ 164 { &vop_inactive_desc, nfs_inactive }, /* inactive */ 165 { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ 166 { &vop_lock_desc, nfs_lock }, /* lock */ 167 { &vop_unlock_desc, nfs_unlock }, /* unlock */ 168 { &vop_bmap_desc, spec_bmap }, /* bmap */ 169 { &vop_strategy_desc, spec_strategy }, /* strategy */ 170 { &vop_print_desc, nfs_print }, /* print */ 171 { &vop_islocked_desc, nfs_islocked }, /* islocked */ 172 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ 173 { &vop_advlock_desc, spec_advlock }, /* advlock */ 174 { &vop_reallocblks_desc, spec_reallocblks }, /* reallocblks */ 175 { &vop_bwrite_desc, vop_generic_bwrite }, 176 { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } 177 }; 178 struct vnodeopv_desc spec_nfsv2nodeop_opv_desc = 179 { &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries }; 180 181 #ifdef FIFO 182 int (**fifo_nfsv2nodeop_p) __P((void *)); 183 struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = { 184 { &vop_default_desc, vn_default_error }, 185 { &vop_lookup_desc, fifo_lookup }, /* lookup */ 186 { &vop_create_desc, fifo_create }, /* create */ 187 { &vop_mknod_desc, fifo_mknod }, /* mknod */ 188 { &vop_open_desc, fifo_open }, /* open */ 189 { &vop_close_desc, nfsfifo_close }, /* close */ 190 { &vop_access_desc, nfsspec_access }, /* access */ 191 { &vop_getattr_desc, nfs_getattr }, /* getattr */ 192 { &vop_setattr_desc, nfs_setattr }, /* setattr */ 193 { &vop_read_desc, nfsfifo_read }, /* read */ 194 { &vop_write_desc, nfsfifo_write }, /* write */ 195 { &vop_lease_desc, fifo_lease_check }, /* lease */ 196 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 197 { &vop_select_desc, fifo_select }, /* select */ 198 { &vop_revoke_desc, fifo_revoke }, /* revoke */ 199 { &vop_fsync_desc, nfs_fsync }, /* fsync */ 200 { &vop_remove_desc, fifo_remove }, /* remove */ 201 { &vop_link_desc, fifo_link }, /* link */ 202 { &vop_rename_desc, fifo_rename }, /* rename */ 203 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 204 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 205 { &vop_symlink_desc, fifo_symlink }, /* symlink */ 206 { &vop_readdir_desc, fifo_readdir }, /* readdir */ 207 { &vop_readlink_desc, fifo_readlink }, /* readlink */ 208 { &vop_abortop_desc, fifo_abortop }, /* abortop */ 209 { &vop_inactive_desc, nfs_inactive }, /* inactive */ 210 { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ 211 { &vop_lock_desc, nfs_lock }, /* lock */ 212 { &vop_unlock_desc, nfs_unlock }, /* unlock */ 213 { &vop_bmap_desc, fifo_bmap }, /* bmap */ 214 { &vop_strategy_desc, fifo_badop }, /* strategy */ 215 { &vop_print_desc, nfs_print }, /* print */ 216 { &vop_islocked_desc, nfs_islocked }, /* islocked */ 217 { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ 218 { &vop_advlock_desc, fifo_advlock }, /* advlock */ 219 { &vop_reallocblks_desc, fifo_reallocblks }, /* reallocblks */ 220 { &vop_bwrite_desc, vop_generic_bwrite }, 221 { (struct vnodeop_desc*)NULL, (int(*) __P((void *)))NULL } 222 }; 223 struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc = 224 { &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries }; 225 #endif /* FIFO */ 226 227 /* 228 * Global variables 229 */ 230 extern u_int32_t nfs_true, nfs_false; 231 extern u_int32_t nfs_xdrneg1; 232 extern struct nfsstats nfsstats; 233 extern nfstype nfsv3_type[9]; 234 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 235 int nfs_numasync = 0; 236 237 /* 238 * nfs null call from vfs. 239 */ 240 int 241 nfs_null(vp, cred, procp) 242 struct vnode *vp; 243 struct ucred *cred; 244 struct proc *procp; 245 { 246 caddr_t bpos, dpos; 247 int error = 0; 248 struct mbuf *mreq, *mrep, *md, *mb; 249 250 nfsm_reqhead(vp, NFSPROC_NULL, 0); 251 nfsm_request(vp, NFSPROC_NULL, procp, cred); 252 nfsm_reqdone; 253 return (error); 254 } 255 256 /* 257 * nfs access vnode op. 258 * For nfs version 2, just return ok. File accesses may fail later. 259 * For nfs version 3, use the access rpc to check accessibility. If file modes 260 * are changed on the server, accesses might still fail later. 261 */ 262 int 263 nfs_access(v) 264 void *v; 265 { 266 struct vop_access_args /* { 267 struct vnode *a_vp; 268 int a_mode; 269 struct ucred *a_cred; 270 struct proc *a_p; 271 } */ *ap = v; 272 register struct vnode *vp = ap->a_vp; 273 register u_int32_t *tl; 274 register caddr_t cp; 275 register int32_t t1, t2; 276 caddr_t bpos, dpos, cp2; 277 int error = 0, attrflag; 278 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 279 u_int32_t mode, rmode; 280 int v3 = NFS_ISV3(vp); 281 282 /* 283 * Disallow write attempts on filesystems mounted read-only; 284 * unless the file is a socket, fifo, or a block or character 285 * device resident on the filesystem. 286 */ 287 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 288 switch (vp->v_type) { 289 case VREG: 290 case VDIR: 291 case VLNK: 292 return (EROFS); 293 default: 294 break; 295 } 296 } 297 /* 298 * For nfs v3, do an access rpc, otherwise you are stuck emulating 299 * ufs_access() locally using the vattr. This may not be correct, 300 * since the server may apply other access criteria such as 301 * client uid-->server uid mapping that we do not know about, but 302 * this is better than just returning anything that is lying about 303 * in the cache. 304 */ 305 if (v3) { 306 nfsstats.rpccnt[NFSPROC_ACCESS]++; 307 nfsm_reqhead(vp, NFSPROC_ACCESS, NFSX_FH(v3) + NFSX_UNSIGNED); 308 nfsm_fhtom(vp, v3); 309 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); 310 if (ap->a_mode & VREAD) 311 mode = NFSV3ACCESS_READ; 312 else 313 mode = 0; 314 if (vp->v_type == VDIR) { 315 if (ap->a_mode & VWRITE) 316 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND | 317 NFSV3ACCESS_DELETE); 318 if (ap->a_mode & VEXEC) 319 mode |= NFSV3ACCESS_LOOKUP; 320 } else { 321 if (ap->a_mode & VWRITE) 322 mode |= (NFSV3ACCESS_MODIFY | NFSV3ACCESS_EXTEND); 323 if (ap->a_mode & VEXEC) 324 mode |= NFSV3ACCESS_EXECUTE; 325 } 326 *tl = txdr_unsigned(mode); 327 nfsm_request(vp, NFSPROC_ACCESS, ap->a_p, ap->a_cred); 328 nfsm_postop_attr(vp, attrflag); 329 if (!error) { 330 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 331 rmode = fxdr_unsigned(u_int32_t, *tl); 332 /* 333 * The NFS V3 spec does not clarify whether or not 334 * the returned access bits can be a superset of 335 * the ones requested, so... 336 */ 337 if ((rmode & mode) != mode) 338 error = EACCES; 339 } 340 nfsm_reqdone; 341 return (error); 342 } else 343 return (nfsspec_access(ap)); 344 } 345 346 /* 347 * nfs open vnode op 348 * Check to see if the type is ok 349 * and that deletion is not in progress. 350 * For paged in text files, you will need to flush the page cache 351 * if consistency is lost. 352 */ 353 /* ARGSUSED */ 354 int 355 nfs_open(v) 356 void *v; 357 { 358 struct vop_open_args /* { 359 struct vnode *a_vp; 360 int a_mode; 361 struct ucred *a_cred; 362 struct proc *a_p; 363 } */ *ap = v; 364 register struct vnode *vp = ap->a_vp; 365 struct nfsnode *np = VTONFS(vp); 366 struct vattr vattr; 367 int error; 368 369 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) { 370 #ifdef DIAGNOSTIC 371 printf("open eacces vtyp=%d\n",vp->v_type); 372 #endif 373 return (EACCES); 374 } 375 376 /* 377 * Initialize read and write creds here, for swapfiles 378 * and other paths that don't set the creds themselves. 379 */ 380 381 if (ap->a_mode & FREAD) { 382 if (np->n_rcred) { 383 crfree(np->n_rcred); 384 } 385 np->n_rcred = ap->a_cred; 386 crhold(np->n_rcred); 387 } 388 if (ap->a_mode & FWRITE) { 389 if (np->n_wcred) { 390 crfree(np->n_wcred); 391 } 392 np->n_wcred = ap->a_cred; 393 crhold(np->n_wcred); 394 } 395 396 if (np->n_flag & NMODIFIED) { 397 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 398 ap->a_p, 1)) == EINTR) 399 return (error); 400 uvm_vnp_uncache(vp); 401 np->n_attrstamp = 0; 402 if (vp->v_type == VDIR) 403 np->n_direofoffset = 0; 404 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 405 if (error) 406 return (error); 407 np->n_mtime = vattr.va_mtime.tv_sec; 408 } else { 409 error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p); 410 if (error) 411 return (error); 412 if (np->n_mtime != vattr.va_mtime.tv_sec) { 413 if (vp->v_type == VDIR) 414 np->n_direofoffset = 0; 415 if ((error = nfs_vinvalbuf(vp, V_SAVE, 416 ap->a_cred, ap->a_p, 1)) == EINTR) 417 return (error); 418 uvm_vnp_uncache(vp); 419 np->n_mtime = vattr.va_mtime.tv_sec; 420 } 421 } 422 np->n_attrstamp = 0; /* For Open/Close consistency */ 423 return (0); 424 } 425 426 /* 427 * nfs close vnode op 428 * What an NFS client should do upon close after writing is a debatable issue. 429 * Most NFS clients push delayed writes to the server upon close, basically for 430 * two reasons: 431 * 1 - So that any write errors may be reported back to the client process 432 * doing the close system call. By far the two most likely errors are 433 * NFSERR_NOSPC and NFSERR_DQUOT to indicate space allocation failure. 434 * 2 - To put a worst case upper bound on cache inconsistency between 435 * multiple clients for the file. 436 * There is also a consistency problem for Version 2 of the protocol w.r.t. 437 * not being able to tell if other clients are writing a file concurrently, 438 * since there is no way of knowing if the changed modify time in the reply 439 * is only due to the write for this client. 440 * (NFS Version 3 provides weak cache consistency data in the reply that 441 * should be sufficient to detect and handle this case.) 442 * 443 * The current code does the following: 444 * for NFS Version 2 - play it safe and flush/invalidate all dirty buffers 445 * for NFS Version 3 - flush dirty buffers to the server but don't invalidate 446 * or commit them (this satisfies 1 and 2 except for the 447 * case where the server crashes after this close but 448 * before the commit RPC, which is felt to be "good 449 * enough". Changing the last argument to nfs_flush() to 450 * a 1 would force a commit operation, if it is felt a 451 * commit is necessary now. 452 */ 453 /* ARGSUSED */ 454 int 455 nfs_close(v) 456 void *v; 457 { 458 struct vop_close_args /* { 459 struct vnodeop_desc *a_desc; 460 struct vnode *a_vp; 461 int a_fflag; 462 struct ucred *a_cred; 463 struct proc *a_p; 464 } */ *ap = v; 465 register struct vnode *vp = ap->a_vp; 466 register struct nfsnode *np = VTONFS(vp); 467 int error = 0; 468 469 if (vp->v_type == VREG) { 470 if (np->n_flag & NMODIFIED) { 471 if (NFS_ISV3(vp)) { 472 error = nfs_flush(vp, ap->a_cred, MNT_WAIT, ap->a_p, 0); 473 np->n_flag &= ~NMODIFIED; 474 } else 475 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1); 476 np->n_attrstamp = 0; 477 } 478 if (np->n_flag & NWRITEERR) { 479 np->n_flag &= ~NWRITEERR; 480 error = np->n_error; 481 } 482 } 483 return (error); 484 } 485 486 /* 487 * nfs getattr call from vfs. 488 */ 489 int 490 nfs_getattr(v) 491 void *v; 492 { 493 struct vop_getattr_args /* { 494 struct vnode *a_vp; 495 struct vattr *a_vap; 496 struct ucred *a_cred; 497 struct proc *a_p; 498 } */ *ap = v; 499 register struct vnode *vp = ap->a_vp; 500 register struct nfsnode *np = VTONFS(vp); 501 register caddr_t cp; 502 register u_int32_t *tl; 503 register int32_t t1, t2; 504 caddr_t bpos, dpos; 505 int error = 0; 506 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 507 int v3 = NFS_ISV3(vp); 508 509 /* 510 * Update local times for special files. 511 */ 512 if (np->n_flag & (NACC | NUPD)) 513 np->n_flag |= NCHG; 514 /* 515 * First look in the cache. 516 */ 517 if (nfs_getattrcache(vp, ap->a_vap) == 0) 518 return (0); 519 nfsstats.rpccnt[NFSPROC_GETATTR]++; 520 nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH(v3)); 521 nfsm_fhtom(vp, v3); 522 nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred); 523 if (!error) 524 nfsm_loadattr(vp, ap->a_vap); 525 nfsm_reqdone; 526 return (error); 527 } 528 529 /* 530 * nfs setattr call. 531 */ 532 int 533 nfs_setattr(v) 534 void *v; 535 { 536 struct vop_setattr_args /* { 537 struct vnodeop_desc *a_desc; 538 struct vnode *a_vp; 539 struct vattr *a_vap; 540 struct ucred *a_cred; 541 struct proc *a_p; 542 } */ *ap = v; 543 register struct vnode *vp = ap->a_vp; 544 register struct nfsnode *np = VTONFS(vp); 545 register struct vattr *vap = ap->a_vap; 546 int error = 0; 547 u_quad_t tsize = 0; 548 549 /* 550 * Setting of flags is not supported. 551 */ 552 if (vap->va_flags != VNOVAL) 553 return (EOPNOTSUPP); 554 555 /* 556 * Disallow write attempts if the filesystem is mounted read-only. 557 */ 558 if ((vap->va_uid != (uid_t)VNOVAL || 559 vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || 560 vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL) && 561 (vp->v_mount->mnt_flag & MNT_RDONLY)) 562 return (EROFS); 563 if (vap->va_size != VNOVAL) { 564 switch (vp->v_type) { 565 case VDIR: 566 return (EISDIR); 567 case VCHR: 568 case VBLK: 569 case VSOCK: 570 case VFIFO: 571 if (vap->va_mtime.tv_sec == VNOVAL && 572 vap->va_atime.tv_sec == VNOVAL && 573 vap->va_mode == (mode_t)VNOVAL && 574 vap->va_uid == (uid_t)VNOVAL && 575 vap->va_gid == (gid_t)VNOVAL) 576 return (0); 577 vap->va_size = VNOVAL; 578 break; 579 default: 580 /* 581 * Disallow write attempts if the filesystem is 582 * mounted read-only. 583 */ 584 if (vp->v_mount->mnt_flag & MNT_RDONLY) 585 return (EROFS); 586 if (vap->va_size == 0) 587 error = nfs_vinvalbuf(vp, 0, 588 ap->a_cred, ap->a_p, 1); 589 else 590 error = nfs_vinvalbuf(vp, V_SAVE, 591 ap->a_cred, ap->a_p, 1); 592 if (error) 593 return (error); 594 tsize = np->n_size; 595 np->n_size = np->n_vattr.va_size = vap->va_size; 596 uvm_vnp_setsize(vp, np->n_size); 597 }; 598 } else if ((vap->va_mtime.tv_sec != VNOVAL || 599 vap->va_atime.tv_sec != VNOVAL) && 600 vp->v_type == VREG && 601 (error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 602 ap->a_p, 1)) == EINTR) 603 return (error); 604 error = nfs_setattrrpc(vp, vap, ap->a_cred, ap->a_p); 605 if (error && vap->va_size != VNOVAL) { 606 np->n_size = np->n_vattr.va_size = tsize; 607 uvm_vnp_setsize(vp, np->n_size); 608 } 609 return (error); 610 } 611 612 /* 613 * Do an nfs setattr rpc. 614 */ 615 int 616 nfs_setattrrpc(vp, vap, cred, procp) 617 struct vnode *vp; 618 struct vattr *vap; 619 struct ucred *cred; 620 struct proc *procp; 621 { 622 register struct nfsv2_sattr *sp; 623 register caddr_t cp; 624 register int32_t t1, t2; 625 caddr_t bpos, dpos, cp2; 626 u_int32_t *tl; 627 int error = 0, wccflag = NFSV3_WCCRATTR; 628 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 629 int v3 = NFS_ISV3(vp); 630 631 nfsstats.rpccnt[NFSPROC_SETATTR]++; 632 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH(v3) + NFSX_SATTR(v3)); 633 nfsm_fhtom(vp, v3); 634 if (v3) { 635 nfsm_v3attrbuild(vap, TRUE); 636 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); 637 *tl = nfs_false; 638 } else { 639 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 640 if (vap->va_mode == (mode_t)VNOVAL) 641 sp->sa_mode = nfs_xdrneg1; 642 else 643 sp->sa_mode = vtonfsv2_mode(vp->v_type, vap->va_mode); 644 if (vap->va_uid == (uid_t)VNOVAL) 645 sp->sa_uid = nfs_xdrneg1; 646 else 647 sp->sa_uid = txdr_unsigned(vap->va_uid); 648 if (vap->va_gid == (gid_t)VNOVAL) 649 sp->sa_gid = nfs_xdrneg1; 650 else 651 sp->sa_gid = txdr_unsigned(vap->va_gid); 652 sp->sa_size = txdr_unsigned(vap->va_size); 653 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 654 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 655 } 656 nfsm_request(vp, NFSPROC_SETATTR, procp, cred); 657 if (v3) { 658 nfsm_wcc_data(vp, wccflag); 659 } else 660 nfsm_loadattr(vp, (struct vattr *)0); 661 nfsm_reqdone; 662 return (error); 663 } 664 665 /* 666 * nfs lookup call, one step at a time... 667 * First look in cache 668 * If not found, unlock the directory nfsnode and do the rpc 669 */ 670 int 671 nfs_lookup(v) 672 void *v; 673 { 674 struct vop_lookup_args /* { 675 struct vnodeop_desc *a_desc; 676 struct vnode *a_dvp; 677 struct vnode **a_vpp; 678 struct componentname *a_cnp; 679 } */ *ap = v; 680 register struct componentname *cnp = ap->a_cnp; 681 register struct vnode *dvp = ap->a_dvp; 682 register struct vnode **vpp = ap->a_vpp; 683 struct proc *p = cnp->cn_proc; 684 register int flags = cnp->cn_flags; 685 register struct vnode *newvp; 686 register u_int32_t *tl; 687 register caddr_t cp; 688 register int32_t t1, t2; 689 struct nfsmount *nmp; 690 caddr_t bpos, dpos, cp2; 691 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 692 long len; 693 nfsfh_t *fhp; 694 struct nfsnode *np; 695 int lockparent, wantparent, error = 0, attrflag, fhsize; 696 int v3 = NFS_ISV3(dvp); 697 698 *vpp = NULLVP; 699 if ((flags & ISLASTCN) && (dvp->v_mount->mnt_flag & MNT_RDONLY) && 700 (cnp->cn_nameiop == DELETE || cnp->cn_nameiop == RENAME)) 701 return (EROFS); 702 if (dvp->v_type != VDIR) 703 return (ENOTDIR); 704 lockparent = flags & LOCKPARENT; 705 wantparent = flags & (LOCKPARENT|WANTPARENT); 706 nmp = VFSTONFS(dvp->v_mount); 707 np = VTONFS(dvp); 708 if ((error = cache_lookup(dvp, vpp, cnp)) != 0 && error != ENOENT) { 709 struct vattr vattr; 710 int vpid; 711 712 newvp = *vpp; 713 vpid = newvp->v_id; 714 /* 715 * See the comment starting `Step through' in ufs/ufs_lookup.c 716 * for an explanation of the locking protocol 717 */ 718 if (dvp == newvp) { 719 VREF(newvp); 720 error = 0; 721 } else 722 error = vget(newvp, LK_EXCLUSIVE, p); 723 724 if (!error) { 725 if (vpid == newvp->v_id) { 726 if (!VOP_GETATTR(newvp, &vattr, cnp->cn_cred, cnp->cn_proc) 727 && vattr.va_ctime.tv_sec == VTONFS(newvp)->n_ctime) { 728 nfsstats.lookupcache_hits++; 729 if (cnp->cn_nameiop != LOOKUP && 730 (flags & ISLASTCN)) 731 cnp->cn_flags |= SAVENAME; 732 return (0); 733 } 734 cache_purge(newvp); 735 } 736 vrele(newvp); 737 } 738 *vpp = NULLVP; 739 } 740 error = 0; 741 newvp = NULLVP; 742 nfsstats.lookupcache_misses++; 743 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 744 len = cnp->cn_namelen; 745 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 746 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 747 nfsm_fhtom(dvp, v3); 748 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 749 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 750 if (error) { 751 nfsm_postop_attr(dvp, attrflag); 752 m_freem(mrep); 753 goto nfsmout; 754 } 755 nfsm_getfh(fhp, fhsize, v3); 756 757 /* 758 * Handle RENAME case... 759 */ 760 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { 761 if (NFS_CMPFH(np, fhp, fhsize)) { 762 m_freem(mrep); 763 return (EISDIR); 764 } 765 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np); 766 if (error) { 767 m_freem(mrep); 768 return (error); 769 } 770 newvp = NFSTOV(np); 771 if (v3) { 772 nfsm_postop_attr(newvp, attrflag); 773 nfsm_postop_attr(dvp, attrflag); 774 } else 775 nfsm_loadattr(newvp, (struct vattr *)0); 776 *vpp = newvp; 777 m_freem(mrep); 778 cnp->cn_flags |= SAVENAME; 779 return (0); 780 } 781 782 if (NFS_CMPFH(np, fhp, fhsize)) { 783 VREF(dvp); 784 newvp = dvp; 785 } else { 786 error = nfs_nget(dvp->v_mount, fhp, fhsize, &np); 787 if (error) { 788 m_freem(mrep); 789 return (error); 790 } 791 newvp = NFSTOV(np); 792 } 793 if (v3) { 794 nfsm_postop_attr(newvp, attrflag); 795 nfsm_postop_attr(dvp, attrflag); 796 } else 797 nfsm_loadattr(newvp, (struct vattr *)0); 798 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 799 cnp->cn_flags |= SAVENAME; 800 if ((cnp->cn_flags & MAKEENTRY) && 801 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { 802 np->n_ctime = np->n_vattr.va_ctime.tv_sec; 803 cache_enter(dvp, newvp, cnp); 804 } 805 *vpp = newvp; 806 nfsm_reqdone; 807 if (error) { 808 if (newvp != NULLVP) 809 vrele(newvp); 810 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && 811 (flags & ISLASTCN) && error == ENOENT) { 812 if (dvp->v_mount->mnt_flag & MNT_RDONLY) 813 error = EROFS; 814 else 815 error = EJUSTRETURN; 816 } 817 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 818 cnp->cn_flags |= SAVENAME; 819 } 820 return (error); 821 } 822 823 /* 824 * nfs read call. 825 * Just call nfs_bioread() to do the work. 826 */ 827 int 828 nfs_read(v) 829 void *v; 830 { 831 struct vop_read_args /* { 832 struct vnode *a_vp; 833 struct uio *a_uio; 834 int a_ioflag; 835 struct ucred *a_cred; 836 } */ *ap = v; 837 register struct vnode *vp = ap->a_vp; 838 839 if (vp->v_type != VREG) 840 return (EPERM); 841 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); 842 } 843 844 /* 845 * nfs readlink call 846 */ 847 int 848 nfs_readlink(v) 849 void *v; 850 { 851 struct vop_readlink_args /* { 852 struct vnode *a_vp; 853 struct uio *a_uio; 854 struct ucred *a_cred; 855 } */ *ap = v; 856 register struct vnode *vp = ap->a_vp; 857 858 if (vp->v_type != VLNK) 859 return (EPERM); 860 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred)); 861 } 862 863 /* 864 * Do a readlink rpc. 865 * Called by nfs_doio() from below the buffer cache. 866 */ 867 int 868 nfs_readlinkrpc(vp, uiop, cred) 869 register struct vnode *vp; 870 struct uio *uiop; 871 struct ucred *cred; 872 { 873 register u_int32_t *tl; 874 register caddr_t cp; 875 register int32_t t1, t2; 876 caddr_t bpos, dpos, cp2; 877 int error = 0, len, attrflag; 878 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 879 int v3 = NFS_ISV3(vp); 880 881 nfsstats.rpccnt[NFSPROC_READLINK]++; 882 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH(v3)); 883 nfsm_fhtom(vp, v3); 884 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred); 885 if (v3) 886 nfsm_postop_attr(vp, attrflag); 887 if (!error) { 888 nfsm_strsiz(len, NFS_MAXPATHLEN); 889 nfsm_mtouio(uiop, len); 890 } 891 nfsm_reqdone; 892 return (error); 893 } 894 895 /* 896 * nfs read rpc call 897 * Ditto above 898 */ 899 int 900 nfs_readrpc(vp, uiop) 901 struct vnode *vp; 902 struct uio *uiop; 903 { 904 u_int32_t *tl; 905 caddr_t cp; 906 int32_t t1, t2; 907 caddr_t bpos, dpos, cp2; 908 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 909 struct nfsmount *nmp; 910 int error = 0, len, retlen, tsiz, eof, attrflag; 911 int v3 = NFS_ISV3(vp); 912 913 #ifndef nolint 914 eof = 0; 915 #endif 916 nmp = VFSTONFS(vp->v_mount); 917 tsiz = uiop->uio_resid; 918 if (uiop->uio_offset + tsiz > 0xffffffff && !v3) 919 return (EFBIG); 920 while (tsiz > 0) { 921 nfsstats.rpccnt[NFSPROC_READ]++; 922 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 923 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH(v3) + NFSX_UNSIGNED * 3); 924 nfsm_fhtom(vp, v3); 925 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED * 3); 926 if (v3) { 927 txdr_hyper(uiop->uio_offset, tl); 928 *(tl + 2) = txdr_unsigned(len); 929 } else { 930 *tl++ = txdr_unsigned(uiop->uio_offset); 931 *tl++ = txdr_unsigned(len); 932 *tl = 0; 933 } 934 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, 935 VTONFS(vp)->n_rcred); 936 if (v3) { 937 nfsm_postop_attr(vp, attrflag); 938 if (error) { 939 m_freem(mrep); 940 goto nfsmout; 941 } 942 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 943 eof = fxdr_unsigned(int, *(tl + 1)); 944 } else 945 nfsm_loadattr(vp, (struct vattr *)0); 946 nfsm_strsiz(retlen, nmp->nm_rsize); 947 nfsm_mtouio(uiop, retlen); 948 m_freem(mrep); 949 tsiz -= retlen; 950 if (v3) { 951 if (eof || retlen == 0) 952 tsiz = 0; 953 } else if (retlen < len) 954 tsiz = 0; 955 } 956 nfsmout: 957 return (error); 958 } 959 960 /* 961 * nfs write call 962 */ 963 int 964 nfs_writerpc(vp, uiop, iomode, must_commit) 965 struct vnode *vp; 966 struct uio *uiop; 967 int *iomode, *must_commit; 968 { 969 u_int32_t *tl; 970 caddr_t cp; 971 int32_t t1, t2, backup; 972 caddr_t bpos, dpos, cp2; 973 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 974 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 975 int error = 0, len, tsiz, wccflag = NFSV3_WCCRATTR, rlen, commit; 976 int v3 = NFS_ISV3(vp), committed = NFSV3WRITE_FILESYNC; 977 978 #ifndef DIAGNOSTIC 979 if (uiop->uio_iovcnt != 1) 980 panic("nfs: writerpc iovcnt > 1"); 981 #endif 982 *must_commit = 0; 983 tsiz = uiop->uio_resid; 984 if (uiop->uio_offset + tsiz > 0xffffffff && !v3) 985 return (EFBIG); 986 while (tsiz > 0) { 987 nfsstats.rpccnt[NFSPROC_WRITE]++; 988 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 989 nfsm_reqhead(vp, NFSPROC_WRITE, 990 NFSX_FH(v3) + 5 * NFSX_UNSIGNED + nfsm_rndup(len)); 991 nfsm_fhtom(vp, v3); 992 if (v3) { 993 nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 994 txdr_hyper(uiop->uio_offset, tl); 995 tl += 2; 996 *tl++ = txdr_unsigned(len); 997 *tl++ = txdr_unsigned(*iomode); 998 *tl = txdr_unsigned(len); 999 } else { 1000 register u_int32_t x; 1001 1002 nfsm_build(tl, u_int32_t *, 4 * NFSX_UNSIGNED); 1003 /* Set both "begin" and "current" to non-garbage. */ 1004 x = txdr_unsigned((u_int32_t)uiop->uio_offset); 1005 *tl++ = x; /* "begin offset" */ 1006 *tl++ = x; /* "current offset" */ 1007 x = txdr_unsigned(len); 1008 *tl++ = x; /* total to this offset */ 1009 *tl = x; /* size of this write */ 1010 1011 } 1012 nfsm_uiotom(uiop, len); 1013 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, 1014 VTONFS(vp)->n_wcred); 1015 if (v3) { 1016 wccflag = NFSV3_WCCCHK; 1017 nfsm_wcc_data(vp, wccflag); 1018 if (!error) { 1019 nfsm_dissect(tl, u_int32_t *, 2 * NFSX_UNSIGNED 1020 + NFSX_V3WRITEVERF); 1021 rlen = fxdr_unsigned(int, *tl++); 1022 if (rlen == 0) { 1023 error = NFSERR_IO; 1024 break; 1025 } else if (rlen < len) { 1026 backup = len - rlen; 1027 uiop->uio_iov->iov_base -= backup; 1028 uiop->uio_iov->iov_len += backup; 1029 uiop->uio_offset -= backup; 1030 uiop->uio_resid += backup; 1031 len = rlen; 1032 } 1033 commit = fxdr_unsigned(int, *tl++); 1034 1035 /* 1036 * Return the lowest committment level 1037 * obtained by any of the RPCs. 1038 */ 1039 if (committed == NFSV3WRITE_FILESYNC) 1040 committed = commit; 1041 else if (committed == NFSV3WRITE_DATASYNC && 1042 commit == NFSV3WRITE_UNSTABLE) 1043 committed = commit; 1044 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) { 1045 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1046 NFSX_V3WRITEVERF); 1047 nmp->nm_flag |= NFSMNT_HASWRITEVERF; 1048 } else if (bcmp((caddr_t)tl, 1049 (caddr_t)nmp->nm_verf, NFSX_V3WRITEVERF)) { 1050 *must_commit = 1; 1051 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 1052 NFSX_V3WRITEVERF); 1053 } 1054 } 1055 } else 1056 nfsm_loadattr(vp, (struct vattr *)0); 1057 if (wccflag) 1058 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.tv_sec; 1059 m_freem(mrep); 1060 tsiz -= len; 1061 } 1062 nfsmout: 1063 *iomode = committed; 1064 if (error) 1065 uiop->uio_resid = tsiz; 1066 return (error); 1067 } 1068 1069 /* 1070 * nfs mknod rpc 1071 * For NFS v2 this is a kludge. Use a create rpc but with the IFMT bits of the 1072 * mode set to specify the file type and the size field for rdev. 1073 */ 1074 int 1075 nfs_mknodrpc(dvp, vpp, cnp, vap) 1076 register struct vnode *dvp; 1077 register struct vnode **vpp; 1078 register struct componentname *cnp; 1079 register struct vattr *vap; 1080 { 1081 register struct nfsv2_sattr *sp; 1082 register u_int32_t *tl; 1083 register caddr_t cp; 1084 register int32_t t1, t2; 1085 struct vnode *newvp = (struct vnode *)0; 1086 struct nfsnode *np; 1087 char *cp2; 1088 caddr_t bpos, dpos; 1089 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0; 1090 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1091 u_int32_t rdev; 1092 int v3 = NFS_ISV3(dvp); 1093 1094 if (vap->va_type == VCHR || vap->va_type == VBLK) 1095 rdev = txdr_unsigned(vap->va_rdev); 1096 else if (vap->va_type == VFIFO || vap->va_type == VSOCK) 1097 rdev = nfs_xdrneg1; 1098 else { 1099 VOP_ABORTOP(dvp, cnp); 1100 vput(dvp); 1101 return (EOPNOTSUPP); 1102 } 1103 nfsstats.rpccnt[NFSPROC_MKNOD]++; 1104 nfsm_reqhead(dvp, NFSPROC_MKNOD, NFSX_FH(v3) + 4 * NFSX_UNSIGNED + 1105 + nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1106 nfsm_fhtom(dvp, v3); 1107 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1108 if (v3) { 1109 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); 1110 *tl++ = vtonfsv3_type(vap->va_type); 1111 nfsm_v3attrbuild(vap, FALSE); 1112 if (vap->va_type == VCHR || vap->va_type == VBLK) { 1113 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 1114 *tl++ = txdr_unsigned(major(vap->va_rdev)); 1115 *tl = txdr_unsigned(minor(vap->va_rdev)); 1116 } 1117 } else { 1118 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1119 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1120 sp->sa_uid = nfs_xdrneg1; 1121 sp->sa_gid = nfs_xdrneg1; 1122 sp->sa_size = rdev; 1123 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1124 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1125 } 1126 nfsm_request(dvp, NFSPROC_MKNOD, cnp->cn_proc, cnp->cn_cred); 1127 if (!error) { 1128 nfsm_mtofh(dvp, newvp, v3, gotvp); 1129 if (!gotvp) { 1130 if (newvp) { 1131 vrele(newvp); 1132 newvp = (struct vnode *)0; 1133 } 1134 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1135 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1136 if (!error) 1137 newvp = NFSTOV(np); 1138 } 1139 } 1140 if (v3) 1141 nfsm_wcc_data(dvp, wccflag); 1142 nfsm_reqdone; 1143 if (error) { 1144 if (newvp) 1145 vrele(newvp); 1146 } else { 1147 if (cnp->cn_flags & MAKEENTRY) 1148 cache_enter(dvp, newvp, cnp); 1149 *vpp = newvp; 1150 } 1151 FREE(cnp->cn_pnbuf, M_NAMEI); 1152 VTONFS(dvp)->n_flag |= NMODIFIED; 1153 if (!wccflag) 1154 VTONFS(dvp)->n_attrstamp = 0; 1155 vrele(dvp); 1156 return (error); 1157 } 1158 1159 /* 1160 * nfs mknod vop 1161 * just call nfs_mknodrpc() to do the work. 1162 */ 1163 /* ARGSUSED */ 1164 int 1165 nfs_mknod(v) 1166 void *v; 1167 { 1168 struct vop_mknod_args /* { 1169 struct vnode *a_dvp; 1170 struct vnode **a_vpp; 1171 struct componentname *a_cnp; 1172 struct vattr *a_vap; 1173 } */ *ap = v; 1174 struct vnode *newvp; 1175 int error; 1176 1177 error = nfs_mknodrpc(ap->a_dvp, &newvp, ap->a_cnp, ap->a_vap); 1178 if (!error) 1179 vrele(newvp); 1180 return (error); 1181 } 1182 1183 static u_long create_verf; 1184 /* 1185 * nfs file create call 1186 */ 1187 int 1188 nfs_create(v) 1189 void *v; 1190 { 1191 struct vop_create_args /* { 1192 struct vnode *a_dvp; 1193 struct vnode **a_vpp; 1194 struct componentname *a_cnp; 1195 struct vattr *a_vap; 1196 } */ *ap = v; 1197 register struct vnode *dvp = ap->a_dvp; 1198 register struct vattr *vap = ap->a_vap; 1199 register struct componentname *cnp = ap->a_cnp; 1200 register struct nfsv2_sattr *sp; 1201 register u_int32_t *tl; 1202 register caddr_t cp; 1203 register int32_t t1, t2; 1204 struct nfsnode *np = (struct nfsnode *)0; 1205 struct vnode *newvp = (struct vnode *)0; 1206 caddr_t bpos, dpos, cp2; 1207 int error = 0, wccflag = NFSV3_WCCRATTR, gotvp = 0, fmode = 0; 1208 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1209 int v3 = NFS_ISV3(dvp); 1210 1211 /* 1212 * Oops, not for me.. 1213 */ 1214 if (vap->va_type == VSOCK) 1215 return (nfs_mknodrpc(dvp, ap->a_vpp, cnp, vap)); 1216 1217 #ifdef VA_EXCLUSIVE 1218 if (vap->va_vaflags & VA_EXCLUSIVE) 1219 fmode |= O_EXCL; 1220 #endif 1221 again: 1222 nfsstats.rpccnt[NFSPROC_CREATE]++; 1223 nfsm_reqhead(dvp, NFSPROC_CREATE, NFSX_FH(v3) + 2 * NFSX_UNSIGNED + 1224 nfsm_rndup(cnp->cn_namelen) + NFSX_SATTR(v3)); 1225 nfsm_fhtom(dvp, v3); 1226 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1227 if (v3) { 1228 nfsm_build(tl, u_int32_t *, NFSX_UNSIGNED); 1229 if (fmode & O_EXCL) { 1230 *tl = txdr_unsigned(NFSV3CREATE_EXCLUSIVE); 1231 nfsm_build(tl, u_int32_t *, NFSX_V3CREATEVERF); 1232 if (in_ifaddr.tqh_first) 1233 *tl++ = in_ifaddr.tqh_first->ia_addr.sin_addr.s_addr; 1234 else 1235 *tl++ = create_verf; 1236 *tl = ++create_verf; 1237 } else { 1238 *tl = txdr_unsigned(NFSV3CREATE_UNCHECKED); 1239 nfsm_v3attrbuild(vap, FALSE); 1240 } 1241 } else { 1242 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1243 sp->sa_mode = vtonfsv2_mode(vap->va_type, vap->va_mode); 1244 sp->sa_uid = nfs_xdrneg1; 1245 sp->sa_gid = nfs_xdrneg1; 1246 sp->sa_size = 0; 1247 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1248 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1249 } 1250 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1251 if (!error) { 1252 nfsm_mtofh(dvp, newvp, v3, gotvp); 1253 if (!gotvp) { 1254 if (newvp) { 1255 vrele(newvp); 1256 newvp = (struct vnode *)0; 1257 } 1258 error = nfs_lookitup(dvp, cnp->cn_nameptr, 1259 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc, &np); 1260 if (!error) 1261 newvp = NFSTOV(np); 1262 } 1263 } 1264 if (v3) 1265 nfsm_wcc_data(dvp, wccflag); 1266 nfsm_reqdone; 1267 if (error) { 1268 if (v3 && (fmode & O_EXCL) && error == NFSERR_NOTSUPP) { 1269 fmode &= ~O_EXCL; 1270 goto again; 1271 } 1272 if (newvp) 1273 vrele(newvp); 1274 } else if (v3 && (fmode & O_EXCL)) 1275 error = nfs_setattrrpc(newvp, vap, cnp->cn_cred, cnp->cn_proc); 1276 if (!error) { 1277 if (cnp->cn_flags & MAKEENTRY) 1278 cache_enter(dvp, newvp, cnp); 1279 *ap->a_vpp = newvp; 1280 } 1281 FREE(cnp->cn_pnbuf, M_NAMEI); 1282 VTONFS(dvp)->n_flag |= NMODIFIED; 1283 if (!wccflag) 1284 VTONFS(dvp)->n_attrstamp = 0; 1285 vrele(dvp); 1286 return (error); 1287 } 1288 1289 /* 1290 * nfs file remove call 1291 * To try and make nfs semantics closer to ufs semantics, a file that has 1292 * other processes using the vnode is renamed instead of removed and then 1293 * removed later on the last close. 1294 * - If v_usecount > 1 1295 * If a rename is not already in the works 1296 * call nfs_sillyrename() to set it up 1297 * else 1298 * do the remove rpc 1299 */ 1300 int 1301 nfs_remove(v) 1302 void *v; 1303 { 1304 struct vop_remove_args /* { 1305 struct vnodeop_desc *a_desc; 1306 struct vnode * a_dvp; 1307 struct vnode * a_vp; 1308 struct componentname * a_cnp; 1309 } */ *ap = v; 1310 register struct vnode *vp = ap->a_vp; 1311 register struct vnode *dvp = ap->a_dvp; 1312 register struct componentname *cnp = ap->a_cnp; 1313 register struct nfsnode *np = VTONFS(vp); 1314 int error = 0; 1315 struct vattr vattr; 1316 1317 #ifndef DIAGNOSTIC 1318 if ((cnp->cn_flags & HASBUF) == 0) 1319 panic("nfs_remove: no name"); 1320 if (vp->v_usecount < 1) 1321 panic("nfs_remove: bad v_usecount"); 1322 #endif 1323 if (vp->v_type == VDIR) 1324 error = EPERM; 1325 else if (vp->v_usecount == 1 || (np->n_sillyrename && 1326 VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) == 0 && 1327 vattr.va_nlink > 1)) { 1328 /* 1329 * Purge the name cache so that the chance of a lookup for 1330 * the name succeeding while the remove is in progress is 1331 * minimized. Without node locking it can still happen, such 1332 * that an I/O op returns ESTALE, but since you get this if 1333 * another host removes the file.. 1334 */ 1335 cache_purge(vp); 1336 /* 1337 * throw away biocache buffers, mainly to avoid 1338 * unnecessary delayed writes later. 1339 */ 1340 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1); 1341 /* Do the rpc */ 1342 if (error != EINTR) 1343 error = nfs_removerpc(dvp, cnp->cn_nameptr, 1344 cnp->cn_namelen, cnp->cn_cred, cnp->cn_proc); 1345 /* 1346 * Kludge City: If the first reply to the remove rpc is lost.. 1347 * the reply to the retransmitted request will be ENOENT 1348 * since the file was in fact removed 1349 * Therefore, we cheat and return success. 1350 */ 1351 if (error == ENOENT) 1352 error = 0; 1353 } else if (!np->n_sillyrename) 1354 error = nfs_sillyrename(dvp, vp, cnp); 1355 FREE(cnp->cn_pnbuf, M_NAMEI); 1356 np->n_attrstamp = 0; 1357 vrele(dvp); 1358 vrele(vp); 1359 return (error); 1360 } 1361 1362 /* 1363 * nfs file remove rpc called from nfs_inactive 1364 */ 1365 int 1366 nfs_removeit(sp) 1367 register struct sillyrename *sp; 1368 { 1369 1370 return (nfs_removerpc(sp->s_dvp, sp->s_name, sp->s_namlen, sp->s_cred, 1371 (struct proc *)0)); 1372 } 1373 1374 /* 1375 * Nfs remove rpc, called from nfs_remove() and nfs_removeit(). 1376 */ 1377 int 1378 nfs_removerpc(dvp, name, namelen, cred, proc) 1379 register struct vnode *dvp; 1380 char *name; 1381 int namelen; 1382 struct ucred *cred; 1383 struct proc *proc; 1384 { 1385 register u_int32_t *tl; 1386 register caddr_t cp; 1387 register int32_t t1, t2; 1388 caddr_t bpos, dpos, cp2; 1389 int error = 0, wccflag = NFSV3_WCCRATTR; 1390 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1391 int v3 = NFS_ISV3(dvp); 1392 1393 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1394 nfsm_reqhead(dvp, NFSPROC_REMOVE, 1395 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(namelen)); 1396 nfsm_fhtom(dvp, v3); 1397 nfsm_strtom(name, namelen, NFS_MAXNAMLEN); 1398 nfsm_request(dvp, NFSPROC_REMOVE, proc, cred); 1399 if (v3) 1400 nfsm_wcc_data(dvp, wccflag); 1401 nfsm_reqdone; 1402 VTONFS(dvp)->n_flag |= NMODIFIED; 1403 if (!wccflag) 1404 VTONFS(dvp)->n_attrstamp = 0; 1405 return (error); 1406 } 1407 1408 /* 1409 * nfs file rename call 1410 */ 1411 int 1412 nfs_rename(v) 1413 void *v; 1414 { 1415 struct vop_rename_args /* { 1416 struct vnode *a_fdvp; 1417 struct vnode *a_fvp; 1418 struct componentname *a_fcnp; 1419 struct vnode *a_tdvp; 1420 struct vnode *a_tvp; 1421 struct componentname *a_tcnp; 1422 } */ *ap = v; 1423 register struct vnode *fvp = ap->a_fvp; 1424 register struct vnode *tvp = ap->a_tvp; 1425 register struct vnode *fdvp = ap->a_fdvp; 1426 register struct vnode *tdvp = ap->a_tdvp; 1427 register struct componentname *tcnp = ap->a_tcnp; 1428 register struct componentname *fcnp = ap->a_fcnp; 1429 int error; 1430 1431 #ifndef DIAGNOSTIC 1432 if ((tcnp->cn_flags & HASBUF) == 0 || 1433 (fcnp->cn_flags & HASBUF) == 0) 1434 panic("nfs_rename: no name"); 1435 #endif 1436 /* Check for cross-device rename */ 1437 if ((fvp->v_mount != tdvp->v_mount) || 1438 (tvp && (fvp->v_mount != tvp->v_mount))) { 1439 error = EXDEV; 1440 goto out; 1441 } 1442 1443 /* 1444 * If the tvp exists and is in use, sillyrename it before doing the 1445 * rename of the new file over it. 1446 */ 1447 if (tvp && tvp->v_usecount > 1 && !VTONFS(tvp)->n_sillyrename && 1448 tvp->v_type != VDIR && !nfs_sillyrename(tdvp, tvp, tcnp)) { 1449 vrele(tvp); 1450 tvp = NULL; 1451 } 1452 1453 error = nfs_renamerpc(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen, 1454 tdvp, tcnp->cn_nameptr, tcnp->cn_namelen, tcnp->cn_cred, 1455 tcnp->cn_proc); 1456 1457 if (fvp->v_type == VDIR) { 1458 if (tvp != NULL && tvp->v_type == VDIR) 1459 cache_purge(tdvp); 1460 cache_purge(fdvp); 1461 } 1462 out: 1463 if (tdvp == tvp) 1464 vrele(tdvp); 1465 else 1466 vput(tdvp); 1467 if (tvp) 1468 vput(tvp); 1469 vrele(fdvp); 1470 vrele(fvp); 1471 /* 1472 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1473 */ 1474 if (error == ENOENT) 1475 error = 0; 1476 return (error); 1477 } 1478 1479 /* 1480 * nfs file rename rpc called from nfs_remove() above 1481 */ 1482 int 1483 nfs_renameit(sdvp, scnp, sp) 1484 struct vnode *sdvp; 1485 struct componentname *scnp; 1486 register struct sillyrename *sp; 1487 { 1488 return (nfs_renamerpc(sdvp, scnp->cn_nameptr, scnp->cn_namelen, 1489 sdvp, sp->s_name, sp->s_namlen, scnp->cn_cred, scnp->cn_proc)); 1490 } 1491 1492 /* 1493 * Do an nfs rename rpc. Called from nfs_rename() and nfs_renameit(). 1494 */ 1495 int 1496 nfs_renamerpc(fdvp, fnameptr, fnamelen, tdvp, tnameptr, tnamelen, cred, proc) 1497 register struct vnode *fdvp; 1498 char *fnameptr; 1499 int fnamelen; 1500 register struct vnode *tdvp; 1501 char *tnameptr; 1502 int tnamelen; 1503 struct ucred *cred; 1504 struct proc *proc; 1505 { 1506 register u_int32_t *tl; 1507 register caddr_t cp; 1508 register int32_t t1, t2; 1509 caddr_t bpos, dpos, cp2; 1510 int error = 0, fwccflag = NFSV3_WCCRATTR, twccflag = NFSV3_WCCRATTR; 1511 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1512 int v3 = NFS_ISV3(fdvp); 1513 1514 nfsstats.rpccnt[NFSPROC_RENAME]++; 1515 nfsm_reqhead(fdvp, NFSPROC_RENAME, 1516 (NFSX_FH(v3) + NFSX_UNSIGNED)*2 + nfsm_rndup(fnamelen) + 1517 nfsm_rndup(tnamelen)); 1518 nfsm_fhtom(fdvp, v3); 1519 nfsm_strtom(fnameptr, fnamelen, NFS_MAXNAMLEN); 1520 nfsm_fhtom(tdvp, v3); 1521 nfsm_strtom(tnameptr, tnamelen, NFS_MAXNAMLEN); 1522 nfsm_request(fdvp, NFSPROC_RENAME, proc, cred); 1523 if (v3) { 1524 nfsm_wcc_data(fdvp, fwccflag); 1525 nfsm_wcc_data(tdvp, twccflag); 1526 } 1527 nfsm_reqdone; 1528 VTONFS(fdvp)->n_flag |= NMODIFIED; 1529 VTONFS(tdvp)->n_flag |= NMODIFIED; 1530 if (!fwccflag) 1531 VTONFS(fdvp)->n_attrstamp = 0; 1532 if (!twccflag) 1533 VTONFS(tdvp)->n_attrstamp = 0; 1534 return (error); 1535 } 1536 1537 /* 1538 * nfs hard link create call 1539 */ 1540 int 1541 nfs_link(v) 1542 void *v; 1543 { 1544 struct vop_link_args /* { 1545 struct vnode *a_dvp; 1546 struct vnode *a_vp; 1547 struct componentname *a_cnp; 1548 } */ *ap = v; 1549 register struct vnode *vp = ap->a_vp; 1550 register struct vnode *dvp = ap->a_dvp; 1551 register struct componentname *cnp = ap->a_cnp; 1552 register u_int32_t *tl; 1553 register caddr_t cp; 1554 register int32_t t1, t2; 1555 caddr_t bpos, dpos, cp2; 1556 int error = 0, wccflag = NFSV3_WCCRATTR, attrflag = 0; 1557 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1558 int v3 = NFS_ISV3(vp); 1559 1560 1561 if (dvp->v_mount != vp->v_mount) { 1562 FREE(cnp->cn_pnbuf, M_NAMEI); 1563 if (vp == dvp) 1564 vrele(dvp); 1565 else 1566 vput(dvp); 1567 return (EXDEV); 1568 } 1569 1570 /* 1571 * Push all writes to the server, so that the attribute cache 1572 * doesn't get "out of sync" with the server. 1573 * XXX There should be a better way! 1574 */ 1575 VOP_FSYNC(vp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc); 1576 1577 nfsstats.rpccnt[NFSPROC_LINK]++; 1578 nfsm_reqhead(vp, NFSPROC_LINK, 1579 NFSX_FH(v3)*2 + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1580 nfsm_fhtom(vp, v3); 1581 nfsm_fhtom(dvp, v3); 1582 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1583 nfsm_request(vp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); 1584 if (v3) { 1585 nfsm_postop_attr(vp, attrflag); 1586 nfsm_wcc_data(dvp, wccflag); 1587 } 1588 nfsm_reqdone; 1589 FREE(cnp->cn_pnbuf, M_NAMEI); 1590 VTONFS(dvp)->n_flag |= NMODIFIED; 1591 if (!attrflag) 1592 VTONFS(vp)->n_attrstamp = 0; 1593 if (!wccflag) 1594 VTONFS(dvp)->n_attrstamp = 0; 1595 vput(dvp); 1596 /* 1597 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1598 */ 1599 if (error == EEXIST) 1600 error = 0; 1601 return (error); 1602 } 1603 1604 /* 1605 * nfs symbolic link create call 1606 */ 1607 int 1608 nfs_symlink(v) 1609 void *v; 1610 { 1611 struct vop_symlink_args /* { 1612 struct vnode *a_dvp; 1613 struct vnode **a_vpp; 1614 struct componentname *a_cnp; 1615 struct vattr *a_vap; 1616 char *a_target; 1617 } */ *ap = v; 1618 register struct vnode *dvp = ap->a_dvp; 1619 register struct vattr *vap = ap->a_vap; 1620 register struct componentname *cnp = ap->a_cnp; 1621 register struct nfsv2_sattr *sp; 1622 register u_int32_t *tl; 1623 register caddr_t cp; 1624 register int32_t t1, t2; 1625 caddr_t bpos, dpos, cp2; 1626 int slen, error = 0, wccflag = NFSV3_WCCRATTR, gotvp; 1627 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1628 struct vnode *newvp = (struct vnode *)0; 1629 int v3 = NFS_ISV3(dvp); 1630 1631 nfsstats.rpccnt[NFSPROC_SYMLINK]++; 1632 slen = strlen(ap->a_target); 1633 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH(v3) + 2*NFSX_UNSIGNED + 1634 nfsm_rndup(cnp->cn_namelen) + nfsm_rndup(slen) + NFSX_SATTR(v3)); 1635 nfsm_fhtom(dvp, v3); 1636 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1637 if (v3) 1638 nfsm_v3attrbuild(vap, FALSE); 1639 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN); 1640 if (!v3) { 1641 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1642 sp->sa_mode = vtonfsv2_mode(VLNK, vap->va_mode); 1643 sp->sa_uid = nfs_xdrneg1; 1644 sp->sa_gid = nfs_xdrneg1; 1645 sp->sa_size = nfs_xdrneg1; 1646 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1647 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1648 } 1649 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred); 1650 if (v3) { 1651 if (!error) 1652 nfsm_mtofh(dvp, newvp, v3, gotvp); 1653 nfsm_wcc_data(dvp, wccflag); 1654 } 1655 nfsm_reqdone; 1656 if (newvp) 1657 vrele(newvp); 1658 FREE(cnp->cn_pnbuf, M_NAMEI); 1659 VTONFS(dvp)->n_flag |= NMODIFIED; 1660 if (!wccflag) 1661 VTONFS(dvp)->n_attrstamp = 0; 1662 vrele(dvp); 1663 /* 1664 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1665 */ 1666 if (error == EEXIST) 1667 error = 0; 1668 return (error); 1669 } 1670 1671 /* 1672 * nfs make dir call 1673 */ 1674 int 1675 nfs_mkdir(v) 1676 void *v; 1677 { 1678 struct vop_mkdir_args /* { 1679 struct vnode *a_dvp; 1680 struct vnode **a_vpp; 1681 struct componentname *a_cnp; 1682 struct vattr *a_vap; 1683 } */ *ap = v; 1684 register struct vnode *dvp = ap->a_dvp; 1685 register struct vattr *vap = ap->a_vap; 1686 register struct componentname *cnp = ap->a_cnp; 1687 register struct nfsv2_sattr *sp; 1688 register u_int32_t *tl; 1689 register caddr_t cp; 1690 register int32_t t1, t2; 1691 register int len; 1692 struct nfsnode *np = (struct nfsnode *)0; 1693 struct vnode *newvp = (struct vnode *)0; 1694 caddr_t bpos, dpos, cp2; 1695 int error = 0, wccflag = NFSV3_WCCRATTR; 1696 int gotvp = 0; 1697 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1698 int v3 = NFS_ISV3(dvp); 1699 1700 len = cnp->cn_namelen; 1701 nfsstats.rpccnt[NFSPROC_MKDIR]++; 1702 nfsm_reqhead(dvp, NFSPROC_MKDIR, 1703 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len) + NFSX_SATTR(v3)); 1704 nfsm_fhtom(dvp, v3); 1705 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1706 if (v3) { 1707 nfsm_v3attrbuild(vap, FALSE); 1708 } else { 1709 nfsm_build(sp, struct nfsv2_sattr *, NFSX_V2SATTR); 1710 sp->sa_mode = vtonfsv2_mode(VDIR, vap->va_mode); 1711 sp->sa_uid = nfs_xdrneg1; 1712 sp->sa_gid = nfs_xdrneg1; 1713 sp->sa_size = nfs_xdrneg1; 1714 txdr_nfsv2time(&vap->va_atime, &sp->sa_atime); 1715 txdr_nfsv2time(&vap->va_mtime, &sp->sa_mtime); 1716 } 1717 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred); 1718 if (!error) 1719 nfsm_mtofh(dvp, newvp, v3, gotvp); 1720 if (v3) 1721 nfsm_wcc_data(dvp, wccflag); 1722 nfsm_reqdone; 1723 VTONFS(dvp)->n_flag |= NMODIFIED; 1724 if (!wccflag) 1725 VTONFS(dvp)->n_attrstamp = 0; 1726 /* 1727 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 1728 * if we can succeed in looking up the directory. 1729 */ 1730 if (error == EEXIST || (!error && !gotvp)) { 1731 if (newvp) { 1732 vrele(newvp); 1733 newvp = (struct vnode *)0; 1734 } 1735 error = nfs_lookitup(dvp, cnp->cn_nameptr, len, cnp->cn_cred, 1736 cnp->cn_proc, &np); 1737 if (!error) { 1738 newvp = NFSTOV(np); 1739 if (newvp->v_type != VDIR) 1740 error = EEXIST; 1741 } 1742 } 1743 if (error) { 1744 if (newvp) 1745 vrele(newvp); 1746 } else 1747 *ap->a_vpp = newvp; 1748 FREE(cnp->cn_pnbuf, M_NAMEI); 1749 vrele(dvp); 1750 return (error); 1751 } 1752 1753 /* 1754 * nfs remove directory call 1755 */ 1756 int 1757 nfs_rmdir(v) 1758 void *v; 1759 { 1760 struct vop_rmdir_args /* { 1761 struct vnode *a_dvp; 1762 struct vnode *a_vp; 1763 struct componentname *a_cnp; 1764 } */ *ap = v; 1765 register struct vnode *vp = ap->a_vp; 1766 register struct vnode *dvp = ap->a_dvp; 1767 register struct componentname *cnp = ap->a_cnp; 1768 register u_int32_t *tl; 1769 register caddr_t cp; 1770 register int32_t t1, t2; 1771 caddr_t bpos, dpos, cp2; 1772 int error = 0, wccflag = NFSV3_WCCRATTR; 1773 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1774 int v3 = NFS_ISV3(dvp); 1775 1776 if (dvp == vp) { 1777 vrele(dvp); 1778 vrele(dvp); 1779 FREE(cnp->cn_pnbuf, M_NAMEI); 1780 return (EINVAL); 1781 } 1782 nfsstats.rpccnt[NFSPROC_RMDIR]++; 1783 nfsm_reqhead(dvp, NFSPROC_RMDIR, 1784 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(cnp->cn_namelen)); 1785 nfsm_fhtom(dvp, v3); 1786 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1787 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred); 1788 if (v3) 1789 nfsm_wcc_data(dvp, wccflag); 1790 nfsm_reqdone; 1791 FREE(cnp->cn_pnbuf, M_NAMEI); 1792 VTONFS(dvp)->n_flag |= NMODIFIED; 1793 if (!wccflag) 1794 VTONFS(dvp)->n_attrstamp = 0; 1795 cache_purge(dvp); 1796 cache_purge(vp); 1797 vrele(vp); 1798 vrele(dvp); 1799 /* 1800 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 1801 */ 1802 if (error == ENOENT) 1803 error = 0; 1804 return (error); 1805 } 1806 1807 1808 /* 1809 * The readdir logic below has a big design bug. It stores the NFS cookie in 1810 * the returned uio->uio_offset but does not store the verifier (it cannot). 1811 * Instead, the code stores the verifier in the nfsnode and applies that 1812 * verifies to all cookies, no matter what verifier was originally with 1813 * the cookie. 1814 * 1815 * From a practical standpoint, this is not a problem since almost all 1816 * NFS servers do not change the validity of cookies across deletes 1817 * and inserts. 1818 */ 1819 1820 struct nfs_dirent { 1821 u_int32_t cookie[2]; 1822 struct dirent dirent; 1823 }; 1824 1825 #define NFS_DIRHDSIZ (sizeof (struct nfs_dirent) - (MAXNAMLEN + 1)) 1826 #define NFS_DIRENT_OVERHEAD offsetof(struct nfs_dirent, dirent) 1827 1828 /* 1829 * nfs readdir call 1830 */ 1831 int 1832 nfs_readdir(v) 1833 void *v; 1834 { 1835 struct vop_readdir_args /* { 1836 struct vnode *a_vp; 1837 struct uio *a_uio; 1838 struct ucred *a_cred; 1839 int *a_eofflag; 1840 u_long **a_cookies; 1841 int *a_ncookies; 1842 } */ *ap = v; 1843 struct vnode *vp = ap->a_vp; 1844 struct nfsnode *np = VTONFS(vp); 1845 struct uio *uio = ap->a_uio; 1846 int tresid, error; 1847 struct vattr vattr; 1848 u_long *cookies = NULL; 1849 int ncookies = 0, cnt; 1850 u_int64_t newoff = uio->uio_offset; 1851 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 1852 struct uio readdir_uio; 1853 struct iovec readdir_iovec; 1854 struct proc * p = uio->uio_procp; 1855 int done = 0, eof = 0; 1856 struct ucred *cred = ap->a_cred; 1857 void *data; 1858 1859 if (vp->v_type != VDIR) 1860 return (EPERM); 1861 /* 1862 * First, check for hit on the EOF offset cache 1863 */ 1864 if (np->n_direofoffset != 0 && 1865 uio->uio_offset == np->n_direofoffset) { 1866 if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 && 1867 np->n_mtime == vattr.va_mtime.tv_sec) { 1868 nfsstats.direofcache_hits++; 1869 *ap->a_eofflag = 1; 1870 return (0); 1871 } 1872 } 1873 1874 if (uio->uio_resid < NFS_FABLKSIZE) 1875 return (EINVAL); 1876 1877 tresid = uio->uio_resid; 1878 1879 if (uio->uio_rw != UIO_READ) 1880 return (EINVAL); 1881 1882 if (ap->a_cookies) { 1883 ncookies = uio->uio_resid / 20; 1884 1885 MALLOC(cookies, u_long *, sizeof(*cookies) * ncookies, 1886 M_TEMP, M_WAITOK); 1887 *ap->a_ncookies = ncookies; 1888 *ap->a_cookies = cookies; 1889 } 1890 1891 if ((nmp->nm_flag & (NFSMNT_NFSV3 | NFSMNT_GOTFSINFO)) == NFSMNT_NFSV3) 1892 (void)nfs_fsinfo(nmp, vp, cred, p); 1893 1894 cnt = 5; 1895 1896 MALLOC(data, void *, NFS_DIRBLKSIZ, M_TEMP, 1897 M_WAITOK); 1898 1899 do { 1900 struct nfs_dirent *ndp = data; 1901 1902 readdir_iovec.iov_len = NFS_DIRBLKSIZ; 1903 readdir_iovec.iov_base = data; 1904 readdir_uio.uio_offset = newoff; 1905 readdir_uio.uio_iov = &readdir_iovec; 1906 readdir_uio.uio_iovcnt = 1; 1907 readdir_uio.uio_segflg = UIO_SYSSPACE; 1908 readdir_uio.uio_rw = UIO_READ; 1909 readdir_uio.uio_resid = NFS_DIRBLKSIZ; 1910 readdir_uio.uio_procp = curproc; 1911 1912 if (nmp->nm_flag & NFSMNT_RDIRPLUS) { 1913 error = nfs_readdirplusrpc(vp, &readdir_uio, cred, 1914 &eof); 1915 if (error == NFSERR_NOTSUPP) 1916 nmp->nm_flag &= ~NFSMNT_RDIRPLUS; 1917 } 1918 if ((nmp->nm_flag & NFSMNT_RDIRPLUS) == 0) 1919 error = nfs_readdirrpc(vp, &readdir_uio, cred, &eof); 1920 1921 if (error == NFSERR_BAD_COOKIE) 1922 error = EINVAL; 1923 1924 while (error == 0 && 1925 (ap->a_cookies == NULL || ncookies != 0) && 1926 ndp < (struct nfs_dirent *)readdir_iovec.iov_base) { 1927 struct dirent *dp = &ndp->dirent; 1928 int reclen = dp->d_reclen; 1929 1930 dp->d_reclen -= NFS_DIRENT_OVERHEAD; 1931 1932 if (uio->uio_resid < dp->d_reclen) { 1933 done = 1; 1934 break; 1935 } 1936 1937 error = uiomove((caddr_t)dp, dp->d_reclen, uio); 1938 if (error) 1939 break; 1940 1941 newoff = fxdr_hyper(&ndp->cookie[0]); 1942 1943 if (ap->a_cookies != NULL) { 1944 *cookies = newoff; 1945 cookies++; 1946 ncookies--; 1947 } 1948 1949 ndp = (struct nfs_dirent *)((u_int8_t *)ndp + reclen); 1950 } 1951 } while (!error && !done && !eof && cnt--); 1952 1953 FREE(data, M_TEMP); 1954 data = NULL; 1955 1956 if (ap->a_cookies) { 1957 if (error) { 1958 FREE(*ap->a_cookies, M_TEMP); 1959 *ap->a_cookies = NULL; 1960 *ap->a_ncookies = 0; 1961 } else { 1962 *ap->a_ncookies -= ncookies; 1963 } 1964 } 1965 1966 if (!error) 1967 uio->uio_offset = newoff; 1968 1969 if (!error && (eof || uio->uio_resid == tresid)) { 1970 nfsstats.direofcache_misses++; 1971 *ap->a_eofflag = 1; 1972 return (0); 1973 } 1974 1975 *ap->a_eofflag = 0; 1976 return (error); 1977 } 1978 1979 1980 /* 1981 * The function below stuff the cookies in after the name 1982 */ 1983 1984 /* 1985 * Readdir rpc call. 1986 */ 1987 int 1988 nfs_readdirrpc(struct vnode *vp, 1989 struct uio *uiop, 1990 struct ucred *cred, 1991 int *end_of_directory) 1992 { 1993 register int len, left; 1994 struct nfs_dirent *ndp = NULL; 1995 register struct dirent *dp = NULL; 1996 register u_int32_t *tl; 1997 register caddr_t cp; 1998 register int32_t t1, t2; 1999 caddr_t bpos, dpos, cp2; 2000 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2001 nfsuint64 cookie; 2002 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2003 struct nfsnode *dnp = VTONFS(vp); 2004 u_quad_t fileno; 2005 int error = 0, tlen, more_dirs = 1, blksiz = 0, bigenough = 1; 2006 int attrflag; 2007 int v3 = NFS_ISV3(vp); 2008 2009 #ifndef DIAGNOSTIC 2010 if (uiop->uio_iovcnt != 1 || 2011 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1))) 2012 panic("nfs readdirrpc bad uio"); 2013 #endif 2014 2015 txdr_hyper(uiop->uio_offset, &cookie.nfsuquad[0]); 2016 2017 /* 2018 * Loop around doing readdir rpc's of size nm_readdirsize 2019 * truncated to a multiple of NFS_READDIRBLKSIZ. 2020 * The stopping criteria is EOF or buffer full. 2021 */ 2022 while (more_dirs && bigenough) { 2023 nfsstats.rpccnt[NFSPROC_READDIR]++; 2024 nfsm_reqhead(vp, NFSPROC_READDIR, NFSX_FH(v3) + 2025 NFSX_READDIR(v3)); 2026 nfsm_fhtom(vp, v3); 2027 if (v3) { 2028 nfsm_build(tl, u_int32_t *, 5 * NFSX_UNSIGNED); 2029 *tl++ = cookie.nfsuquad[0]; 2030 *tl++ = cookie.nfsuquad[1]; 2031 if (cookie.nfsuquad[0] == 0 && 2032 cookie.nfsuquad[1] == 0) { 2033 *tl++ = 0; 2034 *tl++ = 0; 2035 } else { 2036 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2037 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2038 } 2039 } else { 2040 nfsm_build(tl, u_int32_t *, 2 * NFSX_UNSIGNED); 2041 *tl++ = cookie.nfsuquad[1]; 2042 } 2043 *tl = txdr_unsigned(nmp->nm_readdirsize); 2044 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred); 2045 if (v3) { 2046 nfsm_postop_attr(vp, attrflag); 2047 if (!error) { 2048 nfsm_dissect(tl, u_int32_t *, 2049 2 * NFSX_UNSIGNED); 2050 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2051 dnp->n_cookieverf.nfsuquad[1] = *tl; 2052 } else { 2053 m_freem(mrep); 2054 goto nfsmout; 2055 } 2056 } 2057 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2058 more_dirs = fxdr_unsigned(int, *tl); 2059 2060 /* loop thru the dir entries, doctoring them to 4bsd form */ 2061 while (more_dirs && bigenough) { 2062 if (v3) { 2063 nfsm_dissect(tl, u_int32_t *, 2064 3 * NFSX_UNSIGNED); 2065 fileno = fxdr_hyper(tl); 2066 len = fxdr_unsigned(int, *(tl + 2)); 2067 } else { 2068 nfsm_dissect(tl, u_int32_t *, 2069 2 * NFSX_UNSIGNED); 2070 fileno = fxdr_unsigned(u_quad_t, *tl++); 2071 len = fxdr_unsigned(int, *tl); 2072 } 2073 if (len <= 0 || len > NFS_MAXNAMLEN) { 2074 error = EBADRPC; 2075 m_freem(mrep); 2076 goto nfsmout; 2077 } 2078 tlen = nfsm_rndup(len + 1); 2079 left = NFS_READDIRBLKSIZ - blksiz; 2080 if ((tlen + NFS_DIRHDSIZ) > left) { 2081 dp->d_reclen += left; 2082 (caddr_t)uiop->uio_iov->iov_base += left; 2083 uiop->uio_iov->iov_len -= left; 2084 uiop->uio_resid -= left; 2085 blksiz = 0; 2086 } 2087 if ((tlen + NFS_DIRHDSIZ) > uiop->uio_resid) 2088 bigenough = 0; 2089 if (bigenough) { 2090 ndp = (struct nfs_dirent *) 2091 uiop->uio_iov->iov_base; 2092 dp = &ndp->dirent; 2093 dp->d_fileno = (int)fileno; 2094 dp->d_namlen = len; 2095 dp->d_reclen = tlen + NFS_DIRHDSIZ; 2096 dp->d_type = DT_UNKNOWN; 2097 blksiz += dp->d_reclen; 2098 if (blksiz == NFS_READDIRBLKSIZ) 2099 blksiz = 0; 2100 uiop->uio_resid -= NFS_DIRHDSIZ; 2101 uiop->uio_iov->iov_base += NFS_DIRHDSIZ; 2102 uiop->uio_iov->iov_len -= NFS_DIRHDSIZ; 2103 nfsm_mtouio(uiop, len); 2104 cp = uiop->uio_iov->iov_base; 2105 tlen -= len; 2106 *cp = '\0'; /* null terminate */ 2107 (caddr_t)uiop->uio_iov->iov_base += tlen; 2108 uiop->uio_iov->iov_len -= tlen; 2109 uiop->uio_resid -= tlen; 2110 } else 2111 nfsm_adv(nfsm_rndup(len)); 2112 if (v3) { 2113 nfsm_dissect(tl, u_int32_t *, 2114 3 * NFSX_UNSIGNED); 2115 } else { 2116 nfsm_dissect(tl, u_int32_t *, 2117 2 * NFSX_UNSIGNED); 2118 } 2119 if (bigenough) { 2120 if (v3) { 2121 ndp->cookie[0] = cookie.nfsuquad[0] = 2122 *tl++; 2123 } else 2124 ndp->cookie[0] = 0; 2125 2126 ndp->cookie[1] = cookie.nfsuquad[1] = *tl++; 2127 } else if (v3) 2128 tl += 2; 2129 else 2130 tl++; 2131 more_dirs = fxdr_unsigned(int, *tl); 2132 } 2133 /* 2134 * If at end of rpc data, get the eof boolean 2135 */ 2136 if (!more_dirs) { 2137 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2138 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2139 } 2140 m_freem(mrep); 2141 } 2142 /* 2143 * Fill last record, iff any, out to a multiple of NFS_READDIRBLKSIZ 2144 * by increasing d_reclen for the last record. 2145 */ 2146 if (blksiz > 0) { 2147 left = NFS_READDIRBLKSIZ - blksiz; 2148 dp->d_reclen += left; 2149 uiop->uio_iov->iov_base += left; 2150 uiop->uio_iov->iov_len -= left; 2151 uiop->uio_resid -= left; 2152 } 2153 2154 /* 2155 * We are now either at the end of the directory or have filled the 2156 * block. 2157 */ 2158 if (bigenough) { 2159 dnp->n_direofoffset = fxdr_hyper(&cookie.nfsuquad[0]); 2160 if (end_of_directory) *end_of_directory = 1; 2161 } else { 2162 if (uiop->uio_resid > 0) 2163 printf("EEK! readdirrpc resid > 0\n"); 2164 } 2165 2166 nfsmout: 2167 return (error); 2168 } 2169 2170 /* 2171 * NFS V3 readdir plus RPC. Used in place of nfs_readdirrpc(). 2172 */ 2173 int 2174 nfs_readdirplusrpc(struct vnode *vp, struct uio *uiop, struct ucred *cred, 2175 int *end_of_directory) 2176 { 2177 register int len, left; 2178 struct nfs_dirent *ndirp = NULL; 2179 register struct dirent *dp = NULL; 2180 register u_int32_t *tl; 2181 register caddr_t cp; 2182 register int32_t t1, t2; 2183 register struct vnode *newvp; 2184 caddr_t bpos, dpos, cp2, dpossav1, dpossav2; 2185 struct mbuf *mreq, *mrep, *md, *mb, *mb2, *mdsav1, *mdsav2; 2186 struct nameidata nami, *ndp = &nami; 2187 struct componentname *cnp = &ndp->ni_cnd; 2188 nfsuint64 cookie; 2189 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2190 struct nfsnode *dnp = VTONFS(vp), *np; 2191 nfsfh_t *fhp; 2192 u_quad_t fileno; 2193 int error = 0, tlen, more_dirs = 1, blksiz = 0, doit, bigenough = 1, i; 2194 int attrflag, fhsize; 2195 2196 #ifndef DIAGNOSTIC 2197 if (uiop->uio_iovcnt != 1 || 2198 (uiop->uio_resid & (NFS_DIRBLKSIZ - 1))) 2199 panic("nfs readdirplusrpc bad uio"); 2200 #endif 2201 ndp->ni_dvp = vp; 2202 newvp = NULLVP; 2203 2204 txdr_hyper(uiop->uio_offset, &cookie.nfsuquad[0]); 2205 2206 /* 2207 * Loop around doing readdir rpc's of size nm_readdirsize 2208 * truncated to a multiple of NFS_READDIRBLKSIZ. 2209 * The stopping criteria is EOF or buffer full. 2210 */ 2211 while (more_dirs && bigenough) { 2212 nfsstats.rpccnt[NFSPROC_READDIRPLUS]++; 2213 nfsm_reqhead(vp, NFSPROC_READDIRPLUS, 2214 NFSX_FH(1) + 6 * NFSX_UNSIGNED); 2215 nfsm_fhtom(vp, 1); 2216 nfsm_build(tl, u_int32_t *, 6 * NFSX_UNSIGNED); 2217 *tl++ = cookie.nfsuquad[0]; 2218 *tl++ = cookie.nfsuquad[1]; 2219 if (cookie.nfsuquad[0] == 0 && 2220 cookie.nfsuquad[1] == 0) { 2221 *tl++ = 0; 2222 *tl++ = 0; 2223 } else { 2224 *tl++ = dnp->n_cookieverf.nfsuquad[0]; 2225 *tl++ = dnp->n_cookieverf.nfsuquad[1]; 2226 } 2227 *tl++ = txdr_unsigned(nmp->nm_readdirsize); 2228 *tl = txdr_unsigned(nmp->nm_rsize); 2229 nfsm_request(vp, NFSPROC_READDIRPLUS, uiop->uio_procp, cred); 2230 nfsm_postop_attr(vp, attrflag); 2231 if (error) { 2232 m_freem(mrep); 2233 goto nfsmout; 2234 } 2235 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2236 dnp->n_cookieverf.nfsuquad[0] = *tl++; 2237 dnp->n_cookieverf.nfsuquad[1] = *tl++; 2238 more_dirs = fxdr_unsigned(int, *tl); 2239 2240 /* loop thru the dir entries, doctoring them to 4bsd form */ 2241 while (more_dirs && bigenough) { 2242 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2243 fileno = fxdr_hyper(tl); 2244 len = fxdr_unsigned(int, *(tl + 2)); 2245 if (len <= 0 || len > NFS_MAXNAMLEN) { 2246 error = EBADRPC; 2247 m_freem(mrep); 2248 goto nfsmout; 2249 } 2250 tlen = nfsm_rndup(len + 1); 2251 left = NFS_READDIRBLKSIZ - blksiz; 2252 if ((tlen + NFS_DIRHDSIZ) > left) { 2253 dp->d_reclen += left; 2254 uiop->uio_iov->iov_base += left; 2255 uiop->uio_iov->iov_len -= left; 2256 uiop->uio_resid -= left; 2257 blksiz = 0; 2258 } 2259 if ((tlen + NFS_DIRHDSIZ) > uiop->uio_resid) 2260 bigenough = 0; 2261 if (bigenough) { 2262 ndirp = (struct nfs_dirent *) 2263 uiop->uio_iov->iov_base; 2264 dp = &ndirp->dirent; 2265 dp->d_fileno = (int)fileno; 2266 dp->d_namlen = len; 2267 dp->d_reclen = tlen + NFS_DIRHDSIZ; 2268 dp->d_type = DT_UNKNOWN; 2269 blksiz += dp->d_reclen; 2270 if (blksiz == NFS_READDIRBLKSIZ) 2271 blksiz = 0; 2272 uiop->uio_resid -= NFS_DIRHDSIZ; 2273 uiop->uio_iov->iov_base += NFS_DIRHDSIZ; 2274 uiop->uio_iov->iov_len -= NFS_DIRHDSIZ; 2275 cnp->cn_nameptr = uiop->uio_iov->iov_base; 2276 cnp->cn_namelen = len; 2277 nfsm_mtouio(uiop, len); 2278 cp = uiop->uio_iov->iov_base; 2279 tlen -= len; 2280 *cp = '\0'; 2281 uiop->uio_iov->iov_base += tlen; 2282 uiop->uio_iov->iov_len -= tlen; 2283 uiop->uio_resid -= tlen; 2284 } else 2285 nfsm_adv(nfsm_rndup(len)); 2286 nfsm_dissect(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2287 if (bigenough) { 2288 ndirp->cookie[0] = cookie.nfsuquad[0] = *tl++; 2289 ndirp->cookie[1] = cookie.nfsuquad[1] = *tl++; 2290 } else 2291 tl += 2; 2292 2293 /* 2294 * Since the attributes are before the file handle 2295 * (sigh), we must skip over the attributes and then 2296 * come back and get them. 2297 */ 2298 attrflag = fxdr_unsigned(int, *tl); 2299 if (attrflag) { 2300 dpossav1 = dpos; 2301 mdsav1 = md; 2302 nfsm_adv(NFSX_V3FATTR); 2303 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2304 doit = fxdr_unsigned(int, *tl); 2305 if (doit) { 2306 nfsm_getfh(fhp, fhsize, 1); 2307 if (NFS_CMPFH(dnp, fhp, fhsize)) { 2308 VREF(vp); 2309 newvp = vp; 2310 np = dnp; 2311 } else { 2312 error = nfs_nget(vp->v_mount, fhp, 2313 fhsize, &np); 2314 if (error) 2315 doit = 0; 2316 else 2317 newvp = NFSTOV(np); 2318 } 2319 } 2320 if (doit) { 2321 dpossav2 = dpos; 2322 dpos = dpossav1; 2323 mdsav2 = md; 2324 md = mdsav1; 2325 nfsm_loadattr(newvp, (struct vattr *)0); 2326 dpos = dpossav2; 2327 md = mdsav2; 2328 dp->d_type = 2329 IFTODT(VTTOIF(np->n_vattr.va_type)); 2330 ndp->ni_vp = newvp; 2331 cnp->cn_hash = 0; 2332 for (cp = cnp->cn_nameptr, i = 1; i <= len; 2333 i++, cp++) 2334 cnp->cn_hash += (unsigned char)*cp * i; 2335 if (cnp->cn_namelen <= NCHNAMLEN) 2336 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp); 2337 } 2338 } else { 2339 /* Just skip over the file handle */ 2340 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2341 i = fxdr_unsigned(int, *tl); 2342 nfsm_adv(nfsm_rndup(i)); 2343 } 2344 if (newvp != NULLVP) { 2345 vrele(newvp); 2346 newvp = NULLVP; 2347 } 2348 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2349 more_dirs = fxdr_unsigned(int, *tl); 2350 } 2351 /* 2352 * If at end of rpc data, get the eof boolean 2353 */ 2354 if (!more_dirs) { 2355 nfsm_dissect(tl, u_int32_t *, NFSX_UNSIGNED); 2356 more_dirs = (fxdr_unsigned(int, *tl) == 0); 2357 } 2358 m_freem(mrep); 2359 } 2360 /* 2361 * Fill last record, iff any, out to a multiple of NFS_READDIRBLKSIZ 2362 * by increasing d_reclen for the last record. 2363 */ 2364 if (blksiz > 0) { 2365 left = NFS_READDIRBLKSIZ - blksiz; 2366 dp->d_reclen += left; 2367 uiop->uio_iov->iov_base += left; 2368 uiop->uio_iov->iov_len -= left; 2369 uiop->uio_resid -= left; 2370 } 2371 2372 /* 2373 * We are now either at the end of the directory or have filled the 2374 * block. 2375 */ 2376 if (bigenough) { 2377 dnp->n_direofoffset = fxdr_hyper(&cookie.nfsuquad[0]); 2378 if (end_of_directory) *end_of_directory = 1; 2379 } else { 2380 if (uiop->uio_resid > 0) 2381 printf("EEK! readdirplusrpc resid > 0\n"); 2382 } 2383 2384 nfsmout: 2385 if (newvp != NULLVP) 2386 vrele(newvp); 2387 return (error); 2388 } 2389 2390 /* 2391 * Silly rename. To make the NFS filesystem that is stateless look a little 2392 * more like the "ufs" a remove of an active vnode is translated to a rename 2393 * to a funny looking filename that is removed by nfs_inactive on the 2394 * nfsnode. There is the potential for another process on a different client 2395 * to create the same funny name between the nfs_lookitup() fails and the 2396 * nfs_rename() completes, but... 2397 */ 2398 int 2399 nfs_sillyrename(dvp, vp, cnp) 2400 struct vnode *dvp, *vp; 2401 struct componentname *cnp; 2402 { 2403 register struct sillyrename *sp; 2404 struct nfsnode *np; 2405 int error; 2406 2407 cache_purge(dvp); 2408 np = VTONFS(vp); 2409 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 2410 M_NFSREQ, M_WAITOK); 2411 sp->s_cred = crdup(cnp->cn_cred); 2412 sp->s_dvp = dvp; 2413 VREF(dvp); 2414 2415 if (vp->v_type == VDIR) { 2416 #ifdef DIAGNOSTIC 2417 printf("nfs: sillyrename dir\n"); 2418 #endif 2419 error = EINVAL; 2420 goto bad; 2421 } 2422 2423 /* Fudge together a funny name */ 2424 sp->s_namlen = sprintf(sp->s_name, ".nfsA%05x4.4", cnp->cn_proc->p_pid); 2425 2426 /* Try lookitups until we get one that isn't there */ 2427 while (nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2428 cnp->cn_proc, (struct nfsnode **)0) == 0) { 2429 sp->s_name[4]++; 2430 if (sp->s_name[4] > 'z') { 2431 error = EINVAL; 2432 goto bad; 2433 } 2434 } 2435 error = nfs_renameit(dvp, cnp, sp); 2436 if (error) 2437 goto bad; 2438 error = nfs_lookitup(dvp, sp->s_name, sp->s_namlen, sp->s_cred, 2439 cnp->cn_proc, &np); 2440 np->n_sillyrename = sp; 2441 return (0); 2442 bad: 2443 vrele(sp->s_dvp); 2444 crfree(sp->s_cred); 2445 FREE((caddr_t)sp, M_NFSREQ); 2446 return (error); 2447 } 2448 2449 /* 2450 * Look up a file name and optionally either update the file handle or 2451 * allocate an nfsnode, depending on the value of npp. 2452 * npp == NULL --> just do the lookup 2453 * *npp == NULL --> allocate a new nfsnode and make sure attributes are 2454 * handled too 2455 * *npp != NULL --> update the file handle in the vnode 2456 */ 2457 int 2458 nfs_lookitup(dvp, name, len, cred, procp, npp) 2459 register struct vnode *dvp; 2460 char *name; 2461 int len; 2462 struct ucred *cred; 2463 struct proc *procp; 2464 struct nfsnode **npp; 2465 { 2466 register u_int32_t *tl; 2467 register caddr_t cp; 2468 register int32_t t1, t2; 2469 struct vnode *newvp = (struct vnode *)0; 2470 struct nfsnode *np, *dnp = VTONFS(dvp); 2471 caddr_t bpos, dpos, cp2; 2472 int error = 0, fhlen, attrflag; 2473 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2474 nfsfh_t *nfhp; 2475 int v3 = NFS_ISV3(dvp); 2476 2477 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 2478 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 2479 NFSX_FH(v3) + NFSX_UNSIGNED + nfsm_rndup(len)); 2480 nfsm_fhtom(dvp, v3); 2481 nfsm_strtom(name, len, NFS_MAXNAMLEN); 2482 nfsm_request(dvp, NFSPROC_LOOKUP, procp, cred); 2483 if (npp && !error) { 2484 nfsm_getfh(nfhp, fhlen, v3); 2485 if (*npp) { 2486 np = *npp; 2487 if (np->n_fhsize > NFS_SMALLFH && fhlen <= NFS_SMALLFH) { 2488 free((caddr_t)np->n_fhp, M_NFSBIGFH); 2489 np->n_fhp = &np->n_fh; 2490 } else if (np->n_fhsize <= NFS_SMALLFH && fhlen>NFS_SMALLFH) 2491 np->n_fhp =(nfsfh_t *)malloc(fhlen,M_NFSBIGFH,M_WAITOK); 2492 bcopy((caddr_t)nfhp, (caddr_t)np->n_fhp, fhlen); 2493 np->n_fhsize = fhlen; 2494 newvp = NFSTOV(np); 2495 } else if (NFS_CMPFH(dnp, nfhp, fhlen)) { 2496 VREF(dvp); 2497 newvp = dvp; 2498 } else { 2499 error = nfs_nget(dvp->v_mount, nfhp, fhlen, &np); 2500 if (error) { 2501 m_freem(mrep); 2502 return (error); 2503 } 2504 newvp = NFSTOV(np); 2505 } 2506 if (v3) { 2507 nfsm_postop_attr(newvp, attrflag); 2508 if (!attrflag && *npp == NULL) { 2509 m_freem(mrep); 2510 vrele(newvp); 2511 return (ENOENT); 2512 } 2513 } else 2514 nfsm_loadattr(newvp, (struct vattr *)0); 2515 } 2516 nfsm_reqdone; 2517 if (npp && *npp == NULL) { 2518 if (error) { 2519 if (newvp) 2520 vrele(newvp); 2521 } else 2522 *npp = np; 2523 } 2524 return (error); 2525 } 2526 2527 /* 2528 * Nfs Version 3 commit rpc 2529 */ 2530 int 2531 nfs_commit(vp, offset, cnt, procp) 2532 struct vnode *vp; 2533 u_quad_t offset; 2534 int cnt; 2535 struct proc *procp; 2536 { 2537 caddr_t cp; 2538 u_int32_t *tl; 2539 int32_t t1, t2; 2540 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2541 caddr_t bpos, dpos, cp2; 2542 int error = 0, wccflag = NFSV3_WCCRATTR; 2543 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2544 2545 if ((nmp->nm_flag & NFSMNT_HASWRITEVERF) == 0) 2546 return (0); 2547 nfsstats.rpccnt[NFSPROC_COMMIT]++; 2548 nfsm_reqhead(vp, NFSPROC_COMMIT, NFSX_FH(1)); 2549 nfsm_fhtom(vp, 1); 2550 nfsm_build(tl, u_int32_t *, 3 * NFSX_UNSIGNED); 2551 txdr_hyper(offset, tl); 2552 tl += 2; 2553 *tl = txdr_unsigned(cnt); 2554 nfsm_request(vp, NFSPROC_COMMIT, procp, VTONFS(vp)->n_wcred); 2555 nfsm_wcc_data(vp, wccflag); 2556 if (!error) { 2557 nfsm_dissect(tl, u_int32_t *, NFSX_V3WRITEVERF); 2558 if (bcmp((caddr_t)nmp->nm_verf, (caddr_t)tl, 2559 NFSX_V3WRITEVERF)) { 2560 bcopy((caddr_t)tl, (caddr_t)nmp->nm_verf, 2561 NFSX_V3WRITEVERF); 2562 error = NFSERR_STALEWRITEVERF; 2563 } 2564 } 2565 nfsm_reqdone; 2566 return (error); 2567 } 2568 2569 /* 2570 * Kludge City.. 2571 * - make nfs_bmap() essentially a no-op that does no translation 2572 * - do nfs_strategy() by doing I/O with nfs_readrpc/nfs_writerpc 2573 * (Maybe I could use the process's page mapping, but I was concerned that 2574 * Kernel Write might not be enabled and also figured copyout() would do 2575 * a lot more work than bcopy() and also it currently happens in the 2576 * context of the swapper process (2). 2577 */ 2578 int 2579 nfs_bmap(v) 2580 void *v; 2581 { 2582 struct vop_bmap_args /* { 2583 struct vnode *a_vp; 2584 daddr_t a_bn; 2585 struct vnode **a_vpp; 2586 daddr_t *a_bnp; 2587 int *a_runp; 2588 } */ *ap = v; 2589 register struct vnode *vp = ap->a_vp; 2590 2591 if (ap->a_vpp != NULL) 2592 *ap->a_vpp = vp; 2593 if (ap->a_bnp != NULL) 2594 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize); 2595 return (0); 2596 } 2597 2598 /* 2599 * Strategy routine. 2600 * For async requests when nfsiod(s) are running, queue the request by 2601 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the 2602 * request. 2603 */ 2604 int 2605 nfs_strategy(v) 2606 void *v; 2607 { 2608 struct vop_strategy_args *ap = v; 2609 struct buf *bp = ap->a_bp; 2610 struct proc *p; 2611 int error = 0; 2612 2613 if ((bp->b_flags & (B_PHYS|B_ASYNC)) == (B_PHYS|B_ASYNC)) 2614 panic("nfs physio/async"); 2615 if (bp->b_flags & B_ASYNC) 2616 p = NULL; 2617 else 2618 p = curproc; /* XXX */ 2619 /* 2620 * If the op is asynchronous and an i/o daemon is waiting 2621 * queue the request, wake it up and wait for completion 2622 * otherwise just do it ourselves. 2623 */ 2624 if ((bp->b_flags & B_ASYNC) == 0 || nfs_asyncio(bp)) 2625 error = nfs_doio(bp, p); 2626 return (error); 2627 } 2628 2629 /* 2630 * fsync vnode op. Just call nfs_flush() with commit == 1. 2631 */ 2632 /* ARGSUSED */ 2633 int 2634 nfs_fsync(v) 2635 void *v; 2636 { 2637 struct vop_fsync_args /* { 2638 struct vnodeop_desc *a_desc; 2639 struct vnode * a_vp; 2640 struct ucred * a_cred; 2641 int a_waitfor; 2642 struct proc * a_p; 2643 } */ *ap = v; 2644 2645 return (nfs_flush(ap->a_vp, ap->a_cred, ap->a_waitfor, ap->a_p, 1)); 2646 } 2647 2648 /* 2649 * Flush all the blocks associated with a vnode. 2650 * Walk through the buffer pool and push any dirty pages 2651 * associated with the vnode. 2652 */ 2653 int 2654 nfs_flush(vp, cred, waitfor, p, commit) 2655 struct vnode *vp; 2656 struct ucred *cred; 2657 int waitfor; 2658 struct proc *p; 2659 int commit; 2660 { 2661 struct nfsnode *np = VTONFS(vp); 2662 struct buf *bp; 2663 int i; 2664 struct buf *nbp; 2665 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 2666 int s, error = 0, slptimeo = 0, slpflag = 0, retv, bvecpos; 2667 int passone = 1; 2668 u_quad_t off = (u_quad_t)-1, endoff = 0, toff; 2669 #ifndef NFS_COMMITBVECSIZ 2670 #define NFS_COMMITBVECSIZ 20 2671 #endif 2672 struct buf *bvec[NFS_COMMITBVECSIZ]; 2673 2674 if (nmp->nm_flag & NFSMNT_INT) 2675 slpflag = PCATCH; 2676 if (!commit) 2677 passone = 0; 2678 /* 2679 * A b_flags == (B_DELWRI | B_NEEDCOMMIT) block has been written to the 2680 * server, but nas not been committed to stable storage on the server 2681 * yet. On the first pass, the byte range is worked out and the commit 2682 * rpc is done. On the second pass, nfs_writebp() is called to do the 2683 * job. 2684 */ 2685 again: 2686 bvecpos = 0; 2687 if (NFS_ISV3(vp) && commit) { 2688 s = splbio(); 2689 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2690 nbp = bp->b_vnbufs.le_next; 2691 if (bvecpos >= NFS_COMMITBVECSIZ) 2692 break; 2693 if ((bp->b_flags & (B_BUSY | B_DELWRI | B_NEEDCOMMIT)) 2694 != (B_DELWRI | B_NEEDCOMMIT)) 2695 continue; 2696 bremfree(bp); 2697 bp->b_flags |= (B_BUSY | B_WRITEINPROG); 2698 /* 2699 * A list of these buffers is kept so that the 2700 * second loop knows which buffers have actually 2701 * been committed. This is necessary, since there 2702 * may be a race between the commit rpc and new 2703 * uncommitted writes on the file. 2704 */ 2705 bvec[bvecpos++] = bp; 2706 toff = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + 2707 bp->b_dirtyoff; 2708 if (toff < off) 2709 off = toff; 2710 toff += (u_quad_t)(bp->b_dirtyend - bp->b_dirtyoff); 2711 if (toff > endoff) 2712 endoff = toff; 2713 } 2714 splx(s); 2715 } 2716 if (bvecpos > 0) { 2717 /* 2718 * Commit data on the server, as required. 2719 */ 2720 retv = nfs_commit(vp, off, (int)(endoff - off), p); 2721 if (retv == NFSERR_STALEWRITEVERF) 2722 nfs_clearcommit(vp->v_mount); 2723 /* 2724 * Now, either mark the blocks I/O done or mark the 2725 * blocks dirty, depending on whether the commit 2726 * succeeded. 2727 */ 2728 for (i = 0; i < bvecpos; i++) { 2729 bp = bvec[i]; 2730 bp->b_flags &= ~(B_NEEDCOMMIT | B_WRITEINPROG); 2731 if (retv) 2732 brelse(bp); 2733 else { 2734 s = splbio(); 2735 buf_undirty(bp); 2736 vp->v_numoutput++; 2737 bp->b_flags |= B_ASYNC; 2738 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR); 2739 bp->b_dirtyoff = bp->b_dirtyend = 0; 2740 splx(s); 2741 biodone(bp); 2742 } 2743 } 2744 } 2745 2746 /* 2747 * Start/do any write(s) that are required. 2748 */ 2749 loop: 2750 s = splbio(); 2751 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2752 nbp = bp->b_vnbufs.le_next; 2753 if (bp->b_flags & B_BUSY) { 2754 if (waitfor != MNT_WAIT || passone) 2755 continue; 2756 bp->b_flags |= B_WANTED; 2757 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), 2758 "nfsfsync", slptimeo); 2759 splx(s); 2760 if (error) { 2761 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) 2762 return (EINTR); 2763 if (slpflag == PCATCH) { 2764 slpflag = 0; 2765 slptimeo = 2 * hz; 2766 } 2767 } 2768 goto loop; 2769 } 2770 if ((bp->b_flags & B_DELWRI) == 0) 2771 panic("nfs_fsync: not dirty"); 2772 if ((passone || !commit) && (bp->b_flags & B_NEEDCOMMIT)) 2773 continue; 2774 bremfree(bp); 2775 if (passone || !commit) 2776 bp->b_flags |= (B_BUSY|B_ASYNC); 2777 else 2778 bp->b_flags |= (B_BUSY|B_ASYNC|B_WRITEINPROG|B_NEEDCOMMIT); 2779 splx(s); 2780 VOP_BWRITE(bp); 2781 goto loop; 2782 } 2783 splx(s); 2784 if (passone) { 2785 passone = 0; 2786 goto again; 2787 } 2788 if (waitfor == MNT_WAIT) { 2789 loop2: 2790 s = splbio(); 2791 error = vwaitforio(vp, slpflag, "nfs_fsync", slptimeo); 2792 splx(s); 2793 if (error) { 2794 if (nfs_sigintr(nmp, (struct nfsreq *)0, p)) 2795 return (EINTR); 2796 if (slpflag == PCATCH) { 2797 slpflag = 0; 2798 slptimeo = 2 * hz; 2799 } 2800 goto loop2; 2801 } 2802 2803 if (vp->v_dirtyblkhd.lh_first && commit) { 2804 #if 0 2805 vprint("nfs_fsync: dirty", vp); 2806 #endif 2807 goto loop; 2808 } 2809 } 2810 if (np->n_flag & NWRITEERR) { 2811 error = np->n_error; 2812 np->n_flag &= ~NWRITEERR; 2813 } 2814 return (error); 2815 } 2816 2817 /* 2818 * Return POSIX pathconf information applicable to nfs. 2819 * 2820 * The NFS V2 protocol doesn't support this, so just return EINVAL 2821 * for V2. 2822 */ 2823 /* ARGSUSED */ 2824 int 2825 nfs_pathconf(v) 2826 void *v; 2827 { 2828 #if 0 2829 struct vop_pathconf_args /* { 2830 struct vnode *a_vp; 2831 int a_name; 2832 register_t *a_retval; 2833 } */ *ap = v; 2834 #endif 2835 2836 return (EINVAL); 2837 } 2838 2839 /* 2840 * NFS advisory byte-level locks. 2841 */ 2842 int 2843 nfs_advlock(v) 2844 void *v; 2845 { 2846 struct vop_advlock_args /* { 2847 struct vnode *a_vp; 2848 caddr_t a_id; 2849 int a_op; 2850 struct flock *a_fl; 2851 int a_flags; 2852 } */ *ap = v; 2853 register struct nfsnode *np = VTONFS(ap->a_vp); 2854 2855 return (lf_advlock(&np->n_lockf, np->n_size, ap->a_id, ap->a_op, 2856 ap->a_fl, ap->a_flags)); 2857 } 2858 2859 /* 2860 * Print out the contents of an nfsnode. 2861 */ 2862 int 2863 nfs_print(v) 2864 void *v; 2865 { 2866 struct vop_print_args /* { 2867 struct vnode *a_vp; 2868 } */ *ap = v; 2869 register struct vnode *vp = ap->a_vp; 2870 register struct nfsnode *np = VTONFS(vp); 2871 2872 printf("tag VT_NFS, fileid %ld fsid 0x%lx", 2873 np->n_vattr.va_fileid, np->n_vattr.va_fsid); 2874 #ifdef FIFO 2875 if (vp->v_type == VFIFO) 2876 fifo_printinfo(vp); 2877 #endif 2878 printf("\n"); 2879 return (0); 2880 } 2881 2882 /* 2883 * Just call nfs_writebp() with the force argument set to 1. 2884 */ 2885 int 2886 nfs_bwrite(v) 2887 void *v; 2888 { 2889 struct vop_bwrite_args /* { 2890 struct buf *a_bp; 2891 } */ *ap = v; 2892 2893 return (nfs_writebp(ap->a_bp, 1)); 2894 } 2895 2896 /* 2897 * This is a clone of vop_generic_bwrite(), except that B_WRITEINPROG isn't set unless 2898 * the force flag is one and it also handles the B_NEEDCOMMIT flag. 2899 */ 2900 int 2901 nfs_writebp(bp, force) 2902 register struct buf *bp; 2903 int force; 2904 { 2905 register int oldflags = bp->b_flags, retv = 1; 2906 register struct proc *p = curproc; /* XXX */ 2907 off_t off; 2908 int s; 2909 2910 if(!(bp->b_flags & B_BUSY)) 2911 panic("bwrite: buffer is not busy???"); 2912 2913 #ifdef fvdl_debug 2914 printf("nfs_writebp(%x): vp %x voff %d vend %d doff %d dend %d\n", 2915 bp, bp->b_vp, bp->b_validoff, bp->b_validend, bp->b_dirtyoff, 2916 bp->b_dirtyend); 2917 #endif 2918 bp->b_flags &= ~(B_READ|B_DONE|B_ERROR); 2919 2920 s = splbio(); 2921 buf_undirty(bp); 2922 2923 if ((oldflags & B_ASYNC) && !(oldflags & B_DELWRI) && p) 2924 ++p->p_stats->p_ru.ru_oublock; 2925 2926 bp->b_vp->v_numoutput++; 2927 splx(s); 2928 2929 /* 2930 * If B_NEEDCOMMIT is set, a commit rpc may do the trick. If not 2931 * an actual write will have to be scheduled via. VOP_STRATEGY(). 2932 * If B_WRITEINPROG is already set, then push it with a write anyhow. 2933 */ 2934 if ((oldflags & (B_NEEDCOMMIT | B_WRITEINPROG)) == B_NEEDCOMMIT) { 2935 off = ((u_quad_t)bp->b_blkno) * DEV_BSIZE + bp->b_dirtyoff; 2936 bp->b_flags |= B_WRITEINPROG; 2937 retv = nfs_commit(bp->b_vp, off, bp->b_dirtyend-bp->b_dirtyoff, 2938 bp->b_proc); 2939 bp->b_flags &= ~B_WRITEINPROG; 2940 if (!retv) { 2941 bp->b_dirtyoff = bp->b_dirtyend = 0; 2942 bp->b_flags &= ~B_NEEDCOMMIT; 2943 biodone(bp); 2944 } else if (retv == NFSERR_STALEWRITEVERF) 2945 nfs_clearcommit(bp->b_vp->v_mount); 2946 } 2947 if (retv) { 2948 if (force) 2949 bp->b_flags |= B_WRITEINPROG; 2950 VOP_STRATEGY(bp); 2951 } 2952 2953 if( (oldflags & B_ASYNC) == 0) { 2954 int rtval = biowait(bp); 2955 if (!(oldflags & B_DELWRI) && p) { 2956 ++p->p_stats->p_ru.ru_oublock; 2957 } 2958 brelse(bp); 2959 return (rtval); 2960 } 2961 2962 return (0); 2963 } 2964 2965 /* 2966 * nfs special file access vnode op. 2967 * Essentially just get vattr and then imitate iaccess() since the device is 2968 * local to the client. 2969 */ 2970 int 2971 nfsspec_access(v) 2972 void *v; 2973 { 2974 struct vop_access_args /* { 2975 struct vnode *a_vp; 2976 int a_mode; 2977 struct ucred *a_cred; 2978 struct proc *a_p; 2979 } */ *ap = v; 2980 struct vattr va; 2981 struct vnode *vp = ap->a_vp; 2982 int error; 2983 2984 /* 2985 * Disallow write attempts on filesystems mounted read-only; 2986 * unless the file is a socket, fifo, or a block or character 2987 * device resident on the filesystem. 2988 */ 2989 if ((ap->a_mode & VWRITE) && (vp->v_mount->mnt_flag & MNT_RDONLY)) { 2990 switch (vp->v_type) { 2991 case VREG: 2992 case VDIR: 2993 case VLNK: 2994 return (EROFS); 2995 default: 2996 break; 2997 } 2998 } 2999 3000 error = VOP_GETATTR(vp, &va, ap->a_cred, ap->a_p); 3001 if (error) 3002 return (error); 3003 3004 return (vaccess(va.va_mode, va.va_uid, va.va_gid, ap->a_mode, 3005 ap->a_cred)); 3006 } 3007 3008 /* 3009 * Read wrapper for special devices. 3010 */ 3011 int 3012 nfsspec_read(v) 3013 void *v; 3014 { 3015 struct vop_read_args /* { 3016 struct vnode *a_vp; 3017 struct uio *a_uio; 3018 int a_ioflag; 3019 struct ucred *a_cred; 3020 } */ *ap = v; 3021 register struct nfsnode *np = VTONFS(ap->a_vp); 3022 3023 /* 3024 * Set access flag. 3025 */ 3026 np->n_flag |= NACC; 3027 np->n_atim.tv_sec = time.tv_sec; 3028 np->n_atim.tv_nsec = time.tv_usec * 1000; 3029 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap)); 3030 } 3031 3032 /* 3033 * Write wrapper for special devices. 3034 */ 3035 int 3036 nfsspec_write(v) 3037 void *v; 3038 { 3039 struct vop_write_args /* { 3040 struct vnode *a_vp; 3041 struct uio *a_uio; 3042 int a_ioflag; 3043 struct ucred *a_cred; 3044 } */ *ap = v; 3045 register struct nfsnode *np = VTONFS(ap->a_vp); 3046 3047 /* 3048 * Set update flag. 3049 */ 3050 np->n_flag |= NUPD; 3051 np->n_mtim.tv_sec = time.tv_sec; 3052 np->n_mtim.tv_nsec = time.tv_usec * 1000; 3053 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap)); 3054 } 3055 3056 /* 3057 * Close wrapper for special devices. 3058 * 3059 * Update the times on the nfsnode then do device close. 3060 */ 3061 int 3062 nfsspec_close(v) 3063 void *v; 3064 { 3065 struct vop_close_args /* { 3066 struct vnode *a_vp; 3067 int a_fflag; 3068 struct ucred *a_cred; 3069 struct proc *a_p; 3070 } */ *ap = v; 3071 register struct vnode *vp = ap->a_vp; 3072 register struct nfsnode *np = VTONFS(vp); 3073 struct vattr vattr; 3074 3075 if (np->n_flag & (NACC | NUPD)) { 3076 np->n_flag |= NCHG; 3077 if (vp->v_usecount == 1 && 3078 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3079 VATTR_NULL(&vattr); 3080 if (np->n_flag & NACC) 3081 vattr.va_atime = np->n_atim; 3082 if (np->n_flag & NUPD) 3083 vattr.va_mtime = np->n_mtim; 3084 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3085 } 3086 } 3087 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 3088 } 3089 3090 #ifdef FIFO 3091 /* 3092 * Read wrapper for fifos. 3093 */ 3094 int 3095 nfsfifo_read(v) 3096 void *v; 3097 { 3098 struct vop_read_args /* { 3099 struct vnode *a_vp; 3100 struct uio *a_uio; 3101 int a_ioflag; 3102 struct ucred *a_cred; 3103 } */ *ap = v; 3104 extern int (**fifo_vnodeop_p) __P((void *)); 3105 register struct nfsnode *np = VTONFS(ap->a_vp); 3106 3107 /* 3108 * Set access flag. 3109 */ 3110 np->n_flag |= NACC; 3111 np->n_atim.tv_sec = time.tv_sec; 3112 np->n_atim.tv_nsec = time.tv_usec * 1000; 3113 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap)); 3114 } 3115 3116 /* 3117 * Write wrapper for fifos. 3118 */ 3119 int 3120 nfsfifo_write(v) 3121 void *v; 3122 { 3123 struct vop_write_args /* { 3124 struct vnode *a_vp; 3125 struct uio *a_uio; 3126 int a_ioflag; 3127 struct ucred *a_cred; 3128 } */ *ap = v; 3129 extern int (**fifo_vnodeop_p) __P((void *)); 3130 register struct nfsnode *np = VTONFS(ap->a_vp); 3131 3132 /* 3133 * Set update flag. 3134 */ 3135 np->n_flag |= NUPD; 3136 np->n_mtim.tv_sec = time.tv_sec; 3137 np->n_mtim.tv_nsec = time.tv_usec * 1000; 3138 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap)); 3139 } 3140 3141 /* 3142 * Close wrapper for fifos. 3143 * 3144 * Update the times on the nfsnode then do fifo close. 3145 */ 3146 int 3147 nfsfifo_close(v) 3148 void *v; 3149 { 3150 struct vop_close_args /* { 3151 struct vnode *a_vp; 3152 int a_fflag; 3153 struct ucred *a_cred; 3154 struct proc *a_p; 3155 } */ *ap = v; 3156 register struct vnode *vp = ap->a_vp; 3157 register struct nfsnode *np = VTONFS(vp); 3158 struct vattr vattr; 3159 extern int (**fifo_vnodeop_p) __P((void *)); 3160 3161 if (np->n_flag & (NACC | NUPD)) { 3162 if (np->n_flag & NACC) { 3163 np->n_atim.tv_sec = time.tv_sec; 3164 np->n_atim.tv_nsec = time.tv_usec * 1000; 3165 } 3166 if (np->n_flag & NUPD) { 3167 np->n_mtim.tv_sec = time.tv_sec; 3168 np->n_mtim.tv_nsec = time.tv_usec * 1000; 3169 } 3170 np->n_flag |= NCHG; 3171 if (vp->v_usecount == 1 && 3172 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 3173 VATTR_NULL(&vattr); 3174 if (np->n_flag & NACC) 3175 vattr.va_atime = np->n_atim; 3176 if (np->n_flag & NUPD) 3177 vattr.va_mtime = np->n_mtim; 3178 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 3179 } 3180 } 3181 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 3182 } 3183 #endif /* ! FIFO */ 3184