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