1 /* $NetBSD: nfs_vnops.c,v 1.43 1994/12/13 20:15:47 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.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 nfsstats.lookupcache_hits++; 631 if (cnp->cn_nameiop != LOOKUP && 632 (flags & ISLASTCN)) 633 cnp->cn_flags |= SAVENAME; 634 return (0); 635 } else if (NQNFS_CKCACHABLE(dvp, NQL_READ)) { 636 if (np->n_lrev != np->n_brev || 637 (np->n_flag & NMODIFIED)) { 638 np->n_direofoffset = 0; 639 cache_purge(dvp); 640 error = nfs_vinvalbuf(dvp, 0, 641 cnp->cn_cred, cnp->cn_proc, 642 1); 643 if (error == EINTR) 644 return (error); 645 np->n_brev = np->n_lrev; 646 } else { 647 nfsstats.lookupcache_hits++; 648 if (cnp->cn_nameiop != LOOKUP && 649 (flags & ISLASTCN)) 650 cnp->cn_flags |= SAVENAME; 651 return (0); 652 } 653 } 654 } else if (!VOP_GETATTR(vdp, &vattr, cnp->cn_cred, cnp->cn_proc) && 655 vattr.va_ctime.ts_sec == VTONFS(vdp)->n_ctime) { 656 nfsstats.lookupcache_hits++; 657 if (cnp->cn_nameiop != LOOKUP && 658 (flags & ISLASTCN)) 659 cnp->cn_flags |= SAVENAME; 660 return (0); 661 } 662 cache_purge(vdp); 663 } 664 vrele(vdp); 665 } 666 *vpp = NULLVP; 667 } 668 error = 0; 669 nfsstats.lookupcache_misses++; 670 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 671 len = cnp->cn_namelen; 672 nfsm_reqhead(dvp, NFSPROC_LOOKUP, NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 673 674 /* 675 * For nqnfs optionally piggyback a getlease request for the name 676 * being looked up. 677 */ 678 if (nmp->nm_flag & NFSMNT_NQNFS) { 679 nfsm_build(tl, u_long *, NFSX_UNSIGNED); 680 if ((nmp->nm_flag & NFSMNT_NQLOOKLEASE) && 681 ((cnp->cn_flags & MAKEENTRY) && 682 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN)))) 683 *tl = txdr_unsigned(nmp->nm_leaseterm); 684 else 685 *tl = 0; 686 } 687 nfsm_fhtom(dvp); 688 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 689 reqtime = time.tv_sec; 690 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 691 nfsmout: 692 if (error) { 693 if ((cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) && 694 (flags & ISLASTCN) && error == ENOENT) 695 error = EJUSTRETURN; 696 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 697 cnp->cn_flags |= SAVENAME; 698 return (error); 699 } 700 if (nmp->nm_flag & NFSMNT_NQNFS) { 701 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 702 if (*tl) { 703 nqlflag = fxdr_unsigned(int, *tl); 704 nfsm_dissect(tl, u_long *, 4*NFSX_UNSIGNED); 705 cachable = fxdr_unsigned(int, *tl++); 706 reqtime += fxdr_unsigned(int, *tl++); 707 fxdr_hyper(tl, &frev); 708 } else 709 nqlflag = 0; 710 } 711 nfsm_dissect(fhp, nfsv2fh_t *, NFSX_FH); 712 713 /* 714 * Handle RENAME case... 715 */ 716 if (cnp->cn_nameiop == RENAME && wantparent && (flags & ISLASTCN)) { 717 if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 718 m_freem(mrep); 719 return (EISDIR); 720 } 721 if (error = nfs_nget(dvp->v_mount, fhp, &np)) { 722 m_freem(mrep); 723 return (error); 724 } 725 newvp = NFSTOV(np); 726 if (error = 727 nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 728 vrele(newvp); 729 m_freem(mrep); 730 return (error); 731 } 732 *vpp = newvp; 733 m_freem(mrep); 734 cnp->cn_flags |= SAVENAME; 735 return (0); 736 } 737 738 if (!bcmp(np->n_fh.fh_bytes, (caddr_t)fhp, NFSX_FH)) { 739 VREF(dvp); 740 newvp = dvp; 741 } else { 742 if (error = nfs_nget(dvp->v_mount, fhp, &np)) { 743 m_freem(mrep); 744 return (error); 745 } 746 newvp = NFSTOV(np); 747 } 748 if (error = nfs_loadattrcache(&newvp, &md, &dpos, (struct vattr *)0)) { 749 vrele(newvp); 750 m_freem(mrep); 751 return (error); 752 } 753 m_freem(mrep); 754 *vpp = newvp; 755 if (cnp->cn_nameiop != LOOKUP && (flags & ISLASTCN)) 756 cnp->cn_flags |= SAVENAME; 757 if ((cnp->cn_flags & MAKEENTRY) && 758 (cnp->cn_nameiop != DELETE || !(flags & ISLASTCN))) { 759 if ((nmp->nm_flag & NFSMNT_NQNFS) == 0) 760 np->n_ctime = np->n_vattr.va_ctime.ts_sec; 761 else if (nqlflag && reqtime > time.tv_sec) 762 nqnfs_clientlease(nmp, np, nqlflag, cachable, reqtime, 763 frev); 764 cache_enter(dvp, *vpp, cnp); 765 } 766 return (0); 767 } 768 769 /* 770 * nfs read call. 771 * Just call nfs_bioread() to do the work. 772 */ 773 int 774 nfs_read(ap) 775 struct vop_read_args /* { 776 struct vnode *a_vp; 777 struct uio *a_uio; 778 int a_ioflag; 779 struct ucred *a_cred; 780 } */ *ap; 781 { 782 register struct vnode *vp = ap->a_vp; 783 784 if (vp->v_type != VREG) 785 return (EPERM); 786 return (nfs_bioread(vp, ap->a_uio, ap->a_ioflag, ap->a_cred)); 787 } 788 789 /* 790 * nfs readlink call 791 */ 792 int 793 nfs_readlink(ap) 794 struct vop_readlink_args /* { 795 struct vnode *a_vp; 796 struct uio *a_uio; 797 struct ucred *a_cred; 798 } */ *ap; 799 { 800 register struct vnode *vp = ap->a_vp; 801 802 if (vp->v_type != VLNK) 803 return (EPERM); 804 return (nfs_bioread(vp, ap->a_uio, 0, ap->a_cred)); 805 } 806 807 /* 808 * Do a readlink rpc. 809 * Called by nfs_doio() from below the buffer cache. 810 */ 811 int 812 nfs_readlinkrpc(vp, uiop, cred) 813 register struct vnode *vp; 814 struct uio *uiop; 815 struct ucred *cred; 816 { 817 register u_long *tl; 818 register caddr_t cp; 819 register long t1; 820 caddr_t bpos, dpos, cp2; 821 int error = 0; 822 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 823 long len; 824 825 nfsstats.rpccnt[NFSPROC_READLINK]++; 826 nfsm_reqhead(vp, NFSPROC_READLINK, NFSX_FH); 827 nfsm_fhtom(vp); 828 nfsm_request(vp, NFSPROC_READLINK, uiop->uio_procp, cred); 829 nfsm_strsiz(len, NFS_MAXPATHLEN); 830 nfsm_mtouio(uiop, len); 831 nfsm_reqdone; 832 return (error); 833 } 834 835 /* 836 * nfs read rpc call 837 * Ditto above 838 */ 839 int 840 nfs_readrpc(vp, uiop, cred) 841 register struct vnode *vp; 842 struct uio *uiop; 843 struct ucred *cred; 844 { 845 register u_long *tl; 846 register caddr_t cp; 847 register long t1; 848 caddr_t bpos, dpos, cp2; 849 int error = 0; 850 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 851 struct nfsmount *nmp; 852 long len, retlen, tsiz; 853 854 nmp = VFSTONFS(vp->v_mount); 855 tsiz = uiop->uio_resid; 856 if (uiop->uio_offset + tsiz > 0xffffffff && 857 (nmp->nm_flag & NFSMNT_NQNFS) == 0) 858 return (EFBIG); 859 while (tsiz > 0) { 860 nfsstats.rpccnt[NFSPROC_READ]++; 861 len = (tsiz > nmp->nm_rsize) ? nmp->nm_rsize : tsiz; 862 nfsm_reqhead(vp, NFSPROC_READ, NFSX_FH+NFSX_UNSIGNED*3); 863 nfsm_fhtom(vp); 864 nfsm_build(tl, u_long *, NFSX_UNSIGNED*3); 865 if (nmp->nm_flag & NFSMNT_NQNFS) { 866 txdr_hyper(&uiop->uio_offset, tl); 867 *(tl + 2) = txdr_unsigned(len); 868 } else { 869 *tl++ = txdr_unsigned(uiop->uio_offset); 870 *tl++ = txdr_unsigned(len); 871 *tl = 0; 872 } 873 nfsm_request(vp, NFSPROC_READ, uiop->uio_procp, cred); 874 nfsm_loadattr(vp, (struct vattr *)0); 875 nfsm_strsiz(retlen, nmp->nm_rsize); 876 nfsm_mtouio(uiop, retlen); 877 m_freem(mrep); 878 if (retlen < len) 879 tsiz = 0; 880 else 881 tsiz -= len; 882 } 883 nfsmout: 884 return (error); 885 } 886 887 /* 888 * nfs write call 889 */ 890 int 891 nfs_writerpc(vp, uiop, cred, ioflags) 892 register struct vnode *vp; 893 struct uio *uiop; 894 struct ucred *cred; 895 int ioflags; 896 { 897 register u_long *tl; 898 register caddr_t cp; 899 register long t1; 900 caddr_t bpos, dpos, cp2; 901 int error = 0; 902 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 903 struct nfsmount *nmp; 904 struct nfsnode *np = VTONFS(vp); 905 u_quad_t frev; 906 long len, tsiz; 907 908 nmp = VFSTONFS(vp->v_mount); 909 tsiz = uiop->uio_resid; 910 if (uiop->uio_offset + tsiz > 0xffffffff && 911 (nmp->nm_flag & NFSMNT_NQNFS) == 0) 912 return (EFBIG); 913 while (tsiz > 0) { 914 nfsstats.rpccnt[NFSPROC_WRITE]++; 915 len = (tsiz > nmp->nm_wsize) ? nmp->nm_wsize : tsiz; 916 nfsm_reqhead(vp, NFSPROC_WRITE, 917 NFSX_FH+NFSX_UNSIGNED*4+nfsm_rndup(len)); 918 nfsm_fhtom(vp); 919 nfsm_build(tl, u_long *, NFSX_UNSIGNED * 4); 920 if (nmp->nm_flag & NFSMNT_NQNFS) { 921 txdr_hyper(&uiop->uio_offset, tl); 922 tl += 2; 923 *tl++ = 0; 924 } else { 925 *++tl = txdr_unsigned(uiop->uio_offset); 926 tl += 2; 927 } 928 *tl = txdr_unsigned(len); 929 nfsm_uiotom(uiop, len); 930 nfsm_request(vp, NFSPROC_WRITE, uiop->uio_procp, cred); 931 nfsm_loadattr(vp, (struct vattr *)0); 932 if (nmp->nm_flag & NFSMNT_MYWRITE) 933 VTONFS(vp)->n_mtime = VTONFS(vp)->n_vattr.va_mtime.ts_sec; 934 else if ((nmp->nm_flag & NFSMNT_NQNFS) && 935 NQNFS_CKCACHABLE(vp, NQL_WRITE)) { 936 nfsm_dissect(tl, u_long *, 2*NFSX_UNSIGNED); 937 fxdr_hyper(tl, &frev); 938 if (frev > np->n_brev) 939 np->n_brev = frev; 940 } 941 m_freem(mrep); 942 tsiz -= len; 943 } 944 nfsmout: 945 if (error) 946 uiop->uio_resid = tsiz; 947 return (error); 948 } 949 950 /* 951 * nfs mknod call 952 * This is a kludge. Use a create rpc but with the IFMT bits of the mode 953 * set to specify the file type and the size field for rdev. 954 */ 955 /* ARGSUSED */ 956 int 957 nfs_mknod(ap) 958 struct vop_mknod_args /* { 959 struct vnode *a_dvp; 960 struct vnode **a_vpp; 961 struct componentname *a_cnp; 962 struct vattr *a_vap; 963 } */ *ap; 964 { 965 register struct vnode *dvp = ap->a_dvp; 966 register struct vattr *vap = ap->a_vap; 967 register struct componentname *cnp = ap->a_cnp; 968 register struct nfsv2_sattr *sp; 969 register u_long *tl; 970 register caddr_t cp; 971 register long t1, t2; 972 struct vnode *newvp; 973 struct vattr vattr; 974 char *cp2; 975 caddr_t bpos, dpos; 976 int error = 0, isnq; 977 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 978 u_long rdev; 979 980 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 981 if (vap->va_type == VCHR || vap->va_type == VBLK) 982 rdev = txdr_unsigned(vap->va_rdev); 983 #ifdef FIFO 984 else if (vap->va_type == VFIFO) 985 rdev = 0xffffffff; 986 #endif /* FIFO */ 987 else { 988 VOP_ABORTOP(dvp, cnp); 989 vput(dvp); 990 return (EOPNOTSUPP); 991 } 992 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 993 VOP_ABORTOP(dvp, cnp); 994 vput(dvp); 995 return (error); 996 } 997 newvp = NULLVP; 998 nfsstats.rpccnt[NFSPROC_CREATE]++; 999 nfsm_reqhead(dvp, NFSPROC_CREATE, 1000 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR(isnq)); 1001 nfsm_fhtom(dvp); 1002 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1003 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 1004 sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 1005 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1006 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1007 if (isnq) { 1008 sp->sa_nqrdev = rdev; 1009 sp->sa_nqflags = 0; 1010 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 1011 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 1012 } else { 1013 sp->sa_nfssize = rdev; 1014 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 1015 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 1016 } 1017 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1018 nfsm_mtofh(dvp, newvp); 1019 nfsm_reqdone; 1020 if (!error && (cnp->cn_flags & MAKEENTRY)) 1021 cache_enter(dvp, newvp, cnp); 1022 FREE(cnp->cn_pnbuf, M_NAMEI); 1023 VTONFS(dvp)->n_flag |= NMODIFIED; 1024 VTONFS(dvp)->n_attrstamp = 0; 1025 vrele(dvp); 1026 if (newvp != NULLVP) 1027 vrele(newvp); 1028 return (error); 1029 } 1030 1031 /* 1032 * nfs file create call 1033 */ 1034 int 1035 nfs_create(ap) 1036 struct vop_create_args /* { 1037 struct vnode *a_dvp; 1038 struct vnode **a_vpp; 1039 struct componentname *a_cnp; 1040 struct vattr *a_vap; 1041 } */ *ap; 1042 { 1043 register struct vnode *dvp = ap->a_dvp; 1044 register struct vattr *vap = ap->a_vap; 1045 register struct componentname *cnp = ap->a_cnp; 1046 register struct nfsv2_sattr *sp; 1047 register u_long *tl; 1048 register caddr_t cp; 1049 register long t1, t2; 1050 caddr_t bpos, dpos, cp2; 1051 int error = 0, isnq; 1052 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1053 struct vattr vattr; 1054 1055 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1056 VOP_ABORTOP(dvp, cnp); 1057 vput(dvp); 1058 return (error); 1059 } 1060 nfsstats.rpccnt[NFSPROC_CREATE]++; 1061 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 1062 nfsm_reqhead(dvp, NFSPROC_CREATE, 1063 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)+NFSX_SATTR(isnq)); 1064 nfsm_fhtom(dvp); 1065 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1066 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 1067 sp->sa_mode = vtonfs_mode(vap->va_type, vap->va_mode); 1068 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1069 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1070 if (isnq) { 1071 u_quad_t qval = 0; 1072 1073 txdr_hyper(&qval, &sp->sa_nqsize); 1074 sp->sa_nqflags = 0; 1075 sp->sa_nqrdev = -1; 1076 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 1077 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 1078 } else { 1079 sp->sa_nfssize = 0; 1080 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 1081 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 1082 } 1083 nfsm_request(dvp, NFSPROC_CREATE, cnp->cn_proc, cnp->cn_cred); 1084 nfsm_mtofh(dvp, *ap->a_vpp); 1085 nfsm_reqdone; 1086 if (!error && (cnp->cn_flags & MAKEENTRY)) 1087 cache_enter(dvp, *ap->a_vpp, cnp); 1088 FREE(cnp->cn_pnbuf, M_NAMEI); 1089 VTONFS(dvp)->n_flag |= NMODIFIED; 1090 VTONFS(dvp)->n_attrstamp = 0; 1091 vrele(dvp); 1092 return (error); 1093 } 1094 1095 /* 1096 * nfs file remove call 1097 * To try and make nfs semantics closer to ufs semantics, a file that has 1098 * other processes using the vnode is renamed instead of removed and then 1099 * removed later on the last close. 1100 * - If v_usecount > 1 1101 * If a rename is not already in the works 1102 * call nfs_sillyrename() to set it up 1103 * else 1104 * do the remove rpc 1105 */ 1106 int 1107 nfs_remove(ap) 1108 struct vop_remove_args /* { 1109 struct vnodeop_desc *a_desc; 1110 struct vnode * a_dvp; 1111 struct vnode * a_vp; 1112 struct componentname * a_cnp; 1113 } */ *ap; 1114 { 1115 register struct vnode *vp = ap->a_vp; 1116 register struct vnode *dvp = ap->a_dvp; 1117 register struct componentname *cnp = ap->a_cnp; 1118 register struct nfsnode *np = VTONFS(vp); 1119 register u_long *tl; 1120 register caddr_t cp; 1121 register long t2; 1122 caddr_t bpos, dpos; 1123 int error = 0; 1124 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1125 struct vattr vattr; 1126 1127 if (vp->v_usecount > 1) { 1128 if (!np->n_sillyrename) 1129 error = nfs_sillyrename(dvp, vp, cnp); 1130 else if (VOP_GETATTR(vp, &vattr, cnp->cn_cred, cnp->cn_proc) 1131 == 0 && vattr.va_nlink > 1) 1132 /* 1133 * If we already have a silly name but there are more 1134 * than one links, just proceed with the NFS remove 1135 * request, as the bits will remain available (modulo 1136 * network races). This avoids silently ignoring the 1137 * attempted removal of a non-silly entry. 1138 */ 1139 goto doit; 1140 } else { 1141 doit: 1142 /* 1143 * Purge the name cache so that the chance of a lookup for 1144 * the name succeeding while the remove is in progress is 1145 * minimized. Without node locking it can still happen, such 1146 * that an I/O op returns ESTALE, but since you get this if 1147 * another host removes the file.. 1148 */ 1149 cache_purge(vp); 1150 /* 1151 * Throw away biocache buffers. Mainly to avoid 1152 * unnecessary delayed writes. 1153 */ 1154 error = nfs_vinvalbuf(vp, 0, cnp->cn_cred, cnp->cn_proc, 1); 1155 if (error == EINTR) 1156 return (error); 1157 /* Do the rpc */ 1158 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1159 nfsm_reqhead(dvp, NFSPROC_REMOVE, 1160 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 1161 nfsm_fhtom(dvp); 1162 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1163 nfsm_request(dvp, NFSPROC_REMOVE, cnp->cn_proc, cnp->cn_cred); 1164 nfsm_reqdone; 1165 FREE(cnp->cn_pnbuf, M_NAMEI); 1166 VTONFS(dvp)->n_flag |= NMODIFIED; 1167 VTONFS(dvp)->n_attrstamp = 0; 1168 /* 1169 * Kludge City: If the first reply to the remove rpc is lost.. 1170 * the reply to the retransmitted request will be ENOENT 1171 * since the file was in fact removed 1172 * Therefore, we cheat and return success. 1173 */ 1174 if (error == ENOENT) 1175 error = 0; 1176 } 1177 np->n_attrstamp = 0; 1178 vrele(dvp); 1179 vrele(vp); 1180 return (error); 1181 } 1182 1183 /* 1184 * nfs file remove rpc called from nfs_inactive 1185 */ 1186 int 1187 nfs_removeit(sp) 1188 register struct sillyrename *sp; 1189 { 1190 register u_long *tl; 1191 register caddr_t cp; 1192 register long t2; 1193 caddr_t bpos, dpos; 1194 int error = 0; 1195 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1196 1197 nfsstats.rpccnt[NFSPROC_REMOVE]++; 1198 nfsm_reqhead(sp->s_dvp, NFSPROC_REMOVE, 1199 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(sp->s_namlen)); 1200 nfsm_fhtom(sp->s_dvp); 1201 nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN); 1202 nfsm_request(sp->s_dvp, NFSPROC_REMOVE, NULL, sp->s_cred); 1203 nfsm_reqdone; 1204 VTONFS(sp->s_dvp)->n_flag |= NMODIFIED; 1205 VTONFS(sp->s_dvp)->n_attrstamp = 0; 1206 return (error); 1207 } 1208 1209 /* 1210 * nfs file rename call 1211 */ 1212 int 1213 nfs_rename(ap) 1214 struct vop_rename_args /* { 1215 struct vnode *a_fdvp; 1216 struct vnode *a_fvp; 1217 struct componentname *a_fcnp; 1218 struct vnode *a_tdvp; 1219 struct vnode *a_tvp; 1220 struct componentname *a_tcnp; 1221 } */ *ap; 1222 { 1223 register struct vnode *fvp = ap->a_fvp; 1224 register struct vnode *tvp = ap->a_tvp; 1225 register struct vnode *fdvp = ap->a_fdvp; 1226 register struct vnode *tdvp = ap->a_tdvp; 1227 register struct componentname *tcnp = ap->a_tcnp; 1228 register struct componentname *fcnp = ap->a_fcnp; 1229 register u_long *tl; 1230 register caddr_t cp; 1231 register long t2; 1232 caddr_t bpos, dpos; 1233 int error = 0; 1234 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1235 1236 /* Check for cross-device rename */ 1237 if ((fvp->v_mount != tdvp->v_mount) || 1238 (tvp && (fvp->v_mount != tvp->v_mount))) { 1239 error = EXDEV; 1240 goto out; 1241 } 1242 1243 1244 nfsstats.rpccnt[NFSPROC_RENAME]++; 1245 nfsm_reqhead(fdvp, NFSPROC_RENAME, 1246 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(fcnp->cn_namelen)+ 1247 nfsm_rndup(fcnp->cn_namelen)); /* or fcnp->cn_cred?*/ 1248 nfsm_fhtom(fdvp); 1249 nfsm_strtom(fcnp->cn_nameptr, fcnp->cn_namelen, NFS_MAXNAMLEN); 1250 nfsm_fhtom(tdvp); 1251 nfsm_strtom(tcnp->cn_nameptr, tcnp->cn_namelen, NFS_MAXNAMLEN); 1252 nfsm_request(fdvp, NFSPROC_RENAME, tcnp->cn_proc, tcnp->cn_cred); 1253 nfsm_reqdone; 1254 VTONFS(fdvp)->n_flag |= NMODIFIED; 1255 VTONFS(fdvp)->n_attrstamp = 0; 1256 VTONFS(tdvp)->n_flag |= NMODIFIED; 1257 VTONFS(tdvp)->n_attrstamp = 0; 1258 if (fvp->v_type == VDIR) { 1259 if (tvp != NULL && tvp->v_type == VDIR) 1260 cache_purge(tdvp); 1261 cache_purge(fdvp); 1262 } 1263 out: 1264 if (tdvp == tvp) 1265 vrele(tdvp); 1266 else 1267 vput(tdvp); 1268 if (tvp) 1269 vput(tvp); 1270 vrele(fdvp); 1271 vrele(fvp); 1272 /* 1273 * Kludge: Map ENOENT => 0 assuming that it is a reply to a retry. 1274 */ 1275 if (error == ENOENT) 1276 error = 0; 1277 return (error); 1278 } 1279 1280 /* 1281 * nfs file rename rpc called from nfs_remove() above 1282 */ 1283 int 1284 nfs_renameit(sdvp, scnp, sp) 1285 struct vnode *sdvp; 1286 struct componentname *scnp; 1287 register struct sillyrename *sp; 1288 { 1289 register u_long *tl; 1290 register caddr_t cp; 1291 register long t2; 1292 caddr_t bpos, dpos; 1293 int error = 0; 1294 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1295 1296 nfsstats.rpccnt[NFSPROC_RENAME]++; 1297 nfsm_reqhead(sdvp, NFSPROC_RENAME, 1298 (NFSX_FH+NFSX_UNSIGNED)*2+nfsm_rndup(scnp->cn_namelen)+ 1299 nfsm_rndup(sp->s_namlen)); 1300 nfsm_fhtom(sdvp); 1301 nfsm_strtom(scnp->cn_nameptr, scnp->cn_namelen, NFS_MAXNAMLEN); 1302 nfsm_fhtom(sdvp); 1303 nfsm_strtom(sp->s_name, sp->s_namlen, NFS_MAXNAMLEN); 1304 nfsm_request(sdvp, NFSPROC_RENAME, scnp->cn_proc, scnp->cn_cred); 1305 nfsm_reqdone; 1306 FREE(scnp->cn_pnbuf, M_NAMEI); 1307 VTONFS(sdvp)->n_flag |= NMODIFIED; 1308 VTONFS(sdvp)->n_attrstamp = 0; 1309 return (error); 1310 } 1311 1312 /* 1313 * nfs hard link create call 1314 */ 1315 int 1316 nfs_link(ap) 1317 struct vop_link_args /* { 1318 struct vnode *a_vp; 1319 struct vnode *a_tdvp; 1320 struct componentname *a_cnp; 1321 } */ *ap; 1322 { 1323 register struct vnode *vp = ap->a_vp; 1324 register struct vnode *tdvp = ap->a_tdvp; 1325 register struct componentname *cnp = ap->a_cnp; 1326 register u_long *tl; 1327 register caddr_t cp; 1328 register long t2; 1329 caddr_t bpos, dpos; 1330 int error = 0; 1331 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1332 1333 if (vp->v_mount != tdvp->v_mount) { 1334 /*VOP_ABORTOP(vp, cnp);*/ 1335 if (tdvp == vp) 1336 vrele(vp); 1337 else 1338 vput(vp); 1339 return (EXDEV); 1340 } 1341 1342 /* 1343 * Push all writes to the server, so that the attribute cache 1344 * doesn't get "out of sync" with the server. 1345 * XXX There should be a better way! 1346 */ 1347 VOP_FSYNC(tdvp, cnp->cn_cred, MNT_WAIT, cnp->cn_proc); 1348 1349 nfsstats.rpccnt[NFSPROC_LINK]++; 1350 nfsm_reqhead(tdvp, NFSPROC_LINK, 1351 NFSX_FH*2+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 1352 nfsm_fhtom(tdvp); 1353 nfsm_fhtom(vp); 1354 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1355 nfsm_request(tdvp, NFSPROC_LINK, cnp->cn_proc, cnp->cn_cred); 1356 nfsm_reqdone; 1357 FREE(cnp->cn_pnbuf, M_NAMEI); 1358 VTONFS(tdvp)->n_attrstamp = 0; 1359 VTONFS(vp)->n_flag |= NMODIFIED; 1360 VTONFS(vp)->n_attrstamp = 0; 1361 vrele(vp); 1362 /* 1363 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1364 */ 1365 if (error == EEXIST) 1366 error = 0; 1367 return (error); 1368 } 1369 1370 /* 1371 * nfs symbolic link create call 1372 */ 1373 /* start here */ 1374 int 1375 nfs_symlink(ap) 1376 struct vop_symlink_args /* { 1377 struct vnode *a_dvp; 1378 struct vnode **a_vpp; 1379 struct componentname *a_cnp; 1380 struct vattr *a_vap; 1381 char *a_target; 1382 } */ *ap; 1383 { 1384 register struct vnode *dvp = ap->a_dvp; 1385 register struct vattr *vap = ap->a_vap; 1386 register struct componentname *cnp = ap->a_cnp; 1387 register struct nfsv2_sattr *sp; 1388 register u_long *tl; 1389 register caddr_t cp; 1390 register long t2; 1391 caddr_t bpos, dpos; 1392 int slen, error = 0, isnq; 1393 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1394 1395 nfsstats.rpccnt[NFSPROC_SYMLINK]++; 1396 slen = strlen(ap->a_target); 1397 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 1398 nfsm_reqhead(dvp, NFSPROC_SYMLINK, NFSX_FH+2*NFSX_UNSIGNED+ 1399 nfsm_rndup(cnp->cn_namelen)+nfsm_rndup(slen)+NFSX_SATTR(isnq)); 1400 nfsm_fhtom(dvp); 1401 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1402 nfsm_strtom(ap->a_target, slen, NFS_MAXPATHLEN); 1403 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 1404 sp->sa_mode = vtonfs_mode(VLNK, vap->va_mode); 1405 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1406 sp->sa_gid = txdr_unsigned(cnp->cn_cred->cr_gid); 1407 if (isnq) { 1408 quad_t qval = -1; 1409 1410 txdr_hyper(&qval, &sp->sa_nqsize); 1411 sp->sa_nqflags = 0; 1412 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 1413 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 1414 } else { 1415 sp->sa_nfssize = -1; 1416 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 1417 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 1418 } 1419 nfsm_request(dvp, NFSPROC_SYMLINK, cnp->cn_proc, cnp->cn_cred); 1420 nfsm_reqdone; 1421 FREE(cnp->cn_pnbuf, M_NAMEI); 1422 VTONFS(dvp)->n_flag |= NMODIFIED; 1423 VTONFS(dvp)->n_attrstamp = 0; 1424 vrele(dvp); 1425 /* 1426 * Kludge: Map EEXIST => 0 assuming that it is a reply to a retry. 1427 */ 1428 if (error == EEXIST) 1429 error = 0; 1430 return (error); 1431 } 1432 1433 /* 1434 * nfs make dir call 1435 */ 1436 int 1437 nfs_mkdir(ap) 1438 struct vop_mkdir_args /* { 1439 struct vnode *a_dvp; 1440 struct vnode **a_vpp; 1441 struct componentname *a_cnp; 1442 struct vattr *a_vap; 1443 } */ *ap; 1444 { 1445 register struct vnode *dvp = ap->a_dvp; 1446 register struct vattr *vap = ap->a_vap; 1447 register struct componentname *cnp = ap->a_cnp; 1448 register struct vnode **vpp = ap->a_vpp; 1449 register struct nfsv2_sattr *sp; 1450 register u_long *tl; 1451 register caddr_t cp; 1452 register long t1, t2; 1453 register int len; 1454 caddr_t bpos, dpos, cp2; 1455 int error = 0, firsttry = 1, isnq; 1456 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1457 struct vattr vattr; 1458 1459 if (error = VOP_GETATTR(dvp, &vattr, cnp->cn_cred, cnp->cn_proc)) { 1460 VOP_ABORTOP(dvp, cnp); 1461 vput(dvp); 1462 return (error); 1463 } 1464 len = cnp->cn_namelen; 1465 isnq = (VFSTONFS(dvp->v_mount)->nm_flag & NFSMNT_NQNFS); 1466 nfsstats.rpccnt[NFSPROC_MKDIR]++; 1467 nfsm_reqhead(dvp, NFSPROC_MKDIR, 1468 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)+NFSX_SATTR(isnq)); 1469 nfsm_fhtom(dvp); 1470 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1471 nfsm_build(sp, struct nfsv2_sattr *, NFSX_SATTR(isnq)); 1472 sp->sa_mode = vtonfs_mode(VDIR, vap->va_mode); 1473 sp->sa_uid = txdr_unsigned(cnp->cn_cred->cr_uid); 1474 sp->sa_gid = txdr_unsigned(vattr.va_gid); 1475 if (isnq) { 1476 quad_t qval = -1; 1477 1478 txdr_hyper(&qval, &sp->sa_nqsize); 1479 sp->sa_nqflags = 0; 1480 txdr_nqtime(&vap->va_atime, &sp->sa_nqatime); 1481 txdr_nqtime(&vap->va_mtime, &sp->sa_nqmtime); 1482 } else { 1483 sp->sa_nfssize = -1; 1484 txdr_nfstime(&vap->va_atime, &sp->sa_nfsatime); 1485 txdr_nfstime(&vap->va_mtime, &sp->sa_nfsmtime); 1486 } 1487 nfsm_request(dvp, NFSPROC_MKDIR, cnp->cn_proc, cnp->cn_cred); 1488 nfsm_mtofh(dvp, *vpp); 1489 nfsm_reqdone; 1490 VTONFS(dvp)->n_flag |= NMODIFIED; 1491 VTONFS(dvp)->n_attrstamp = 0; 1492 /* 1493 * Kludge: Map EEXIST => 0 assuming that you have a reply to a retry 1494 * if we can succeed in looking up the directory. 1495 * "firsttry" is necessary since the macros may "goto nfsmout" which 1496 * is above the if on errors. (Ugh) 1497 */ 1498 if (error == EEXIST && firsttry) { 1499 firsttry = 0; 1500 error = 0; 1501 nfsstats.rpccnt[NFSPROC_LOOKUP]++; 1502 *vpp = NULL; 1503 nfsm_reqhead(dvp, NFSPROC_LOOKUP, 1504 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(len)); 1505 nfsm_fhtom(dvp); 1506 nfsm_strtom(cnp->cn_nameptr, len, NFS_MAXNAMLEN); 1507 nfsm_request(dvp, NFSPROC_LOOKUP, cnp->cn_proc, cnp->cn_cred); 1508 nfsm_mtofh(dvp, *vpp); 1509 if ((*vpp)->v_type != VDIR) { 1510 vput(*vpp); 1511 error = EEXIST; 1512 } 1513 m_freem(mrep); 1514 } 1515 FREE(cnp->cn_pnbuf, M_NAMEI); 1516 vrele(dvp); 1517 return (error); 1518 } 1519 1520 /* 1521 * nfs remove directory call 1522 */ 1523 int 1524 nfs_rmdir(ap) 1525 struct vop_rmdir_args /* { 1526 struct vnode *a_dvp; 1527 struct vnode *a_vp; 1528 struct componentname *a_cnp; 1529 } */ *ap; 1530 { 1531 register struct vnode *vp = ap->a_vp; 1532 register struct vnode *dvp = ap->a_dvp; 1533 register struct componentname *cnp = ap->a_cnp; 1534 register u_long *tl; 1535 register caddr_t cp; 1536 register long t2; 1537 caddr_t bpos, dpos; 1538 int error = 0; 1539 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1540 1541 if (dvp == vp) { 1542 vrele(dvp); 1543 vrele(dvp); 1544 FREE(cnp->cn_pnbuf, M_NAMEI); 1545 return (EINVAL); 1546 } 1547 nfsstats.rpccnt[NFSPROC_RMDIR]++; 1548 nfsm_reqhead(dvp, NFSPROC_RMDIR, 1549 NFSX_FH+NFSX_UNSIGNED+nfsm_rndup(cnp->cn_namelen)); 1550 nfsm_fhtom(dvp); 1551 nfsm_strtom(cnp->cn_nameptr, cnp->cn_namelen, NFS_MAXNAMLEN); 1552 nfsm_request(dvp, NFSPROC_RMDIR, cnp->cn_proc, cnp->cn_cred); 1553 nfsm_reqdone; 1554 FREE(cnp->cn_pnbuf, M_NAMEI); 1555 VTONFS(dvp)->n_flag |= NMODIFIED; 1556 VTONFS(dvp)->n_attrstamp = 0; 1557 cache_purge(dvp); 1558 cache_purge(vp); 1559 vrele(vp); 1560 vrele(dvp); 1561 /* 1562 * Kludge: Map ENOENT => 0 assuming that you have a reply to a retry. 1563 */ 1564 if (error == ENOENT) 1565 error = 0; 1566 return (error); 1567 } 1568 1569 /* 1570 * nfs readdir call 1571 * Although cookie is defined as opaque, I translate it to/from net byte 1572 * order so that it looks more sensible. This appears consistent with the 1573 * Ultrix implementation of NFS. 1574 */ 1575 int 1576 nfs_readdir(ap) 1577 struct vop_readdir_args /* { 1578 struct vnode *a_vp; 1579 struct uio *a_uio; 1580 struct ucred *a_cred; 1581 int *a_eofflag; 1582 u_long *a_cookies; 1583 int a_ncookies; 1584 } */ *ap; 1585 { 1586 register struct vnode *vp = ap->a_vp; 1587 register struct nfsnode *np = VTONFS(vp); 1588 register struct uio *uio = ap->a_uio; 1589 int tresid, error; 1590 struct vattr vattr; 1591 1592 /* 1593 * We don't allow exporting NFS mounts, and currently local requests 1594 * do not need cookies. 1595 */ 1596 if (ap->a_ncookies) 1597 panic("nfs_readdir: not hungry"); 1598 1599 if (vp->v_type != VDIR) 1600 return (EPERM); 1601 /* 1602 * First, check for hit on the EOF offset cache 1603 */ 1604 if (uio->uio_offset != 0 && uio->uio_offset == np->n_direofoffset && 1605 (np->n_flag & NMODIFIED) == 0) { 1606 if (VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NQNFS) { 1607 if (NQNFS_CKCACHABLE(vp, NQL_READ)) { 1608 nfsstats.direofcache_hits++; 1609 return (0); 1610 } 1611 } else if (VOP_GETATTR(vp, &vattr, ap->a_cred, uio->uio_procp) == 0 && 1612 np->n_mtime == vattr.va_mtime.ts_sec) { 1613 nfsstats.direofcache_hits++; 1614 return (0); 1615 } 1616 } 1617 1618 /* 1619 * Call nfs_bioread() to do the real work. 1620 */ 1621 tresid = uio->uio_resid; 1622 error = nfs_bioread(vp, uio, 0, ap->a_cred); 1623 1624 if (!error && uio->uio_resid == tresid) 1625 nfsstats.direofcache_misses++; 1626 return (error); 1627 } 1628 1629 /* 1630 * Readdir rpc call. 1631 * Called from below the buffer cache by nfs_doio(). 1632 */ 1633 int 1634 nfs_readdirrpc(vp, uiop, cred) 1635 register struct vnode *vp; 1636 struct uio *uiop; 1637 struct ucred *cred; 1638 { 1639 register long len; 1640 register struct dirent *dp; 1641 register u_long *tl; 1642 register caddr_t cp; 1643 register long t1; 1644 long tlen, lastlen; 1645 caddr_t bpos, dpos, cp2; 1646 int error = 0; 1647 struct mbuf *mreq, *mrep, *md, *mb, *mb2; 1648 struct mbuf *md2; 1649 caddr_t dpos2; 1650 int siz; 1651 int more_dirs = 1; 1652 u_long off, savoff; 1653 struct dirent *savdp; 1654 struct nfsmount *nmp; 1655 struct nfsnode *np = VTONFS(vp); 1656 long tresid; 1657 1658 nmp = VFSTONFS(vp->v_mount); 1659 tresid = uiop->uio_resid; 1660 /* 1661 * Loop around doing readdir rpc's of size uio_resid or nm_rsize, 1662 * whichever is smaller, truncated to a multiple of NFS_DIRBLKSIZ. 1663 * The stopping criteria is EOF or buffer full. 1664 */ 1665 while (more_dirs && uiop->uio_resid >= NFS_DIRBLKSIZ) { 1666 nfsstats.rpccnt[NFSPROC_READDIR]++; 1667 nfsm_reqhead(vp, NFSPROC_READDIR, 1668 NFSX_FH + 2 * NFSX_UNSIGNED); 1669 nfsm_fhtom(vp); 1670 nfsm_build(tl, u_long *, 2 * NFSX_UNSIGNED); 1671 off = (u_long)uiop->uio_offset; 1672 *tl++ = txdr_unsigned(off); 1673 *tl = txdr_unsigned(((uiop->uio_resid > nmp->nm_rsize) ? 1674 nmp->nm_rsize : uiop->uio_resid) & ~(NFS_DIRBLKSIZ-1)); 1675 nfsm_request(vp, NFSPROC_READDIR, uiop->uio_procp, cred); 1676 siz = 0; 1677 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1678 more_dirs = fxdr_unsigned(int, *tl); 1679 1680 /* Save the position so that we can do nfsm_mtouio() later */ 1681 dpos2 = dpos; 1682 md2 = md; 1683 1684 /* loop thru the dir entries, doctoring them to 4bsd form */ 1685 #ifdef lint 1686 dp = (struct dirent *)0; 1687 #endif /* lint */ 1688 while (more_dirs && siz < uiop->uio_resid) { 1689 savoff = off; /* Hold onto offset and dp */ 1690 savdp = dp; 1691 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1692 dp = (struct dirent *)tl; 1693 dp->d_fileno = fxdr_unsigned(u_long, *tl++); 1694 len = fxdr_unsigned(int, *tl); 1695 if (len <= 0 || len > NFS_MAXNAMLEN) { 1696 error = EBADRPC; 1697 m_freem(mrep); 1698 goto nfsmout; 1699 } 1700 dp->d_namlen = (u_char)len; 1701 dp->d_type = DT_UNKNOWN; 1702 nfsm_adv(len); /* Point past name */ 1703 tlen = nfsm_rndup(len); 1704 /* 1705 * This should not be necessary, but some servers have 1706 * broken XDR such that these bytes are not null filled. 1707 */ 1708 if (tlen != len) { 1709 *dpos = '\0'; /* Null-terminate */ 1710 nfsm_adv(tlen - len); 1711 len = tlen; 1712 } 1713 nfsm_dissect(tl, u_long *, 2 * NFSX_UNSIGNED); 1714 off = fxdr_unsigned(u_long, *tl); 1715 *tl++ = 0; /* Ensures null termination of name */ 1716 more_dirs = fxdr_unsigned(int, *tl); 1717 dp->d_reclen = len + 4 * NFSX_UNSIGNED; 1718 siz += dp->d_reclen; 1719 } 1720 /* 1721 * If at end of rpc data, get the eof boolean 1722 */ 1723 if (!more_dirs) { 1724 nfsm_dissect(tl, u_long *, NFSX_UNSIGNED); 1725 more_dirs = (fxdr_unsigned(int, *tl) == 0); 1726 1727 /* 1728 * If at EOF, cache directory offset 1729 */ 1730 if (!more_dirs) 1731 np->n_direofoffset = off; 1732 } 1733 /* 1734 * If there is too much to fit in the data buffer, use savoff and 1735 * savdp to trim off the last record. 1736 * --> we are not at eof 1737 */ 1738 if (siz > uiop->uio_resid) { 1739 off = savoff; 1740 siz -= dp->d_reclen; 1741 dp = savdp; 1742 more_dirs = 0; /* Paranoia */ 1743 } 1744 if (siz > 0) { 1745 lastlen = dp->d_reclen; 1746 md = md2; 1747 dpos = dpos2; 1748 nfsm_mtouio(uiop, siz); 1749 uiop->uio_offset = (off_t)off; 1750 } else 1751 more_dirs = 0; /* Ugh, never happens, but in case.. */ 1752 m_freem(mrep); 1753 } 1754 /* 1755 * Fill last record, iff any, out to a multiple of NFS_DIRBLKSIZ 1756 * by increasing d_reclen for the last record. 1757 */ 1758 if (uiop->uio_resid < tresid) { 1759 len = uiop->uio_resid & (NFS_DIRBLKSIZ - 1); 1760 if (len > 0) { 1761 dp = (struct dirent *) 1762 (uiop->uio_iov->iov_base - lastlen); 1763 dp->d_reclen += len; 1764 uiop->uio_iov->iov_base += len; 1765 uiop->uio_iov->iov_len -= len; 1766 uiop->uio_resid -= len; 1767 } 1768 } 1769 nfsmout: 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 register struct vattr *vap; 2381 register gid_t *gp; 2382 register struct ucred *cred = ap->a_cred; 2383 mode_t mode = ap->a_mode; 2384 struct vattr vattr; 2385 register int i; 2386 int error; 2387 2388 /* 2389 * If you're the super-user, 2390 * you always get access. 2391 */ 2392 if (cred->cr_uid == 0) 2393 return (0); 2394 vap = &vattr; 2395 if (error = VOP_GETATTR(ap->a_vp, vap, cred, ap->a_p)) 2396 return (error); 2397 /* 2398 * Access check is based on only one of owner, group, public. 2399 * If not owner, then check group. If not a member of the 2400 * group, then check public access. 2401 */ 2402 if (cred->cr_uid != vap->va_uid) { 2403 mode >>= 3; 2404 gp = cred->cr_groups; 2405 for (i = 0; i < cred->cr_ngroups; i++, gp++) 2406 if (vap->va_gid == *gp) 2407 goto found; 2408 mode >>= 3; 2409 found: 2410 ; 2411 } 2412 return ((vap->va_mode & mode) == mode ? 0 : EACCES); 2413 } 2414 2415 /* 2416 * Read wrapper for special devices. 2417 */ 2418 int 2419 nfsspec_read(ap) 2420 struct vop_read_args /* { 2421 struct vnode *a_vp; 2422 struct uio *a_uio; 2423 int a_ioflag; 2424 struct ucred *a_cred; 2425 } */ *ap; 2426 { 2427 register struct nfsnode *np = VTONFS(ap->a_vp); 2428 2429 /* 2430 * Set access flag. 2431 */ 2432 np->n_flag |= NACC; 2433 np->n_atim = time; 2434 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_read), ap)); 2435 } 2436 2437 /* 2438 * Write wrapper for special devices. 2439 */ 2440 int 2441 nfsspec_write(ap) 2442 struct vop_write_args /* { 2443 struct vnode *a_vp; 2444 struct uio *a_uio; 2445 int a_ioflag; 2446 struct ucred *a_cred; 2447 } */ *ap; 2448 { 2449 register struct nfsnode *np = VTONFS(ap->a_vp); 2450 2451 /* 2452 * Set update flag. 2453 */ 2454 np->n_flag |= NUPD; 2455 np->n_mtim = time; 2456 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_write), ap)); 2457 } 2458 2459 /* 2460 * Close wrapper for special devices. 2461 * 2462 * Update the times on the nfsnode then do device close. 2463 */ 2464 int 2465 nfsspec_close(ap) 2466 struct vop_close_args /* { 2467 struct vnode *a_vp; 2468 int a_fflag; 2469 struct ucred *a_cred; 2470 struct proc *a_p; 2471 } */ *ap; 2472 { 2473 register struct vnode *vp = ap->a_vp; 2474 register struct nfsnode *np = VTONFS(vp); 2475 struct vattr vattr; 2476 2477 if (np->n_flag & (NACC | NUPD)) { 2478 np->n_flag |= NCHG; 2479 if (vp->v_usecount == 1 && 2480 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 2481 VATTR_NULL(&vattr); 2482 if (np->n_flag & NACC) { 2483 vattr.va_atime.ts_sec = np->n_atim.tv_sec; 2484 vattr.va_atime.ts_nsec = 2485 np->n_atim.tv_usec * 1000; 2486 } 2487 if (np->n_flag & NUPD) { 2488 vattr.va_mtime.ts_sec = np->n_mtim.tv_sec; 2489 vattr.va_mtime.ts_nsec = 2490 np->n_mtim.tv_usec * 1000; 2491 } 2492 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 2493 } 2494 } 2495 return (VOCALL(spec_vnodeop_p, VOFFSET(vop_close), ap)); 2496 } 2497 2498 #ifdef FIFO 2499 /* 2500 * Read wrapper for fifos. 2501 */ 2502 int 2503 nfsfifo_read(ap) 2504 struct vop_read_args /* { 2505 struct vnode *a_vp; 2506 struct uio *a_uio; 2507 int a_ioflag; 2508 struct ucred *a_cred; 2509 } */ *ap; 2510 { 2511 extern int (**fifo_vnodeop_p)(); 2512 register struct nfsnode *np = VTONFS(ap->a_vp); 2513 2514 /* 2515 * Set access flag. 2516 */ 2517 np->n_flag |= NACC; 2518 np->n_atim = time; 2519 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_read), ap)); 2520 } 2521 2522 /* 2523 * Write wrapper for fifos. 2524 */ 2525 int 2526 nfsfifo_write(ap) 2527 struct vop_write_args /* { 2528 struct vnode *a_vp; 2529 struct uio *a_uio; 2530 int a_ioflag; 2531 struct ucred *a_cred; 2532 } */ *ap; 2533 { 2534 extern int (**fifo_vnodeop_p)(); 2535 register struct nfsnode *np = VTONFS(ap->a_vp); 2536 2537 /* 2538 * Set update flag. 2539 */ 2540 np->n_flag |= NUPD; 2541 np->n_mtim = time; 2542 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_write), ap)); 2543 } 2544 2545 /* 2546 * Close wrapper for fifos. 2547 * 2548 * Update the times on the nfsnode then do fifo close. 2549 */ 2550 int 2551 nfsfifo_close(ap) 2552 struct vop_close_args /* { 2553 struct vnode *a_vp; 2554 int a_fflag; 2555 struct ucred *a_cred; 2556 struct proc *a_p; 2557 } */ *ap; 2558 { 2559 register struct vnode *vp = ap->a_vp; 2560 register struct nfsnode *np = VTONFS(vp); 2561 struct vattr vattr; 2562 extern int (**fifo_vnodeop_p)(); 2563 2564 if (np->n_flag & (NACC | NUPD)) { 2565 if (np->n_flag & NACC) 2566 np->n_atim = time; 2567 if (np->n_flag & NUPD) 2568 np->n_mtim = time; 2569 np->n_flag |= NCHG; 2570 if (vp->v_usecount == 1 && 2571 (vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { 2572 VATTR_NULL(&vattr); 2573 if (np->n_flag & NACC) { 2574 vattr.va_atime.ts_sec = np->n_atim.tv_sec; 2575 vattr.va_atime.ts_nsec = 2576 np->n_atim.tv_usec * 1000; 2577 } 2578 if (np->n_flag & NUPD) { 2579 vattr.va_mtime.ts_sec = np->n_mtim.tv_sec; 2580 vattr.va_mtime.ts_nsec = 2581 np->n_mtim.tv_usec * 1000; 2582 } 2583 (void)VOP_SETATTR(vp, &vattr, ap->a_cred, ap->a_p); 2584 } 2585 } 2586 return (VOCALL(fifo_vnodeop_p, VOFFSET(vop_close), ap)); 2587 } 2588 #endif /* FIFO */ 2589