aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2011-04-07 22:45:07 -0400
committerDave Chinner <david@fromorbit.com>2011-04-07 22:45:07 -0400
commitfd074841cfe01b006465fb9388091012585e8dfb (patch)
tree7ec409fade00b6c18987e1cb2a62443c074ce274
parentcd4a3c503c185f5f0a20f04f90da0a6966dd03bd (diff)
xfs: push the AIL from memory reclaim and periodic sync
When we are short on memory, we want to expedite the cleaning of dirty objects. Hence when we run short on memory, we need to kick the AIL flushing into action to clean as many dirty objects as quickly as possible. To implement this, sample the lsn of the log item at the head of the AIL and use that as the push target for the AIL flush. Further, we keep items in the AIL that are dirty that are not tracked any other way, so we can get objects sitting in the AIL that don't get written back until the AIL is pushed. Hence to get the filesystem to the idle state, we might need to push the AIL to flush out any remaining dirty objects sitting in the AIL. This requires the same push mechanism as the reclaim push. This patch also renames xfs_trans_ail_tail() to xfs_ail_min_lsn() to match the new xfs_ail_max_lsn() function introduced in this patch. Similarly for xfs_trans_ail_push -> xfs_ail_push. Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Alex Elder <aelder@sgi.com>
-rw-r--r--fs/xfs/linux-2.6/xfs_sync.c7
-rw-r--r--fs/xfs/xfs_log.c6
-rw-r--r--fs/xfs/xfs_trans_ail.c50
-rw-r--r--fs/xfs/xfs_trans_priv.h7
4 files changed, 61 insertions, 9 deletions
diff --git a/fs/xfs/linux-2.6/xfs_sync.c b/fs/xfs/linux-2.6/xfs_sync.c
index debe2822c93..9ad956052b6 100644
--- a/fs/xfs/linux-2.6/xfs_sync.c
+++ b/fs/xfs/linux-2.6/xfs_sync.c
@@ -22,6 +22,7 @@
22#include "xfs_log.h" 22#include "xfs_log.h"
23#include "xfs_inum.h" 23#include "xfs_inum.h"
24#include "xfs_trans.h" 24#include "xfs_trans.h"
25#include "xfs_trans_priv.h"
25#include "xfs_sb.h" 26#include "xfs_sb.h"
26#include "xfs_ag.h" 27#include "xfs_ag.h"
27#include "xfs_mount.h" 28#include "xfs_mount.h"
@@ -462,6 +463,9 @@ xfs_sync_worker(
462 else 463 else
463 xfs_log_force(mp, 0); 464 xfs_log_force(mp, 0);
464 error = xfs_qm_sync(mp, SYNC_TRYLOCK); 465 error = xfs_qm_sync(mp, SYNC_TRYLOCK);
466
467 /* start pushing all the metadata that is currently dirty */
468 xfs_ail_push_all(mp->m_ail);
465 } 469 }
466 470
467 /* queue us up again */ 471 /* queue us up again */
@@ -1027,8 +1031,9 @@ xfs_reclaim_inode_shrink(
1027 1031
1028 mp = container_of(shrink, struct xfs_mount, m_inode_shrink); 1032 mp = container_of(shrink, struct xfs_mount, m_inode_shrink);
1029 if (nr_to_scan) { 1033 if (nr_to_scan) {
1030 /* kick background reclaimer */ 1034 /* kick background reclaimer and push the AIL */
1031 xfs_syncd_queue_reclaim(mp); 1035 xfs_syncd_queue_reclaim(mp);
1036 xfs_ail_push_all(mp->m_ail);
1032 1037
1033 if (!(gfp_mask & __GFP_FS)) 1038 if (!(gfp_mask & __GFP_FS))
1034 return -1; 1039 return -1;
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 25efa9b8a60..24643169e63 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -761,7 +761,7 @@ xfs_log_need_covered(xfs_mount_t *mp)
761 break; 761 break;
762 case XLOG_STATE_COVER_NEED: 762 case XLOG_STATE_COVER_NEED:
763 case XLOG_STATE_COVER_NEED2: 763 case XLOG_STATE_COVER_NEED2:
764 if (!xfs_trans_ail_tail(log->l_ailp) && 764 if (!xfs_ail_min_lsn(log->l_ailp) &&
765 xlog_iclogs_empty(log)) { 765 xlog_iclogs_empty(log)) {
766 if (log->l_covered_state == XLOG_STATE_COVER_NEED) 766 if (log->l_covered_state == XLOG_STATE_COVER_NEED)
767 log->l_covered_state = XLOG_STATE_COVER_DONE; 767 log->l_covered_state = XLOG_STATE_COVER_DONE;
@@ -801,7 +801,7 @@ xlog_assign_tail_lsn(
801 xfs_lsn_t tail_lsn; 801 xfs_lsn_t tail_lsn;
802 struct log *log = mp->m_log; 802 struct log *log = mp->m_log;
803 803
804 tail_lsn = xfs_trans_ail_tail(mp->m_ail); 804 tail_lsn = xfs_ail_min_lsn(mp->m_ail);
805 if (!tail_lsn) 805 if (!tail_lsn)
806 tail_lsn = atomic64_read(&log->l_last_sync_lsn); 806 tail_lsn = atomic64_read(&log->l_last_sync_lsn);
807 807
@@ -1239,7 +1239,7 @@ xlog_grant_push_ail(
1239 * the filesystem is shutting down. 1239 * the filesystem is shutting down.
1240 */ 1240 */
1241 if (!XLOG_FORCED_SHUTDOWN(log)) 1241 if (!XLOG_FORCED_SHUTDOWN(log))
1242 xfs_trans_ail_push(log->l_ailp, threshold_lsn); 1242 xfs_ail_push(log->l_ailp, threshold_lsn);
1243} 1243}
1244 1244
1245/* 1245/*
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 8012bfbc6dc..acdb92f14d5 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -90,6 +90,20 @@ xfs_ail_min(
90 return list_first_entry(&ailp->xa_ail, xfs_log_item_t, li_ail); 90 return list_first_entry(&ailp->xa_ail, xfs_log_item_t, li_ail);
91} 91}
92 92
93 /*
94 * Return a pointer to the last item in the AIL. If the AIL is empty, then
95 * return NULL.
96 */
97static xfs_log_item_t *
98xfs_ail_max(
99 struct xfs_ail *ailp)
100{
101 if (list_empty(&ailp->xa_ail))
102 return NULL;
103
104 return list_entry(ailp->xa_ail.prev, xfs_log_item_t, li_ail);
105}
106
93/* 107/*
94 * Return a pointer to the item which follows the given item in the AIL. If 108 * Return a pointer to the item which follows the given item in the AIL. If
95 * the given item is the last item in the list, then return NULL. 109 * the given item is the last item in the list, then return NULL.
@@ -114,7 +128,7 @@ xfs_ail_next(
114 * item in the AIL. 128 * item in the AIL.
115 */ 129 */
116xfs_lsn_t 130xfs_lsn_t
117xfs_trans_ail_tail( 131xfs_ail_min_lsn(
118 struct xfs_ail *ailp) 132 struct xfs_ail *ailp)
119{ 133{
120 xfs_lsn_t lsn = 0; 134 xfs_lsn_t lsn = 0;
@@ -130,6 +144,25 @@ xfs_trans_ail_tail(
130} 144}
131 145
132/* 146/*
147 * Return the maximum lsn held in the AIL, or zero if the AIL is empty.
148 */
149static xfs_lsn_t
150xfs_ail_max_lsn(
151 struct xfs_ail *ailp)
152{
153 xfs_lsn_t lsn = 0;
154 xfs_log_item_t *lip;
155
156 spin_lock(&ailp->xa_lock);
157 lip = xfs_ail_max(ailp);
158 if (lip)
159 lsn = lip->li_lsn;
160 spin_unlock(&ailp->xa_lock);
161
162 return lsn;
163}
164
165/*
133 * AIL traversal cursor initialisation. 166 * AIL traversal cursor initialisation.
134 * 167 *
135 * The cursor keeps track of where our current traversal is up 168 * The cursor keeps track of where our current traversal is up
@@ -504,7 +537,7 @@ xfs_ail_worker(
504 * any of the objects, so the lock is not needed. 537 * any of the objects, so the lock is not needed.
505 */ 538 */
506void 539void
507xfs_trans_ail_push( 540xfs_ail_push(
508 struct xfs_ail *ailp, 541 struct xfs_ail *ailp,
509 xfs_lsn_t threshold_lsn) 542 xfs_lsn_t threshold_lsn)
510{ 543{
@@ -526,6 +559,19 @@ xfs_trans_ail_push(
526} 559}
527 560
528/* 561/*
562 * Push out all items in the AIL immediately
563 */
564void
565xfs_ail_push_all(
566 struct xfs_ail *ailp)
567{
568 xfs_lsn_t threshold_lsn = xfs_ail_max_lsn(ailp);
569
570 if (threshold_lsn)
571 xfs_ail_push(ailp, threshold_lsn);
572}
573
574/*
529 * This is to be called when an item is unlocked that may have 575 * This is to be called when an item is unlocked that may have
530 * been in the AIL. It will wake up the first member of the AIL 576 * been in the AIL. It will wake up the first member of the AIL
531 * wait list if this item's unlocking might allow it to progress. 577 * wait list if this item's unlocking might allow it to progress.
diff --git a/fs/xfs/xfs_trans_priv.h b/fs/xfs/xfs_trans_priv.h
index 6ebd322bd37..6b164e9e9a1 100644
--- a/fs/xfs/xfs_trans_priv.h
+++ b/fs/xfs/xfs_trans_priv.h
@@ -104,12 +104,13 @@ xfs_trans_ail_delete(
104 xfs_trans_ail_delete_bulk(ailp, &lip, 1); 104 xfs_trans_ail_delete_bulk(ailp, &lip, 1);
105} 105}
106 106
107void xfs_trans_ail_push(struct xfs_ail *, xfs_lsn_t); 107void xfs_ail_push(struct xfs_ail *, xfs_lsn_t);
108void xfs_ail_push_all(struct xfs_ail *);
109xfs_lsn_t xfs_ail_min_lsn(struct xfs_ail *ailp);
110
108void xfs_trans_unlocked_item(struct xfs_ail *, 111void xfs_trans_unlocked_item(struct xfs_ail *,
109 xfs_log_item_t *); 112 xfs_log_item_t *);
110 113
111xfs_lsn_t xfs_trans_ail_tail(struct xfs_ail *ailp);
112
113struct xfs_log_item *xfs_trans_ail_cursor_first(struct xfs_ail *ailp, 114struct xfs_log_item *xfs_trans_ail_cursor_first(struct xfs_ail *ailp,
114 struct xfs_ail_cursor *cur, 115 struct xfs_ail_cursor *cur,
115 xfs_lsn_t lsn); 116 xfs_lsn_t lsn);