mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-04 18:59:37 +00:00
MFC r326657:
Fix livelock in ufsdirhash_create().
This commit is contained in:
parent
56580f3f6d
commit
f4c225ae42
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/stable/10/; revision=326846
@ -189,9 +189,11 @@ ufsdirhash_create(struct inode *ip)
|
||||
struct dirhash *ndh;
|
||||
struct dirhash *dh;
|
||||
struct vnode *vp;
|
||||
bool excl;
|
||||
|
||||
ndh = dh = NULL;
|
||||
vp = ip->i_vnode;
|
||||
excl = false;
|
||||
for (;;) {
|
||||
/* Racy check for i_dirhash to prefetch a dirhash structure. */
|
||||
if (ip->i_dirhash == NULL && ndh == NULL) {
|
||||
@ -228,7 +230,10 @@ ufsdirhash_create(struct inode *ip)
|
||||
ufsdirhash_hold(dh);
|
||||
VI_UNLOCK(vp);
|
||||
|
||||
/* Acquire a shared lock on existing hashes. */
|
||||
/* Acquire a lock on existing hashes. */
|
||||
if (excl)
|
||||
sx_xlock(&dh->dh_lock);
|
||||
else
|
||||
sx_slock(&dh->dh_lock);
|
||||
|
||||
/* The hash could've been recycled while we were waiting. */
|
||||
@ -250,9 +255,10 @@ ufsdirhash_create(struct inode *ip)
|
||||
* so we can recreate it. If we fail the upgrade, drop our
|
||||
* lock and try again.
|
||||
*/
|
||||
if (sx_try_upgrade(&dh->dh_lock))
|
||||
if (excl || sx_try_upgrade(&dh->dh_lock))
|
||||
break;
|
||||
sx_sunlock(&dh->dh_lock);
|
||||
excl = true;
|
||||
}
|
||||
/* Free the preallocated structure if it was not necessary. */
|
||||
if (ndh) {
|
||||
|
Loading…
Reference in New Issue
Block a user