Close a race between concurrent calls to ufsdirhash_recycle() and
ufsdirhash_free() introduced in my last commit by removing the dirhash about to be free'd in ufsdirhash_free() from the global dirhash list before dropping the sx lock. Tested by: kris
This commit is contained in:
parent
849a6bf2d2
commit
82d0acb613
@ -460,6 +460,16 @@ ufsdirhash_free_locked(struct inode *ip)
|
|||||||
ip->i_dirhash = NULL;
|
ip->i_dirhash = NULL;
|
||||||
VI_UNLOCK(vp);
|
VI_UNLOCK(vp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove the hash from the list since we are going to free its
|
||||||
|
* memory.
|
||||||
|
*/
|
||||||
|
DIRHASHLIST_LOCK();
|
||||||
|
if (dh->dh_onlist)
|
||||||
|
TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list);
|
||||||
|
ufs_dirhashmem -= dh->dh_memreq;
|
||||||
|
DIRHASHLIST_UNLOCK();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* At this point, any waiters for the lock should hold their
|
* At this point, any waiters for the lock should hold their
|
||||||
* own reference on the dirhash structure. They will drop
|
* own reference on the dirhash structure. They will drop
|
||||||
@ -479,11 +489,6 @@ ufsdirhash_free_locked(struct inode *ip)
|
|||||||
if (dh->dh_blkfree != NULL)
|
if (dh->dh_blkfree != NULL)
|
||||||
FREE(dh->dh_blkfree, M_DIRHASH);
|
FREE(dh->dh_blkfree, M_DIRHASH);
|
||||||
}
|
}
|
||||||
DIRHASHLIST_LOCK();
|
|
||||||
if (dh->dh_onlist)
|
|
||||||
TAILQ_REMOVE(&ufsdirhash_list, dh, dh_list);
|
|
||||||
ufs_dirhashmem -= dh->dh_memreq;
|
|
||||||
DIRHASHLIST_UNLOCK();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Drop the inode's reference to the data structure.
|
* Drop the inode's reference to the data structure.
|
||||||
|
Loading…
Reference in New Issue
Block a user