diff options
author | jhb <jhb@FreeBSD.org> | 2008-09-22 20:53:22 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2008-09-22 20:53:22 +0000 |
commit | 82d0acb613c29a480c45a4e6baafc795717e68ba (patch) | |
tree | 777dd5bfb969889047b245f93182e644547d68fe /sys | |
parent | 849a6bf2d2e4f033bf8cdaee48416508a3cdf1fe (diff) | |
download | FreeBSD-src-82d0acb613c29a480c45a4e6baafc795717e68ba.zip FreeBSD-src-82d0acb613c29a480c45a4e6baafc795717e68ba.tar.gz |
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
Diffstat (limited to 'sys')
-rw-r--r-- | sys/ufs/ufs/ufs_dirhash.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/sys/ufs/ufs/ufs_dirhash.c b/sys/ufs/ufs/ufs_dirhash.c index 6aab479..0042ec0 100644 --- a/sys/ufs/ufs/ufs_dirhash.c +++ b/sys/ufs/ufs/ufs_dirhash.c @@ -461,6 +461,16 @@ ufsdirhash_free_locked(struct inode *ip) 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 * own reference on the dirhash structure. They will drop * that reference once they grab the vnode interlock and see @@ -479,11 +489,6 @@ ufsdirhash_free_locked(struct inode *ip) if (dh->dh_blkfree != NULL) 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. |