]>
Commit | Line | Data |
---|---|---|
cc67517a GKH |
1 | From david@fromorbit.com Fri Apr 2 11:10:21 2010 |
2 | From: Dave Chinner <david@fromorbit.com> | |
3 | Date: Fri, 12 Mar 2010 09:42:11 +1100 | |
4 | Subject: xfs: fix stale inode flush avoidance | |
5 | To: stable@kernel.org | |
6 | Cc: xfs@oss.sgi.com | |
7 | Message-ID: <1268347337-7160-14-git-send-email-david@fromorbit.com> | |
8 | ||
9 | From: Dave Chinner <david@fromorbit.com> | |
10 | ||
11 | commit 4b6a46882cca8349e8942e2650c33b11bc571c92 upstream | |
12 | ||
13 | When reclaiming stale inodes, we need to guarantee that inodes are | |
14 | unpinned before returning with a "clean" status. If we don't we can | |
15 | reclaim inodes that are pinned, leading to use after free in the | |
16 | transaction subsystem as transactions complete. | |
17 | ||
18 | Signed-off-by: Dave Chinner <david@fromorbit.com> | |
19 | Reviewed-by: Christoph Hellwig <hch@lst.de> | |
20 | Signed-off-by: Alex Elder <aelder@sgi.com> | |
21 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
22 | ||
23 | --- | |
24 | fs/xfs/xfs_inode.c | 21 +++++++++++++++------ | |
25 | 1 file changed, 15 insertions(+), 6 deletions(-) | |
26 | ||
27 | --- a/fs/xfs/xfs_inode.c | |
28 | +++ b/fs/xfs/xfs_inode.c | |
29 | @@ -2878,13 +2878,9 @@ xfs_iflush( | |
30 | ||
31 | /* | |
32 | * If the inode isn't dirty, then just release the inode flush lock and | |
33 | - * do nothing. Treat stale inodes the same; we cannot rely on the | |
34 | - * backing buffer remaining stale in cache for the remaining life of | |
35 | - * the stale inode and so xfs_itobp() below may give us a buffer that | |
36 | - * no longer contains inodes below. Doing this stale check here also | |
37 | - * avoids forcing the log on pinned, stale inodes. | |
38 | + * do nothing. | |
39 | */ | |
40 | - if (xfs_inode_clean(ip) || xfs_iflags_test(ip, XFS_ISTALE)) { | |
41 | + if (xfs_inode_clean(ip)) { | |
42 | xfs_ifunlock(ip); | |
43 | return 0; | |
44 | } | |
45 | @@ -2908,6 +2904,19 @@ xfs_iflush( | |
46 | xfs_iunpin_wait(ip); | |
47 | ||
48 | /* | |
49 | + * For stale inodes we cannot rely on the backing buffer remaining | |
50 | + * stale in cache for the remaining life of the stale inode and so | |
51 | + * xfs_itobp() below may give us a buffer that no longer contains | |
52 | + * inodes below. We have to check this after ensuring the inode is | |
53 | + * unpinned so that it is safe to reclaim the stale inode after the | |
54 | + * flush call. | |
55 | + */ | |
56 | + if (xfs_iflags_test(ip, XFS_ISTALE)) { | |
57 | + xfs_ifunlock(ip); | |
58 | + return 0; | |
59 | + } | |
60 | + | |
61 | + /* | |
62 | * This may have been unpinned because the filesystem is shutting | |
63 | * down forcibly. If that's the case we must not write this inode | |
64 | * to disk, because the log record didn't make it to disk! |