* holding the lock before removing the inode from the AIL.
         */
        if (need_ail) {
-               bool                    mlip_changed = false;
+               xfs_lsn_t       tail_lsn = 0;
 
                /* this is an opencoded batch version of xfs_trans_ail_delete */
                spin_lock(&ailp->ail_lock);
                list_for_each_entry(blip, &tmp, li_bio_list) {
                        if (INODE_ITEM(blip)->ili_logged &&
-                           blip->li_lsn == INODE_ITEM(blip)->ili_flush_lsn)
-                               mlip_changed |= xfs_ail_delete_one(ailp, blip);
-                       else {
+                           blip->li_lsn == INODE_ITEM(blip)->ili_flush_lsn) {
+                               /*
+                                * xfs_ail_update_finish() only cares about the
+                                * lsn of the first tail item removed, any
+                                * others will be at the same or higher lsn so
+                                * we just ignore them.
+                                */
+                               xfs_lsn_t lsn = xfs_ail_delete_one(ailp, blip);
+                               if (!tail_lsn && lsn)
+                                       tail_lsn = lsn;
+                       } else {
                                xfs_clear_li_failed(blip);
                        }
                }
-               xfs_ail_update_finish(ailp, mlip_changed);
+               xfs_ail_update_finish(ailp, tail_lsn);
        }
 
        /*
 
  * We need the AIL lock in order to get a coherent read of the lsn of the last
  * item in the AIL.
  */
+static xfs_lsn_t
+__xfs_ail_min_lsn(
+       struct xfs_ail          *ailp)
+{
+       struct xfs_log_item     *lip = xfs_ail_min(ailp);
+
+       if (lip)
+               return lip->li_lsn;
+       return 0;
+}
+
 xfs_lsn_t
 xfs_ail_min_lsn(
        struct xfs_ail          *ailp)
 {
-       xfs_lsn_t               lsn = 0;
-       struct xfs_log_item     *lip;
+       xfs_lsn_t               lsn;
 
        spin_lock(&ailp->ail_lock);
-       lip = xfs_ail_min(ailp);
-       if (lip)
-               lsn = lip->li_lsn;
+       lsn = __xfs_ail_min_lsn(ailp);
        spin_unlock(&ailp->ail_lock);
 
        return lsn;
 void
 xfs_ail_update_finish(
        struct xfs_ail          *ailp,
-       bool                    do_tail_update) __releases(ailp->ail_lock)
+       xfs_lsn_t               old_lsn) __releases(ailp->ail_lock)
 {
        struct xfs_mount        *mp = ailp->ail_mount;
 
-       if (!do_tail_update) {
+       /* if the tail lsn hasn't changed, don't do updates or wakeups. */
+       if (!old_lsn || old_lsn == __xfs_ail_min_lsn(ailp)) {
                spin_unlock(&ailp->ail_lock);
                return;
        }
        xfs_lsn_t               lsn) __releases(ailp->ail_lock)
 {
        struct xfs_log_item     *mlip;
-       int                     mlip_changed = 0;
+       xfs_lsn_t               tail_lsn = 0;
        int                     i;
        LIST_HEAD(tmp);
 
                                continue;
 
                        trace_xfs_ail_move(lip, lip->li_lsn, lsn);
+                       if (mlip == lip && !tail_lsn)
+                               tail_lsn = lip->li_lsn;
+
                        xfs_ail_delete(ailp, lip);
-                       if (mlip == lip)
-                               mlip_changed = 1;
                } else {
                        trace_xfs_ail_insert(lip, 0, lsn);
                }
        if (!list_empty(&tmp))
                xfs_ail_splice(ailp, cur, &tmp, lsn);
 
-       xfs_ail_update_finish(ailp, mlip_changed);
+       xfs_ail_update_finish(ailp, tail_lsn);
 }
 
-bool
+/*
+ * Delete one log item from the AIL.
+ *
+ * If this item was at the tail of the AIL, return the LSN of the log item so
+ * that we can use it to check if the LSN of the tail of the log has moved
+ * when finishing up the AIL delete process in xfs_ail_update_finish().
+ */
+xfs_lsn_t
 xfs_ail_delete_one(
        struct xfs_ail          *ailp,
        struct xfs_log_item     *lip)
 {
        struct xfs_log_item     *mlip = xfs_ail_min(ailp);
+       xfs_lsn_t               lsn = lip->li_lsn;
 
        trace_xfs_ail_delete(lip, mlip->li_lsn, lip->li_lsn);
        xfs_ail_delete(ailp, lip);
        clear_bit(XFS_LI_IN_AIL, &lip->li_flags);
        lip->li_lsn = 0;
 
-       return mlip == lip;
+       if (mlip == lip)
+               return lsn;
+       return 0;
 }
 
 /**
        int                     shutdown_type)
 {
        struct xfs_mount        *mp = ailp->ail_mount;
-       bool                    need_update;
+       xfs_lsn_t               tail_lsn;
 
        if (!test_bit(XFS_LI_IN_AIL, &lip->li_flags)) {
                spin_unlock(&ailp->ail_lock);
                return;
        }
 
-       need_update = xfs_ail_delete_one(ailp, lip);
-       xfs_ail_update_finish(ailp, need_update);
+       tail_lsn = xfs_ail_delete_one(ailp, lip);
+       xfs_ail_update_finish(ailp, tail_lsn);
 }
 
 int
 
        xfs_trans_ail_update_bulk(ailp, NULL, &lip, 1, lsn);
 }
 
-bool xfs_ail_delete_one(struct xfs_ail *ailp, struct xfs_log_item *lip);
-void xfs_ail_update_finish(struct xfs_ail *ailp, bool do_tail_update)
+xfs_lsn_t xfs_ail_delete_one(struct xfs_ail *ailp, struct xfs_log_item *lip);
+void xfs_ail_update_finish(struct xfs_ail *ailp, xfs_lsn_t old_lsn)
                        __releases(ailp->ail_lock);
 void xfs_trans_ail_delete(struct xfs_ail *ailp, struct xfs_log_item *lip,
                int shutdown_type);