]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/3.6.7/xfs-fix-buffer-shudown-reference-count-mismatch.patch
Linux 4.14.112
[thirdparty/kernel/stable-queue.git] / releases / 3.6.7 / xfs-fix-buffer-shudown-reference-count-mismatch.patch
CommitLineData
12552882
GKH
1From 03b1293edad462ad1ad62bcc5160c76758e450d5 Mon Sep 17 00:00:00 2001
2From: Dave Chinner <david@fromorbit.com>
3Date: Fri, 2 Nov 2012 14:23:12 +1100
4Subject: xfs: fix buffer shudown reference count mismatch
5
6From: Dave Chinner <david@fromorbit.com>
7
8commit 03b1293edad462ad1ad62bcc5160c76758e450d5 upstream.
9
10When we shut down the filesystem, we have to unpin and free all the
11buffers currently active in the CIL. To do this we unpin and remove
12them in one operation as a result of a failed iclogbuf write. For
13buffers, we do this removal via a simultated IO completion of after
14marking the buffer stale.
15
16At the time we do this, we have two references to the buffer - the
17active LRU reference and the buf log item. The LRU reference is
18removed by marking the buffer stale, and the active CIL reference is
19by the xfs_buf_iodone() callback that is run by
20xfs_buf_do_callbacks() during ioend processing (via the bp->b_iodone
21callback).
22
23However, ioend processing requires one more reference - that of the
24IO that it is completing. We don't have this reference, so we free
25the buffer prematurely and use it after it is freed. For buffers
26marked with XBF_ASYNC, this leads to assert failures in
27xfs_buf_rele() on debug kernels because the b_hold count is zero.
28
29Fix this by making sure we take the necessary IO reference before
30starting IO completion processing on the stale buffer, and set the
31XBF_ASYNC flag to ensure that IO completion processing removes all
32the active references from the buffer to ensure it is fully torn
33down.
34
35Signed-off-by: Dave Chinner <dchinner@redhat.com>
36Reviewed-by: Mark Tinguely <tinguely@sgi.com>
37Signed-off-by: Ben Myers <bpm@sgi.com>
38Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
39
40---
41 fs/xfs/xfs_buf_item.c | 18 ++++++++++++++++++
42 1 file changed, 18 insertions(+)
43
44--- a/fs/xfs/xfs_buf_item.c
45+++ b/fs/xfs/xfs_buf_item.c
46@@ -526,7 +526,25 @@ xfs_buf_item_unpin(
47 }
48 xfs_buf_relse(bp);
49 } else if (freed && remove) {
50+ /*
51+ * There are currently two references to the buffer - the active
52+ * LRU reference and the buf log item. What we are about to do
53+ * here - simulate a failed IO completion - requires 3
54+ * references.
55+ *
56+ * The LRU reference is removed by the xfs_buf_stale() call. The
57+ * buf item reference is removed by the xfs_buf_iodone()
58+ * callback that is run by xfs_buf_do_callbacks() during ioend
59+ * processing (via the bp->b_iodone callback), and then finally
60+ * the ioend processing will drop the IO reference if the buffer
61+ * is marked XBF_ASYNC.
62+ *
63+ * Hence we need to take an additional reference here so that IO
64+ * completion processing doesn't free the buffer prematurely.
65+ */
66 xfs_buf_lock(bp);
67+ xfs_buf_hold(bp);
68+ bp->b_flags |= XBF_ASYNC;
69 xfs_buf_ioerror(bp, EIO);
70 XFS_BUF_UNDONE(bp);
71 xfs_buf_stale(bp);