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