diff options
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r-- | fs/btrfs/ordered-data.c | 48 |
1 files changed, 27 insertions, 21 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 5c2a9e78a949..a127c0ebb2dc 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -16,7 +16,6 @@ | |||
16 | * Boston, MA 021110-1307, USA. | 16 | * Boston, MA 021110-1307, USA. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/gfp.h> | ||
20 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
21 | #include <linux/blkdev.h> | 20 | #include <linux/blkdev.h> |
22 | #include <linux/writeback.h> | 21 | #include <linux/writeback.h> |
@@ -174,7 +173,6 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
174 | if (!entry) | 173 | if (!entry) |
175 | return -ENOMEM; | 174 | return -ENOMEM; |
176 | 175 | ||
177 | mutex_lock(&tree->mutex); | ||
178 | entry->file_offset = file_offset; | 176 | entry->file_offset = file_offset; |
179 | entry->start = start; | 177 | entry->start = start; |
180 | entry->len = len; | 178 | entry->len = len; |
@@ -190,16 +188,17 @@ int btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
190 | INIT_LIST_HEAD(&entry->list); | 188 | INIT_LIST_HEAD(&entry->list); |
191 | INIT_LIST_HEAD(&entry->root_extent_list); | 189 | INIT_LIST_HEAD(&entry->root_extent_list); |
192 | 190 | ||
191 | spin_lock(&tree->lock); | ||
193 | node = tree_insert(&tree->tree, file_offset, | 192 | node = tree_insert(&tree->tree, file_offset, |
194 | &entry->rb_node); | 193 | &entry->rb_node); |
195 | BUG_ON(node); | 194 | BUG_ON(node); |
195 | spin_unlock(&tree->lock); | ||
196 | 196 | ||
197 | spin_lock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); | 197 | spin_lock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); |
198 | list_add_tail(&entry->root_extent_list, | 198 | list_add_tail(&entry->root_extent_list, |
199 | &BTRFS_I(inode)->root->fs_info->ordered_extents); | 199 | &BTRFS_I(inode)->root->fs_info->ordered_extents); |
200 | spin_unlock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); | 200 | spin_unlock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); |
201 | 201 | ||
202 | mutex_unlock(&tree->mutex); | ||
203 | BUG_ON(node); | 202 | BUG_ON(node); |
204 | return 0; | 203 | return 0; |
205 | } | 204 | } |
@@ -216,9 +215,9 @@ int btrfs_add_ordered_sum(struct inode *inode, | |||
216 | struct btrfs_ordered_inode_tree *tree; | 215 | struct btrfs_ordered_inode_tree *tree; |
217 | 216 | ||
218 | tree = &BTRFS_I(inode)->ordered_tree; | 217 | tree = &BTRFS_I(inode)->ordered_tree; |
219 | mutex_lock(&tree->mutex); | 218 | spin_lock(&tree->lock); |
220 | list_add_tail(&sum->list, &entry->list); | 219 | list_add_tail(&sum->list, &entry->list); |
221 | mutex_unlock(&tree->mutex); | 220 | spin_unlock(&tree->lock); |
222 | return 0; | 221 | return 0; |
223 | } | 222 | } |
224 | 223 | ||
@@ -232,15 +231,16 @@ int btrfs_add_ordered_sum(struct inode *inode, | |||
232 | * to make sure this function only returns 1 once for a given ordered extent. | 231 | * to make sure this function only returns 1 once for a given ordered extent. |
233 | */ | 232 | */ |
234 | int btrfs_dec_test_ordered_pending(struct inode *inode, | 233 | int btrfs_dec_test_ordered_pending(struct inode *inode, |
234 | struct btrfs_ordered_extent **cached, | ||
235 | u64 file_offset, u64 io_size) | 235 | u64 file_offset, u64 io_size) |
236 | { | 236 | { |
237 | struct btrfs_ordered_inode_tree *tree; | 237 | struct btrfs_ordered_inode_tree *tree; |
238 | struct rb_node *node; | 238 | struct rb_node *node; |
239 | struct btrfs_ordered_extent *entry; | 239 | struct btrfs_ordered_extent *entry = NULL; |
240 | int ret; | 240 | int ret; |
241 | 241 | ||
242 | tree = &BTRFS_I(inode)->ordered_tree; | 242 | tree = &BTRFS_I(inode)->ordered_tree; |
243 | mutex_lock(&tree->mutex); | 243 | spin_lock(&tree->lock); |
244 | node = tree_search(tree, file_offset); | 244 | node = tree_search(tree, file_offset); |
245 | if (!node) { | 245 | if (!node) { |
246 | ret = 1; | 246 | ret = 1; |
@@ -264,7 +264,11 @@ int btrfs_dec_test_ordered_pending(struct inode *inode, | |||
264 | else | 264 | else |
265 | ret = 1; | 265 | ret = 1; |
266 | out: | 266 | out: |
267 | mutex_unlock(&tree->mutex); | 267 | if (!ret && cached && entry) { |
268 | *cached = entry; | ||
269 | atomic_inc(&entry->refs); | ||
270 | } | ||
271 | spin_unlock(&tree->lock); | ||
268 | return ret == 0; | 272 | return ret == 0; |
269 | } | 273 | } |
270 | 274 | ||
@@ -291,13 +295,14 @@ int btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) | |||
291 | 295 | ||
292 | /* | 296 | /* |
293 | * remove an ordered extent from the tree. No references are dropped | 297 | * remove an ordered extent from the tree. No references are dropped |
294 | * and you must wake_up entry->wait. You must hold the tree mutex | 298 | * and you must wake_up entry->wait. You must hold the tree lock |
295 | * while you call this function. | 299 | * while you call this function. |
296 | */ | 300 | */ |
297 | static int __btrfs_remove_ordered_extent(struct inode *inode, | 301 | static int __btrfs_remove_ordered_extent(struct inode *inode, |
298 | struct btrfs_ordered_extent *entry) | 302 | struct btrfs_ordered_extent *entry) |
299 | { | 303 | { |
300 | struct btrfs_ordered_inode_tree *tree; | 304 | struct btrfs_ordered_inode_tree *tree; |
305 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
301 | struct rb_node *node; | 306 | struct rb_node *node; |
302 | 307 | ||
303 | tree = &BTRFS_I(inode)->ordered_tree; | 308 | tree = &BTRFS_I(inode)->ordered_tree; |
@@ -307,12 +312,13 @@ static int __btrfs_remove_ordered_extent(struct inode *inode, | |||
307 | set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags); | 312 | set_bit(BTRFS_ORDERED_COMPLETE, &entry->flags); |
308 | 313 | ||
309 | spin_lock(&BTRFS_I(inode)->accounting_lock); | 314 | spin_lock(&BTRFS_I(inode)->accounting_lock); |
315 | WARN_ON(!BTRFS_I(inode)->outstanding_extents); | ||
310 | BTRFS_I(inode)->outstanding_extents--; | 316 | BTRFS_I(inode)->outstanding_extents--; |
311 | spin_unlock(&BTRFS_I(inode)->accounting_lock); | 317 | spin_unlock(&BTRFS_I(inode)->accounting_lock); |
312 | btrfs_unreserve_metadata_for_delalloc(BTRFS_I(inode)->root, | 318 | btrfs_unreserve_metadata_for_delalloc(BTRFS_I(inode)->root, |
313 | inode, 1); | 319 | inode, 1); |
314 | 320 | ||
315 | spin_lock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); | 321 | spin_lock(&root->fs_info->ordered_extent_lock); |
316 | list_del_init(&entry->root_extent_list); | 322 | list_del_init(&entry->root_extent_list); |
317 | 323 | ||
318 | /* | 324 | /* |
@@ -324,7 +330,7 @@ static int __btrfs_remove_ordered_extent(struct inode *inode, | |||
324 | !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY)) { | 330 | !mapping_tagged(inode->i_mapping, PAGECACHE_TAG_DIRTY)) { |
325 | list_del_init(&BTRFS_I(inode)->ordered_operations); | 331 | list_del_init(&BTRFS_I(inode)->ordered_operations); |
326 | } | 332 | } |
327 | spin_unlock(&BTRFS_I(inode)->root->fs_info->ordered_extent_lock); | 333 | spin_unlock(&root->fs_info->ordered_extent_lock); |
328 | 334 | ||
329 | return 0; | 335 | return 0; |
330 | } | 336 | } |
@@ -340,9 +346,9 @@ int btrfs_remove_ordered_extent(struct inode *inode, | |||
340 | int ret; | 346 | int ret; |
341 | 347 | ||
342 | tree = &BTRFS_I(inode)->ordered_tree; | 348 | tree = &BTRFS_I(inode)->ordered_tree; |
343 | mutex_lock(&tree->mutex); | 349 | spin_lock(&tree->lock); |
344 | ret = __btrfs_remove_ordered_extent(inode, entry); | 350 | ret = __btrfs_remove_ordered_extent(inode, entry); |
345 | mutex_unlock(&tree->mutex); | 351 | spin_unlock(&tree->lock); |
346 | wake_up(&entry->wait); | 352 | wake_up(&entry->wait); |
347 | 353 | ||
348 | return ret; | 354 | return ret; |
@@ -567,7 +573,7 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_extent(struct inode *inode, | |||
567 | struct btrfs_ordered_extent *entry = NULL; | 573 | struct btrfs_ordered_extent *entry = NULL; |
568 | 574 | ||
569 | tree = &BTRFS_I(inode)->ordered_tree; | 575 | tree = &BTRFS_I(inode)->ordered_tree; |
570 | mutex_lock(&tree->mutex); | 576 | spin_lock(&tree->lock); |
571 | node = tree_search(tree, file_offset); | 577 | node = tree_search(tree, file_offset); |
572 | if (!node) | 578 | if (!node) |
573 | goto out; | 579 | goto out; |
@@ -578,7 +584,7 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_extent(struct inode *inode, | |||
578 | if (entry) | 584 | if (entry) |
579 | atomic_inc(&entry->refs); | 585 | atomic_inc(&entry->refs); |
580 | out: | 586 | out: |
581 | mutex_unlock(&tree->mutex); | 587 | spin_unlock(&tree->lock); |
582 | return entry; | 588 | return entry; |
583 | } | 589 | } |
584 | 590 | ||
@@ -594,7 +600,7 @@ btrfs_lookup_first_ordered_extent(struct inode *inode, u64 file_offset) | |||
594 | struct btrfs_ordered_extent *entry = NULL; | 600 | struct btrfs_ordered_extent *entry = NULL; |
595 | 601 | ||
596 | tree = &BTRFS_I(inode)->ordered_tree; | 602 | tree = &BTRFS_I(inode)->ordered_tree; |
597 | mutex_lock(&tree->mutex); | 603 | spin_lock(&tree->lock); |
598 | node = tree_search(tree, file_offset); | 604 | node = tree_search(tree, file_offset); |
599 | if (!node) | 605 | if (!node) |
600 | goto out; | 606 | goto out; |
@@ -602,7 +608,7 @@ btrfs_lookup_first_ordered_extent(struct inode *inode, u64 file_offset) | |||
602 | entry = rb_entry(node, struct btrfs_ordered_extent, rb_node); | 608 | entry = rb_entry(node, struct btrfs_ordered_extent, rb_node); |
603 | atomic_inc(&entry->refs); | 609 | atomic_inc(&entry->refs); |
604 | out: | 610 | out: |
605 | mutex_unlock(&tree->mutex); | 611 | spin_unlock(&tree->lock); |
606 | return entry; | 612 | return entry; |
607 | } | 613 | } |
608 | 614 | ||
@@ -629,7 +635,7 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset, | |||
629 | else | 635 | else |
630 | offset = ALIGN(offset, BTRFS_I(inode)->root->sectorsize); | 636 | offset = ALIGN(offset, BTRFS_I(inode)->root->sectorsize); |
631 | 637 | ||
632 | mutex_lock(&tree->mutex); | 638 | spin_lock(&tree->lock); |
633 | disk_i_size = BTRFS_I(inode)->disk_i_size; | 639 | disk_i_size = BTRFS_I(inode)->disk_i_size; |
634 | 640 | ||
635 | /* truncate file */ | 641 | /* truncate file */ |
@@ -735,7 +741,7 @@ out: | |||
735 | */ | 741 | */ |
736 | if (ordered) | 742 | if (ordered) |
737 | __btrfs_remove_ordered_extent(inode, ordered); | 743 | __btrfs_remove_ordered_extent(inode, ordered); |
738 | mutex_unlock(&tree->mutex); | 744 | spin_unlock(&tree->lock); |
739 | if (ordered) | 745 | if (ordered) |
740 | wake_up(&ordered->wait); | 746 | wake_up(&ordered->wait); |
741 | return ret; | 747 | return ret; |
@@ -762,7 +768,7 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, | |||
762 | if (!ordered) | 768 | if (!ordered) |
763 | return 1; | 769 | return 1; |
764 | 770 | ||
765 | mutex_lock(&tree->mutex); | 771 | spin_lock(&tree->lock); |
766 | list_for_each_entry_reverse(ordered_sum, &ordered->list, list) { | 772 | list_for_each_entry_reverse(ordered_sum, &ordered->list, list) { |
767 | if (disk_bytenr >= ordered_sum->bytenr) { | 773 | if (disk_bytenr >= ordered_sum->bytenr) { |
768 | num_sectors = ordered_sum->len / sectorsize; | 774 | num_sectors = ordered_sum->len / sectorsize; |
@@ -777,7 +783,7 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, | |||
777 | } | 783 | } |
778 | } | 784 | } |
779 | out: | 785 | out: |
780 | mutex_unlock(&tree->mutex); | 786 | spin_unlock(&tree->lock); |
781 | btrfs_put_ordered_extent(ordered); | 787 | btrfs_put_ordered_extent(ordered); |
782 | return ret; | 788 | return ret; |
783 | } | 789 | } |