1 /* $NetBSD: nfs_vnops.c,v 1.50 1995/03/18 05:56:32 gwr 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.10 (Berkeley) 8/11/94 39 */ 40 41 /* 42 * vnode op calls for sun nfs version 2 43 */ 44 45 #include <sys/param.h> 46 #include <sys/proc.h> 47 #include <sys/kernel.h> 48 #include <sys/systm.h> 49 #include <sys/mount.h> 50 #include <sys/buf.h> 51 #include <sys/malloc.h> 52 #include <sys/mbuf.h> 53 #include <sys/conf.h> 54 #include <sys/namei.h> 55 #include <sys/vnode.h> 56 #include <sys/map.h> 57 #include <sys/dirent.h> 58 #include <sys/lockf.h> 59 60 #include <vm/vm.h> 61 62 #include <miscfs/specfs/specdev.h> 63 #include <miscfs/fifofs/fifo.h> 64 65 #include <nfs/rpcv2.h> 66 #include <nfs/nfsv2.h> 67 #include <nfs/nfs.h> 68 #include <nfs/nfsnode.h> 69 #include <nfs/nfsmount.h> 70 #include <nfs/xdr_subs.h> 71 #include <nfs/nfsm_subs.h> 72 #include <nfs/nqnfs.h> 73 74 /* Defs */ 75 #define TRUE 1 76 #define FALSE 0 77 78 /* 79 * Global vfs data structures for nfs 80 */ 81 int (**nfsv2_vnodeop_p)(); 82 struct vnodeopv_entry_desc nfsv2_vnodeop_entries[] = { 83 { &vop_default_desc, vn_default_error }, 84 { &vop_lookup_desc, nfs_lookup }, /* lookup */ 85 { &vop_create_desc, nfs_create }, /* create */ 86 { &vop_mknod_desc, nfs_mknod }, /* mknod */ 87 { &vop_open_desc, nfs_open }, /* open */ 88 { &vop_close_desc, nfs_close }, /* close */ 89 { &vop_access_desc, nfs_access }, /* access */ 90 { &vop_getattr_desc, nfs_getattr }, /* getattr */ 91 { &vop_setattr_desc, nfs_setattr }, /* setattr */ 92 { &vop_read_desc, nfs_read }, /* read */ 93 { &vop_write_desc, nfs_write }, /* write */ 94 { &vop_lease_desc, nfs_lease_check }, /* lease */ 95 { &vop_ioctl_desc, nfs_ioctl }, /* ioctl */ 96 { &vop_select_desc, nfs_select }, /* select */ 97 { &vop_mmap_desc, nfs_mmap }, /* mmap */ 98 { &vop_fsync_desc, nfs_fsync }, /* fsync */ 99 { &vop_seek_desc, nfs_seek }, /* seek */ 100 { &vop_remove_desc, nfs_remove }, /* remove */ 101 { &vop_link_desc, nfs_link }, /* link */ 102 { &vop_rename_desc, nfs_rename }, /* rename */ 103 { &vop_mkdir_desc, nfs_mkdir }, /* mkdir */ 104 { &vop_rmdir_desc, nfs_rmdir }, /* rmdir */ 105 { &vop_symlink_desc, nfs_symlink }, /* symlink */ 106 { &vop_readdir_desc, nfs_readdir }, /* readdir */ 107 { &vop_readlink_desc, nfs_readlink }, /* readlink */ 108 { &vop_abortop_desc, nfs_abortop }, /* abortop */ 109 { &vop_inactive_desc, nfs_inactive }, /* inactive */ 110 { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ 111 { &vop_lock_desc, nfs_lock }, /* lock */ 112 { &vop_unlock_desc, nfs_unlock }, /* unlock */ 113 { &vop_bmap_desc, nfs_bmap }, /* bmap */ 114 { &vop_strategy_desc, nfs_strategy }, /* strategy */ 115 { &vop_print_desc, nfs_print }, /* print */ 116 { &vop_islocked_desc, nfs_islocked }, /* islocked */ 117 { &vop_pathconf_desc, nfs_pathconf }, /* pathconf */ 118 { &vop_advlock_desc, nfs_advlock }, /* advlock */ 119 { &vop_blkatoff_desc, nfs_blkatoff }, /* blkatoff */ 120 { &vop_valloc_desc, nfs_valloc }, /* valloc */ 121 { &vop_reallocblks_desc, nfs_reallocblks }, /* reallocblks */ 122 { &vop_vfree_desc, nfs_vfree }, /* vfree */ 123 { &vop_truncate_desc, nfs_truncate }, /* truncate */ 124 { &vop_update_desc, nfs_update }, /* update */ 125 { &vop_bwrite_desc, vn_bwrite }, 126 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 127 }; 128 struct vnodeopv_desc nfsv2_vnodeop_opv_desc = 129 { &nfsv2_vnodeop_p, nfsv2_vnodeop_entries }; 130 131 /* 132 * Special device vnode ops 133 */ 134 int (**spec_nfsv2nodeop_p)(); 135 struct vnodeopv_entry_desc spec_nfsv2nodeop_entries[] = { 136 { &vop_default_desc, vn_default_error }, 137 { &vop_lookup_desc, spec_lookup }, /* lookup */ 138 { &vop_create_desc, spec_create }, /* create */ 139 { &vop_mknod_desc, spec_mknod }, /* mknod */ 140 { &vop_open_desc, spec_open }, /* open */ 141 { &vop_close_desc, nfsspec_close }, /* close */ 142 { &vop_access_desc, nfsspec_access }, /* access */ 143 { &vop_getattr_desc, nfs_getattr }, /* getattr */ 144 { &vop_setattr_desc, nfs_setattr }, /* setattr */ 145 { &vop_read_desc, nfsspec_read }, /* read */ 146 { &vop_write_desc, nfsspec_write }, /* write */ 147 { &vop_lease_desc, spec_lease_check }, /* lease */ 148 { &vop_ioctl_desc, spec_ioctl }, /* ioctl */ 149 { &vop_select_desc, spec_select }, /* select */ 150 { &vop_mmap_desc, spec_mmap }, /* mmap */ 151 { &vop_fsync_desc, nfs_fsync }, /* fsync */ 152 { &vop_seek_desc, spec_seek }, /* seek */ 153 { &vop_remove_desc, spec_remove }, /* remove */ 154 { &vop_link_desc, spec_link }, /* link */ 155 { &vop_rename_desc, spec_rename }, /* rename */ 156 { &vop_mkdir_desc, spec_mkdir }, /* mkdir */ 157 { &vop_rmdir_desc, spec_rmdir }, /* rmdir */ 158 { &vop_symlink_desc, spec_symlink }, /* symlink */ 159 { &vop_readdir_desc, spec_readdir }, /* readdir */ 160 { &vop_readlink_desc, spec_readlink }, /* readlink */ 161 { &vop_abortop_desc, spec_abortop }, /* abortop */ 162 { &vop_inactive_desc, nfs_inactive }, /* inactive */ 163 { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ 164 { &vop_lock_desc, nfs_lock }, /* lock */ 165 { &vop_unlock_desc, nfs_unlock }, /* unlock */ 166 { &vop_bmap_desc, spec_bmap }, /* bmap */ 167 { &vop_strategy_desc, spec_strategy }, /* strategy */ 168 { &vop_print_desc, nfs_print }, /* print */ 169 { &vop_islocked_desc, nfs_islocked }, /* islocked */ 170 { &vop_pathconf_desc, spec_pathconf }, /* pathconf */ 171 { &vop_advlock_desc, spec_advlock }, /* advlock */ 172 { &vop_blkatoff_desc, spec_blkatoff }, /* blkatoff */ 173 { &vop_valloc_desc, spec_valloc }, /* valloc */ 174 { &vop_reallocblks_desc, spec_reallocblks }, /* reallocblks */ 175 { &vop_vfree_desc, spec_vfree }, /* vfree */ 176 { &vop_truncate_desc, spec_truncate }, /* truncate */ 177 { &vop_update_desc, nfs_update }, /* update */ 178 { &vop_bwrite_desc, vn_bwrite }, 179 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 180 }; 181 struct vnodeopv_desc spec_nfsv2nodeop_opv_desc = 182 { &spec_nfsv2nodeop_p, spec_nfsv2nodeop_entries }; 183 184 #ifdef FIFO 185 int (**fifo_nfsv2nodeop_p)(); 186 struct vnodeopv_entry_desc fifo_nfsv2nodeop_entries[] = { 187 { &vop_default_desc, vn_default_error }, 188 { &vop_lookup_desc, fifo_lookup }, /* lookup */ 189 { &vop_create_desc, fifo_create }, /* create */ 190 { &vop_mknod_desc, fifo_mknod }, /* mknod */ 191 { &vop_open_desc, fifo_open }, /* open */ 192 { &vop_close_desc, nfsfifo_close }, /* close */ 193 { &vop_access_desc, nfsspec_access }, /* access */ 194 { &vop_getattr_desc, nfs_getattr }, /* getattr */ 195 { &vop_setattr_desc, nfs_setattr }, /* setattr */ 196 { &vop_read_desc, nfsfifo_read }, /* read */ 197 { &vop_write_desc, nfsfifo_write }, /* write */ 198 { &vop_lease_desc, fifo_lease_check }, /* lease */ 199 { &vop_ioctl_desc, fifo_ioctl }, /* ioctl */ 200 { &vop_select_desc, fifo_select }, /* select */ 201 { &vop_mmap_desc, fifo_mmap }, /* mmap */ 202 { &vop_fsync_desc, nfs_fsync }, /* fsync */ 203 { &vop_seek_desc, fifo_seek }, /* seek */ 204 { &vop_remove_desc, fifo_remove }, /* remove */ 205 { &vop_link_desc, fifo_link }, /* link */ 206 { &vop_rename_desc, fifo_rename }, /* rename */ 207 { &vop_mkdir_desc, fifo_mkdir }, /* mkdir */ 208 { &vop_rmdir_desc, fifo_rmdir }, /* rmdir */ 209 { &vop_symlink_desc, fifo_symlink }, /* symlink */ 210 { &vop_readdir_desc, fifo_readdir }, /* readdir */ 211 { &vop_readlink_desc, fifo_readlink }, /* readlink */ 212 { &vop_abortop_desc, fifo_abortop }, /* abortop */ 213 { &vop_inactive_desc, nfs_inactive }, /* inactive */ 214 { &vop_reclaim_desc, nfs_reclaim }, /* reclaim */ 215 { &vop_lock_desc, nfs_lock }, /* lock */ 216 { &vop_unlock_desc, nfs_unlock }, /* unlock */ 217 { &vop_bmap_desc, fifo_bmap }, /* bmap */ 218 { &vop_strategy_desc, fifo_badop }, /* strategy */ 219 { &vop_print_desc, nfs_print }, /* print */ 220 { &vop_islocked_desc, nfs_islocked }, /* islocked */ 221 { &vop_pathconf_desc, fifo_pathconf }, /* pathconf */ 222 { &vop_advlock_desc, fifo_advlock }, /* advlock */ 223 { &vop_blkatoff_desc, fifo_blkatoff }, /* blkatoff */ 224 { &vop_valloc_desc, fifo_valloc }, /* valloc */ 225 { &vop_reallocblks_desc, fifo_reallocblks }, /* reallocblks */ 226 { &vop_vfree_desc, fifo_vfree }, /* vfree */ 227 { &vop_truncate_desc, fifo_truncate }, /* truncate */ 228 { &vop_update_desc, nfs_update }, /* update */ 229 { &vop_bwrite_desc, vn_bwrite }, 230 { (struct vnodeop_desc*)NULL, (int(*)())NULL } 231 }; 232 struct vnodeopv_desc fifo_nfsv2nodeop_opv_desc = 233 { &fifo_nfsv2nodeop_p, fifo_nfsv2nodeop_entries }; 234 #endif /* FIFO */ 235 236 void nqnfs_clientlease(); 237 238 /* 239 * Global variables 240 */ 241 extern u_long nfs_procids[NFS_NPROCS]; 242 extern u_long nfs_prog, nfs_vers, nfs_true, nfs_false; 243 struct proc *nfs_iodwant[NFS_MAXASYNCDAEMON]; 244 int nfs_numasync = 0; 245 #define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1)) 246 247 /* 248 * nfs null call from vfs. 249 */ 250 int 251 nfs_null(vp, cred, procp) 252 struct vnode *vp; 253 struct ucred *cred; 254 struct proc *procp; 255 { 256 caddr_t bpos, dpos; 257 int error = 0; 258 struct mbuf *mreq, *mrep, *md, *mb; 259 260 nfsm_reqhead(vp, NFSPROC_NULL, 0); 261 nfsm_request(vp, NFSPROC_NULL, procp, cred); 262 nfsm_reqdone; 263 return (error); 264 } 265 266 /* 267 * nfs access vnode op. 268 * For nfs, just return ok. File accesses may fail later. 269 * For nqnfs, use the access rpc to check accessibility. If file modes are 270 * changed on the server, accesses might still fail later. 271 */ 272 int 273 nfs_access(ap) 274 struct vop_access_args /* { 275 struct vnode *a_vp; 276 int a_mode; 277 struct ucred *a_cred; 278 struct proc *a_p; 279 } */ *ap; 280 { 281 register struct vnode *vp = ap->a_vp; 282 register u_long *tl; 283 register caddr_t cp; 284 caddr_t bpos, dpos; 285 int error = 0; 286 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 287 288 /* 289 * For nqnfs, do an access rpc, otherwise you are stuck emulating 290 * ufs_access() locally using the vattr. This may not be correct, 291 * since the server may apply other access criteria such as 292 * client uid-->server uid mapping that we do not know about, but 293 * this is better than just returning anything that is lying about 294 * in the cache. 295 */ 296 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { 297 nfsstats.rpccnt[NQNFSPROC_ACCESS]++; 298 nfsm_reqhead(vp, NQNFSPROC_ACCESS, NFSX_FH + 3 * NFSX_UNSIGNED); 299 nfsm_fhtom(vp); 300 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 301 if (ap->a_mode & VREAD) 302 *tl++ = nfs_true; 303 else 304 *tl++ = nfs_false; 305 if (ap->a_mode & VWRITE) 306 *tl++ = nfs_true; 307 else 308 *tl++ = nfs_false; 309 if (ap->a_mode & VEXEC) 310 *tl = nfs_true; 311 else 312 *tl = nfs_false; 313 nfsm_request(vp, NQNFSPROC_ACCESS, ap->a_p, ap->a_cred); 314 nfsm_reqdone; 315 return (error); 316 } else 317 return (nfsspec_access(ap)); 318 } 319 320 /* 321 * nfs open vnode op 322 * Check to see if the type is ok 323 * and that deletion is not in progress. 324 * For paged in text files, you will need to flush the page cache 325 * if consistency is lost. 326 */ 327 /* ARGSUSED */ 328 int 329 nfs_open(ap) 330 struct vop_open_args /* { 331 struct vnode *a_vp; 332 int a_mode; 333 struct ucred *a_cred; 334 struct proc *a_p; 335 } */ *ap; 336 { 337 register struct vnode *vp = ap->a_vp; 338 struct nfsnode *np = VTONFS(vp); 339 struct nfsmount *nmp = VFSTONFS(vp->v_mount); 340 struct vattr vattr; 341 int error; 342 343 if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK) 344 return (EACCES); 345 if (vp->v_flag & VTEXT) { 346 /* 347 * Get a valid lease. If cached data is stale, flush it. 348 */ 349 if (nmp->nm_flag & NFSMNT_NQNFS) { 350 if (NQNFS_CKINVALID(vp, np, NQL_READ)) { 351 do { 352 error = nqnfs_getlease(vp, NQL_READ, ap->a_cred, ap->a_p); 353 } while (error == NQNFS_EXPIRED); 354 if (error) 355 return (error); 356 if (np->n_lrev != np->n_brev || 357 (np->n_flag & NQNFSNONCACHE)) { 358 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 359 ap->a_p, 1)) == EINTR) 360 return (error); 361 (void) vnode_pager_uncache(vp); 362 np->n_brev = np->n_lrev; 363 } 364 } 365 } else { 366 if (np->n_flag & NMODIFIED) { 367 if ((error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, 368 ap->a_p, 1)) == EINTR) 369 return (error); 370 (void) vnode_pager_uncache(vp); 371 np->n_attrstamp = 0; 372 np->n_direofoffset = 0; 373 if (error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p)) 374 return (error); 375 np->n_mtime = vattr.va_mtime.ts_sec; 376 } else { 377 if (error = VOP_GETATTR(vp, &vattr, ap->a_cred, ap->a_p)) 378 return (error); 379 if (np->n_mtime != vattr.va_mtime.ts_sec) { 380 np->n_direofoffset = 0; 381 if ((error = nfs_vinvalbuf(vp, V_SAVE, 382 ap->a_cred, ap->a_p, 1)) == EINTR) 383 return (error); 384 (void) vnode_pager_uncache(vp); 385 np->n_mtime = vattr.va_mtime.ts_sec; 386 } 387 } 388 } 389 } else if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) 390 np->n_attrstamp = 0; /* For Open/Close consistency */ 391 return (0); 392 } 393 394 /* 395 * nfs close vnode op 396 * For reg files, invalidate any buffer cache entries. 397 */ 398 /* ARGSUSED */ 399 int 400 nfs_close(ap) 401 struct vop_close_args /* { 402 struct vnodeop_desc *a_desc; 403 struct vnode *a_vp; 404 int a_fflag; 405 struct ucred *a_cred; 406 struct proc *a_p; 407 } */ *ap; 408 { 409 register struct vnode *vp = ap->a_vp; 410 register struct nfsnode *np = VTONFS(vp); 411 int error = 0; 412 413 if (vp->v_type == VREG) { 414 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) == 0 && 415 (np->n_flag & NMODIFIED)) { 416 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1); 417 np->n_attrstamp = 0; 418 } 419 if (np->n_flag & NWRITEERR) { 420 np->n_flag &= ~NWRITEERR; 421 error = np->n_error; 422 } 423 } 424 return (error); 425 } 426 427 /* 428 * nfs getattr call from vfs. 429 */ 430 int 431 nfs_getattr(ap) 432 struct vop_getattr_args /* { 433 struct vnode *a_vp; 434 struct vattr *a_vap; 435 struct ucred *a_cred; 436 struct proc *a_p; 437 } */ *ap; 438 { 439 register struct vnode *vp = ap->a_vp; 440 register struct nfsnode *np = VTONFS(vp); 441 register caddr_t cp; 442 caddr_t bpos, dpos; 443 int error = 0; 444 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 445 446 /* 447 * Update local times for special files. 448 */ 449 if (np->n_flag & (NACC | NUPD)) 450 np->n_flag |= NCHG; 451 /* 452 * First look in the cache. 453 */ 454 if (nfs_getattrcache(vp, ap->a_vap) == 0) 455 return (0); 456 nfsstats.rpccnt[NFSPROC_GETATTR]++; 457 nfsm_reqhead(vp, NFSPROC_GETATTR, NFSX_FH); 458 nfsm_fhtom(vp); 459 nfsm_request(vp, NFSPROC_GETATTR, ap->a_p, ap->a_cred); 460 nfsm_loadattr(vp, ap->a_vap); 461 nfsm_reqdone; 462 return (error); 463 } 464 465 /* 466 * nfs setattr call. 467 */ 468 int 469 nfs_setattr(ap) 470 struct vop_setattr_args /* { 471 struct vnodeop_desc *a_desc; 472 struct vnode *a_vp; 473 struct vattr *a_vap; 474 struct ucred *a_cred; 475 struct proc *a_p; 476 } */ *ap; 477 { 478 register struct nfsv2_sattr *sp; 479 register caddr_t cp; 480 register long t1; 481 caddr_t bpos, dpos, cp2; 482 u_long *tl; 483 int error = 0, isnq; 484 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 485 register struct vnode *vp = ap->a_vp; 486 register struct nfsnode *np = VTONFS(vp); 487 register struct vattr *vap = ap->a_vap; 488 u_quad_t frev, tsize; 489 490 if (vap->va_size != VNOVAL) { 491 switch (vp->v_type) { 492 case VDIR: 493 return (EISDIR); 494 case VCHR: 495 case VBLK: 496 if (vap->va_mtime.ts_sec == VNOVAL && 497 vap->va_atime.ts_sec == VNOVAL && 498 vap->va_mode == (u_short)VNOVAL && 499 vap->va_uid == VNOVAL && 500 vap->va_gid == VNOVAL) 501 return (0); 502 vap->va_size = VNOVAL; 503 break; 504 default: 505 if (np->n_flag & NMODIFIED) { 506 if (vap->va_size == 0) 507 error = nfs_vinvalbuf(vp, 0, 508 ap->a_cred, ap->a_p, 1); 509 else 510 error = nfs_vinvalbuf(vp, V_SAVE, 511 ap->a_cred, ap->a_p, 1); 512 if (error) 513 return (error); 514 } 515 tsize = np->n_size; 516 np->n_size = np->n_vattr.va_size = vap->va_size; 517 vnode_pager_setsize(vp, (u_long)np->n_size); 518 } 519 } else if ((vap->va_mtime.ts_sec != VNOVAL || 520 vap->va_atime.ts_sec != VNOVAL) && (np->n_flag & NMODIFIED)) { 521 error = nfs_vinvalbuf(vp, V_SAVE, ap->a_cred, ap->a_p, 1); 522 if (error == EINTR) 523 return (error); 524 } 525 nfsstats.rpccnt[NFSPROC_SETATTR]++; 526 isnq = (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS); 527 nfsm_reqhead(vp, NFSPROC_SETATTR, NFSX_FH+NFSX_SATTR(isnq)); 528 nfsm_fhtom(vp); 529 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 530 if (vap->va_mode == (u_short)-1) 531 sp->sa_mode = VNOVAL; 532 else 533 sp->sa_mode = vtonfs_mode(vp->v_type, vap->va_mode); 534 if (vap->va_uid == (uid_t)-1) 535 sp->sa_uid = VNOVAL; 536 else 537 sp->sa_uid = txdr_unsigned(vap->va_uid); 538 if (vap->va_gid == (gid_t)-1) 539 sp->sa_gid = VNOVAL; 540 else 541 sp->sa_gid = txdr_unsigned(vap->va_gid); 542 if (isnq) { 543 txdr_hyper(&vap->va_size, &sp->sa_nqsize); 544 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 545 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 546 sp->sa_nqflags = txdr_unsigned(vap->va_flags); 547 sp->sa_nqrdev = VNOVAL; 548 } else { 549 sp->sa_nfssize = txdr_unsigned(vap->va_size); 550 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 551 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 552 } 553 nfsm_request(vp, NFSPROC_SETATTR, ap->a_p, ap->a_cred); 554 nfsm_loadattr(vp, (struct vattr *)0); 555 if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) && 556 NQNFS_CKCACHABLE(vp, NQL_WRITE)) { 557 nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED); 558 fxdr_hyper(tl, &frev); 559 if (frev > np->n_brev) 560 np->n_brev = frev; 561 } 562 nfsm_reqdone; 563 if (error) { 564 np->n_size = np->n_vattr.va_size = tsize; 565 vnode_pager_setsize(vp, (u_long)np->n_size); 566 } 567 return (error); 568 } 569 570 /* 571 * nfs lookup call, one step at a time... 572 * First look in cache 573 * If not found, unlock the directory nfsnode and do the rpc 574 */ 575 int 576 nfs_lookup(ap) 577 struct vop_lookup_args /* { 578 struct vnodeop_desc *a_desc; 579 struct vnode *a_dvp; 580 struct vnode **a_vpp; 581 struct componentname *a_cnp; 582 } */ *ap; 583 { 584 register struct componentname *cnp = ap->a_cnp; 585 register struct vnode *dvp = ap->a_dvp; 586 register struct vnode **vpp = ap->a_vpp; 587 register int flags = cnp->cn_flags; 588 register struct vnode *vdp; 589 register u_long *tl; 590 register caddr_t cp; 591 register long t1, t2; 592 struct nfsmount *nmp; 593 caddr_t bpos, dpos, cp2; 594 time_t reqtime; 595 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 596 struct vnode *newvp; 597 long len; 598 nfsv2fh_t *fhp; 599 struct nfsnode *np; 600 int lockparent, wantparent, error = 0; 601 int nqlflag, cachable; 602 u_quad_t frev; 603 604 *vpp = NULL; 605 if (dvp->v_type != VDIR) 606 return (ENOTDIR); 607 lockparent = flags & LOCKPARENT; 608 wantparent = flags & (LOCKPARENT|WANTPARENT); 609 nmp = VFSTONFS(dvp->v_mount); 610 np = VTONFS(dvp); 611 if ((error = cache_lookup(dvp, vpp, cnp)) && error != ENOENT) { 612 struct vattr vattr; 613 int vpid; 614 615 vdp = *vpp; 616 vpid = vdp->v_id; 617 /* 618 * See the comment starting `Step through' in ufs/ufs_lookup.c 619 * for an explanation of the locking protocol 620 */ 621 if (dvp == vdp) { 622 VREF(vdp); 623 error = 0; 624 } else 625 error = vget(vdp, 1); 626 if (!error) { 627 if (vpid == vdp->v_id) { 628 if (nmp->nm_flag & NFSMNT_NQNFS) { 629 if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) == 0) { 630 cachehit: 631 nfsstats.lookupcache_hits++; 632 if (cnp->cn_nameiop != LOOKUP && 633 (flags & ISLASTCN)) 634 cnp->cn_flags |= SAVENAME; 635 return (0); 636 } else if (NQNFS_CKCACHABLE(dvp, NQL_READ)) { 637 if (np->n_lrev != np->n_brev || 638 (np->n_flag & NMODIFIED)) { 639 np->n_direofoffset = 0; 640 cache_purge(dvp); 641 error = nfs_vinvalbuf(dvp, 0, 642 cnp->cn_cred, cnp->cn_proc, 643 1); 644 if (error == EINTR) 645 return (error); 646 np->n_brev = np->n_lrev; 647 } else 648 goto cachehit; 649 } 650 } else if (!VOP_GETATTR(vdp, &vattr, cnp->cn_cred, cnp->cn_proc) && 651 vattr.va_ctime.ts_sec == VTONFS(vdp)->n_ctime) 652 goto cachehit; 653 cache_purge(vdp); 654 } 655 vrele(vdp); 656 } 657 *vpp = NULLVP; 658 } 659 error = 0; 660 nfsstats.lookupcache_misses++; 661 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 662 len = cnp->cn_namelen; 663 nfsm_reqhead(dvp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 664 665 /* 666 * For nqnfs optionally piggyback a getlease request for the name 667 * being looked up. 668 */ 669 if (nmp->nm_flag & NFSMNT_NQNFS) { 670 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 671 if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) && 672 ((cnp->cn_flags & MAKEENTRY) && 673 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)))) 674 *tl = txdr_unsigned(nmp->nm_leaseterm); 675 else 676 *tl = 0; 677 } 678 nfsm_fhtom(dvp); 679 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 680 reqtime = time.tv_sec; 681 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 682 nfsmout: 683 if (error) { 684 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && 685 (flags & ISLASTCN) && error == ENOENT) 686 error = EJUSTRETURN; 687 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 688 cnp->cn_flags |= SAVENAME; 689 return (error); 690 } 691 if (nmp->nm_flag & NFSMNT_NQNFS) { 692 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 693 if (*tl) { 694 nqlflag = fxdr_unsigned(int, *tl); 695 nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED); 696 cachable = fxdr_unsigned(int, *tl++); 697 reqtime += fxdr_unsigned(int, *tl++); 698 fxdr_hyper(tl, &frev); 699 } else 700 nqlflag = 0; 701 } 702 nfsm_dissect(fhp, nfsv2fh_t *, NFSX_FH); 703 704 /* 705 * Handle RENAME case... 706 */ 707 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { 708 if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 709 m_freem(mrep); 710 return (EISDIR); 711 } 712 if (error = nfs_nget(dvp->v_mount, fhp, &np)) { 713 m_freem(mrep); 714 return (error); 715 } 716 newvp = NFSTOV(np); 717 if (error = 718 nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 719 vrele(newvp); 720 m_freem(mrep); 721 return (error); 722 } 723 *vpp = newvp; 724 m_freem(mrep); 725 cnp->cn_flags |= SAVENAME; 726 return (0); 727 } 728 729 if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 730 VREF(dvp); 731 newvp = dvp; 732 } else { 733 if (error = nfs_nget(dvp->v_mount, fhp, &np)) { 734 m_freem(mrep); 735 return (error); 736 } 737 newvp = NFSTOV(np); 738 } 739 if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 740 vrele(newvp); 741 m_freem(mrep); 742 return (error); 743 } 744 m_freem(mrep); 745 *vpp = newvp; 746 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 747 cnp->cn_flags |= SAVENAME; 748 if ((cnp->cn_flags & MAKEENTRY) && 749 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { 750 if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) 751 np->n_ctime = np->n_vattr.va_ctime.ts_sec; 752 else if (nqlflag && reqtime > time.tv_sec) 753 nqnfs_clientlease(nmp, np, nqlflag, cachable, reqtime, 754 frev); 755 cache_enter(dvp, *vpp, cnp); 756 } 757 return (0); 758 } 759 760 /* 761 * nfs read call. 762 * Just call nfs_bioread() to do the work. 763 */ 764 int 765 nfs_read(ap) 766 struct vop_read_args /* { 767 struct vnode *a_vp; 768 struct uio *a_uio; 769 int a_ioflag; 770 struct ucred *a_cred; 771 } */ *ap; 772 { 773 register struct vnode *vp = ap->a_vp; 774 775 if (vp->v_type != VREG) 776 return (EPERM); 777 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); 778 } 779 780 /* 781 * nfs readlink call 782 */ 783 int 784 nfs_readlink(ap) 785 struct vop_readlink_args /* { 786 struct vnode *a_vp; 787 struct uio *a_uio; 788 struct ucred *a_cred; 789 } */ *ap; 790 { 791 register struct vnode *vp = ap->a_vp; 792 793 if (vp->v_type != VLNK) 794 return (EPERM); 795 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred)); 796 } 797 798 /* 799 * Do a readlink rpc. 800 * Called by nfs_doio() from below the buffer cache. 801 */ 802 int 803 nfs_readlinkrpc(vp, uiop, cred) 804 register struct vnode *vp; 805 struct uio *uiop; 806 struct ucred *cred; 807 { 808 register u_long *tl; 809 register caddr_t cp; 810 register long t1; 811 caddr_t bpos, dpos, cp2; 812 int error = 0; 813 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 814 long len; 815 816 nfsstats.rpccnt[NFSPROC_READLINK]++; 817 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH); 818 nfsm_fhtom(vp); 819 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred); 820 nfsm_strsiz(len, NFS_MAXPATHLEN); 821 nfsm_mtouio(uiop, len); 822 nfsm_reqdone; 823 return (error); 824 } 825 826 /* 827 * nfs read rpc call 828 * Ditto above 829 */ 830 int 831 nfs_readrpc(vp, uiop, cred) 832 register struct vnode *vp; 833 struct uio *uiop; 834 struct ucred *cred; 835 { 836 register u_long *tl; 837 register caddr_t cp; 838 register long t1; 839 caddr_t bpos, dpos, cp2; 840 int error = 0; 841 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 842 struct nfsmount *nmp; 843 long len, retlen, tsiz; 844 845 nmp = VFSTONFS(vp->v_mount); 846 tsiz = uiop->uio_resid; 847 if (uiop->uio_offset + tsiz > 0xffffffff && 848 (nmp->nm_flag & NFSMNT_NQNFS) == 0) 849 return (EFBIG); 850 while (tsiz > 0) { 851 nfsstats.rpccnt[NFSPROC_READ]++; 852 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 853 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH+NFSX_UNSIGNED*3); 854 nfsm_fhtom(vp); 855 nfsm_build(tl, u_long *, NFSX_UNSIGNED*3); 856 if (nmp->nm_flag & NFSMNT_NQNFS) { 857 txdr_hyper(&uiop->uio_offset, tl); 858 *(tl + 2) = txdr_unsigned(len); 859 } else { 860 *tl++ = txdr_unsigned(uiop->uio_offset); 861 *tl++ = txdr_unsigned(len); 862 *tl = 0; 863 } 864 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred); 865 nfsm_loadattr(vp, (struct vattr *)0); 866 nfsm_strsiz(retlen, nmp->nm_rsize); 867 nfsm_mtouio(uiop, retlen); 868 m_freem(mrep); 869 if (retlen < len) 870 tsiz = 0; 871 else 872 tsiz -= len; 873 } 874 nfsmout: 875 return (error); 876 } 877 878 /* 879 * nfs write call 880 */ 881 int 882 nfs_writerpc(vp, uiop, cred, ioflags) 883 register struct vnode *vp; 884 struct uio *uiop; 885 struct ucred *cred; 886 int ioflags; 887 { 888 register u_long *tl; 889 register caddr_t cp; 890 register long t1; 891 caddr_t bpos, dpos, cp2; 892 int error = 0; 893 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 894 struct nfsmount *nmp; 895 struct nfsnode *np = VTONFS(vp); 896 u_quad_t frev; 897 long len, tsiz; 898 899 nmp = VFSTONFS(vp->v_mount); 900 tsiz = uiop->uio_resid; 901 if (uiop->uio_offset + tsiz > 0xffffffff && 902 (nmp->nm_flag & NFSMNT_NQNFS) == 0) 903 return (EFBIG); 904 while (tsiz > 0) { 905 nfsstats.rpccnt[NFSPROC_WRITE]++; 906 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 907 nfsm_reqhead(vp, NFSPROC_WRITE, 908 NFSX_FH+NFSX_UNSIGNED*4+nfsm_rndup(len)); 909 nfsm_fhtom(vp); 910 nfsm_build(tl, u_long *, NFSX_UNSIGNED * 4); 911 if (nmp->nm_flag & NFSMNT_NQNFS) { 912 txdr_hyper(&uiop->uio_offset, tl); 913 tl += 2; 914 *tl++ = 0; 915 *tl = txdr_unsigned(len); 916 } else { 917 register u_int32_t x; 918 /* Set both "begin" and "current" to non-garbage. */ 919 x = txdr_unsigned((u_int32_t)uiop->uio_offset); 920 *tl++ = x; /* "begin offset" */ 921 *tl++ = x; /* "current offset" */ 922 x = txdr_unsigned(len); 923 *tl++ = x; /* total to this offset */ 924 *tl = x; /* size of this write */ 925 } 926 nfsm_uiotom(uiop, len); 927 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred); 928 nfsm_loadattr(vp, (struct vattr *)0); 929 if (nmp->nm_flag & NFSMNT_MYWRITE) 930 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.ts_sec; 931 else if ((nmp->nm_flag & NFSMNT_NQNFS) && 932 NQNFS_CKCACHABLE(vp, NQL_WRITE)) { 933 nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED); 934 fxdr_hyper(tl, &frev); 935 if (frev > np->n_brev) 936 np->n_brev = frev; 937 } 938 m_freem(mrep); 939 tsiz -= len; 940 } 941 nfsmout: 942 if (error) 943 uiop->uio_resid = tsiz; 944 return (error); 945 } 946 947 /* 948 * nfs mknod call 949 * This is a kludge. Use a create rpc but with the IFMT bits of the mode 950 * set to specify the file type and the size field for rdev. 951 */ 952 /* ARGSUSED */ 953 int 954 nfs_mknod(ap) 955 struct vop_mknod_args /* { 956 struct vnode *a_dvp; 957 struct vnode **a_vpp; 958 struct componentname *a_cnp; 959 struct vattr *a_vap; 960 } */ *ap; 961 { 962 register struct vnode *dvp = ap->a_dvp; 963 register struct vattr *vap = ap->a_vap; 964 register struct componentname *cnp = ap->a_cnp; 965 register struct nfsv2_sattr *sp; 966 register u_long *tl; 967 register caddr_t cp; 968 register long t1, t2; 969 struct vnode *newvp; 970 struct vattr vattr; 971 char *cp2; 972 caddr_t bpos, dpos; 973 int error = 0, isnq; 974 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 975 u_long rdev; 976 977 if (vap->va_type == VCHR || vap->va_type == VBLK) 978 rdev = txdr_unsigned(vap->va_rdev); 979 #ifdef FIFO 980 else if (vap->va_type == VFIFO) 981 rdev = 0xffffffff; 982 #endif /* FIFO */ 983 else { 984 VOP_ABORTOP(dvp, cnp); 985 vput(dvp); 986 return (EOPNOTSUPP); 987 } 988 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 989 VOP_ABORTOP(dvp, cnp); 990 vput(dvp); 991 return (error); 992 } 993 newvp = NULLVP; 994 nfsstats.rpccnt[NFSPROC_CREATE]++; 995 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 996 nfsm_reqhead(dvp, NFSPROC_CREATE, 997 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR(isnq)); 998 nfsm_fhtom(dvp); 999 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1000 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 1001 sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 1002 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1003 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1004 if (isnq) { 1005 sp->sa_nqrdev = rdev; 1006 sp->sa_nqflags = 0; 1007 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 1008 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 1009 } else { 1010 sp->sa_nfssize = rdev; 1011 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 1012 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 1013 } 1014 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1015 nfsm_mtofh(dvp, newvp); 1016 nfsm_reqdone; 1017 if (!error && (cnp->cn_flags & MAKEENTRY)) 1018 cache_enter(dvp, newvp, cnp); 1019 FREE(cnp->cn_pnbuf, M_NAMEI); 1020 VTONFS(dvp)->n_flag |= NMODIFIED; 1021 VTONFS(dvp)->n_attrstamp = 0; 1022 vrele(dvp); 1023 if (newvp != NULLVP) 1024 vrele(newvp); 1025 return (error); 1026 } 1027 1028 /* 1029 * nfs file create call 1030 */ 1031 int 1032 nfs_create(ap) 1033 struct vop_create_args /* { 1034 struct vnode *a_dvp; 1035 struct vnode **a_vpp; 1036 struct componentname *a_cnp; 1037 struct vattr *a_vap; 1038 } */ *ap; 1039 { 1040 register struct vnode *dvp = ap->a_dvp; 1041 register struct vattr *vap = ap->a_vap; 1042 register struct componentname *cnp = ap->a_cnp; 1043 register struct nfsv2_sattr *sp; 1044 register u_long *tl; 1045 register caddr_t cp; 1046 register long t1, t2; 1047 caddr_t bpos, dpos, cp2; 1048 int error = 0, isnq; 1049 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1050 struct vattr vattr; 1051 1052 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1053 VOP_ABORTOP(dvp, cnp); 1054 vput(dvp); 1055 return (error); 1056 } 1057 nfsstats.rpccnt[NFSPROC_CREATE]++; 1058 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 1059 nfsm_reqhead(dvp, NFSPROC_CREATE, 1060 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR(isnq)); 1061 nfsm_fhtom(dvp); 1062 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1063 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 1064 sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 1065 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1066 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1067 if (isnq) { 1068 u_quad_t qval = 0; 1069 1070 txdr_hyper(&qval, &sp->sa_nqsize); 1071 sp->sa_nqrdev = -1; 1072 sp->sa_nqflags = 0; 1073 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 1074 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 1075 } else { 1076 sp->sa_nfssize = 0; 1077 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 1078 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 1079 } 1080 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1081 nfsm_mtofh(dvp, *ap->a_vpp); 1082 nfsm_reqdone; 1083 if (!error && (cnp->cn_flags & MAKEENTRY)) 1084 cache_enter(dvp, *ap->a_vpp, cnp); 1085 FREE(cnp->cn_pnbuf, M_NAMEI); 1086 VTONFS(dvp)->n_flag |= NMODIFIED; 1087 VTONFS(dvp)->n_attrstamp = 0; 1088 vrele(dvp); 1089 return (error); 1090 } 1091 1092 /* 1093 * nfs file remove call 1094 * To try and make nfs semantics closer to ufs semantics, a file that has 1095 * other processes using the vnode is renamed instead of removed and then 1096 * removed later on the last close. 1097 * - If v_usecount > 1 1098 * If a rename is not already in the works 1099 * call nfs_sillyrename() to set it up 1100 * else 1101 * do the remove rpc 1102 */ 1103 int 1104 nfs_remove(ap) 1105 struct vop_remove_args /* { 1106 struct vnodeop_desc *a_desc; 1107 struct vnode * a_dvp; 1108 struct vnode * a_vp; 1109 struct componentname * a_cnp; 1110 } */ *ap; 1111 { 1112 register struct vnode *vp = ap->a_vp; 1113 register struct vnode *dvp = ap->a_dvp; 1114 register struct componentname *cnp = ap->a_cnp; 1115 register struct nfsnode *np = VTONFS(vp); 1116 register u_long *tl; 1117 register caddr_t cp; 1118 register long t2; 1119 caddr_t bpos, dpos; 1120 int error = 0; 1121 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1122 struct vattr vattr; 1123 1124 if (vp->v_usecount > 1) { 1125 if (!np->n_sillyrename) 1126 error = nfs_sillyrename(dvp, vp, cnp); 1127 else if (VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) 1128 == 0 && vattr.va_nlink > 1) 1129 /* 1130 * If we already have a silly name but there are more 1131 * than one links, just proceed with the NFS remove 1132 * request, as the bits will remain available (modulo 1133 * network races). This avoids silently ignoring the 1134 * attempted removal of a non-silly entry. 1135 */ 1136 goto doit; 1137 } else { 1138 doit: 1139 /* 1140 * Purge the name cache so that the chance of a lookup for 1141 * the name succeeding while the remove is in progress is 1142 * minimized. Without node locking it can still happen, such 1143 * that an I/O op returns ESTALE, but since you get this if 1144 * another host removes the file.. 1145 */ 1146 cache_purge(vp); 1147 /* 1148 * Throw away biocache buffers. Mainly to avoid 1149 * unnecessary delayed writes. 1150 */ 1151 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1); 1152 if (error == EINTR) 1153 return (error); 1154 /* Do the rpc */ 1155 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1156 nfsm_reqhead(dvp, NFSPROC_REMOVE, 1157 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 1158 nfsm_fhtom(dvp); 1159 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1160 nfsm_request(dvp, NFSPROC_REMOVE, cnp->cn_proc, cnp->cn_cred); 1161 nfsm_reqdone; 1162 FREE(cnp->cn_pnbuf, M_NAMEI); 1163 VTONFS(dvp)->n_flag |= NMODIFIED; 1164 VTONFS(dvp)->n_attrstamp = 0; 1165 /* 1166 * Kludge City: If the first reply to the remove rpc is lost.. 1167 * the reply to the retransmitted request will be ENOENT 1168 * since the file was in fact removed 1169 * Therefore, we cheat and return success. 1170 */ 1171 if (error == ENOENT) 1172 error = 0; 1173 } 1174 np->n_attrstamp = 0; 1175 vrele(dvp); 1176 vrele(vp); 1177 return (error); 1178 } 1179 1180 /* 1181 * nfs file remove rpc called from nfs_inactive 1182 */ 1183 int 1184 nfs_removeit(sp) 1185 register struct sillyrename *sp; 1186 { 1187 register u_long *tl; 1188 register caddr_t cp; 1189 register long t2; 1190 caddr_t bpos, dpos; 1191 int error = 0; 1192 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1193 1194 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1195 nfsm_reqhead(sp->s_dvp, NFSPROC_REMOVE, 1196 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(sp->s_namlen)); 1197 nfsm_fhtom(sp->s_dvp); 1198 nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN); 1199 nfsm_request(sp->s_dvp, NFSPROC_REMOVE, NULL, sp->s_cred); 1200 nfsm_reqdone; 1201 VTONFS(sp->s_dvp)->n_flag |= NMODIFIED; 1202 VTONFS(sp->s_dvp)->n_attrstamp = 0; 1203 return (error); 1204 } 1205 1206 /* 1207 * nfs file rename call 1208 */ 1209 int 1210 nfs_rename(ap) 1211 struct vop_rename_args /* { 1212 struct vnode *a_fdvp; 1213 struct vnode *a_fvp; 1214 struct componentname *a_fcnp; 1215 struct vnode *a_tdvp; 1216 struct vnode *a_tvp; 1217 struct componentname *a_tcnp; 1218 } */ *ap; 1219 { 1220 register struct vnode *fvp = ap->a_fvp; 1221 register struct vnode *tvp = ap->a_tvp; 1222 register struct vnode *fdvp = ap->a_fdvp; 1223 register struct vnode *tdvp = ap->a_tdvp; 1224 register struct componentname *tcnp = ap->a_tcnp; 1225 register struct componentname *fcnp = ap->a_fcnp; 1226 register u_long *tl; 1227 register caddr_t cp; 1228 register long t2; 1229 caddr_t bpos, dpos; 1230 int error = 0; 1231 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1232 1233 /* Check for cross-device rename */ 1234 if ((fvp->v_mount != tdvp->v_mount) || 1235 (tvp && (fvp->v_mount != tvp->v_mount))) { 1236 error = EXDEV; 1237 goto out; 1238 } 1239 1240 1241 nfsstats.rpccnt[NFSPROC_RENAME]++; 1242 nfsm_reqhead(fdvp, NFSPROC_RENAME, 1243 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(fcnp->cn_namelen)+ 1244 nfsm_rndup(fcnp->cn_namelen)); /* or fcnp->cn_cred?*/ 1245 nfsm_fhtom(fdvp); 1246 nfsm_strtom(fcnp->cn_nameptr, fcnp->cn_namelen, NFS_MAXNAMLEN); 1247 nfsm_fhtom(tdvp); 1248 nfsm_strtom(tcnp->cn_nameptr, tcnp->cn_namelen, NFS_MAXNAMLEN); 1249 nfsm_request(fdvp, NFSPROC_RENAME, tcnp->cn_proc, tcnp->cn_cred); 1250 nfsm_reqdone; 1251 VTONFS(fdvp)->n_flag |= NMODIFIED; 1252 VTONFS(fdvp)->n_attrstamp = 0; 1253 VTONFS(tdvp)->n_flag |= NMODIFIED; 1254 VTONFS(tdvp)->n_attrstamp = 0; 1255 if (fvp->v_type == VDIR) { 1256 if (tvp != NULL && tvp->v_type == VDIR) 1257 cache_purge(tdvp); 1258 cache_purge(fdvp); 1259 } 1260 out: 1261 if (tdvp == tvp) 1262 vrele(tdvp); 1263 else 1264 vput(tdvp); 1265 if (tvp) 1266 vput(tvp); 1267 vrele(fdvp); 1268 vrele(fvp); 1269 /* 1270 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1271 */ 1272 if (error == ENOENT) 1273 error = 0; 1274 return (error); 1275 } 1276 1277 /* 1278 * nfs file rename rpc called from nfs_remove() above 1279 */ 1280 int 1281 nfs_renameit(sdvp, scnp, sp) 1282 struct vnode *sdvp; 1283 struct componentname *scnp; 1284 register struct sillyrename *sp; 1285 { 1286 register u_long *tl; 1287 register caddr_t cp; 1288 register long t2; 1289 caddr_t bpos, dpos; 1290 int error = 0; 1291 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1292 1293 nfsstats.rpccnt[NFSPROC_RENAME]++; 1294 nfsm_reqhead(sdvp, NFSPROC_RENAME, 1295 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(scnp->cn_namelen)+ 1296 nfsm_rndup(sp->s_namlen)); 1297 nfsm_fhtom(sdvp); 1298 nfsm_strtom(scnp->cn_nameptr, scnp->cn_namelen, NFS_MAXNAMLEN); 1299 nfsm_fhtom(sdvp); 1300 nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN); 1301 nfsm_request(sdvp, NFSPROC_RENAME, scnp->cn_proc, scnp->cn_cred); 1302 nfsm_reqdone; 1303 FREE(scnp->cn_pnbuf, M_NAMEI); 1304 VTONFS(sdvp)->n_flag |= NMODIFIED; 1305 VTONFS(sdvp)->n_attrstamp = 0; 1306 return (error); 1307 } 1308 1309 /* 1310 * nfs hard link create call 1311 */ 1312 int 1313 nfs_link(ap) 1314 struct vop_link_args /* { 1315 struct vnode *a_vp; 1316 struct vnode *a_tdvp; 1317 struct componentname *a_cnp; 1318 } */ *ap; 1319 { 1320 register struct vnode *vp = ap->a_vp; 1321 register struct vnode *tdvp = ap->a_tdvp; 1322 register struct componentname *cnp = ap->a_cnp; 1323 register u_long *tl; 1324 register caddr_t cp; 1325 register long t2; 1326 caddr_t bpos, dpos; 1327 int error = 0; 1328 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1329 1330 if (vp->v_mount != tdvp->v_mount) { 1331 /*VOP_ABORTOP(vp, cnp);*/ 1332 if (tdvp == vp) 1333 vrele(vp); 1334 else 1335 vput(vp); 1336 return (EXDEV); 1337 } 1338 1339 /* 1340 * Push all writes to the server, so that the attribute cache 1341 * doesn't get "out of sync" with the server. 1342 * XXX There should be a better way! 1343 */ 1344 VOP_FSYNC(tdvp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc); 1345 1346 nfsstats.rpccnt[NFSPROC_LINK]++; 1347 nfsm_reqhead(tdvp, NFSPROC_LINK, 1348 NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 1349 nfsm_fhtom(tdvp); 1350 nfsm_fhtom(vp); 1351 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1352 nfsm_request(tdvp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); 1353 nfsm_reqdone; 1354 FREE(cnp->cn_pnbuf, M_NAMEI); 1355 VTONFS(tdvp)->n_attrstamp = 0; 1356 VTONFS(vp)->n_flag |= NMODIFIED; 1357 VTONFS(vp)->n_attrstamp = 0; 1358 vrele(vp); 1359 /* 1360 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1361 */ 1362 if (error == EEXIST) 1363 error = 0; 1364 return (error); 1365 } 1366 1367 /* 1368 * nfs symbolic link create call 1369 */ 1370 /* start here */ 1371 int 1372 nfs_symlink(ap) 1373 struct vop_symlink_args /* { 1374 struct vnode *a_dvp; 1375 struct vnode **a_vpp; 1376 struct componentname *a_cnp; 1377 struct vattr *a_vap; 1378 char *a_target; 1379 } */ *ap; 1380 { 1381 register struct vnode *dvp = ap->a_dvp; 1382 register struct vattr *vap = ap->a_vap; 1383 register struct componentname *cnp = ap->a_cnp; 1384 register struct nfsv2_sattr *sp; 1385 register u_long *tl; 1386 register caddr_t cp; 1387 register long t2; 1388 caddr_t bpos, dpos; 1389 int slen, error = 0, isnq; 1390 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1391 1392 nfsstats.rpccnt[NFSPROC_SYMLINK]++; 1393 slen = strlen(ap->a_target); 1394 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 1395 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH+2*NFSX_UNSIGNED+ 1396 nfsm_rndup(cnp->cn_namelen)+nfsm_rndup(slen)+NFSX_SATTR(isnq)); 1397 nfsm_fhtom(dvp); 1398 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1399 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN); 1400 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 1401 sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode); 1402 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1403 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 1404 if (isnq) { 1405 quad_t qval = -1; 1406 1407 txdr_hyper(&qval, &sp->sa_nqsize); 1408 sp->sa_nqflags = 0; 1409 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 1410 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 1411 } else { 1412 sp->sa_nfssize = -1; 1413 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 1414 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 1415 } 1416 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred); 1417 nfsm_reqdone; 1418 FREE(cnp->cn_pnbuf, M_NAMEI); 1419 VTONFS(dvp)->n_flag |= NMODIFIED; 1420 VTONFS(dvp)->n_attrstamp = 0; 1421 vrele(dvp); 1422 /* 1423 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1424 */ 1425 if (error == EEXIST) 1426 error = 0; 1427 return (error); 1428 } 1429 1430 /* 1431 * nfs make dir call 1432 */ 1433 int 1434 nfs_mkdir(ap) 1435 struct vop_mkdir_args /* { 1436 struct vnode *a_dvp; 1437 struct vnode **a_vpp; 1438 struct componentname *a_cnp; 1439 struct vattr *a_vap; 1440 } */ *ap; 1441 { 1442 register struct vnode *dvp = ap->a_dvp; 1443 register struct vattr *vap = ap->a_vap; 1444 register struct componentname *cnp = ap->a_cnp; 1445 register struct vnode **vpp = ap->a_vpp; 1446 register struct nfsv2_sattr *sp; 1447 register u_long *tl; 1448 register caddr_t cp; 1449 register long t1, t2; 1450 register int len; 1451 caddr_t bpos, dpos, cp2; 1452 int error = 0, firsttry = 1, isnq; 1453 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1454 struct vattr vattr; 1455 1456 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1457 VOP_ABORTOP(dvp, cnp); 1458 vput(dvp); 1459 return (error); 1460 } 1461 len = cnp->cn_namelen; 1462 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 1463 nfsstats.rpccnt[NFSPROC_MKDIR]++; 1464 nfsm_reqhead(dvp, NFSPROC_MKDIR, 1465 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)+NFSX_SATTR(isnq)); 1466 nfsm_fhtom(dvp); 1467 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1468 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 1469 sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode); 1470 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1471 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1472 if (isnq) { 1473 quad_t qval = -1; 1474 1475 txdr_hyper(&qval, &sp->sa_nqsize); 1476 sp->sa_nqflags = 0; 1477 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 1478 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 1479 } else { 1480 sp->sa_nfssize = -1; 1481 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 1482 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 1483 } 1484 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred); 1485 nfsm_mtofh(dvp, *vpp); 1486 nfsm_reqdone; 1487 VTONFS(dvp)->n_flag |= NMODIFIED; 1488 VTONFS(dvp)->n_attrstamp = 0; 1489 /* 1490 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 1491 * if we can succeed in looking up the directory. 1492 * "firsttry" is necessary since the macros may "goto nfsmout" which 1493 * is above the if on errors. (Ugh) 1494 */ 1495 if (error == EEXIST && firsttry) { 1496 firsttry = 0; 1497 error = 0; 1498 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 1499 *vpp = NULL; 1500 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 1501 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 1502 nfsm_fhtom(dvp); 1503 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1504 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 1505 nfsm_mtofh(dvp, *vpp); 1506 if ((*vpp)->v_type != VDIR) { 1507 vput(*vpp); 1508 error = EEXIST; 1509 } 1510 m_freem(mrep); 1511 } 1512 FREE(cnp->cn_pnbuf, M_NAMEI); 1513 vrele(dvp); 1514 return (error); 1515 } 1516 1517 /* 1518 * nfs remove directory call 1519 */ 1520 int 1521 nfs_rmdir(ap) 1522 struct vop_rmdir_args /* { 1523 struct vnode *a_dvp; 1524 struct vnode *a_vp; 1525 struct componentname *a_cnp; 1526 } */ *ap; 1527 { 1528 register struct vnode *vp = ap->a_vp; 1529 register struct vnode *dvp = ap->a_dvp; 1530 register struct componentname *cnp = ap->a_cnp; 1531 register u_long *tl; 1532 register caddr_t cp; 1533 register long t2; 1534 caddr_t bpos, dpos; 1535 int error = 0; 1536 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1537 1538 if (dvp == vp) { 1539 vrele(dvp); 1540 vrele(dvp); 1541 FREE(cnp->cn_pnbuf, M_NAMEI); 1542 return (EINVAL); 1543 } 1544 nfsstats.rpccnt[NFSPROC_RMDIR]++; 1545 nfsm_reqhead(dvp, NFSPROC_RMDIR, 1546 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 1547 nfsm_fhtom(dvp); 1548 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1549 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred); 1550 nfsm_reqdone; 1551 FREE(cnp->cn_pnbuf, M_NAMEI); 1552 VTONFS(dvp)->n_flag |= NMODIFIED; 1553 VTONFS(dvp)->n_attrstamp = 0; 1554 cache_purge(dvp); 1555 cache_purge(vp); 1556 vrele(vp); 1557 vrele(dvp); 1558 /* 1559 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 1560 */ 1561 if (error == ENOENT) 1562 error = 0; 1563 return (error); 1564 } 1565 1566 /* 1567 * nfs readdir call 1568 * Although cookie is defined as opaque, I translate it to/from net byte 1569 * order so that it looks more sensible. This appears consistent with the 1570 * Ultrix implementation of NFS. 1571 */ 1572 int 1573 nfs_readdir(ap) 1574 struct vop_readdir_args /* { 1575 struct vnode *a_vp; 1576 struct uio *a_uio; 1577 struct ucred *a_cred; 1578 int *a_eofflag; 1579 u_long *a_cookies; 1580 int a_ncookies; 1581 } */ *ap; 1582 { 1583 register struct vnode *vp = ap->a_vp; 1584 register struct nfsnode *np = VTONFS(vp); 1585 register struct uio *uio = ap->a_uio; 1586 int tresid, error; 1587 struct vattr vattr; 1588 1589 /* 1590 * We don't allow exporting NFS mounts, and currently local requests 1591 * do not need cookies. 1592 */ 1593 if (ap->a_ncookies) 1594 panic("nfs_readdir: not hungry"); 1595 1596 if (vp->v_type != VDIR) 1597 return (EPERM); 1598 /* 1599 * First, check for hit on the EOF offset cache 1600 */ 1601 if (uio->uio_offset != 0 && uio->uio_offset == np->n_direofoffset && 1602 (np->n_flag & NMODIFIED) == 0) { 1603 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { 1604 if (NQNFS_CKCACHABLE(vp, NQL_READ)) { 1605 nfsstats.direofcache_hits++; 1606 return (0); 1607 } 1608 } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 && 1609 np->n_mtime == vattr.va_mtime.ts_sec) { 1610 nfsstats.direofcache_hits++; 1611 return (0); 1612 } 1613 } 1614 1615 /* 1616 * Call nfs_bioread() to do the real work. 1617 */ 1618 tresid = uio->uio_resid; 1619 error = nfs_bioread(vp, uio, 0, ap->a_cred); 1620 1621 if (!error && uio->uio_resid == tresid) 1622 nfsstats.direofcache_misses++; 1623 return (error); 1624 } 1625 1626 /* 1627 * Readdir rpc call. 1628 * Called from below the buffer cache by nfs_doio(). 1629 */ 1630 int 1631 nfs_readdirrpc(vp, uiop, cred) 1632 register struct vnode *vp; 1633 struct uio *uiop; 1634 struct ucred *cred; 1635 { 1636 register long len; 1637 register struct dirent *dp; 1638 register u_long *tl; 1639 register caddr_t cp; 1640 register long t1; 1641 long tlen, lastlen; 1642 caddr_t bpos, dpos, cp2; 1643 int error = 0; 1644 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1645 struct mbuf *md2; 1646 caddr_t dpos2; 1647 int siz; 1648 int more_dirs = 1; 1649 u_long off, savoff; 1650 struct dirent *savdp; 1651 struct nfsmount *nmp; 1652 struct nfsnode *np = VTONFS(vp); 1653 long tresid, extra; 1654 1655 nmp = VFSTONFS(vp->v_mount); 1656 extra = uiop->uio_resid & (NFS_DIRBLKSIZ - 1); 1657 uiop->uio_resid -= extra; 1658 tresid = uiop->uio_resid; 1659 /* 1660 * Loop around doing readdir rpc's of size uio_resid or nm_rsize, 1661 * whichever is smaller, truncated to a multiple of NFS_DIRBLKSIZ. 1662 * The stopping criteria is EOF or buffer full. 1663 */ 1664 while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) { 1665 nfsstats.rpccnt[NFSPROC_READDIR]++; 1666 nfsm_reqhead(vp, NFSPROC_READDIR, 1667 NFSX_FH + 2 * NFSX_UNSIGNED); 1668 nfsm_fhtom(vp); 1669 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 1670 off = (u_long)uiop->uio_offset; 1671 *tl++ = txdr_unsigned(off); 1672 *tl = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ? 1673 nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1)); 1674 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred); 1675 siz = 0; 1676 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1677 more_dirs = fxdr_unsigned(int, *tl); 1678 1679 /* Save the position so that we can do nfsm_mtouio() later */ 1680 dpos2 = dpos; 1681 md2 = md; 1682 1683 /* loop thru the dir entries, doctoring them to 4bsd form */ 1684 #ifdef lint 1685 dp = (struct dirent *)0; 1686 #endif /* lint */ 1687 while (more_dirs && siz < uiop->uio_resid) { 1688 savoff = off; /* Hold onto offset and dp */ 1689 savdp = dp; 1690 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1691 dp = (struct dirent *)tl; 1692 dp->d_fileno = fxdr_unsigned(u_long, *tl++); 1693 len = fxdr_unsigned(int, *tl); 1694 if (len <= 0 || len > NFS_MAXNAMLEN) { 1695 error = EBADRPC; 1696 m_freem(mrep); 1697 goto nfsmout; 1698 } 1699 dp->d_namlen = (u_char)len; 1700 dp->d_type = DT_UNKNOWN; 1701 nfsm_adv(len); /* Point past name */ 1702 tlen = nfsm_rndup(len); 1703 /* 1704 * This should not be necessary, but some servers have 1705 * broken XDR such that these bytes are not null filled. 1706 */ 1707 if (tlen != len) { 1708 *dpos = '\0'; /* Null-terminate */ 1709 nfsm_adv(tlen - len); 1710 len = tlen; 1711 } 1712 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1713 off = fxdr_unsigned(u_long, *tl); 1714 *tl++ = 0; /* Ensures null termination of name */ 1715 more_dirs = fxdr_unsigned(int, *tl); 1716 dp->d_reclen = len + 4 * NFSX_UNSIGNED; 1717 siz += dp->d_reclen; 1718 } 1719 /* 1720 * If at end of rpc data, get the eof boolean 1721 */ 1722 if (!more_dirs) { 1723 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1724 more_dirs = (fxdr_unsigned(int, *tl) == 0); 1725 1726 /* 1727 * If at EOF, cache directory offset 1728 */ 1729 if (!more_dirs) 1730 np->n_direofoffset = off; 1731 } 1732 /* 1733 * If there is too much to fit in the data buffer, use savoff and 1734 * savdp to trim off the last record. 1735 * --> we are not at eof 1736 */ 1737 if (siz > uiop->uio_resid) { 1738 off = savoff; 1739 siz -= dp->d_reclen; 1740 dp = savdp; 1741 more_dirs = 0; /* Paranoia */ 1742 } 1743 if (siz > 0) { 1744 lastlen = dp->d_reclen; 1745 md = md2; 1746 dpos = dpos2; 1747 nfsm_mtouio(uiop, siz); 1748 uiop->uio_offset = (off_t)off; 1749 } else 1750 more_dirs = 0; /* Ugh, never happens, but in case.. */ 1751 m_freem(mrep); 1752 } 1753 /* 1754 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 1755 * by increasing d_reclen for the last record. 1756 */ 1757 if (uiop->uio_resid < tresid) { 1758 len = uiop->uio_resid & (NFS_DIRBLKSIZ - 1); 1759 if (len > 0) { 1760 dp = (struct dirent *) 1761 (uiop->uio_iov->iov_base - lastlen); 1762 dp->d_reclen += len; 1763 uiop->uio_iov->iov_base += len; 1764 uiop->uio_iov->iov_len -= len; 1765 uiop->uio_resid -= len; 1766 } 1767 } 1768 nfsmout: 1769 uiop->uio_resid += extra; 1770 return (error); 1771 } 1772 1773 /* 1774 * Nqnfs readdir_and_lookup RPC. Used in place of nfs_readdirrpc(). 1775 */ 1776 int 1777 nfs_readdirlookrpc(vp, uiop, cred) 1778 struct vnode *vp; 1779 register struct uio *uiop; 1780 struct ucred *cred; 1781 { 1782 register int len; 1783 register struct dirent *dp; 1784 register u_long *tl; 1785 register caddr_t cp; 1786 register long t1; 1787 caddr_t bpos, dpos, cp2; 1788 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1789 struct nameidata nami, *ndp = &nami; 1790 struct componentname *cnp = &ndp->ni_cnd; 1791 u_long off, endoff, fileno; 1792 time_t reqtime, ltime; 1793 struct nfsmount *nmp; 1794 struct nfsnode *np; 1795 struct vnode *newvp; 1796 nfsv2fh_t *fhp; 1797 u_quad_t frev; 1798 int error = 0, tlen, more_dirs = 1, tresid, doit, bigenough, i; 1799 int cachable; 1800 1801 if (uiop->uio_iovcnt != 1) 1802 panic("nfs rdirlook"); 1803 nmp = VFSTONFS(vp->v_mount); 1804 tresid = uiop->uio_resid; 1805 ndp->ni_dvp = vp; 1806 newvp = NULLVP; 1807 /* 1808 * Loop around doing readdir rpc's of size uio_resid or nm_rsize, 1809 * whichever is smaller, truncated to a multiple of NFS_DIRBLKSIZ. 1810 * The stopping criteria is EOF or buffer full. 1811 */ 1812 while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) { 1813 nfsstats.rpccnt[NQNFSPROC_READDIRLOOK]++; 1814 nfsm_reqhead(vp, NQNFSPROC_READDIRLOOK, 1815 NFSX_FH + 3 * NFSX_UNSIGNED); 1816 nfsm_fhtom(vp); 1817 nfsm_build(tl, u_long *, 3 * NFSX_UNSIGNED); 1818 off = (u_long)uiop->uio_offset; 1819 *tl++ = txdr_unsigned(off); 1820 *tl++ = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ? 1821 nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1)); 1822 if (nmp->nm_flag & NFSMNT_NQLOOKLEASE) 1823 *tl = txdr_unsigned(nmp->nm_leaseterm); 1824 else 1825 *tl = 0; 1826 reqtime = time.tv_sec; 1827 nfsm_request(vp, NQNFSPROC_READDIRLOOK, uiop->uio_procp, cred); 1828 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1829 more_dirs = fxdr_unsigned(int, *tl); 1830 1831 /* loop thru the dir entries, doctoring them to 4bsd form */ 1832 bigenough = 1; 1833 while (more_dirs && bigenough) { 1834 doit = 1; 1835 nfsm_dissect(tl, u_long *, 4 * NFSX_UNSIGNED); 1836 if (nmp->nm_flag & NFSMNT_NQLOOKLEASE) { 1837 cachable = fxdr_unsigned(int, *tl++); 1838 ltime = reqtime + fxdr_unsigned(int, *tl++); 1839 fxdr_hyper(tl, &frev); 1840 } 1841 nfsm_dissect(fhp, nfsv2fh_t *, NFSX_FH); 1842 if (!bcmp(VTONFS(vp)->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 1843 VREF(vp); 1844 newvp = vp; 1845 np = VTONFS(vp); 1846 } else { 1847 if (error = nfs_nget(vp->v_mount, fhp, &np)) 1848 doit = 0; 1849 newvp = NFSTOV(np); 1850 } 1851 if (error = nfs_loadattrcache(&newvp, &md, &dpos, 1852 (struct vattr *)0)) 1853 doit = 0; 1854 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1855 fileno = fxdr_unsigned(u_long, *tl++); 1856 len = fxdr_unsigned(int, *tl); 1857 if (len <= 0 || len > NFS_MAXNAMLEN) { 1858 error = EBADRPC; 1859 m_freem(mrep); 1860 goto nfsmout; 1861 } 1862 tlen = (len + 4) & ~0x3; 1863 if ((tlen + DIRHDSIZ) > uiop->uio_resid) 1864 bigenough = 0; 1865 if (bigenough && doit) { 1866 dp = (struct dirent *)uiop->uio_iov->iov_base; 1867 dp->d_fileno = fileno; 1868 dp->d_namlen = len; 1869 dp->d_reclen = tlen + DIRHDSIZ; 1870 dp->d_type = 1871 IFTODT(VTTOIF(np->n_vattr.va_type)); 1872 uiop->uio_resid -= DIRHDSIZ; 1873 uiop->uio_iov->iov_base += DIRHDSIZ; 1874 uiop->uio_iov->iov_len -= DIRHDSIZ; 1875 cnp->cn_nameptr = uiop->uio_iov->iov_base; 1876 cnp->cn_namelen = len; 1877 ndp->ni_vp = newvp; 1878 nfsm_mtouio(uiop, len); 1879 cp = uiop->uio_iov->iov_base; 1880 tlen -= len; 1881 for (i = 0; i < tlen; i++) 1882 *cp++ = '\0'; 1883 uiop->uio_iov->iov_base += tlen; 1884 uiop->uio_iov->iov_len -= tlen; 1885 uiop->uio_resid -= tlen; 1886 cnp->cn_hash = 0; 1887 for (cp = cnp->cn_nameptr, i = 1; i <= len; i++, cp++) 1888 cnp->cn_hash += (unsigned char)*cp * i; 1889 if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) && 1890 ltime > time.tv_sec) 1891 nqnfs_clientlease(nmp, np, NQL_READ, 1892 cachable, ltime, frev); 1893 if (cnp->cn_namelen <= NCHNAMLEN) 1894 cache_enter(ndp->ni_dvp, ndp->ni_vp, cnp); 1895 } else { 1896 nfsm_adv(nfsm_rndup(len)); 1897 } 1898 if (newvp != NULLVP) { 1899 vrele(newvp); 1900 newvp = NULLVP; 1901 } 1902 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1903 if (bigenough) 1904 endoff = off = fxdr_unsigned(u_long, *tl++); 1905 else 1906 endoff = fxdr_unsigned(u_long, *tl++); 1907 more_dirs = fxdr_unsigned(int, *tl); 1908 } 1909 /* 1910 * If at end of rpc data, get the eof boolean 1911 */ 1912 if (!more_dirs) { 1913 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1914 more_dirs = (fxdr_unsigned(int, *tl) == 0); 1915 1916 /* 1917 * If at EOF, cache directory offset 1918 */ 1919 if (!more_dirs) 1920 VTONFS(vp)->n_direofoffset = endoff; 1921 } 1922 if (uiop->uio_resid < tresid) 1923 uiop->uio_offset = (off_t)off; 1924 else 1925 more_dirs = 0; 1926 m_freem(mrep); 1927 } 1928 /* 1929 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 1930 * by increasing d_reclen for the last record. 1931 */ 1932 if (uiop->uio_resid < tresid) { 1933 len = uiop->uio_resid & (NFS_DIRBLKSIZ - 1); 1934 if (len > 0) { 1935 dp->d_reclen += len; 1936 uiop->uio_iov->iov_base += len; 1937 uiop->uio_iov->iov_len -= len; 1938 uiop->uio_resid -= len; 1939 } 1940 } 1941 nfsmout: 1942 if (newvp != NULLVP) 1943 vrele(newvp); 1944 return (error); 1945 } 1946 static char hextoasc[] = "0123456789abcdef"; 1947 1948 /* 1949 * Silly rename. To make the NFS filesystem that is stateless look a little 1950 * more like the "ufs" a remove of an active vnode is translated to a rename 1951 * to a funny looking filename that is removed by nfs_inactive on the 1952 * nfsnode. There is the potential for another process on a different client 1953 * to create the same funny name between the nfs_lookitup() fails and the 1954 * nfs_rename() completes, but... 1955 */ 1956 int 1957 nfs_sillyrename(dvp, vp, cnp) 1958 struct vnode *dvp, *vp; 1959 struct componentname *cnp; 1960 { 1961 register struct nfsnode *np; 1962 register struct sillyrename *sp; 1963 int error; 1964 short pid; 1965 1966 cache_purge(dvp); 1967 np = VTONFS(vp); 1968 #ifdef SILLYSEPARATE 1969 MALLOC(sp, struct sillyrename *, sizeof (struct sillyrename), 1970 M_NFSREQ, M_WAITOK); 1971 #else 1972 sp = &np->n_silly; 1973 #endif 1974 sp->s_cred = crdup(cnp->cn_cred); 1975 sp->s_dvp = dvp; 1976 VREF(dvp); 1977 1978 /* Fudge together a funny name */ 1979 pid = cnp->cn_proc->p_pid; 1980 bcopy(".nfsAxxxx4.4", sp->s_name, 13); 1981 sp->s_namlen = 12; 1982 sp->s_name[8] = hextoasc[pid & 0xf]; 1983 sp->s_name[7] = hextoasc[(pid >> 4) & 0xf]; 1984 sp->s_name[6] = hextoasc[(pid >> 8) & 0xf]; 1985 sp->s_name[5] = hextoasc[(pid >> 12) & 0xf]; 1986 1987 /* Try lookitups until we get one that isn't there */ 1988 while (nfs_lookitup(sp, (nfsv2fh_t *)0, cnp->cn_proc) == 0) { 1989 sp->s_name[4]++; 1990 if (sp->s_name[4] > 'z') { 1991 error = EINVAL; 1992 goto bad; 1993 } 1994 } 1995 if (error = nfs_renameit(dvp, cnp, sp)) 1996 goto bad; 1997 nfs_lookitup(sp, &np->n_fh, cnp->cn_proc); 1998 np->n_sillyrename = sp; 1999 return (0); 2000 bad: 2001 vrele(sp->s_dvp); 2002 crfree(sp->s_cred); 2003 #ifdef SILLYSEPARATE 2004 free((caddr_t)sp, M_NFSREQ); 2005 #endif 2006 return (error); 2007 } 2008 2009 /* 2010 * Look up a file name for silly rename stuff. 2011 * Just like nfs_lookup() except that it doesn't load returned values 2012 * into the nfsnode table. 2013 * If fhp != NULL it copies the returned file handle out 2014 */ 2015 int 2016 nfs_lookitup(sp, fhp, procp) 2017 register struct sillyrename *sp; 2018 nfsv2fh_t *fhp; 2019 struct proc *procp; 2020 { 2021 register struct vnode *vp = sp->s_dvp; 2022 register u_long *tl; 2023 register caddr_t cp; 2024 register long t1, t2; 2025 caddr_t bpos, dpos, cp2; 2026 int error = 0, isnq; 2027 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 2028 long len; 2029 2030 isnq = (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS); 2031 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 2032 len = sp->s_namlen; 2033 nfsm_reqhead(vp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 2034 if (isnq) { 2035 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 2036 *tl = 0; 2037 } 2038 nfsm_fhtom(vp); 2039 nfsm_strtom(sp->s_name, len, NFS_MAXNAMLEN); 2040 nfsm_request(vp, NFSPROC_LOOKUP, procp, sp->s_cred); 2041 if (fhp != NULL) { 2042 if (isnq) 2043 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 2044 nfsm_dissect(cp, caddr_t, NFSX_FH); 2045 bcopy(cp, (caddr_t)fhp, NFSX_FH); 2046 } 2047 nfsm_reqdone; 2048 return (error); 2049 } 2050 2051 /* 2052 * Kludge City.. 2053 * - make nfs_bmap() essentially a no-op that does no translation 2054 * - do nfs_strategy() by faking physical I/O with nfs_readrpc/nfs_writerpc 2055 * after mapping the physical addresses into Kernel Virtual space in the 2056 * nfsiobuf area. 2057 * (Maybe I could use the process's page mapping, but I was concerned that 2058 * Kernel Write might not be enabled and also figured copyout() would do 2059 * a lot more work than bcopy() and also it currently happens in the 2060 * context of the swapper process (2). 2061 */ 2062 int 2063 nfs_bmap(ap) 2064 struct vop_bmap_args /* { 2065 struct vnode *a_vp; 2066 daddr_t a_bn; 2067 struct vnode **a_vpp; 2068 daddr_t *a_bnp; 2069 int *a_runp; 2070 } */ *ap; 2071 { 2072 register struct vnode *vp = ap->a_vp; 2073 2074 if (ap->a_vpp != NULL) 2075 *ap->a_vpp = vp; 2076 if (ap->a_bnp != NULL) 2077 *ap->a_bnp = ap->a_bn * btodb(vp->v_mount->mnt_stat.f_iosize); 2078 return (0); 2079 } 2080 2081 /* 2082 * Strategy routine. 2083 * For async requests when nfsiod(s) are running, queue the request by 2084 * calling nfs_asyncio(), otherwise just all nfs_doio() to do the 2085 * request. 2086 */ 2087 int 2088 nfs_strategy(ap) 2089 struct vop_strategy_args *ap; 2090 { 2091 register struct buf *bp = ap->a_bp; 2092 struct ucred *cr; 2093 struct proc *p; 2094 int error = 0; 2095 2096 if ((bp->b_flags & (B_PHYS|B_ASYNC)) == (B_PHYS|B_ASYNC)) 2097 panic("nfs physio/async"); 2098 if (bp->b_flags & B_ASYNC) 2099 p = (struct proc *)0; 2100 else 2101 p = curproc; /* XXX */ 2102 if (bp->b_flags & B_READ) 2103 cr = bp->b_rcred; 2104 else 2105 cr = bp->b_wcred; 2106 /* 2107 * If the op is asynchronous and an i/o daemon is waiting 2108 * queue the request, wake it up and wait for completion 2109 * otherwise just do it ourselves. 2110 */ 2111 if ((bp->b_flags & B_ASYNC) == 0 || 2112 nfs_asyncio(bp, NOCRED)) 2113 error = nfs_doio(bp, cr, p); 2114 return (error); 2115 } 2116 2117 /* 2118 * Mmap a file 2119 * 2120 * NB Currently unsupported. 2121 */ 2122 /* ARGSUSED */ 2123 int 2124 nfs_mmap(ap) 2125 struct vop_mmap_args /* { 2126 struct vnode *a_vp; 2127 int a_fflags; 2128 struct ucred *a_cred; 2129 struct proc *a_p; 2130 } */ *ap; 2131 { 2132 2133 return (EINVAL); 2134 } 2135 2136 /* 2137 * Flush all the blocks associated with a vnode. 2138 * Walk through the buffer pool and push any dirty pages 2139 * associated with the vnode. 2140 */ 2141 /* ARGSUSED */ 2142 int 2143 nfs_fsync(ap) 2144 struct vop_fsync_args /* { 2145 struct vnodeop_desc *a_desc; 2146 struct vnode * a_vp; 2147 struct ucred * a_cred; 2148 int a_waitfor; 2149 struct proc * a_p; 2150 } */ *ap; 2151 { 2152 register struct vnode *vp = ap->a_vp; 2153 register struct nfsnode *np = VTONFS(vp); 2154 register struct buf *bp; 2155 struct buf *nbp; 2156 struct nfsmount *nmp; 2157 int s, error = 0, slptimeo = 0, slpflag = 0; 2158 2159 nmp = VFSTONFS(vp->v_mount); 2160 if (nmp->nm_flag & NFSMNT_INT) 2161 slpflag = PCATCH; 2162 loop: 2163 s = splbio(); 2164 for (bp = vp->v_dirtyblkhd.lh_first; bp; bp = nbp) { 2165 nbp = bp->b_vnbufs.le_next; 2166 if (bp->b_flags & B_BUSY) { 2167 if (ap->a_waitfor != MNT_WAIT) 2168 continue; 2169 bp->b_flags |= B_WANTED; 2170 error = tsleep((caddr_t)bp, slpflag | (PRIBIO + 1), 2171 "nfsfsync", slptimeo); 2172 splx(s); 2173 if (error) { 2174 if (nfs_sigintr(nmp, (struct nfsreq *)0, ap->a_p)) 2175 return (EINTR); 2176 if (slpflag == PCATCH) { 2177 slpflag = 0; 2178 slptimeo = 2 * hz; 2179 } 2180 } 2181 goto loop; 2182 } 2183 if ((bp->b_flags & B_DELWRI) == 0) 2184 panic("nfs_fsync: not dirty"); 2185 bremfree(bp); 2186 bp->b_flags |= B_BUSY; 2187 splx(s); 2188 bp->b_flags |= B_ASYNC; 2189 VOP_BWRITE(bp); 2190 goto loop; 2191 } 2192 splx(s); 2193 if (ap->a_waitfor == MNT_WAIT) { 2194 while (vp->v_numoutput) { 2195 vp->v_flag |= VBWAIT; 2196 error = tsleep((caddr_t)&vp->v_numoutput, 2197 slpflag | (PRIBIO + 1), "nfsfsync", slptimeo); 2198 if (error) { 2199 if (nfs_sigintr(nmp, (struct nfsreq *)0, ap->a_p)) 2200 return (EINTR); 2201 if (slpflag == PCATCH) { 2202 slpflag = 0; 2203 slptimeo = 2 * hz; 2204 } 2205 } 2206 } 2207 if (vp->v_dirtyblkhd.lh_first) { 2208 #ifdef DIAGNOSTIC 2209 vprint("nfs_fsync: dirty", vp); 2210 #endif 2211 goto loop; 2212 } 2213 } 2214 if (np->n_flag & NWRITEERR) { 2215 error = np->n_error; 2216 np->n_flag &= ~NWRITEERR; 2217 } 2218 return (error); 2219 } 2220 2221 /* 2222 * Return POSIX pathconf information applicable to nfs. 2223 * 2224 * Currently the NFS protocol does not support getting such 2225 * information from the remote server. 2226 */ 2227 /* ARGSUSED */ 2228 nfs_pathconf(ap) 2229 struct vop_pathconf_args /* { 2230 struct vnode *a_vp; 2231 int a_name; 2232 register_t *a_retval; 2233 } */ *ap; 2234 { 2235 2236 return (EINVAL); 2237 } 2238 2239 /* 2240 * NFS advisory byte-level locks. 2241 */ 2242 int 2243 nfs_advlock(ap) 2244 struct vop_advlock_args /* { 2245 struct vnode *a_vp; 2246 caddr_t a_id; 2247 int a_op; 2248 struct flock *a_fl; 2249 int a_flags; 2250 } */ *ap; 2251 { 2252 register struct nfsnode *np = VTONFS(ap->a_vp); 2253 2254 return (lf_advlock(&np->n_lockf, np->n_size, ap->a_id, ap->a_op, 2255 ap->a_fl, ap->a_flags)); 2256 } 2257 2258 /* 2259 * Print out the contents of an nfsnode. 2260 */ 2261 int 2262 nfs_print(ap) 2263 struct vop_print_args /* { 2264 struct vnode *a_vp; 2265 } */ *ap; 2266 { 2267 register struct vnode *vp = ap->a_vp; 2268 register struct nfsnode *np = VTONFS(vp); 2269 2270 printf("tag VT_NFS, fileid %d fsid 0x%x", 2271 np->n_vattr.va_fileid, np->n_vattr.va_fsid); 2272 #ifdef FIFO 2273 if (vp->v_type == VFIFO) 2274 fifo_printinfo(vp); 2275 #endif /* FIFO */ 2276 printf("\n"); 2277 } 2278 2279 /* 2280 * NFS directory offset lookup. 2281 * Currently unsupported. 2282 */ 2283 int 2284 nfs_blkatoff(ap) 2285 struct vop_blkatoff_args /* { 2286 struct vnode *a_vp; 2287 off_t a_offset; 2288 char **a_res; 2289 struct buf **a_bpp; 2290 } */ *ap; 2291 { 2292 2293 return (EOPNOTSUPP); 2294 } 2295 2296 /* 2297 * NFS flat namespace allocation. 2298 * Currently unsupported. 2299 */ 2300 int 2301 nfs_valloc(ap) 2302 struct vop_valloc_args /* { 2303 struct vnode *a_pvp; 2304 int a_mode; 2305 struct ucred *a_cred; 2306 struct vnode **a_vpp; 2307 } */ *ap; 2308 { 2309 2310 return (EOPNOTSUPP); 2311 } 2312 2313 /* 2314 * NFS flat namespace free. 2315 * Currently unsupported. 2316 */ 2317 int 2318 nfs_vfree(ap) 2319 struct vop_vfree_args /* { 2320 struct vnode *a_pvp; 2321 ino_t a_ino; 2322 int a_mode; 2323 } */ *ap; 2324 { 2325 2326 return (EOPNOTSUPP); 2327 } 2328 2329 /* 2330 * NFS file truncation. 2331 */ 2332 int 2333 nfs_truncate(ap) 2334 struct vop_truncate_args /* { 2335 struct vnode *a_vp; 2336 off_t a_length; 2337 int a_flags; 2338 struct ucred *a_cred; 2339 struct proc *a_p; 2340 } */ *ap; 2341 { 2342 2343 /* Use nfs_setattr */ 2344 printf("nfs_truncate: need to implement!!"); 2345 return (EOPNOTSUPP); 2346 } 2347 2348 /* 2349 * NFS update. 2350 */ 2351 int 2352 nfs_update(ap) 2353 struct vop_update_args /* { 2354 struct vnode *a_vp; 2355 struct timeval *a_ta; 2356 struct timeval *a_tm; 2357 int a_waitfor; 2358 } */ *ap; 2359 { 2360 2361 /* Use nfs_setattr */ 2362 printf("nfs_update: need to implement!!"); 2363 return (EOPNOTSUPP); 2364 } 2365 2366 /* 2367 * nfs special file access vnode op. 2368 * Essentially just get vattr and then imitate iaccess() since the device is 2369 * local to the client. 2370 */ 2371 int 2372 nfsspec_access(ap) 2373 struct vop_access_args /* { 2374 struct vnode *a_vp; 2375 int a_mode; 2376 struct ucred *a_cred; 2377 struct proc *a_p; 2378 } */ *ap; 2379 { 2380 struct vattr va; 2381 int error; 2382 2383 if (error = VOP_GETATTR(ap->a_vp, &va, ap->a_cred, ap->a_p)) 2384 return (error); 2385 2386 return (vaccess(va.va_mode, va.va_uid, va.va_gid, ap->a_mode, 2387 ap->a_cred)); 2388 } 2389 2390 /* 2391 * Read wrapper for special devices. 2392 */ 2393 int 2394 nfsspec_read(ap) 2395 struct vop_read_args /* { 2396 struct vnode *a_vp; 2397 struct uio *a_uio; 2398 int a_ioflag; 2399 struct ucred *a_cred; 2400 } */ *ap; 2401 { 2402 register struct nfsnode *np = VTONFS(ap->a_vp); 2403 2404 /* 2405 * Set access flag. 2406 */ 2407 np->n_flag |= NACC; 2408 np->n_atim = time; 2409 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap)); 2410 } 2411 2412 /* 2413 * Write wrapper for special devices. 2414 */ 2415 int 2416 nfsspec_write(ap) 2417 struct vop_write_args /* { 2418 struct vnode *a_vp; 2419 struct uio *a_uio; 2420 int a_ioflag; 2421 struct ucred *a_cred; 2422 } */ *ap; 2423 { 2424 register struct nfsnode *np = VTONFS(ap->a_vp); 2425 2426 /* 2427 * Set update flag. 2428 */ 2429 np->n_flag |= NUPD; 2430 np->n_mtim = time; 2431 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap)); 2432 } 2433 2434 /* 2435 * Close wrapper for special devices. 2436 * 2437 * Update the times on the nfsnode then do device close. 2438 */ 2439 int 2440 nfsspec_close(ap) 2441 struct vop_close_args /* { 2442 struct vnode *a_vp; 2443 int a_fflag; 2444 struct ucred *a_cred; 2445 struct proc *a_p; 2446 } */ *ap; 2447 { 2448 register struct vnode *vp = ap->a_vp; 2449 register struct nfsnode *np = VTONFS(vp); 2450 struct vattr vattr; 2451 2452 if (np->n_flag & (NACC | NUPD)) { 2453 np->n_flag |= NCHG; 2454 if (vp->v_usecount == 1 && 2455 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 2456 VATTR_NULL(&vattr); 2457 if (np->n_flag & NACC) { 2458 vattr.va_atime.ts_sec = np->n_atim.tv_sec; 2459 vattr.va_atime.ts_nsec = 2460 np->n_atim.tv_usec * 1000; 2461 } 2462 if (np->n_flag & NUPD) { 2463 vattr.va_mtime.ts_sec = np->n_mtim.tv_sec; 2464 vattr.va_mtime.ts_nsec = 2465 np->n_mtim.tv_usec * 1000; 2466 } 2467 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 2468 } 2469 } 2470 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 2471 } 2472 2473 #ifdef FIFO 2474 /* 2475 * Read wrapper for fifos. 2476 */ 2477 int 2478 nfsfifo_read(ap) 2479 struct vop_read_args /* { 2480 struct vnode *a_vp; 2481 struct uio *a_uio; 2482 int a_ioflag; 2483 struct ucred *a_cred; 2484 } */ *ap; 2485 { 2486 extern int (**fifo_vnodeop_p)(); 2487 register struct nfsnode *np = VTONFS(ap->a_vp); 2488 2489 /* 2490 * Set access flag. 2491 */ 2492 np->n_flag |= NACC; 2493 np->n_atim = time; 2494 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap)); 2495 } 2496 2497 /* 2498 * Write wrapper for fifos. 2499 */ 2500 int 2501 nfsfifo_write(ap) 2502 struct vop_write_args /* { 2503 struct vnode *a_vp; 2504 struct uio *a_uio; 2505 int a_ioflag; 2506 struct ucred *a_cred; 2507 } */ *ap; 2508 { 2509 extern int (**fifo_vnodeop_p)(); 2510 register struct nfsnode *np = VTONFS(ap->a_vp); 2511 2512 /* 2513 * Set update flag. 2514 */ 2515 np->n_flag |= NUPD; 2516 np->n_mtim = time; 2517 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap)); 2518 } 2519 2520 /* 2521 * Close wrapper for fifos. 2522 * 2523 * Update the times on the nfsnode then do fifo close. 2524 */ 2525 int 2526 nfsfifo_close(ap) 2527 struct vop_close_args /* { 2528 struct vnode *a_vp; 2529 int a_fflag; 2530 struct ucred *a_cred; 2531 struct proc *a_p; 2532 } */ *ap; 2533 { 2534 register struct vnode *vp = ap->a_vp; 2535 register struct nfsnode *np = VTONFS(vp); 2536 struct vattr vattr; 2537 extern int (**fifo_vnodeop_p)(); 2538 2539 if (np->n_flag & (NACC | NUPD)) { 2540 if (np->n_flag & NACC) 2541 np->n_atim = time; 2542 if (np->n_flag & NUPD) 2543 np->n_mtim = time; 2544 np->n_flag |= NCHG; 2545 if (vp->v_usecount == 1 && 2546 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 2547 VATTR_NULL(&vattr); 2548 if (np->n_flag & NACC) { 2549 vattr.va_atime.ts_sec = np->n_atim.tv_sec; 2550 vattr.va_atime.ts_nsec = 2551 np->n_atim.tv_usec * 1000; 2552 } 2553 if (np->n_flag & NUPD) { 2554 vattr.va_mtime.ts_sec = np->n_mtim.tv_sec; 2555 vattr.va_mtime.ts_nsec = 2556 np->n_mtim.tv_usec * 1000; 2557 } 2558 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 2559 } 2560 } 2561 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 2562 } 2563 #endif /* FIFO */ 2564