xfs: convert to SPDX license tags
[linux-2.6-block.git] / fs / xfs / xfs_trans_ail.c
index d4a2445215e6e5ddfbce41c2dde3c21b0e511d0d..55326f971cb36bb87e35552f461a81a1c206ef3f 100644 (file)
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc.
  * Copyright (c) 2008 Dave Chinner
  * All Rights Reserved.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it would be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write the Free Software Foundation,
- * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 #include "xfs.h"
 #include "xfs_fs.h"
 #ifdef DEBUG
 /*
  * Check that the list is sorted as it should be.
+ *
+ * Called with the ail lock held, but we don't want to assert fail with it
+ * held otherwise we'll lock everything up and won't be able to debug the
+ * cause. Hence we sample and check the state under the AIL lock and return if
+ * everything is fine, otherwise we drop the lock and run the ASSERT checks.
+ * Asserts may not be fatal, so pick the lock back up and continue onwards.
  */
 STATIC void
 xfs_ail_check(
-       struct xfs_ail  *ailp,
-       xfs_log_item_t  *lip)
+       struct xfs_ail          *ailp,
+       struct xfs_log_item     *lip)
 {
-       xfs_log_item_t  *prev_lip;
+       struct xfs_log_item     *prev_lip;
+       struct xfs_log_item     *next_lip;
+       xfs_lsn_t               prev_lsn = NULLCOMMITLSN;
+       xfs_lsn_t               next_lsn = NULLCOMMITLSN;
+       xfs_lsn_t               lsn;
+       bool                    in_ail;
+
 
        if (list_empty(&ailp->ail_head))
                return;
 
        /*
-        * Check the next and previous entries are valid.
+        * Sample then check the next and previous entries are valid.
         */
-       ASSERT((lip->li_flags & XFS_LI_IN_AIL) != 0);
-       prev_lip = list_entry(lip->li_ail.prev, xfs_log_item_t, li_ail);
-       if (&prev_lip->li_ail != &ailp->ail_head)
-               ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) <= 0);
-
-       prev_lip = list_entry(lip->li_ail.next, xfs_log_item_t, li_ail);
+       in_ail = test_bit(XFS_LI_IN_AIL, &lip->li_flags);
+       prev_lip = list_entry(lip->li_ail.prev, struct xfs_log_item, li_ail);
        if (&prev_lip->li_ail != &ailp->ail_head)
-               ASSERT(XFS_LSN_CMP(prev_lip->li_lsn, lip->li_lsn) >= 0);
+               prev_lsn = prev_lip->li_lsn;
+       next_lip = list_entry(lip->li_ail.next, struct xfs_log_item, li_ail);
+       if (&next_lip->li_ail != &ailp->ail_head)
+               next_lsn = next_lip->li_lsn;
+       lsn = lip->li_lsn;
 
+       if (in_ail &&
+           (prev_lsn == NULLCOMMITLSN || XFS_LSN_CMP(prev_lsn, lsn) <= 0) &&
+           (next_lsn == NULLCOMMITLSN || XFS_LSN_CMP(next_lsn, lsn) >= 0))
+               return;
 
+       spin_unlock(&ailp->ail_lock);
+       ASSERT(in_ail);
+       ASSERT(prev_lsn == NULLCOMMITLSN || XFS_LSN_CMP(prev_lsn, lsn) <= 0);
+       ASSERT(next_lsn == NULLCOMMITLSN || XFS_LSN_CMP(next_lsn, lsn) >= 0);
+       spin_lock(&ailp->ail_lock);
 }
 #else /* !DEBUG */
 #define        xfs_ail_check(a,l)
@@ -684,7 +693,7 @@ xfs_trans_ail_update_bulk(
 
        for (i = 0; i < nr_items; i++) {
                struct xfs_log_item *lip = log_items[i];
-               if (lip->li_flags & XFS_LI_IN_AIL) {
+               if (test_and_set_bit(XFS_LI_IN_AIL, &lip->li_flags)) {
                        /* check if we really need to move the item */
                        if (XFS_LSN_CMP(lsn, lip->li_lsn) <= 0)
                                continue;
@@ -694,7 +703,6 @@ xfs_trans_ail_update_bulk(
                        if (mlip == lip)
                                mlip_changed = 1;
                } else {
-                       lip->li_flags |= XFS_LI_IN_AIL;
                        trace_xfs_ail_insert(lip, 0, lsn);
                }
                lip->li_lsn = lsn;
@@ -725,7 +733,7 @@ xfs_ail_delete_one(
        trace_xfs_ail_delete(lip, mlip->li_lsn, lip->li_lsn);
        xfs_ail_delete(ailp, lip);
        xfs_clear_li_failed(lip);
-       lip->li_flags &= ~XFS_LI_IN_AIL;
+       clear_bit(XFS_LI_IN_AIL, &lip->li_flags);
        lip->li_lsn = 0;
 
        return mlip == lip;
@@ -761,7 +769,7 @@ xfs_trans_ail_delete(
        struct xfs_mount        *mp = ailp->ail_mount;
        bool                    mlip_changed;
 
-       if (!(lip->li_flags & XFS_LI_IN_AIL)) {
+       if (!test_bit(XFS_LI_IN_AIL, &lip->li_flags)) {
                spin_unlock(&ailp->ail_lock);
                if (!XFS_FORCED_SHUTDOWN(mp)) {
                        xfs_alert_tag(mp, XFS_PTAG_AILDELETE,