svn commit: r185761 - head/sys/ufs/ufs

Konstantin Belousov kib at FreeBSD.org
Mon Dec 8 03:04:17 PST 2008


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 <frode nordahl net>
  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();
 }


More information about the svn-src-head mailing list