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 *ndh;
|
||||||
struct dirhash *dh;
|
struct dirhash *dh;
|
||||||
struct vnode *vp;
|
struct vnode *vp;
|
||||||
|
bool excl;
|
||||||
|
|
||||||
ndh = dh = NULL;
|
ndh = dh = NULL;
|
||||||
vp = ip->i_vnode;
|
vp = ip->i_vnode;
|
||||||
|
excl = false;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* Racy check for i_dirhash to prefetch a dirhash structure. */
|
/* Racy check for i_dirhash to prefetch a dirhash structure. */
|
||||||
if (ip->i_dirhash == NULL && ndh == NULL) {
|
if (ip->i_dirhash == NULL && ndh == NULL) {
|
||||||
@ -228,8 +230,11 @@ ufsdirhash_create(struct inode *ip)
|
|||||||
ufsdirhash_hold(dh);
|
ufsdirhash_hold(dh);
|
||||||
VI_UNLOCK(vp);
|
VI_UNLOCK(vp);
|
||||||
|
|
||||||
/* Acquire a shared lock on existing hashes. */
|
/* Acquire a lock on existing hashes. */
|
||||||
sx_slock(&dh->dh_lock);
|
if (excl)
|
||||||
|
sx_xlock(&dh->dh_lock);
|
||||||
|
else
|
||||||
|
sx_slock(&dh->dh_lock);
|
||||||
|
|
||||||
/* The hash could've been recycled while we were waiting. */
|
/* The hash could've been recycled while we were waiting. */
|
||||||
VI_LOCK(vp);
|
VI_LOCK(vp);
|
||||||
@ -250,9 +255,10 @@ ufsdirhash_create(struct inode *ip)
|
|||||||
* so we can recreate it. If we fail the upgrade, drop our
|
* so we can recreate it. If we fail the upgrade, drop our
|
||||||
* lock and try again.
|
* lock and try again.
|
||||||
*/
|
*/
|
||||||
if (sx_try_upgrade(&dh->dh_lock))
|
if (excl || sx_try_upgrade(&dh->dh_lock))
|
||||||
break;
|
break;
|
||||||
sx_sunlock(&dh->dh_lock);
|
sx_sunlock(&dh->dh_lock);
|
||||||
|
excl = true;
|
||||||
}
|
}
|
||||||
/* Free the preallocated structure if it was not necessary. */
|
/* Free the preallocated structure if it was not necessary. */
|
||||||
if (ndh) {
|
if (ndh) {
|
||||||
|
Loading…
Reference in New Issue
Block a user