From owner-svn-src-all@FreeBSD.ORG Mon Dec 8 11:04:17 2008 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 641D71065675; Mon, 8 Dec 2008 11:04:17 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 4CB918FC13; Mon, 8 Dec 2008 11:04:17 +0000 (UTC) (envelope-from kib@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 mB8B4Hc3058123; Mon, 8 Dec 2008 11:04:17 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mB8B4HwA058122; Mon, 8 Dec 2008 11:04:17 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <200812081104.mB8B4HwA058122@svn.freebsd.org> From: Konstantin Belousov Date: Mon, 8 Dec 2008 11:04:17 +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: r185761 - 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: Mon, 08 Dec 2008 11:04:17 -0000 Author: kib Date: Mon Dec 8 11:04:17 2008 New Revision: 185761 URL: http://svn.freebsd.org/changeset/base/185761 Log: The dqrele() function syncs the dq, then acquires the dqh lock, and then does final drop of the the dq reference to put it onto the free list. There is a possibility that the dq would be found by another thread after sync and before the dqh lock is acquired. If that other thread drops the dq before we have taken the dqh lock, the dirty dq is put on the free list. Recheck the DQ_MOD after the dqh lock is relocked. Repeat dqsync() if the dq is dirty. This ensures that up to date dq is written in the quota file and fixes assertion in dqget(). Reported and tested by: Frode Nordahl MFC after: 3 days Modified: head/sys/ufs/ufs/ufs_quota.c Modified: head/sys/ufs/ufs/ufs_quota.c ============================================================================== --- head/sys/ufs/ufs/ufs_quota.c Mon Dec 8 06:54:24 2008 (r185760) +++ head/sys/ufs/ufs/ufs_quota.c Mon Dec 8 11:04:17 2008 (r185761) @@ -1262,7 +1262,7 @@ dqrele(struct vnode *vp, struct dquot *d return; } DQH_UNLOCK(); - +sync: (void) dqsync(vp, dq); DQH_LOCK(); @@ -1271,6 +1271,18 @@ dqrele(struct vnode *vp, struct dquot *d DQH_UNLOCK(); return; } + + /* + * The dq may become dirty after it is synced but before it is + * put to the free list. Checking the DQ_MOD there without + * locking dq should be safe since no other references to the + * dq exist. + */ + if ((dq->dq_flags & DQ_MOD) != 0) { + dq->dq_cnt++; + DQH_UNLOCK(); + goto sync; + } TAILQ_INSERT_TAIL(&dqfreelist, dq, dq_freelist); DQH_UNLOCK(); }