From owner-svn-src-head@freebsd.org Thu Dec 7 09:05:36 2017 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 2F6D2E80F60; Thu, 7 Dec 2017 09:05:36 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id F08C27D973; Thu, 7 Dec 2017 09:05:35 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id vB795ZhN016289; Thu, 7 Dec 2017 09:05:35 GMT (envelope-from kib@FreeBSD.org) Received: (from kib@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id vB795ZNl016288; Thu, 7 Dec 2017 09:05:35 GMT (envelope-from kib@FreeBSD.org) Message-Id: <201712070905.vB795ZNl016288@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kib set sender to kib@FreeBSD.org using -f From: Konstantin Belousov Date: Thu, 7 Dec 2017 09:05:35 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r326657 - head/sys/ufs/ufs X-SVN-Group: head X-SVN-Commit-Author: kib X-SVN-Commit-Paths: head/sys/ufs/ufs X-SVN-Commit-Revision: 326657 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 07 Dec 2017 09:05:36 -0000 Author: kib Date: Thu Dec 7 09:05:34 2017 New Revision: 326657 URL: https://svnweb.freebsd.org/changeset/base/326657 Log: Fix livelock in ufsdirhash_create(). When more than one thread enters ufsdirhash_create() for the same directory and the inode dirhash is instantiated, but the dirhash' hash is not, all of them lock the dirhash shared and then try to upgrade. Since there are several threads owning the lock shared, upgrade fails and the same attempt is repeated, ad infinitum. To break the lockstep, lock the dirhash in exclusive mode after the failed try-upgrade. Reported and tested by: pho Sponsored by: Mellanox Technologies MFC after: 1 week Modified: head/sys/ufs/ufs/ufs_dirhash.c Modified: head/sys/ufs/ufs/ufs_dirhash.c ============================================================================== --- head/sys/ufs/ufs/ufs_dirhash.c Thu Dec 7 07:55:38 2017 (r326656) +++ head/sys/ufs/ufs/ufs_dirhash.c Thu Dec 7 09:05:34 2017 (r326657) @@ -192,9 +192,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) { @@ -231,8 +233,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); @@ -253,9 +258,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) {