svn commit: r326845 - stable/11/sys/ufs/ufs
Konstantin Belousov
kib at FreeBSD.org
Thu Dec 14 11:41:13 UTC 2017
Author: kib
Date: Thu Dec 14 11:41:12 2017
New Revision: 326845
URL: https://svnweb.freebsd.org/changeset/base/326845
Log:
MFC r326657:
Fix livelock in ufsdirhash_create().
Modified:
stable/11/sys/ufs/ufs/ufs_dirhash.c
Directory Properties:
stable/11/ (props changed)
Modified: stable/11/sys/ufs/ufs/ufs_dirhash.c
==============================================================================
--- stable/11/sys/ufs/ufs/ufs_dirhash.c Thu Dec 14 08:57:37 2017 (r326844)
+++ stable/11/sys/ufs/ufs/ufs_dirhash.c Thu Dec 14 11:41:12 2017 (r326845)
@@ -190,9 +190,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) {
@@ -229,8 +231,11 @@ ufsdirhash_create(struct inode *ip)
ufsdirhash_hold(dh);
VI_UNLOCK(vp);
- /* Acquire a shared lock on existing hashes. */
- sx_slock(&dh->dh_lock);
+ /* 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. */
VI_LOCK(vp);
@@ -251,9 +256,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) {
More information about the svn-src-all
mailing list