]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - releases/2.6.32.12/xfs-fix-locking-for-inode-cache-radix-tree-tag-updates.patch
Remove duplicated commits
[thirdparty/kernel/stable-queue.git] / releases / 2.6.32.12 / xfs-fix-locking-for-inode-cache-radix-tree-tag-updates.patch
1 From david@fromorbit.com Fri Apr 2 11:12:53 2010
2 From: Christoph Hellwig <hch@infradead.org>
3 Date: Fri, 12 Mar 2010 09:42:17 +1100
4 Subject: xfs: fix locking for inode cache radix tree tag updates
5 To: stable@kernel.org
6 Cc: xfs@oss.sgi.com
7 Message-ID: <1268347337-7160-20-git-send-email-david@fromorbit.com>
8
9
10 From: Christoph Hellwig <hch@infradead.org>
11
12 commit f1f724e4b523d444c5a598d74505aefa3d6844d2 upstream
13
14 The radix-tree code requires it's users to serialize tag updates
15 against other updates to the tree. While XFS protects tag updates
16 against each other it does not serialize them against updates of the
17 tree contents, which can lead to tag corruption. Fix the inode
18 cache to always take pag_ici_lock in exclusive mode when updating
19 radix tree tags.
20
21 Signed-off-by: Christoph Hellwig <hch@lst.de>
22 Reported-by: Patrick Schreurs <patrick@news-service.com>
23 Tested-by: Patrick Schreurs <patrick@news-service.com>
24 Signed-off-by: Alex Elder <aelder@sgi.com>
25 Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
26 ---
27 fs/xfs/linux-2.6/xfs_sync.c | 4 ++--
28 fs/xfs/xfs_iget.c | 19 +++++++++++++------
29 2 files changed, 15 insertions(+), 8 deletions(-)
30
31 --- a/fs/xfs/linux-2.6/xfs_sync.c
32 +++ b/fs/xfs/linux-2.6/xfs_sync.c
33 @@ -692,12 +692,12 @@ xfs_inode_set_reclaim_tag(
34 xfs_mount_t *mp = ip->i_mount;
35 xfs_perag_t *pag = xfs_get_perag(mp, ip->i_ino);
36
37 - read_lock(&pag->pag_ici_lock);
38 + write_lock(&pag->pag_ici_lock);
39 spin_lock(&ip->i_flags_lock);
40 __xfs_inode_set_reclaim_tag(pag, ip);
41 __xfs_iflags_set(ip, XFS_IRECLAIMABLE);
42 spin_unlock(&ip->i_flags_lock);
43 - read_unlock(&pag->pag_ici_lock);
44 + write_unlock(&pag->pag_ici_lock);
45 xfs_put_perag(mp, pag);
46 }
47
48 --- a/fs/xfs/xfs_iget.c
49 +++ b/fs/xfs/xfs_iget.c
50 @@ -228,13 +228,12 @@ xfs_iget_cache_hit(
51 xfs_itrace_exit_tag(ip, "xfs_iget.alloc");
52
53 /*
54 - * We need to set XFS_INEW atomically with clearing the
55 - * reclaimable tag so that we do have an indicator of the
56 - * inode still being initialized.
57 + * We need to set XFS_IRECLAIM to prevent xfs_reclaim_inode
58 + * from stomping over us while we recycle the inode. We can't
59 + * clear the radix tree reclaimable tag yet as it requires
60 + * pag_ici_lock to be held exclusive.
61 */
62 - ip->i_flags |= XFS_INEW;
63 - ip->i_flags &= ~XFS_IRECLAIMABLE;
64 - __xfs_inode_clear_reclaim_tag(mp, pag, ip);
65 + ip->i_flags |= XFS_IRECLAIM;
66
67 spin_unlock(&ip->i_flags_lock);
68 read_unlock(&pag->pag_ici_lock);
69 @@ -253,7 +252,15 @@ xfs_iget_cache_hit(
70 __xfs_inode_set_reclaim_tag(pag, ip);
71 goto out_error;
72 }
73 +
74 + write_lock(&pag->pag_ici_lock);
75 + spin_lock(&ip->i_flags_lock);
76 + ip->i_flags &= ~(XFS_IRECLAIMABLE | XFS_IRECLAIM);
77 + ip->i_flags |= XFS_INEW;
78 + __xfs_inode_clear_reclaim_tag(mp, pag, ip);
79 inode->i_state = I_LOCK|I_NEW;
80 + spin_unlock(&ip->i_flags_lock);
81 + write_unlock(&pag->pag_ici_lock);
82 } else {
83 /* If the VFS inode is being torn down, pause and try again. */
84 if (!igrab(inode)) {