mirror of
https://git.openafs.org/openafs.git
synced 2025-02-01 14:07:39 +00:00
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:
parent
5abe706a7e
commit
e6aa0b38e9
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user