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