[PATCH 33/45] xfs: reclaim clean dquots first

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Always try to reclaim clean dquots before doing I/O in the dquot shrinker.
This is still a bit suboptimal compared to how e.g. the inode shrinker
works, but it is required for the removal of the global delwri lists.

Signed-off-by: Christoph Hellwig <hch@xxxxxx>

---
 fs/xfs/xfs_qm.c |   35 +++++++++++++++++++++--------------
 1 file changed, 21 insertions(+), 14 deletions(-)

Index: xfs/fs/xfs/xfs_qm.c
===================================================================
--- xfs.orig/fs/xfs/xfs_qm.c	2011-10-27 22:40:08.594173542 +0200
+++ xfs/fs/xfs/xfs_qm.c	2011-10-27 22:40:09.097172140 +0200
@@ -1599,7 +1599,8 @@ xfs_qm_init_quotainos(
 
 STATIC bool
 xfs_qm_dqreclaim_one(
-	struct xfs_dquot	*dqp)
+	struct xfs_dquot	*dqp,
+	bool			write_dirty)
 {
 	struct xfs_mount	*mp = dqp->q_mount;
 	int			error;
@@ -1642,23 +1643,18 @@ xfs_qm_dqreclaim_one(
 	 * dirty dquots.
 	 */
 	if (XFS_DQ_IS_DIRTY(dqp)) {
+		if (!write_dirty)
+			goto out_busy;
+
 		trace_xfs_dqreclaim_dirty(dqp);
 
-		/*
-		 * We flush it delayed write, so don't bother releasing the
-		 * freelist lock.
-		 */
-		error = xfs_qm_dqflush(dqp, 0);
+		mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
+		error = xfs_qm_dqflush(dqp, SYNC_WAIT);
 		if (error) {
 			xfs_warn(mp, "%s: dquot %p flush failed",
 				 __func__, dqp);
 		}
-
-		/*
-		 * Give the dquot another try on the freelist, as the
-		 * flushing will take some time.
-		 */
-		goto out_busy;
+		mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
 	}
 	xfs_dqfunlock(dqp);
 
@@ -1698,7 +1694,7 @@ xfs_qm_shake(
 	struct shrink_control	*sc)
 {
 	int			nr_to_scan = sc->nr_to_scan;
-	struct xfs_dquot	*dqp;
+	struct xfs_dquot	*dqp, *n;
 
 	if ((sc->gfp_mask & (__GFP_FS|__GFP_WAIT)) != (__GFP_FS|__GFP_WAIT))
 		return 0;
@@ -1706,16 +1702,27 @@ xfs_qm_shake(
 	if (!nr_to_scan)
 		goto out;
 
+	/*
+	 * We first try to reclaim only clean dquots, and only if we have to
+	 * start writing dirty ones.
+	 */
 	mutex_lock(&xfs_Gqm->qm_dqfrlist_lock);
+	list_for_each_entry_safe(dqp, n, &xfs_Gqm->qm_dqfrlist, q_freelist) {
+		if (nr_to_scan-- <= 0)
+			goto out_unlock;
+		xfs_qm_dqreclaim_one(dqp, false);
+	}
+
 	while (!list_empty(&xfs_Gqm->qm_dqfrlist)) {
 		if (nr_to_scan-- <= 0)
 			break;
 		dqp = list_first_entry(&xfs_Gqm->qm_dqfrlist, struct xfs_dquot,
 				       q_freelist);
 
-		if (!xfs_qm_dqreclaim_one(dqp))
+		if (!xfs_qm_dqreclaim_one(dqp, true))
 			list_move_tail(&dqp->q_freelist, &xfs_Gqm->qm_dqfrlist);
 	}
+out_unlock:
 	mutex_unlock(&xfs_Gqm->qm_dqfrlist_lock);
 out:
 	return (xfs_Gqm->qm_dqfrlist_cnt / 100) * sysctl_vfs_cache_pressure;

_______________________________________________
xfs mailing list
xfs@xxxxxxxxxxx
http://oss.sgi.com/mailman/listinfo/xfs


[Index of Archives]     [Linux XFS Devel]     [Linux Filesystem Development]     [Filesystem Testing]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux