macos disconnected vnode holding fix

tweak how we hold vcaches to avoid issues with the underlying
vnode having an iocount underrun due to races.

Change-Id: I96526ed52c11aac1124a8cf66458ba3e25e7efb2
Reviewed-on: http://gerrit.openafs.org/2501
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
This commit is contained in:
Derrick Brashear 2010-08-02 14:02:37 -04:00
parent 5abe706a7e
commit e6aa0b38e9
5 changed files with 62 additions and 2 deletions

View File

@ -2206,6 +2206,26 @@ afs_darwin_finalizevnode(struct vcache *avc, struct vnode *dvp, struct component
}
avc->v = nvp;
avc->f.states &=~ CDeadVnode;
/* If we were carrying an extra ref for dirty, hold/push it. */
if (avc->f.ddirty_flags) {
vnode_get(nvp);
vnode_ref(nvp);
}
/* If we were carrying an extra ref for shadow, hold/push it. */
if (avc->f.shadow.vnode) {
vnode_get(nvp);
vnode_ref(nvp);
}
}
/* Drop any extra dirty ref on the old vnode */
if (avc->f.ddirty_flags) {
vnode_put(ovp);
vnode_rele(ovp);
}
/* Drop any extra shadow ref on the old vnode */
if (avc->f.shadow.vnode) {
vnode_put(ovp);
vnode_rele(ovp);
}
vnode_put(ovp);
vnode_rele(ovp);

View File

@ -3399,7 +3399,7 @@ afs_MakeShadowDir(struct vcache *avc, struct dcache *adc)
ObtainWriteLock(&afs_xvcache, 763);
ObtainWriteLock(&afs_disconDirtyLock, 765);
QAdd(&afs_disconShadow, &avc->shadowq);
osi_vnhold(avc, 0);
osi_Assert((afs_RefVCache(avc) == 0));
ReleaseWriteLock(&afs_disconDirtyLock);
ReleaseWriteLock(&afs_xvcache);

View File

@ -1044,6 +1044,7 @@ extern struct vcache *afs_GetVCache(register struct VenusFid *afid,
struct vrequest *areq, afs_int32 * cached,
struct vcache *avc);
extern void afs_PutVCache(register struct vcache *avc);
extern int afs_RefVCache(struct vcache *avc);
extern void afs_ProcessFS(register struct vcache *avc,
register struct AFSFetchStatus *astat,
struct vrequest *areq);

View File

@ -2531,6 +2531,45 @@ findvc_sleep(struct vcache *avc, int flag)
}
}
}
/*!
* Add a reference on an existing vcache entry.
*
* \param tvc Pointer to the vcache.
*
* \note Environment: Must be called with at least one reference from
* elsewhere on the vcache, even if that reference will be dropped.
* The global lock is required.
*
* \return 0 on success, -1 on failure.
*/
int
afs_RefVCache(struct vcache *tvc)
{
#ifdef AFS_DARWIN80_ENV
vnode_t tvp;
#endif
/* AFS_STATCNT(afs_RefVCache); */
#ifdef AFS_DARWIN80_ENV
tvp = AFSTOV(tvc);
if (vnode_get(tvp))
return -1;
if (vnode_ref(tvp)) {
AFS_GUNLOCK();
/* AFSTOV(tvc) may be NULL */
vnode_put(tvp);
AFS_GLOCK();
return -1;
}
#else
osi_vnhold(tvc, 0);
#endif
return 0;
} /*afs_RefVCache */
/*!
* Find a vcache entry given a fid.
*

View File

@ -56,7 +56,7 @@ static_inline void afs_DisconAddDirty(struct vcache *avc, int operation, int loc
ObtainWriteLock(&afs_xvcache, 702);
ObtainWriteLock(&afs_disconDirtyLock, 703);
QAdd(&afs_disconDirty, &avc->dirtyq);
osi_vnhold(avc, 0);
osi_Assert((afs_RefVCache(avc) == 0));
ReleaseWriteLock(&afs_disconDirtyLock);
if (lock)
ReleaseWriteLock(&afs_xvcache);