]> git.ipfire.org Git - ipfire-2.x.git/blame - src/patches/suse-2.6.27.39/patches.suse/ocfs2-Resolve-deadlock-in-ocfs2_xattr_free_.patch
Imported linux-2.6.27.39 suse/xen patches.
[ipfire-2.x.git] / src / patches / suse-2.6.27.39 / patches.suse / ocfs2-Resolve-deadlock-in-ocfs2_xattr_free_.patch
CommitLineData
2cb7cef9
BS
1From: Tao Ma <tao.ma@oracle.com>
2Subject: [PATCH] ocfs2: Resolve deadlock in ocfs2_xattr_free_block.
3Patch-mainline: 2.6.28?
4References: FATE302067
5
6In ocfs2_xattr_free_block, we take a cluster lock on xb_alloc_inode while we
7have a transaction open. This will deadlock the downconvert thread, so fix
8it.
9
10We can clean up how xattr blocks are removed while here - this patch also
11moves the mechanism of releasing xattr block (including both value, xattr
12tree and xattr block) into this function.
13
14Signed-off-by: Tao Ma <tao.ma@oracle.com>
15Signed-off-by: Mark Fasheh <mfasheh@suse.com>
16---
17 fs/ocfs2/xattr.c | 152 +++++++++++++++++++++++++++++-------------------------
18 1 files changed, 82 insertions(+), 70 deletions(-)
19
20diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
21index ed50f9a..bbe87d0 100644
22--- a/fs/ocfs2/xattr.c
23+++ b/fs/ocfs2/xattr.c
24@@ -1443,51 +1443,6 @@ out:
25
26 }
27
28-static int ocfs2_xattr_free_block(handle_t *handle,
29- struct ocfs2_super *osb,
30- struct ocfs2_xattr_block *xb)
31-{
32- struct inode *xb_alloc_inode;
33- struct buffer_head *xb_alloc_bh = NULL;
34- u64 blk = le64_to_cpu(xb->xb_blkno);
35- u16 bit = le16_to_cpu(xb->xb_suballoc_bit);
36- u64 bg_blkno = ocfs2_which_suballoc_group(blk, bit);
37- int ret = 0;
38-
39- xb_alloc_inode = ocfs2_get_system_file_inode(osb,
40- EXTENT_ALLOC_SYSTEM_INODE,
41- le16_to_cpu(xb->xb_suballoc_slot));
42- if (!xb_alloc_inode) {
43- ret = -ENOMEM;
44- mlog_errno(ret);
45- goto out;
46- }
47- mutex_lock(&xb_alloc_inode->i_mutex);
48-
49- ret = ocfs2_inode_lock(xb_alloc_inode, &xb_alloc_bh, 1);
50- if (ret < 0) {
51- mlog_errno(ret);
52- goto out_mutex;
53- }
54- ret = ocfs2_extend_trans(handle, OCFS2_SUBALLOC_FREE);
55- if (ret < 0) {
56- mlog_errno(ret);
57- goto out_unlock;
58- }
59- ret = ocfs2_free_suballoc_bits(handle, xb_alloc_inode, xb_alloc_bh,
60- bit, bg_blkno, 1);
61- if (ret < 0)
62- mlog_errno(ret);
63-out_unlock:
64- ocfs2_inode_unlock(xb_alloc_inode, 1);
65- brelse(xb_alloc_bh);
66-out_mutex:
67- mutex_unlock(&xb_alloc_inode->i_mutex);
68- iput(xb_alloc_inode);
69-out:
70- return ret;
71-}
72-
73 static int ocfs2_remove_value_outside(struct inode*inode,
74 struct buffer_head *bh,
75 struct ocfs2_xattr_header *header)
76@@ -1549,6 +1504,84 @@ static int ocfs2_xattr_block_remove(struct inode *inode,
77 return ret;
78 }
79
80+static int ocfs2_xattr_free_block(struct inode *inode,
81+ u64 block)
82+{
83+ struct inode *xb_alloc_inode;
84+ struct buffer_head *xb_alloc_bh = NULL;
85+ struct buffer_head *blk_bh = NULL;
86+ struct ocfs2_xattr_block *xb;
87+ struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
88+ handle_t *handle;
89+ int ret = 0;
90+ u64 blk, bg_blkno;
91+ u16 bit;
92+
93+ ret = ocfs2_read_block(osb, block, &blk_bh,
94+ OCFS2_BH_CACHED, inode);
95+ if (ret < 0) {
96+ mlog_errno(ret);
97+ goto out;
98+ }
99+
100+ /*Verify the signature of xattr block*/
101+ if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE,
102+ strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) {
103+ ret = -EFAULT;
104+ goto out;
105+ }
106+
107+ ret = ocfs2_xattr_block_remove(inode, blk_bh);
108+ if (ret < 0) {
109+ mlog_errno(ret);
110+ goto out;
111+ }
112+
113+ xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
114+ blk = le64_to_cpu(xb->xb_blkno);
115+ bit = le16_to_cpu(xb->xb_suballoc_bit);
116+ bg_blkno = ocfs2_which_suballoc_group(blk, bit);
117+
118+ xb_alloc_inode = ocfs2_get_system_file_inode(osb,
119+ EXTENT_ALLOC_SYSTEM_INODE,
120+ le16_to_cpu(xb->xb_suballoc_slot));
121+ if (!xb_alloc_inode) {
122+ ret = -ENOMEM;
123+ mlog_errno(ret);
124+ goto out;
125+ }
126+ mutex_lock(&xb_alloc_inode->i_mutex);
127+
128+ ret = ocfs2_inode_lock(xb_alloc_inode, &xb_alloc_bh, 1);
129+ if (ret < 0) {
130+ mlog_errno(ret);
131+ goto out_mutex;
132+ }
133+
134+ handle = ocfs2_start_trans(osb, OCFS2_SUBALLOC_FREE);
135+ if (IS_ERR(handle)) {
136+ ret = PTR_ERR(handle);
137+ mlog_errno(ret);
138+ goto out_unlock;
139+ }
140+
141+ ret = ocfs2_free_suballoc_bits(handle, xb_alloc_inode, xb_alloc_bh,
142+ bit, bg_blkno, 1);
143+ if (ret < 0)
144+ mlog_errno(ret);
145+
146+ ocfs2_commit_trans(osb, handle);
147+out_unlock:
148+ ocfs2_inode_unlock(xb_alloc_inode, 1);
149+ brelse(xb_alloc_bh);
150+out_mutex:
151+ mutex_unlock(&xb_alloc_inode->i_mutex);
152+ iput(xb_alloc_inode);
153+out:
154+ brelse(blk_bh);
155+ return ret;
156+}
157+
158 /*
159 * ocfs2_xattr_remove()
160 *
161@@ -1556,9 +1589,6 @@ static int ocfs2_xattr_block_remove(struct inode *inode,
162 */
163 int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
164 {
165- struct ocfs2_xattr_block *xb;
166- struct buffer_head *blk_bh = NULL;
167- struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
168 struct ocfs2_inode_info *oi = OCFS2_I(inode);
169 struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
170 handle_t *handle;
171@@ -1577,22 +1607,10 @@ int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
172 goto out;
173 }
174 }
175- if (di->i_xattr_loc) {
176- ret = ocfs2_read_block(OCFS2_SB(inode->i_sb),
177- le64_to_cpu(di->i_xattr_loc),
178- &blk_bh, OCFS2_BH_CACHED, inode);
179- if (ret < 0) {
180- mlog_errno(ret);
181- return ret;
182- }
183- /*Verify the signature of xattr block*/
184- if (memcmp((void *)blk_bh->b_data, OCFS2_XATTR_BLOCK_SIGNATURE,
185- strlen(OCFS2_XATTR_BLOCK_SIGNATURE))) {
186- ret = -EFAULT;
187- goto out;
188- }
189
190- ret = ocfs2_xattr_block_remove(inode, blk_bh);
191+ if (di->i_xattr_loc) {
192+ ret = ocfs2_xattr_free_block(inode,
193+ le64_to_cpu(di->i_xattr_loc));
194 if (ret < 0) {
195 mlog_errno(ret);
196 goto out;
197@@ -1613,11 +1631,7 @@ int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
198 goto out_commit;
199 }
200
201- if (di->i_xattr_loc) {
202- xb = (struct ocfs2_xattr_block *)blk_bh->b_data;
203- ocfs2_xattr_free_block(handle, osb, xb);
204- di->i_xattr_loc = cpu_to_le64(0);
205- }
206+ di->i_xattr_loc = 0;
207
208 spin_lock(&oi->ip_lock);
209 oi->ip_dyn_features &= ~(OCFS2_INLINE_XATTR_FL | OCFS2_HAS_XATTR_FL);
210@@ -1630,8 +1644,6 @@ int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
211 out_commit:
212 ocfs2_commit_trans(OCFS2_SB(inode->i_sb), handle);
213 out:
214- brelse(blk_bh);
215-
216 return ret;
217 }
218
219--
2201.5.4.5
221