return NULL;
 }
 
+static inline void
+xfs_buf_list_del(
+       struct xfs_buf          *bp)
+{
+       list_del_init(&bp->b_list);
+       wake_up_var(&bp->b_list);
+}
+
 /*
  * Cancel a delayed write list.
  *
 
                xfs_buf_lock(bp);
                bp->b_flags &= ~_XBF_DELWRI_Q;
-               list_del_init(&bp->b_list);
+               xfs_buf_list_del(bp);
                xfs_buf_relse(bp);
        }
 }
        return true;
 }
 
+/*
+ * Queue a buffer to this delwri list as part of a data integrity operation.
+ * If the buffer is on any other delwri list, we'll wait for that to clear
+ * so that the caller can submit the buffer for IO and wait for the result.
+ * Callers must ensure the buffer is not already on the list.
+ */
+void
+xfs_buf_delwri_queue_here(
+       struct xfs_buf          *bp,
+       struct list_head        *buffer_list)
+{
+       /*
+        * We need this buffer to end up on the /caller's/ delwri list, not any
+        * old list.  This can happen if the buffer is marked stale (which
+        * clears DELWRI_Q) after the AIL queues the buffer to its list but
+        * before the AIL has a chance to submit the list.
+        */
+       while (!list_empty(&bp->b_list)) {
+               xfs_buf_unlock(bp);
+               wait_var_event(&bp->b_list, list_empty(&bp->b_list));
+               xfs_buf_lock(bp);
+       }
+
+       ASSERT(!(bp->b_flags & _XBF_DELWRI_Q));
+
+       xfs_buf_delwri_queue(bp, buffer_list);
+}
+
 /*
  * Compare function is more complex than it needs to be because
  * the return value is only 32 bits and we are doing comparisons
                 * reference and remove it from the list here.
                 */
                if (!(bp->b_flags & _XBF_DELWRI_Q)) {
-                       list_del_init(&bp->b_list);
+                       xfs_buf_list_del(bp);
                        xfs_buf_relse(bp);
                        continue;
                }
                        list_move_tail(&bp->b_list, wait_list);
                } else {
                        bp->b_flags |= XBF_ASYNC;
-                       list_del_init(&bp->b_list);
+                       xfs_buf_list_del(bp);
                }
                __xfs_buf_submit(bp, false);
        }
        while (!list_empty(&wait_list)) {
                bp = list_first_entry(&wait_list, struct xfs_buf, b_list);
 
-               list_del_init(&bp->b_list);
+               xfs_buf_list_del(bp);
 
                /*
                 * Wait on the locked buffer, check for errors and unlock and
 
 /* Delayed Write Buffer Routines */
 extern void xfs_buf_delwri_cancel(struct list_head *);
 extern bool xfs_buf_delwri_queue(struct xfs_buf *, struct list_head *);
+void xfs_buf_delwri_queue_here(struct xfs_buf *bp, struct list_head *bl);
 extern int xfs_buf_delwri_submit(struct list_head *);
 extern int xfs_buf_delwri_submit_nowait(struct list_head *);
 extern int xfs_buf_delwri_pushbuf(struct xfs_buf *, struct list_head *);