summaryrefslogtreecommitdiffstats
path: root/sys/ufs/ufs/ufs_dirhash.c
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2008-09-22 20:53:22 +0000
committerjhb <jhb@FreeBSD.org>2008-09-22 20:53:22 +0000
commit82d0acb613c29a480c45a4e6baafc795717e68ba (patch)
tree777dd5bfb969889047b245f93182e644547d68fe /sys/ufs/ufs/ufs_dirhash.c
parent849a6bf2d2e4f033bf8cdaee48416508a3cdf1fe (diff)
downloadFreeBSD-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/ufs/ufs/ufs_dirhash.c')
-rw-r--r--sys/ufs/ufs/ufs_dirhash.c15
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.
OpenPOWER on IntegriCloud