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