From 82d0acb613c29a480c45a4e6baafc795717e68ba Mon Sep 17 00:00:00 2001 From: jhb Date: Mon, 22 Sep 2008 20:53:22 +0000 Subject: [PATCH] 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 --- sys/ufs/ufs/ufs_dirhash.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/sys/ufs/ufs/ufs_dirhash.c b/sys/ufs/ufs/ufs_dirhash.c index 6aab47967364..0042ec0c2814 100644 --- a/sys/ufs/ufs/ufs_dirhash.c +++ b/sys/ufs/ufs/ufs_dirhash.c @@ -460,6 +460,16 @@ ufsdirhash_free_locked(struct inode *ip) ip->i_dirhash = NULL; 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 @@ -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.