diff --git a/src/afs/SOLARIS/osi_machdep.h b/src/afs/SOLARIS/osi_machdep.h index 1e17748805..9027a0e7ca 100644 --- a/src/afs/SOLARIS/osi_machdep.h +++ b/src/afs/SOLARIS/osi_machdep.h @@ -56,7 +56,23 @@ local_osi_Time() #undef afs_osi_Alloc_NoSleep extern void *afs_osi_Alloc_NoSleep(size_t size); -#define osi_vnhold(avc, r) do { VN_HOLD(AFSTOV(avc)); } while(0) +#ifdef AFS_SUN58_ENV +# define osi_vnhold(avc, r) do { \ + struct vnode *vp = AFSTOV(avc); \ + uint_t prevcount; \ + \ + mutex_enter(&vp->v_lock); \ + prevcount = vp->v_count++; \ + mutex_exit(&vp->v_lock); \ + \ + if (prevcount == 0) { \ + VFS_HOLD(afs_globalVFS); \ + } \ +} while(0) +#else /* !AFS_SUN58_ENV */ +# define osi_vnhold(avc, r) do { VN_HOLD(AFSTOV(avc)); } while(0) +#endif /* !AFS_SUN58_ENV */ + #define gop_rdwr(rw,gp,base,len,offset,segflg,ioflag,ulimit,cr,aresid) \ vn_rdwr((rw),(gp),(base),(len),(offset),(segflg),(ioflag),(ulimit),(cr),(aresid)) #define gop_lookupname(fnamep,segflg,followlink,compvpp) \ diff --git a/src/afs/SOLARIS/osi_vcache.c b/src/afs/SOLARIS/osi_vcache.c index 14a3828684..7435ed3ec5 100644 --- a/src/afs/SOLARIS/osi_vcache.c +++ b/src/afs/SOLARIS/osi_vcache.c @@ -67,4 +67,11 @@ osi_PostPopulateVCache(struct vcache *avc) { AFSTOV(avc)->v_op = afs_ops; AFSTOV(avc)->v_vfsp = afs_globalVFS; vSetType(avc, VREG); + +#ifdef AFS_SUN58_ENV + /* Normally we do this in osi_vnhold when we notice the ref count went from + * 0 -> 1. But if we just setup or reused a vcache, we set the refcount to + * 1 directly. So, we must explicitly VFS_HOLD here. */ + VFS_HOLD(afs_globalVFS); +#endif } diff --git a/src/afs/SOLARIS/osi_vfsops.c b/src/afs/SOLARIS/osi_vfsops.c index c474f8aea0..31e9007cf3 100644 --- a/src/afs/SOLARIS/osi_vfsops.c +++ b/src/afs/SOLARIS/osi_vfsops.c @@ -96,6 +96,20 @@ afs_unmount(struct vfs *afsp, afs_ucred_t *credp) AFS_GUNLOCK(); return ENOTSUP; } + + /* We should have one reference from the caller, and one reference for the + * root vnode; any more and someone is still referencing something */ + if (afsp->vfs_count > 2) { + AFS_GUNLOCK(); + return EBUSY; + } + + /* The root vnode should have one ref for the mount; any more, and someone + * else is using the root vnode */ + if (afs_globalVp && VREFCOUNT_GT(afs_globalVp, 1)) { + AFS_GUNLOCK(); + return EBUSY; + } #endif /* AFS_SUN58_ENV */ afs_globalVFS = 0; diff --git a/src/afs/SOLARIS/osi_vnodeops.c b/src/afs/SOLARIS/osi_vnodeops.c index f02d19f12e..0ec2e09b0b 100644 --- a/src/afs/SOLARIS/osi_vnodeops.c +++ b/src/afs/SOLARIS/osi_vnodeops.c @@ -1815,6 +1815,11 @@ afs_inactive(struct vcache *avc, afs_ucred_t *acred) avc->opens = avc->execsOrWriters = 0; afs_InactiveVCache(avc, acred); + +#ifdef AFS_SUN58_ENV + VFS_RELE(afs_globalVFS); +#endif + return 0; }