diff options
author | Chris Mason <chris.mason@oracle.com> | 2008-01-16 16:09:22 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:59 -0400 |
commit | 4d5e74bc0aec3f54b7e429d77b7c35de042c507d (patch) | |
tree | bba22e2a9cfbe5663a2489c5404fff72639b5277 /fs/btrfs/ordered-data.c | |
parent | 2da98f003f4788b0a72c5f87bc55b061f65f30fa (diff) |
Btrfs: Fix data=ordered vs wait_on_inode deadlock on older kernels
Using ilookup5 during data=ordered writeback could deadlock on I_LOCK. This
saves a pointer to the inode instead.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r-- | fs/btrfs/ordered-data.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index cba2b623d02e..3ee51e10c187 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -25,6 +25,7 @@ | |||
25 | struct tree_entry { | 25 | struct tree_entry { |
26 | u64 root_objectid; | 26 | u64 root_objectid; |
27 | u64 objectid; | 27 | u64 objectid; |
28 | struct inode *inode; | ||
28 | struct rb_node rb_node; | 29 | struct rb_node rb_node; |
29 | }; | 30 | }; |
30 | 31 | ||
@@ -144,6 +145,7 @@ int btrfs_add_ordered_inode(struct inode *inode) | |||
144 | write_lock(&tree->lock); | 145 | write_lock(&tree->lock); |
145 | entry->objectid = inode->i_ino; | 146 | entry->objectid = inode->i_ino; |
146 | entry->root_objectid = root_objectid; | 147 | entry->root_objectid = root_objectid; |
148 | entry->inode = inode; | ||
147 | 149 | ||
148 | node = tree_insert(&tree->tree, root_objectid, | 150 | node = tree_insert(&tree->tree, root_objectid, |
149 | inode->i_ino, &entry->rb_node); | 151 | inode->i_ino, &entry->rb_node); |
@@ -159,7 +161,8 @@ int btrfs_add_ordered_inode(struct inode *inode) | |||
159 | } | 161 | } |
160 | 162 | ||
161 | int btrfs_find_first_ordered_inode(struct btrfs_ordered_inode_tree *tree, | 163 | int btrfs_find_first_ordered_inode(struct btrfs_ordered_inode_tree *tree, |
162 | u64 *root_objectid, u64 *objectid) | 164 | u64 *root_objectid, u64 *objectid, |
165 | struct inode **inode) | ||
163 | { | 166 | { |
164 | struct tree_entry *entry; | 167 | struct tree_entry *entry; |
165 | struct rb_node *node; | 168 | struct rb_node *node; |
@@ -184,13 +187,16 @@ int btrfs_find_first_ordered_inode(struct btrfs_ordered_inode_tree *tree, | |||
184 | } | 187 | } |
185 | 188 | ||
186 | *root_objectid = entry->root_objectid; | 189 | *root_objectid = entry->root_objectid; |
190 | *inode = entry->inode; | ||
191 | atomic_inc(&entry->inode->i_count); | ||
187 | *objectid = entry->objectid; | 192 | *objectid = entry->objectid; |
188 | write_unlock(&tree->lock); | 193 | write_unlock(&tree->lock); |
189 | return 1; | 194 | return 1; |
190 | } | 195 | } |
191 | 196 | ||
192 | int btrfs_find_del_first_ordered_inode(struct btrfs_ordered_inode_tree *tree, | 197 | int btrfs_find_del_first_ordered_inode(struct btrfs_ordered_inode_tree *tree, |
193 | u64 *root_objectid, u64 *objectid) | 198 | u64 *root_objectid, u64 *objectid, |
199 | struct inode **inode) | ||
194 | { | 200 | { |
195 | struct tree_entry *entry; | 201 | struct tree_entry *entry; |
196 | struct rb_node *node; | 202 | struct rb_node *node; |
@@ -216,6 +222,8 @@ int btrfs_find_del_first_ordered_inode(struct btrfs_ordered_inode_tree *tree, | |||
216 | 222 | ||
217 | *root_objectid = entry->root_objectid; | 223 | *root_objectid = entry->root_objectid; |
218 | *objectid = entry->objectid; | 224 | *objectid = entry->objectid; |
225 | *inode = entry->inode; | ||
226 | atomic_inc(&entry->inode->i_count); | ||
219 | rb_erase(node, &tree->tree); | 227 | rb_erase(node, &tree->tree); |
220 | write_unlock(&tree->lock); | 228 | write_unlock(&tree->lock); |
221 | kfree(entry); | 229 | kfree(entry); |