--- /dev/null
+From 03b1293edad462ad1ad62bcc5160c76758e450d5 Mon Sep 17 00:00:00 2001
+From: Dave Chinner <david@fromorbit.com>
+Date: Fri, 2 Nov 2012 14:23:12 +1100
+Subject: xfs: fix buffer shudown reference count mismatch
+
+From: Dave Chinner <david@fromorbit.com>
+
+commit 03b1293edad462ad1ad62bcc5160c76758e450d5 upstream.
+
+When we shut down the filesystem, we have to unpin and free all the
+buffers currently active in the CIL. To do this we unpin and remove
+them in one operation as a result of a failed iclogbuf write. For
+buffers, we do this removal via a simultated IO completion of after
+marking the buffer stale.
+
+At the time we do this, we have two references to the buffer - the
+active LRU reference and the buf log item. The LRU reference is
+removed by marking the buffer stale, and the active CIL reference is
+by the xfs_buf_iodone() callback that is run by
+xfs_buf_do_callbacks() during ioend processing (via the bp->b_iodone
+callback).
+
+However, ioend processing requires one more reference - that of the
+IO that it is completing. We don't have this reference, so we free
+the buffer prematurely and use it after it is freed. For buffers
+marked with XBF_ASYNC, this leads to assert failures in
+xfs_buf_rele() on debug kernels because the b_hold count is zero.
+
+Fix this by making sure we take the necessary IO reference before
+starting IO completion processing on the stale buffer, and set the
+XBF_ASYNC flag to ensure that IO completion processing removes all
+the active references from the buffer to ensure it is fully torn
+down.
+
+Signed-off-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Mark Tinguely <tinguely@sgi.com>
+Signed-off-by: Ben Myers <bpm@sgi.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/xfs/xfs_buf_item.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+--- a/fs/xfs/xfs_buf_item.c
++++ b/fs/xfs/xfs_buf_item.c
+@@ -526,7 +526,25 @@ xfs_buf_item_unpin(
+ }
+ xfs_buf_relse(bp);
+ } else if (freed && remove) {
++ /*
++ * There are currently two references to the buffer - the active
++ * LRU reference and the buf log item. What we are about to do
++ * here - simulate a failed IO completion - requires 3
++ * references.
++ *
++ * The LRU reference is removed by the xfs_buf_stale() call. The
++ * buf item reference is removed by the xfs_buf_iodone()
++ * callback that is run by xfs_buf_do_callbacks() during ioend
++ * processing (via the bp->b_iodone callback), and then finally
++ * the ioend processing will drop the IO reference if the buffer
++ * is marked XBF_ASYNC.
++ *
++ * Hence we need to take an additional reference here so that IO
++ * completion processing doesn't free the buffer prematurely.
++ */
+ xfs_buf_lock(bp);
++ xfs_buf_hold(bp);
++ bp->b_flags |= XBF_ASYNC;
+ xfs_buf_ioerror(bp, EIO);
+ XFS_BUF_UNDONE(bp);
+ xfs_buf_stale(bp);
--- /dev/null
+From 6ce377afd1755eae5c93410ca9a1121dfead7b87 Mon Sep 17 00:00:00 2001
+From: Dave Chinner <dchinner@redhat.com>
+Date: Fri, 2 Nov 2012 11:38:44 +1100
+Subject: xfs: fix reading of wrapped log data
+
+From: Dave Chinner <dchinner@redhat.com>
+
+commit 6ce377afd1755eae5c93410ca9a1121dfead7b87 upstream.
+
+Commit 4439647 ("xfs: reset buffer pointers before freeing them") in
+3.0-rc1 introduced a regression when recovering log buffers that
+wrapped around the end of log. The second part of the log buffer at
+the start of the physical log was being read into the header buffer
+rather than the data buffer, and hence recovery was seeing garbage
+in the data buffer when it got to the region of the log buffer that
+was incorrectly read.
+
+Reported-by: Torsten Kaiser <just.for.lkml@googlemail.com>
+Signed-off-by: Dave Chinner <dchinner@redhat.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Mark Tinguely <tinguely@sgi.com>
+Signed-off-by: Ben Myers <bpm@sgi.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/xfs/xfs_log_recover.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/xfs/xfs_log_recover.c
++++ b/fs/xfs/xfs_log_recover.c
+@@ -3541,7 +3541,7 @@ xlog_do_recovery_pass(
+ * - order is important.
+ */
+ error = xlog_bread_offset(log, 0,
+- bblks - split_bblks, hbp,
++ bblks - split_bblks, dbp,
+ offset + BBTOB(split_bblks));
+ if (error)
+ goto bread_err2;