xfs
[Top] [All Lists]

[PATCH 4/5] xfs: make AIL target updates and compares 32bit safe.

To: xfs@xxxxxxxxxxx
Subject: [PATCH 4/5] xfs: make AIL target updates and compares 32bit safe.
From: Dave Chinner <david@xxxxxxxxxxxxx>
Date: Fri, 6 May 2011 12:54:07 +1000
In-reply-to: <1304650448-28438-1-git-send-email-david@xxxxxxxxxxxxx>
References: <1304650448-28438-1-git-send-email-david@xxxxxxxxxxxxx>
From: Dave Chinner <dchinner@xxxxxxxxxx>

The recent conversion of the xfsaild functionality to a work queue
introduced a hard-to-hit log space grant hang. One of the problems
noticed was that updates of the push target are not 32 bit safe as
the target is a 64 bit value.

We cannot copy a 64 bit LSN without the possibility of corrupting
the result when racing with another updating thread. We have
function to do this update safely without needing to care about
32/64 bit issues - xfs_trans_ail_copy_lsn() - so use that when
updating the AIL push target.

Also move the reading of the target in the push work inside the AIL
lock, and use XFS_LSN_CMP() for the unlocked comparison during work
termination to close read holes as well.

Signed-off-by: Dave Chinner <david@xxxxxxxxxxxxx>
---
 fs/xfs/xfs_trans_ail.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 9f427c2..d7eebbf 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -354,7 +354,7 @@ xfs_ail_worker(
        struct xfs_ail_cursor   *cur = &ailp->xa_cursors;
        xfs_log_item_t          *lip;
        xfs_lsn_t               lsn;
-       xfs_lsn_t               target = ailp->xa_target;
+       xfs_lsn_t               target;
        long                    tout = 10;
        int                     flush_log = 0;
        int                     stuck = 0;
@@ -362,6 +362,7 @@ xfs_ail_worker(
        int                     push_xfsbufd = 0;
 
        spin_lock(&ailp->xa_lock);
+       target = ailp->xa_target;
        xfs_trans_ail_cursor_init(ailp, cur);
        lip = xfs_trans_ail_cursor_first(ailp, cur, ailp->xa_last_pushed_lsn);
        if (!lip || XFS_FORCED_SHUTDOWN(mp)) {
@@ -491,7 +492,7 @@ out_done:
                 * work to do. Wait a bit longer before starting that work.
                 */
                smp_rmb();
-               if (ailp->xa_target == target) {
+               if (XFS_LSN_CMP(ailp->xa_target, target) == 0) {
                        clear_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags);
                        return;
                }
@@ -553,7 +554,7 @@ xfs_ail_push(
         * the XFS_AIL_PUSHING_BIT.
         */
        smp_wmb();
-       ailp->xa_target = threshold_lsn;
+       xfs_trans_ail_copy_lsn(ailp, &ailp->xa_target, &threshold_lsn);
        if (!test_and_set_bit(XFS_AIL_PUSHING_BIT, &ailp->xa_flags))
                queue_delayed_work(xfs_syncd_wq, &ailp->xa_work, 0);
 }
-- 
1.7.4.4

<Prev in Thread] Current Thread [Next in Thread>