From 976be2ca6113dbc2904156f1a72a5b64d604e2ed Mon Sep 17 00:00:00 2001 From: Derrick Brashear Date: Mon, 4 Apr 2005 05:18:41 +0000 Subject: [PATCH] STABLE14-macos103-update-20050403 use system vnodes. one remaining bug, dangling vnodes at shutdown. (cherry picked from commit 2eda44d7eb3c1adc103600a3c3695e37b238441f) --- src/afs/DARWIN/osi_machdep.h | 7 +- src/afs/DARWIN/osi_module.c | 4 + src/afs/DARWIN/osi_vfsops.c | 11 +- src/afs/DARWIN/osi_vm.c | 274 ++----------------------------- src/afs/DARWIN/osi_vnodeops.c | 167 ++++++++++--------- src/afs/VNOPS/afs_vnop_attrs.c | 4 +- src/afs/VNOPS/afs_vnop_remove.c | 40 +---- src/afs/afs.h | 6 +- src/afs/afs_osi.h | 13 +- src/afs/afs_pioctl.c | 8 +- src/afs/afs_vcache.c | 126 ++++++-------- src/afsd/afs.rc.darwin | 2 +- src/config/param.ppc_darwin_70.h | 4 +- 13 files changed, 200 insertions(+), 466 deletions(-) diff --git a/src/afs/DARWIN/osi_machdep.h b/src/afs/DARWIN/osi_machdep.h index 63e88deb2..8850718d5 100644 --- a/src/afs/DARWIN/osi_machdep.h +++ b/src/afs/DARWIN/osi_machdep.h @@ -54,9 +54,10 @@ extern struct timeval time; #define AFS_PROC struct proc -#define osi_vnhold(avc,r) do { \ - if ((avc)->vrefCount) { VN_HOLD(&((avc)->v)); } \ - else (avc)->vrefCount = 1; } while(0) +#define osi_vnhold(avc,r) VN_HOLD(AFSTOV(avc)) +#define VN_HOLD(vp) darwin_vn_hold(vp) +#define VN_RELE(vp) vrele(vp); + #define gop_rdwr(rw,gp,base,len,offset,segflg,unit,cred,aresid) \ vn_rdwr((rw),(gp),(base),(len),(offset),(segflg),(unit),(cred),(aresid),current_proc()) diff --git a/src/afs/DARWIN/osi_module.c b/src/afs/DARWIN/osi_module.c index e880764d0..d4e1136ef 100644 --- a/src/afs/DARWIN/osi_module.c +++ b/src/afs/DARWIN/osi_module.c @@ -40,7 +40,9 @@ afs_modload(struct kmod_info *ki, void *data) return KERN_FAILURE; } sysent[SYS_setgroups].sy_call = Afs_xsetgroups; +#if 0 sysent[SYS_ioctl].sy_call = afs_xioctl; +#endif sysent[AFS_SYSCALL].sy_call = afs3_syscall; sysent[AFS_SYSCALL].sy_narg = 5; sysent[AFS_SYSCALL].sy_parallel = 0; @@ -58,7 +60,9 @@ afs_modunload(struct kmod_info * ki, void *data) if (vfsconf_del("afs")) return KERN_FAILURE; /* give up syscall entries for ioctl & setgroups, which we've stolen */ +#if 0 sysent[SYS_ioctl].sy_call = ioctl; +#endif sysent[SYS_setgroups].sy_call = setgroups; /* give up the stolen syscall entry */ sysent[AFS_SYSCALL].sy_narg = 0; diff --git a/src/afs/DARWIN/osi_vfsops.c b/src/afs/DARWIN/osi_vfsops.c index 846bf2413..64d085eda 100644 --- a/src/afs/DARWIN/osi_vfsops.c +++ b/src/afs/DARWIN/osi_vfsops.c @@ -154,6 +154,15 @@ afs_unmount(mp, flags, p) mp->mnt_data = (qaddr_t) - 1; } else { if (flags & MNT_FORCE) { + if (afs_globalVp) { + AFS_GUNLOCK(); + vrele(AFSTOV(afs_globalVp)); + AFS_GLOCK(); + } + afs_globalVp = NULL; + AFS_GUNLOCK(); + vflush(mp, NULLVP, FORCECLOSE/*0*/); + AFS_GLOCK(); afs_globalVFS = 0; afs_shutdown(); } else { @@ -234,7 +243,7 @@ afs_vget(mp, lfl, vp) int lfl; { int error; - printf("vget called. help!\n"); + //printf("vget called. help!\n"); if (vp->v_usecount < 0) { vprint("bad usecount", vp); panic("afs_vget"); diff --git a/src/afs/DARWIN/osi_vm.c b/src/afs/DARWIN/osi_vm.c index 4dfe738dc..1285bf2f4 100644 --- a/src/afs/DARWIN/osi_vm.c +++ b/src/afs/DARWIN/osi_vm.c @@ -38,55 +38,17 @@ int osi_VM_FlushVCache(struct vcache *avc, int *slept) { struct vnode *vp = AFSTOV(avc); -#ifdef AFS_DARWIN14_ENV - if (UBCINFOEXISTS(vp)) - return EBUSY; -#endif - if (avc->vrefCount > DARWIN_REFBASE) - return EBUSY; - - if (avc->opens) - return EBUSY; - - /* if a lock is held, give up */ - if (CheckLock(&avc->lock)) - return EBUSY; + kern_return_t kret; + off_t size; AFS_GUNLOCK(); - cache_purge(vp); -#ifndef AFS_DARWIN14_ENV - if (UBCINFOEXISTS(vp)) { - ubc_clean(vp, 1); - ubc_uncache(vp); - ubc_release(vp); - ubc_info_free(vp); - } -#else - /* This is literally clean_up_name_parent_ptrs() */ - /* Critical to clean up any state attached to the vnode here since it's - being recycled, and we're not letting refcnt drop to 0 to trigger - normal recycling. */ - if (VNAME(vp) || VPARENT(vp)) { - char *tmp1; - struct vnode *tmp2; - - /* do it this way so we don't block before clearing - these fields. */ - tmp1 = VNAME(vp); - tmp2 = VPARENT(vp); - VNAME(vp) = NULL; - VPARENT(vp) = NULL; - - if (tmp1) { - remove_name(tmp1); - } - - if (tmp2) { - vrele(tmp2); - } +#if 0 + if (!(UBCINFOMISSING(vp) || UBCINFORECLAIMED(vp))) { + size=ubc_getsize(vp); + kret=ubc_invalidate(vp,0,size); } #endif - + cache_purge(vp); AFS_GLOCK(); return 0; @@ -161,6 +123,7 @@ osi_VM_FlushPages(struct vcache *avc, struct AFS_UCRED *credp) printf("VMFlushPages: invalidate failed (error = %d)\n", kret); /* XXX what about when not CStatd */ if (avc->states & CStatd && size != avc->m.Length) + if (UBCISVALID(vp)) ubc_setsize(vp, avc->m.Length); } } @@ -175,181 +138,18 @@ void osi_VM_Truncate(struct vcache *avc, int alen, struct AFS_UCRED *acred) { struct vnode *vp = AFSTOV(avc); - if (UBCINFOEXISTS(vp)) { + if (UBCINFOEXISTS(vp) && UBCISVALID(vp)) { ubc_setsize(vp, alen); } } -/* vnreclaim and vinactive are probably not aggressive enough to keep - enough afs vcaches free, so we try to do some of it ourselves */ -/* XXX there's probably not nearly enough locking here */ -void -osi_VM_TryReclaim(struct vcache *avc, int *slept) -{ - struct proc *p = current_proc(); - struct vnode *vp = AFSTOV(avc); - void *obj; -#ifdef AFS_DARWIN14_ENV - int didhold; -#endif - - if (slept) - *slept = 0; - VN_HOLD(vp); /* remove from inactive list */ - if (!simple_lock_try(&vp->v_interlock)) { - AFS_RELE(vp); - return; - } - if (!UBCINFOEXISTS(vp) || vp->v_usecount != 2+DARWIN_REFBASE) { - simple_unlock(&vp->v_interlock); - AFS_RELE(vp); - return; - } - if (ISSET(vp->v_flag, VUINACTIVE)) { - simple_unlock(&vp->v_interlock); - AFS_RELE(vp); - printf("vnode %x still inactive!", vp); - return; - } -#ifdef AFS_DARWIN14_ENV - if (vp->v_ubcinfo->ui_refcount > 1 || vp->v_ubcinfo->ui_mapped) { - simple_unlock(&vp->v_interlock); - AFS_RELE(vp); - return; - } - if (ISSET(vp->v_flag, VORECLAIM)) { - simple_unlock(&vp->v_interlock); - AFS_RELE(vp); - return; - } -#else - if (vp->v_ubcinfo->ui_holdcnt) { - simple_unlock(&vp->v_interlock); - AFS_RELE(vp); - return; - } -#endif - if (slept && ubc_issetflags(vp, UI_WASMAPPED)) { - /* We can't possibly release this in time for this NewVCache to get it */ - simple_unlock(&vp->v_interlock); - AFS_RELE(vp); - return; - } - -#ifndef AFS_DARWIN14_ENV - vp->v_usecount--; /* we want the usecount to be 1 */ -#endif - - if (slept) { - ReleaseWriteLock(&afs_xvcache); - *slept = 1; - } else - ReleaseReadLock(&afs_xvcache); - AFS_GUNLOCK(); - obj = 0; - if (ubc_issetflags(vp, UI_WASMAPPED)) { - simple_unlock(&vp->v_interlock); -#ifdef AFS_DARWIN14_ENV - ubc_release_named(vp); -#else - ubc_release(vp); -#endif - if (ubc_issetflags(vp, UI_HASOBJREF)) - printf("ubc_release didn't release the reference?!\n"); - } else { -#ifdef AFS_DARWIN14_ENV - SET(vp->v_flag, VORECLAIM); -#endif - if (!vn_lock(vp, LK_EXCLUSIVE|LK_INTERLOCK,current_proc())) { -#ifdef AFS_DARWIN14_ENV - obj = ubc_getobject(vp,UBC_HOLDOBJECT); - if ((didhold = ubc_hold(vp))) - (void)ubc_clean(vp, 0); -#else -#ifdef AFS_DARWIN13_ENV - obj = ubc_getobject(vp,(UBC_NOREACTIVATE|UBC_HOLDOBJECT)); -#else - obj = ubc_getobject(vp); -#endif - (void)ubc_clean(vp, 1); -#endif - vinvalbuf(vp, V_SAVE, &afs_osi_cred, p, 0, 0); - if (vp->v_usecount == -#ifdef AFS_DARWIN14_ENV - 2 + DARWIN_REFBASE -#else - 1 -#endif - ) - VOP_UNLOCK(vp, 0, p); /* was VOP_INACTIVE(vp, p); */ - else - VOP_UNLOCK(vp, 0, p); -#ifdef AFS_DARWIN14_ENV - if (didhold) - ubc_rele(vp); -#endif - if (obj) { - if (ISSET(vp->v_flag, VTERMINATE)) - panic("afs_vnreclaim: already terminating"); - SET(vp->v_flag, VTERMINATE); - memory_object_destroy(obj, 0); - while (ISSET(vp->v_flag, VTERMINATE)) { - SET(vp->v_flag, VTERMWANT); - tsleep((caddr_t)&vp->v_ubcinfo, PINOD, "afs_vnreclaim", 0); - } - } -#ifdef AFS_DARWIN14_ENV - simple_lock(&vp->v_interlock); - CLR(vp->v_flag, VORECLAIM); - if (ISSET((vp)->v_flag, VXWANT)) { - CLR((vp)->v_flag, VXWANT); - wakeup((caddr_t)(vp)); - } - vp->v_usecount--; - simple_unlock(&vp->v_interlock); -#endif - } else { -#ifdef AFS_DARWIN14_ENV - CLR(vp->v_flag, VORECLAIM); -#endif - if (simple_lock_try(&vp->v_interlock)) - panic("afs_vnreclaim: slept, but did no work :("); - if (UBCINFOEXISTS(vp) && vp->v_count == DARWIN_REFBASE + -#ifdef AFS_DARWIN14_ENV - 2 -#else - 1 -#endif - ) { -#ifndef AFS_DARWIN14_ENV - /* We left the refcount high in 1.4 */ - vp->v_usecount++; -#endif - simple_unlock(&vp->v_interlock); - VN_RELE(vp); - } else { -#ifdef AFS_DARWIN14_ENV - /* We left the refcount high in 1.4 */ - vp->v_usecount--; -#endif - simple_unlock(&vp->v_interlock); - } - } - } - AFS_GLOCK(); - if (slept) - ObtainWriteLock(&afs_xvcache,175); - else - ObtainReadLock(&afs_xvcache); -} - void osi_VM_NukePages(struct vnode *vp, off_t offset, off_t size) { +#if 0 void *object; struct vcache *avc = VTOAFS(vp); -#ifdef AFS_DARWIN14_ENV offset = trunc_page(offset); size = round_page(size + 1); while (size) { @@ -358,35 +158,6 @@ osi_VM_NukePages(struct vnode *vp, off_t offset, off_t size) size -= PAGE_SIZE; offset += PAGE_SIZE; } -#else - object = NULL; -#ifdef AFS_DARWIN13_ENV - if (UBCINFOEXISTS(vp)) - object = ubc_getobject(vp, UBC_NOREACTIVATE); -#else - if (UBCINFOEXISTS(vp)) - object = ubc_getobject(vp); -#endif - if (!object) - return; - - offset = trunc_page(offset); - size = round_page(size + 1); - -#ifdef AFS_DARWIN13_ENV - while (size) { - memory_object_page_op(object, (vm_offset_t) offset, - UPL_POP_SET | UPL_POP_BUSY | UPL_POP_DUMP, 0, - 0); - size -= PAGE_SIZE; - offset += PAGE_SIZE; - } -#else - /* This is all we can do, and it's not enough. sucks to be us */ - ubc_setsize(vp, offset); - size = (offset + size > avc->m.Length) ? offset + size : avc->m.Length; - ubc_setsize(vp, size); -#endif #endif } @@ -397,34 +168,23 @@ osi_VM_Setup(struct vcache *avc, int force) struct vnode *vp = AFSTOV(avc); if (UBCISVALID(vp) && ((avc->states & CStatd) || force)) { - if (!UBCINFOEXISTS(vp) && !ISSET(vp->v_flag, VTERMINATE)) { + if (!UBCINFOEXISTS(vp)) { osi_vnhold(avc, 0); avc->states |= CUBCinit; AFS_GUNLOCK(); - if ((error = ubc_info_init(&avc->v))) { + if ((error = ubc_info_init(vp))) { AFS_GLOCK(); avc->states &= ~CUBCinit; - AFS_RELE(avc); + AFS_RELE(vp); return error; } -#ifndef AFS_DARWIN14_ENV - simple_lock(&avc->v.v_interlock); - if (!ubc_issetflags(&avc->v, UI_HASOBJREF)) -#ifdef AFS_DARWIN13_ENV - if (ubc_getobject - (&avc->v, (UBC_NOREACTIVATE | UBC_HOLDOBJECT))) - panic("VM_Setup: null object"); -#else - (void)_ubc_getobject(&avc->v, 1); /* return value not used */ -#endif - simple_unlock(&avc->v.v_interlock); -#endif AFS_GLOCK(); avc->states &= ~CUBCinit; - AFS_RELE(avc); + AFS_RELE(vp); + } + if (UBCINFOEXISTS(vp) && UBCISVALID(vp)) { + ubc_setsize(vp, avc->m.Length); } - if (UBCINFOEXISTS(&avc->v)) - ubc_setsize(&avc->v, avc->m.Length); } return 0; } diff --git a/src/afs/DARWIN/osi_vnodeops.c b/src/afs/DARWIN/osi_vnodeops.c index 5eda837f5..cd49634ff 100644 --- a/src/afs/DARWIN/osi_vnodeops.c +++ b/src/afs/DARWIN/osi_vnodeops.c @@ -139,7 +139,32 @@ struct vnodeopv_desc afs_vnodeop_opv_desc = #define DROPNAME() FREE(name, M_TEMP) +void +darwin_vn_hold(struct vnode *vp) +{ + int haveGlock=ISAFS_GLOCK(); + struct vcache *tvc = VTOAFS(vp); + + tvc->states |= CUBCinit; + if (haveGlock) AFS_GUNLOCK(); + + /* vget needed for 0 ref'd vnode in GetVCache to not panic in vref. + vref needed for multiref'd vnode in vnop_remove not to deadlock + ourselves during vop_inactive, except we also need to not reinst + the ubc... so we just call VREF there now anyway. */ + + if (VREFCOUNT(tvc) > 0) + VREF(((struct vnode *)(vp))); + else + afs_vget(afs_globalVFS, 0, (vp)); + if (UBCINFOMISSING(vp) || UBCINFORECLAIMED(vp)) { + ubc_info_init(vp); + } + + if (haveGlock) AFS_GLOCK(); + tvc->states &= ~CUBCinit; +} int afs_vop_lookup(ap) @@ -190,14 +215,9 @@ afs_vop_lookup(ap) if (UBCINFOMISSING(vp) || UBCINFORECLAIMED(vp)) { -#ifdef AFS_DARWIN14_ENV - if (UBCINFORECLAIMED(vp) && ISSET(vp->v_flag, (VXLOCK|VORECLAIM))) { - DROPNAME(); - return (ENXIO); - } else -#endif ubc_info_init(vp); } + /* The parent directory comes in locked. We unlock it on return * unless the caller wants it left locked. * we also always return the vnode locked. */ @@ -264,15 +284,9 @@ afs_vop_create(ap) (*ap->a_vpp)->v_vfsp = dvp->v_vfsp; vn_lock(*ap->a_vpp, LK_EXCLUSIVE | LK_RETRY, p); if (UBCINFOMISSING(*ap->a_vpp) || UBCINFORECLAIMED(*ap->a_vpp)) { -#ifdef AFS_DARWIN14_ENV - if (UBCINFORECLAIMED(*ap->a_vpp) && ISSET((*ap->a_vpp)->v_flag, - (VXLOCK|VORECLAIM))) { - vput(dvp); - DROPNAME(); - return (ENXIO); - } else -#endif - ubc_info_init(*ap->a_vpp); + vcp->states |= CUBCinit; + ubc_info_init(*ap->a_vpp); + vcp->states &= ~CUBCinit; } } else *ap->a_vpp = 0; @@ -331,7 +345,9 @@ afs_vop_open(ap) if (AFSTOV(vc) != vp) panic("AFS open changed vnode!"); #endif +#if 0 osi_FlushPages(vc, ap->a_cred); +#endif AFS_GUNLOCK(); #ifdef AFS_DARWIN14_ENV if (error && didhold) @@ -357,29 +373,10 @@ afs_vop_close(ap) code = afs_close(avc, ap->a_fflag, ap->a_cred, ap->a_p); else code = afs_close(avc, ap->a_fflag, &afs_osi_cred, ap->a_p); +#if 0 osi_FlushPages(avc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */ - AFS_GUNLOCK(); -#ifdef AFS_DARWIN14_ENV - if (UBCINFOEXISTS(ap->a_vp) && ap->a_vp->v_ubcinfo->ui_refcount < 2) { - ubc_hold(ap->a_vp); - if (ap->a_vp->v_ubcinfo->ui_refcount < 2) { - printf("afs: Imminent ui_refcount panic\n"); - } else { - printf("afs: WARNING: ui_refcount panic averted\n"); - } - } - if (UBCINFOMISSING(ap->a_vp) || - UBCINFORECLAIMED(ap->a_vp)) { - if (UBCINFORECLAIMED(ap->a_vp) && ISSET(ap->a_vp->v_flag, - (VXLOCK|VORECLAIM))) { - printf("no ubc for %x in close, reclaim set\n", ap->a_vp); - return (ENXIO); - } else { - printf("no ubc for %x in close, put back\n", ap->a_vp); - ubc_info_init(ap->a_vp); - } - } #endif + AFS_GUNLOCK(); return code; } @@ -410,6 +407,7 @@ afs_vop_getattr(ap) * } */ *ap; { int code; + AFS_GLOCK(); code = afs_getattr(VTOAFS(ap->a_vp), ap->a_vap, ap->a_cred); AFS_GUNLOCK(); @@ -442,9 +440,12 @@ afs_vop_read(ap) * } */ *ap; { int code; - struct vcache *avc = VTOAFS(ap->a_vp); + struct vnode *vp = ap->a_vp; + struct vcache *avc = VTOAFS(vp); AFS_GLOCK(); +#if 0 osi_FlushPages(avc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */ +#endif code = afs_read(avc, ap->a_uio, ap->a_cred, 0, 0, 0); AFS_GUNLOCK(); return code; @@ -520,7 +521,9 @@ afs_vop_pagein(ap) auio.uio_resid = aiov.iov_len = size; aiov.iov_base = (caddr_t) ioaddr; AFS_GLOCK(); +#if 0 osi_FlushPages(tvc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */ +#endif code = afs_read(tvc, uio, cred, 0, 0, 0); if (code == 0) { ObtainWriteLock(&tvc->lock, 2); @@ -561,9 +564,12 @@ afs_vop_write(ap) struct vcache *avc = VTOAFS(ap->a_vp); void *object; AFS_GLOCK(); +#if 0 osi_FlushPages(avc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */ - if (UBCINFOEXISTS(ap->a_vp)) +#endif + if (UBCINFOEXISTS(ap->a_vp)) { ubc_clean(ap->a_vp, 1); + } if (UBCINFOEXISTS(ap->a_vp)) osi_VM_NukePages(ap->a_vp, ap->a_uio->uio_offset, ap->a_uio->uio_resid); @@ -703,7 +709,9 @@ afs_vop_pageout(ap) #endif /* ] USV */ AFS_GLOCK(); +#if 0 osi_FlushPages(tvc, ap->a_cred); /* hold bozon lock, but not basic vnode lock */ +#endif ObtainWriteLock(&tvc->lock, 1); afs_FakeOpen(tvc); ReleaseWriteLock(&tvc->lock); @@ -808,14 +816,15 @@ afs_vop_fsync(ap) int wait = ap->a_waitfor == MNT_WAIT; int error; register struct vnode *vp = ap->a_vp; + int haveGlock = ISAFS_GLOCK(); - AFS_GLOCK(); - /*vflushbuf(vp, wait); */ + /* afs_vop_lookup glocks, can call us through vinvalbuf from GetVCache */ + if (!haveGlock) AFS_GLOCK(); if (ap->a_cred) error = afs_fsync(VTOAFS(vp), ap->a_cred); else error = afs_fsync(VTOAFS(vp), &afs_osi_cred); - AFS_GUNLOCK(); + if (!haveGlock) AFS_GUNLOCK(); return error; } @@ -850,25 +859,19 @@ afs_vop_remove(ap) error = afs_remove(VTOAFS(dvp), name, cnp->cn_cred); AFS_GUNLOCK(); cache_purge(vp); - if (!error && UBCINFOEXISTS(vp)) { -#ifdef AFS_DARWIN14_ENV + vput(dvp); + if (!error) { + /* necessary so we don't deadlock ourselves in vclean */ + VOP_UNLOCK(vp, 0, cnp->cn_proc); + /* If crashes continue in ubc_hold, comment this out */ - /* (void)ubc_uncache(vp);*/ -#else - int wasmapped = ubc_issetflags(vp, UI_WASMAPPED); - int hasobjref = ubc_issetflags(vp, UI_HASOBJREF); - if (wasmapped) - (void)ubc_uncache(vp); - if (hasobjref) - ubc_release(vp); - /* WARNING vp may not be valid after this */ -#endif + (void)ubc_uncache(vp); } + if (dvp == vp) vrele(vp); else vput(vp); - vput(dvp); FREE_ZONE(cnp->cn_pnbuf, cnp->cn_pnlen, M_NAMEI); DROPNAME(); @@ -933,14 +936,14 @@ afs_vop_rename(ap) register struct vnode *fdvp = ap->a_fdvp; struct proc *p = fcnp->cn_proc; - /* Check for cross-device rename. - * For AFS, this means anything not in AFS-space - */ - if ((0 != strcmp(tdvp->v_mount->mnt_stat.f_fstypename, "afs")) || - (tvp && (0 != strcmp(tvp->v_mount->mnt_stat.f_fstypename, "afs")))) { - error = EXDEV; - goto abortit; - } + /* Check for cross-device rename. + * For AFS, this means anything not in AFS-space + */ + if ((0 != strcmp(tdvp->v_mount->mnt_stat.f_fstypename, "afs")) || + (tvp && (0 != strcmp(tvp->v_mount->mnt_stat.f_fstypename, "afs")))) { + error = EXDEV; + goto abortit; + } /* * if fvp == tvp, we're just removing one name of a pair of @@ -1217,30 +1220,25 @@ afs_vop_reclaim(ap) * struct vnode *a_vp; * } */ *ap; { - int error; + int error = 0; int sl; register struct vnode *vp = ap->a_vp; + int haveGlock = ISAFS_GLOCK(); + struct vcache *tvc = VTOAFS(vp); cache_purge(vp); /* just in case... */ + if (!haveGlock) + AFS_GLOCK(); + error = afs_FlushVCache(VTOAFS(vp), &sl); /* toss our stuff from vnode */ + if (!haveGlock) + AFS_GUNLOCK(); -#if 0 - AFS_GLOCK(); - error = afs_FlushVCache(VTOAFS(vp), &sl); /* tosses our stuff from vnode */ - AFS_GUNLOCK(); - ubc_unlink(vp); if (!error && vp->v_data) panic("afs_reclaim: vnode not cleaned"); - return error; -#else - if (vp->v_usecount == 2) { - vprint("reclaim count==2", vp); - } else if (vp->v_usecount == 1) { - vprint("reclaim count==1", vp); - } else - vprint("reclaim bad count", vp); + if (!error && (tvc->v != NULL)) + panic("afs_reclaim: vcache not cleaned"); - return 0; -#endif + return error; } int @@ -1254,6 +1252,7 @@ afs_vop_lock(ap) if (vp->v_tag == VT_NON) return (ENOENT); + return (lockmgr(&avc->rwlock, ap->a_flags, &vp->v_interlock, ap->a_p)); } @@ -1265,6 +1264,7 @@ afs_vop_unlock(ap) { struct vnode *vp = ap->a_vp; struct vcache *avc = VTOAFS(vp); + return (lockmgr (&avc->rwlock, ap->a_flags | LK_RELEASE, &vp->v_interlock, ap->a_p)); @@ -1282,7 +1282,6 @@ afs_vop_bmap(ap) * int *a_runb; * } */ *ap; { - struct vcache *vcp; int error; if (ap->a_bnp) { *ap->a_bnp = ap->a_bn * (PAGE_SIZE / DEV_BSIZE); @@ -1497,3 +1496,13 @@ afs_vop_cmap(ap) *ap->a_run = MAX(ap->a_size, AFS_CHUNKSIZE(ap->a_foffset)); return 0; } + +void +afs_darwin_getnewvnode(struct vcache *tvc) +{ + while (getnewvnode(VT_AFS, afs_globalVFS, afs_vnodeop_p, &tvc->v)) { + /* no vnodes available, force an alloc (limits be damned)! */ + printf("failed to get vnode\n"); + } + tvc->v->v_data = (void *)tvc; +} diff --git a/src/afs/VNOPS/afs_vnop_attrs.c b/src/afs/VNOPS/afs_vnop_attrs.c index fd1505907..84fd3f235 100644 --- a/src/afs/VNOPS/afs_vnop_attrs.c +++ b/src/afs/VNOPS/afs_vnop_attrs.c @@ -94,8 +94,8 @@ afs_CopyOutAttrs(register struct vcache *avc, register struct vattr *attrs) #elif defined(AFS_OSF_ENV) attrs->va_fsid = avc->v.v_mount->m_stat.f_fsid.val[0]; #elif defined(AFS_DARWIN70_ENV) - attrs->va_fsid = avc->v.v_mount->mnt_stat.f_fsid.val[0]; -#else + attrs->va_fsid = avc->v->v_mount->mnt_stat.f_fsid.val[0]; +#else /* ! AFS_DARWIN70_ENV */ attrs->va_fsid = 1; #endif if (avc->mvstat == 2) { diff --git a/src/afs/VNOPS/afs_vnop_remove.c b/src/afs/VNOPS/afs_vnop_remove.c index 5a1fb9d78..301e4e936 100644 --- a/src/afs/VNOPS/afs_vnop_remove.c +++ b/src/afs/VNOPS/afs_vnop_remove.c @@ -375,14 +375,9 @@ afs_remove(OSI_VC_ARG(adp), aname, acred) #ifdef AFS_AIX_ENV if (tvc && (VREFCOUNT(tvc) > 2) && tvc->opens > 0 && !(tvc->states & CUnlinked)) -#else -#ifdef AFS_DARWIN14_ENV - if (tvc && (VREFCOUNT(tvc) > 1 + DARWIN_REFBASE) && tvc->opens > 0 - && !(tvc->states & CUnlinked)) #else if (tvc && (VREFCOUNT(tvc) > 1) && tvc->opens > 0 && !(tvc->states & CUnlinked)) -#endif #endif { char *unlname = afs_newname(); @@ -429,9 +424,6 @@ afs_remunlink(register struct vcache *avc, register int doit) struct VenusFid dirFid; register struct dcache *tdc; afs_int32 code = 0; -#ifdef AFS_DARWIN14_ENV - int oldref; -#endif if (NBObtainWriteLock(&avc->lock, 423)) return 0; @@ -448,30 +440,17 @@ afs_remunlink(register struct vcache *avc, register int doit) cred = avc->uncred; avc->uncred = NULL; -#if defined(AFS_DARWIN_ENV) && !defined(AFS_DARWIN14_ENV) - /* this is called by vrele (via VOP_INACTIVE) when the refcount - * is 0. we can't just call VN_HOLD since vref will panic. - * we can't just call osi_vnhold because a later AFS_RELE will call - * vrele again, which will try to call VOP_INACTIVE again after - * vn_locking the vnode. which would be fine except that our vrele - * caller also locked the vnode... So instead, we just gimmick the - * refcounts and hope nobody else can touch the file now */ - osi_Assert(VREFCOUNT(avc) == 0); - VREFCOUNT_SET(avc, 1); -#endif +#ifdef AFS_DARWIN_ENV + VREF(AFSTOV(avc)); +#else VN_HOLD(AFSTOV(avc)); +#endif /* We'll only try this once. If it fails, just release the vnode. * Clear after doing hold so that NewVCache doesn't find us yet. */ avc->states &= ~(CUnlinked | CUnlinkedDel); -#ifdef AFS_DARWIN14_ENV - if (VREFCOUNT(avc) < 4) { - oldref = 4 - VREFCOUNT(avc); - VREFCOUNT_SET(avc, 4); - } -#endif ReleaseWriteLock(&avc->lock); dirFid.Cell = avc->fid.Cell; @@ -495,17 +474,6 @@ afs_remunlink(register struct vcache *avc, register int doit) } osi_FreeSmallSpace(unlname); crfree(cred); -#ifdef AFS_DARWIN_ENV -#ifndef AFS_DARWIN14_ENV - osi_Assert(VREFCOUNT(avc) == 1); - VREFCOUNT_SET(avc, 0); -#else - if (oldref) { - int newref = VREFCOUNT(avc) - oldref; - VREFCOUNT_SET(avc, newref); - } -#endif -#endif } } else { ReleaseWriteLock(&avc->lock); diff --git a/src/afs/afs.h b/src/afs/afs.h index 1ec276d38..6c7d4b675 100644 --- a/src/afs/afs.h +++ b/src/afs/afs.h @@ -551,7 +551,7 @@ struct SimpleLocks { #define VPageCleaning 0x2 /* Solaris - Cache Trunc Daemon sez keep out */ #define CPSIZE 2 -#if defined(AFS_XBSD_ENV) +#if defined(AFS_XBSD_ENV) || defined(AFS_DARWIN_ENV) #define vrefCount v->v_usecount #else #define vrefCount v.v_count @@ -594,7 +594,7 @@ struct vtodc { extern afs_uint32 afs_stampValue; /* stamp for pair's usage */ #define MakeStamp() (++afs_stampValue) -#if defined(AFS_XBSD_ENV) +#if defined(AFS_XBSD_ENV) || defined(AFS_DARWIN_ENV) #define VTOAFS(v) ((struct vcache *)(v)->v_data) #define AFSTOV(vc) ((vc)->v) #else @@ -612,7 +612,7 @@ extern afs_uint32 afs_stampValue; /* stamp for pair's usage */ * !(avc->nextfree) && !avc->vlruq.next => (FreeVCList == avc->nextfree) */ struct vcache { -#if defined(AFS_XBSD_ENV) +#if defined(AFS_XBSD_ENV)||defined(AFS_DARWIN_ENV) struct vnode *v; #else struct vnode v; /* Has reference count in v.v_count */ diff --git a/src/afs/afs_osi.h b/src/afs/afs_osi.h index 7390437c1..62c14baaf 100644 --- a/src/afs/afs_osi.h +++ b/src/afs/afs_osi.h @@ -119,6 +119,16 @@ struct afs_osi_WaitHandle { /* * Vnode related macros */ +#if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV) +#define vSetVfsp(vc, vfsp) AFSTOV(vc)->v_mount = (vfsp) +#define vSetType(vc, type) AFSTOV(vc)->v_type = (type) +#define vType(vc) AFSTOV(vc)->v_type +#else +#define vType(vc) (vc)->v.v_type +#define vSetType(vc,type) (vc)->v.v_type = (type) +#define vSetVfsp(vc,vfsp) (vc)->v.v_vfsp = (vfsp) +#endif + #ifndef AFS_OBSD_ENV #if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV) extern int (**afs_vnodeop_p) (); @@ -129,9 +139,6 @@ extern struct vnodeops *afs_ops; #define IsAfsVnode(vc) ((vc)->v_op == afs_ops) #define SetAfsVnode(vc) (vc)->v_op = afs_ops #endif -#define vType(vc) (vc)->v.v_type -#define vSetType(vc,type) (vc)->v.v_type = (type) -#define vSetVfsp(vc,vfsp) (vc)->v.v_vfsp = (vfsp) #endif #ifdef AFS_SGI65_ENV diff --git a/src/afs/afs_pioctl.c b/src/afs/afs_pioctl.c index 2523b70e1..a85298b0b 100644 --- a/src/afs/afs_pioctl.c +++ b/src/afs/afs_pioctl.c @@ -528,16 +528,16 @@ afs_xioctl(void) register int ioctlDone = 0, code = 0; AFS_STATCNT(afs_xioctl); -#if defined(AFS_XBSD_ENV) +#if defined(AFS_DARWIN_ENV) + if ((code = fdgetf(p, uap->fd, &fd))) + return code; +#elif defined(AFS_XBSD_ENV) fdp = p->p_fd; if ((u_int) uap->fd >= fdp->fd_nfiles || (fd = fdp->fd_ofiles[uap->fd]) == NULL) return EBADF; if ((fd->f_flag & (FREAD | FWRITE)) == 0) return EBADF; -#elif defined(AFS_DARWIN_ENV) - if ((code = fdgetf(p, uap->fd, &fd))) - return code; #elif defined(AFS_LINUX22_ENV) ua.com = com; ua.arg = arg; diff --git a/src/afs/afs_vcache.c b/src/afs/afs_vcache.c index 0b72cca34..74957b3eb 100644 --- a/src/afs/afs_vcache.c +++ b/src/afs/afs_vcache.c @@ -183,7 +183,7 @@ afs_FlushVCache(struct vcache *avc, int *slept) afs_osi_Free(avc->linkData, strlen(avc->linkData) + 1); avc->linkData = NULL; } -#if defined(AFS_XBSD_ENV) +#if defined(AFS_XBSD_ENV) || defined(AFS_DARWIN_ENV) /* OK, there are no internal vrefCounts, so there shouldn't * be any more refs here. */ if (avc->v) { @@ -664,30 +664,14 @@ afs_NewVCache(struct VenusFid *afid, struct server *serverp) if (tvc->states & CVFlushed) { refpanic("CVFlushed on VLRU"); +#if 0 } else if (i++ > 2 * afs_cacheStats) { /* even allowing for a few xallocs... */ refpanic("Increase -stat parameter of afsd(VLRU cycle?)"); +#endif } else if (QNext(uq) != tq) { refpanic("VLRU inconsistent"); } -#ifdef AFS_DARWIN_ENV - if ((VREFCOUNT(tvc) < DARWIN_REFBASE) || - (VREFCOUNT(tvc) < 1 + DARWIN_REFBASE && - UBCINFOEXISTS(&tvc->v))) { - VREFCOUNT_SET(tvc, - DARWIN_REFBASE + - (UBCINFOEXISTS(&tvc->v) ? 1 : 0)); - } - if (tvc->opens == 0 && ((tvc->states & CUnlinkedDel) == 0) - && VREFCOUNT(tvc) == DARWIN_REFBASE + 1 - && UBCINFOEXISTS(&tvc->v)) { - osi_VM_TryReclaim(tvc, &fv_slept); - if (fv_slept) { - uq = VLRU.prev; - i = 0; - continue; /* start over - may have raced. */ - } - } -#elif defined(AFS_LINUX22_ENV) +#if defined(AFS_LINUX22_ENV) if (tvc != afs_globalVp && VREFCOUNT(tvc) && tvc->opens == 0) { struct dentry *dentry; struct list_head *cur, *head = &(AFSTOI(tvc))->i_dentry; @@ -727,14 +711,13 @@ restart: } #endif - if (VREFCOUNT(tvc) == -#ifdef AFS_DARWIN_ENV - DARWIN_REFBASE -#else - 0 + if (((VREFCOUNT(tvc) == 0) +#if defined(AFS_DARWIN_ENV) && !defined(UKERNEL) + || ((VREFCOUNT(tvc) == 1) && + (UBCINFOEXISTS(AFSTOV(tvc)))) #endif - && tvc->opens == 0 && (tvc->states & CUnlinkedDel) == 0) { -#if defined(AFS_XBSD_ENV) + ) && tvc->opens == 0 && (tvc->states & CUnlinkedDel) == 0) { +#if defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) /* * vgone() reclaims the vnode, which calls afs_FlushVCache(), * then it puts the vnode on the free list. @@ -742,7 +725,9 @@ restart: * not on the free list. * XXX assume FreeBSD is the same for now. */ + AFS_GUNLOCK(); vgone(AFSTOV(tvc)); + AFS_GLOCK(); code = fv_slept = 0; #else code = afs_FlushVCache(tvc, &fv_slept); @@ -763,7 +748,11 @@ restart: if (!freeVCList) { /* none free, making one is better than a panic */ afs_stats_cmperf.vcacheXAllocs++; /* count in case we have a leak */ + if (afs_cacheStats == afs_stats_cmperf.vcacheXAllocs) printf("would vlru cycle panic\n"); tvc = (struct vcache *)afs_osi_Alloc(sizeof(struct vcache)); +#if defined(AFS_DARWIN_ENV) && !defined(UKERNEL) + tvc->v = NULL; /* important to clean this, or use memset 0 */ +#endif #ifdef KERNEL_HAVE_PIN pin((char *)tvc, sizeof(struct vcache)); /* XXX */ #endif @@ -792,7 +781,7 @@ restart: } #endif /* AFS_OSF_ENV */ -#if defined(AFS_XBSD_ENV) +#if defined(AFS_XBSD_ENV) || defined(AFS_DARWIN_ENV) if (tvc->v) panic("afs_NewVCache(): free vcache with vnode attached"); #endif @@ -814,6 +803,12 @@ restart: AFS_GLOCK(); lockinit(&tvc->rwlock, PINOD, "vcache", 0, 0); #endif +#ifdef AFS_DARWIN_ENV + AFS_GUNLOCK(); + afs_darwin_getnewvnode(tvc); /* includes one refcount */ + AFS_GLOCK(); + lockinit(&tvc->rwlock, PINOD, "vcache", 0, 0); +#endif #ifdef AFS_FBSD_ENV { struct vnode *vp; @@ -949,7 +944,7 @@ restart: /* Hold it for the LRU (should make count 2) */ VN_HOLD(AFSTOV(tvc)); #else /* AFS_OSF_ENV */ -#if !defined(AFS_XBSD_ENV) +#if !(defined (AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)) VREFCOUNT_SET(tvc, 1); /* us */ #endif /* AFS_XBSD_ENV */ #endif /* AFS_OSF_ENV */ @@ -1021,17 +1016,6 @@ restart: #else SetAfsVnode(AFSTOV(tvc)); #endif /* AFS_SGI64_ENV */ -#ifdef AFS_DARWIN_ENV - tvc->v.v_ubcinfo = UBC_INFO_NULL; - lockinit(&tvc->rwlock, PINOD, "vcache rwlock", 0, 0); - cache_purge(AFSTOV(tvc)); - tvc->v.v_data = tvc; - tvc->v.v_tag = VT_AFS; - /* VLISTNONE(&tvc->v); */ - tvc->v.v_freelist.tqe_next = 0; - tvc->v.v_freelist.tqe_prev = (struct vnode **)0xdeadb; - tvc->vrefCount += DARWIN_REFBASE; -#endif /* * The proper value for mvstat (for root fids) is setup by the caller. */ @@ -1236,14 +1220,6 @@ afs_FlushActiveVcaches(register afs_int32 doflocks) crfree(cred); } } -#ifdef AFS_DARWIN_ENV - if (VREFCOUNT(tvc) == 1 + DARWIN_REFBASE - && UBCINFOEXISTS(&tvc->v)) { - if (tvc->opens) - panic("flushactive open, hasubc, but refcnt 1"); - osi_VM_TryReclaim(tvc, 0); - } -#endif } } ReleaseReadLock(&afs_xvcache); @@ -1585,9 +1561,6 @@ afs_ProcessFS(register struct vcache *avc, #ifdef AFS_LINUX22_ENV vcache2inode(avc); /* Set the inode attr cache */ #endif -#ifdef AFS_DARWIN_ENV - osi_VM_Setup(avc, 1); -#endif } /*afs_ProcessFS */ @@ -1722,9 +1695,6 @@ afs_GetVCache(register struct VenusFid *afid, struct vrequest *areq, vcache2inode(tvc); #endif ReleaseWriteLock(&tvc->lock); -#ifdef AFS_DARWIN_ENV - osi_VM_Setup(tvc, 0); -#endif return tvc; } #if defined(AFS_OSF_ENV) @@ -1738,7 +1708,7 @@ afs_GetVCache(register struct VenusFid *afid, struct vrequest *areq, uvm_vnp_uncache(AFSTOV(tvc)); VOP_UNLOCK(AFSTOV(tvc), 0, curproc); #endif -#ifdef AFS_FBSD_ENV +#if defined(AFS_DARWIN_ENV) || defined(AFS_FBSD_ENV) /* * XXX - I really don't like this. Should try to understand better. * It seems that sometimes, when we get called, we already hold the @@ -1762,6 +1732,21 @@ afs_GetVCache(register struct VenusFid *afid, struct vrequest *areq, vinvalbuf(vp, V_SAVE, osi_curcred(), curthread, PINOD, 0); if (!iheldthelock) VOP_UNLOCK(vp, LK_EXCLUSIVE, curthread); +#else +#ifdef AFS_DARWIN_ENV + iheldthelock = VOP_ISLOCKED(vp); + if (!iheldthelock) + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, current_proc()); + /* this is messy. we can call fsync which will try to reobtain this */ + if (VTOAFS(vp) == tvc) + ReleaseWriteLock(&tvc->lock); + if (UBCINFOEXISTS(vp)) { + vinvalbuf(vp, V_SAVE, &afs_osi_cred, current_proc(), PINOD, 0); + } + if (VTOAFS(vp) == tvc) + ObtainWriteLock(&tvc->lock, 954); + if (!iheldthelock) + VOP_UNLOCK(vp, LK_EXCLUSIVE, current_proc()); #else iheldthelock = VOP_ISLOCKED(vp, curproc); if (!iheldthelock) @@ -1769,6 +1754,7 @@ afs_GetVCache(register struct VenusFid *afid, struct vrequest *areq, vinvalbuf(vp, V_SAVE, osi_curcred(), curproc, PINOD, 0); if (!iheldthelock) VOP_UNLOCK(vp, LK_EXCLUSIVE, curproc); +#endif #endif } #endif @@ -2057,22 +2043,6 @@ afs_GetRootVCache(struct VenusFid *afid, struct vrequest *areq, if (vg) continue; #endif /* AFS_OSF_ENV */ -#ifdef AFS_DARWIN14_ENV - /* It'd really suck if we allowed duplicate vcaches for the - * same fid to happen. Wonder if this will work? */ - struct vnode *vp = AFSTOV(tvc); - if (vp->v_flag & (VXLOCK | VORECLAIM | VTERMINATE)) { - printf("precluded FindVCache on %x (%d:%d:%d)\n", - vp, tvc->fid.Fid.Volume, tvc->fid.Fid.Vnode, - tvc->fid.Fid.Unique); - simple_lock(&vp->v_interlock); - SET(vp->v_flag, VTERMWANT); - simple_unlock(&vp->v_interlock); - (void)tsleep((caddr_t) & vp->v_ubcinfo, PINOD, "vget1", 0); - printf("VTERMWANT ended on %x\n", vp); - continue; - } -#endif break; } } @@ -2528,6 +2498,16 @@ afs_FindVCache(struct VenusFid *afid, afs_int32 * retry, afs_int32 flag) osi_vnhold(tvc, retry); /* already held, above */ if (retry && *retry) return 0; +#endif +#ifdef AFS_DARWIN_ENV + tvc->states |= CUBCinit; + AFS_GUNLOCK(); + if (UBCINFOMISSING(AFSTOV(tvc)) || + UBCINFORECLAIMED(AFSTOV(tvc))) { + ubc_info_init(AFSTOV(tvc)); + } + AFS_GLOCK(); + tvc->states &= ~CUBCinit; #endif /* * only move to front of vlru if we have proper vcache locking) @@ -2572,10 +2552,6 @@ afs_FindVCache(struct VenusFid *afid, afs_int32 * retry, afs_int32 flag) #ifdef AFS_LINUX22_ENV if (tvc && (tvc->states & CStatd)) vcache2inode(tvc); /* mainly to reset i_nlink */ -#endif -#ifdef AFS_DARWIN_ENV - if (tvc) - osi_VM_Setup(tvc, 0); #endif return tvc; } /*afs_FindVCache */ diff --git a/src/afsd/afs.rc.darwin b/src/afsd/afs.rc.darwin index dc7e6775a..65a9189f8 100644 --- a/src/afsd/afs.rc.darwin +++ b/src/afsd/afs.rc.darwin @@ -167,4 +167,4 @@ RestartService() StartService } -RunService "$1" +RunService "${1:-start}" diff --git a/src/config/param.ppc_darwin_70.h b/src/config/param.ppc_darwin_70.h index d3a1e6cb1..7a2d62dd5 100644 --- a/src/config/param.ppc_darwin_70.h +++ b/src/config/param.ppc_darwin_70.h @@ -66,8 +66,8 @@ #define direct dirent #define vnode_t struct vnode -#define VN_RELE(vp) vrele(((struct vnode *)(vp))) -#define VN_HOLD(vp) VREF(((struct vnode *)(vp))) +//#define VN_RELE(vp) vrele(((struct vnode *)(vp))) +//#define VN_HOLD(vp) VREF(((struct vnode *)(vp))) #define BIND_8_COMPAT #endif -- 2.39.5