From owner-svn-src-all@FreeBSD.ORG Wed Jun 17 18:55:30 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 46098106564A; Wed, 17 Jun 2009 18:55:30 +0000 (UTC) (envelope-from snb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 19A7F8FC14; Wed, 17 Jun 2009 18:55:30 +0000 (UTC) (envelope-from snb@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n5HItTox084995; Wed, 17 Jun 2009 18:55:29 GMT (envelope-from snb@svn.freebsd.org) Received: (from snb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n5HItT1G084993; Wed, 17 Jun 2009 18:55:29 GMT (envelope-from snb@svn.freebsd.org) Message-Id: <200906171855.n5HItT1G084993@svn.freebsd.org> From: Sean Nicholas Barkas Date: Wed, 17 Jun 2009 18:55:29 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r194387 - head/sys/ufs/ufs X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 17 Jun 2009 18:55:31 -0000 Author: snb Date: Wed Jun 17 18:55:29 2009 New Revision: 194387 URL: http://svn.freebsd.org/changeset/base/194387 Log: Keep dirhash tailq locked throughout the entirety of ufsdirhash_destroy() to fix a potential race pointed out by pjd. Also use TAILQ_FOREACH_SAFE to iterate over dirhashes in ufsdirhash_lowmem(), so that we can continue iterating even after a dirhash is destroyed. Suggested by: pjd Tested by: pho Approved by: dwmalone (mentor) Modified: head/sys/ufs/ufs/ufs_dirhash.c Modified: head/sys/ufs/ufs/ufs_dirhash.c ============================================================================== --- head/sys/ufs/ufs/ufs_dirhash.c Wed Jun 17 18:52:42 2009 (r194386) +++ head/sys/ufs/ufs/ufs_dirhash.c Wed Jun 17 18:55:29 2009 (r194387) @@ -1191,16 +1191,14 @@ ufsdirhash_destroy(struct dirhash *dh) mem = dh->dh_memreq; dh->dh_memreq = 0; - /* Unlock everything, free the detached memory. */ + /* Unlock dirhash and free the detached memory. */ ufsdirhash_release(dh); - DIRHASHLIST_UNLOCK(); for (i = 0; i < narrays; i++) DIRHASH_BLKFREE(hash[i]); free(hash, M_DIRHASH); free(blkfree, M_DIRHASH); /* Account for the returned memory. */ - DIRHASHLIST_LOCK(); ufs_dirhashmem -= mem; return (mem); @@ -1247,7 +1245,7 @@ ufsdirhash_recycle(int wanted) static void ufsdirhash_lowmem() { - struct dirhash *dh; + struct dirhash *dh, *dh_temp; int memfreed = 0; /* XXX: this 10% may need to be adjusted */ int memwanted = ufs_dirhashmem / 10; @@ -1259,8 +1257,7 @@ ufsdirhash_lowmem() * Delete dirhashes not used for more than ufs_dirhashreclaimage * seconds. If we can't get a lock on the dirhash, it will be skipped. */ - for (dh = TAILQ_FIRST(&ufsdirhash_list); dh != NULL; dh = - TAILQ_NEXT(dh, dh_list)) { + TAILQ_FOREACH_SAFE(dh, &ufsdirhash_list, dh_list, dh_temp) { if (!sx_try_xlock(&dh->dh_lock)) continue; if (time_second - dh->dh_lastused > ufs_dirhashreclaimage) @@ -1275,11 +1272,14 @@ ufsdirhash_lowmem() * of the dirhash list. The ones closest to the head should be the * oldest. */ - for (dh = TAILQ_FIRST(&ufsdirhash_list); memfreed < memwanted && - dh !=NULL; dh = TAILQ_NEXT(dh, dh_list)) { - if (!sx_try_xlock(&dh->dh_lock)) - continue; - memfreed += ufsdirhash_destroy(dh); + if (memfreed < memwanted) { + TAILQ_FOREACH_SAFE(dh, &ufsdirhash_list, dh_list, dh_temp) { + if (!sx_try_xlock(&dh->dh_lock)) + continue; + memfreed += ufsdirhash_destroy(dh); + if (memfreed >= memwanted) + break; + } } DIRHASHLIST_UNLOCK(); }