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