]>
Commit | Line | Data |
---|---|---|
12552882 GKH |
1 | From 03b1293edad462ad1ad62bcc5160c76758e450d5 Mon Sep 17 00:00:00 2001 |
2 | From: Dave Chinner <david@fromorbit.com> | |
3 | Date: Fri, 2 Nov 2012 14:23:12 +1100 | |
4 | Subject: xfs: fix buffer shudown reference count mismatch | |
5 | ||
6 | From: Dave Chinner <david@fromorbit.com> | |
7 | ||
8 | commit 03b1293edad462ad1ad62bcc5160c76758e450d5 upstream. | |
9 | ||
10 | When we shut down the filesystem, we have to unpin and free all the | |
11 | buffers currently active in the CIL. To do this we unpin and remove | |
12 | them in one operation as a result of a failed iclogbuf write. For | |
13 | buffers, we do this removal via a simultated IO completion of after | |
14 | marking the buffer stale. | |
15 | ||
16 | At the time we do this, we have two references to the buffer - the | |
17 | active LRU reference and the buf log item. The LRU reference is | |
18 | removed by marking the buffer stale, and the active CIL reference is | |
19 | by the xfs_buf_iodone() callback that is run by | |
20 | xfs_buf_do_callbacks() during ioend processing (via the bp->b_iodone | |
21 | callback). | |
22 | ||
23 | However, ioend processing requires one more reference - that of the | |
24 | IO that it is completing. We don't have this reference, so we free | |
25 | the buffer prematurely and use it after it is freed. For buffers | |
26 | marked with XBF_ASYNC, this leads to assert failures in | |
27 | xfs_buf_rele() on debug kernels because the b_hold count is zero. | |
28 | ||
29 | Fix this by making sure we take the necessary IO reference before | |
30 | starting IO completion processing on the stale buffer, and set the | |
31 | XBF_ASYNC flag to ensure that IO completion processing removes all | |
32 | the active references from the buffer to ensure it is fully torn | |
33 | down. | |
34 | ||
35 | Signed-off-by: Dave Chinner <dchinner@redhat.com> | |
36 | Reviewed-by: Mark Tinguely <tinguely@sgi.com> | |
37 | Signed-off-by: Ben Myers <bpm@sgi.com> | |
38 | Signed-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); |