SDF_RORECOVERY          = 7, /* read only recovery */
        SDF_SKIP_DLM_UNLOCK     = 8,
        SDF_FORCE_AIL_FLUSH     = 9,
-       SDF_AIL1_IO_ERROR       = 10,
-       SDF_FS_FROZEN           = 11,
-       SDF_WITHDRAWING         = 12, /* Will withdraw eventually */
+       SDF_FS_FROZEN           = 10,
+       SDF_WITHDRAWING         = 11, /* Will withdraw eventually */
 };
 
 enum gfs2_freeze_state {
        atomic_t sd_log_in_flight;
        struct bio *sd_log_bio;
        wait_queue_head_t sd_log_flush_wait;
-       int sd_log_error;
+       int sd_log_error; /* First log error */
 
        atomic_t sd_reserving_log;
        wait_queue_head_t sd_reserving_log_wait;
 
                                          &tr->tr_ail2_list);
                                continue;
                        }
-                       if (!test_and_set_bit(SDF_AIL1_IO_ERROR,
-                                             &sdp->sd_flags)) {
+                       if (!cmpxchg(&sdp->sd_log_error, 0, -EIO)) {
                                gfs2_io_error_bh(sdp, bh);
                                gfs2_withdraw_delayed(sdp);
                        }
                                         bd_ail_st_list) {
                bh = bd->bd_bh;
                gfs2_assert(sdp, bd->bd_tr == tr);
-               if (buffer_busy(bh))
+               /*
+                * If another process flagged an io error, e.g. writing to the
+                * journal, error all other bhs and move them off the ail1 to
+                * prevent a tight loop when unmount tries to flush ail1,
+                * regardless of whether they're still busy. If no outside
+                * errors were found and the buffer is busy, move to the next.
+                * If the ail buffer is not busy and caught an error, flag it
+                * for others.
+                */
+               if (!sdp->sd_log_error && buffer_busy(bh))
                        continue;
                if (!buffer_uptodate(bh) &&
-                   !test_and_set_bit(SDF_AIL1_IO_ERROR, &sdp->sd_flags)) {
+                   !cmpxchg(&sdp->sd_log_error, 0, -EIO)) {
                        gfs2_io_error_bh(sdp, bh);
                        gfs2_withdraw_delayed(sdp);
                }
 
                return;
        if (!gfs2_withdrawn(sdp)) {
                fs_err(sdp, "gfs2_quotad: %s error %d\n", msg, error);
-               sdp->sd_log_error = error;
+               cmpxchg(&sdp->sd_log_error, 0, error);
                wake_up(&sdp->sd_logd_waitq);
        }
 }