diff options
Diffstat (limited to 'fs/btrfs/ordered-data.c')
-rw-r--r-- | fs/btrfs/ordered-data.c | 97 |
1 files changed, 40 insertions, 57 deletions
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 051c7fe551dd..7772f02ba28e 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
@@ -25,6 +25,8 @@ | |||
25 | #include "btrfs_inode.h" | 25 | #include "btrfs_inode.h" |
26 | #include "extent_io.h" | 26 | #include "extent_io.h" |
27 | 27 | ||
28 | static struct kmem_cache *btrfs_ordered_extent_cache; | ||
29 | |||
28 | static u64 entry_end(struct btrfs_ordered_extent *entry) | 30 | static u64 entry_end(struct btrfs_ordered_extent *entry) |
29 | { | 31 | { |
30 | if (entry->file_offset + entry->len < entry->file_offset) | 32 | if (entry->file_offset + entry->len < entry->file_offset) |
@@ -187,7 +189,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset, | |||
187 | struct btrfs_ordered_extent *entry; | 189 | struct btrfs_ordered_extent *entry; |
188 | 190 | ||
189 | tree = &BTRFS_I(inode)->ordered_tree; | 191 | tree = &BTRFS_I(inode)->ordered_tree; |
190 | entry = kzalloc(sizeof(*entry), GFP_NOFS); | 192 | entry = kmem_cache_zalloc(btrfs_ordered_extent_cache, GFP_NOFS); |
191 | if (!entry) | 193 | if (!entry) |
192 | return -ENOMEM; | 194 | return -ENOMEM; |
193 | 195 | ||
@@ -421,7 +423,7 @@ void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry) | |||
421 | list_del(&sum->list); | 423 | list_del(&sum->list); |
422 | kfree(sum); | 424 | kfree(sum); |
423 | } | 425 | } |
424 | kfree(entry); | 426 | kmem_cache_free(btrfs_ordered_extent_cache, entry); |
425 | } | 427 | } |
426 | } | 428 | } |
427 | 429 | ||
@@ -466,8 +468,7 @@ void btrfs_remove_ordered_extent(struct inode *inode, | |||
466 | * wait for all the ordered extents in a root. This is done when balancing | 468 | * wait for all the ordered extents in a root. This is done when balancing |
467 | * space between drives. | 469 | * space between drives. |
468 | */ | 470 | */ |
469 | void btrfs_wait_ordered_extents(struct btrfs_root *root, | 471 | void btrfs_wait_ordered_extents(struct btrfs_root *root, int delay_iput) |
470 | int nocow_only, int delay_iput) | ||
471 | { | 472 | { |
472 | struct list_head splice; | 473 | struct list_head splice; |
473 | struct list_head *cur; | 474 | struct list_head *cur; |
@@ -482,15 +483,6 @@ void btrfs_wait_ordered_extents(struct btrfs_root *root, | |||
482 | cur = splice.next; | 483 | cur = splice.next; |
483 | ordered = list_entry(cur, struct btrfs_ordered_extent, | 484 | ordered = list_entry(cur, struct btrfs_ordered_extent, |
484 | root_extent_list); | 485 | root_extent_list); |
485 | if (nocow_only && | ||
486 | !test_bit(BTRFS_ORDERED_NOCOW, &ordered->flags) && | ||
487 | !test_bit(BTRFS_ORDERED_PREALLOC, &ordered->flags)) { | ||
488 | list_move(&ordered->root_extent_list, | ||
489 | &root->fs_info->ordered_extents); | ||
490 | cond_resched_lock(&root->fs_info->ordered_extent_lock); | ||
491 | continue; | ||
492 | } | ||
493 | |||
494 | list_del_init(&ordered->root_extent_list); | 486 | list_del_init(&ordered->root_extent_list); |
495 | atomic_inc(&ordered->refs); | 487 | atomic_inc(&ordered->refs); |
496 | 488 | ||
@@ -775,7 +767,6 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset, | |||
775 | struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; | 767 | struct btrfs_ordered_inode_tree *tree = &BTRFS_I(inode)->ordered_tree; |
776 | u64 disk_i_size; | 768 | u64 disk_i_size; |
777 | u64 new_i_size; | 769 | u64 new_i_size; |
778 | u64 i_size_test; | ||
779 | u64 i_size = i_size_read(inode); | 770 | u64 i_size = i_size_read(inode); |
780 | struct rb_node *node; | 771 | struct rb_node *node; |
781 | struct rb_node *prev = NULL; | 772 | struct rb_node *prev = NULL; |
@@ -835,55 +826,30 @@ int btrfs_ordered_update_i_size(struct inode *inode, u64 offset, | |||
835 | break; | 826 | break; |
836 | if (test->file_offset >= i_size) | 827 | if (test->file_offset >= i_size) |
837 | break; | 828 | break; |
838 | if (test->file_offset >= disk_i_size) | 829 | if (test->file_offset >= disk_i_size) { |
830 | /* | ||
831 | * we don't update disk_i_size now, so record this | ||
832 | * undealt i_size. Or we will not know the real | ||
833 | * i_size. | ||
834 | */ | ||
835 | if (test->outstanding_isize < offset) | ||
836 | test->outstanding_isize = offset; | ||
837 | if (ordered && | ||
838 | ordered->outstanding_isize > | ||
839 | test->outstanding_isize) | ||
840 | test->outstanding_isize = | ||
841 | ordered->outstanding_isize; | ||
839 | goto out; | 842 | goto out; |
840 | } | ||
841 | new_i_size = min_t(u64, offset, i_size); | ||
842 | |||
843 | /* | ||
844 | * at this point, we know we can safely update i_size to at least | ||
845 | * the offset from this ordered extent. But, we need to | ||
846 | * walk forward and see if ios from higher up in the file have | ||
847 | * finished. | ||
848 | */ | ||
849 | if (ordered) { | ||
850 | node = rb_next(&ordered->rb_node); | ||
851 | } else { | ||
852 | if (prev) | ||
853 | node = rb_next(prev); | ||
854 | else | ||
855 | node = rb_first(&tree->tree); | ||
856 | } | ||
857 | |||
858 | /* | ||
859 | * We are looking for an area between our current extent and the next | ||
860 | * ordered extent to update the i_size to. There are 3 cases here | ||
861 | * | ||
862 | * 1) We don't actually have anything and we can update to i_size. | ||
863 | * 2) We have stuff but they already did their i_size update so again we | ||
864 | * can just update to i_size. | ||
865 | * 3) We have an outstanding ordered extent so the most we can update | ||
866 | * our disk_i_size to is the start of the next offset. | ||
867 | */ | ||
868 | i_size_test = i_size; | ||
869 | for (; node; node = rb_next(node)) { | ||
870 | test = rb_entry(node, struct btrfs_ordered_extent, rb_node); | ||
871 | |||
872 | if (test_bit(BTRFS_ORDERED_UPDATED_ISIZE, &test->flags)) | ||
873 | continue; | ||
874 | if (test->file_offset > offset) { | ||
875 | i_size_test = test->file_offset; | ||
876 | break; | ||
877 | } | 843 | } |
878 | } | 844 | } |
845 | new_i_size = min_t(u64, offset, i_size); | ||
879 | 846 | ||
880 | /* | 847 | /* |
881 | * i_size_test is the end of a region after this ordered | 848 | * Some ordered extents may completed before the current one, and |
882 | * extent where there are no ordered extents, we can safely set | 849 | * we hold the real i_size in ->outstanding_isize. |
883 | * disk_i_size to this. | ||
884 | */ | 850 | */ |
885 | if (i_size_test > offset) | 851 | if (ordered && ordered->outstanding_isize > new_i_size) |
886 | new_i_size = min_t(u64, i_size_test, i_size); | 852 | new_i_size = min_t(u64, ordered->outstanding_isize, i_size); |
887 | BTRFS_I(inode)->disk_i_size = new_i_size; | 853 | BTRFS_I(inode)->disk_i_size = new_i_size; |
888 | ret = 0; | 854 | ret = 0; |
889 | out: | 855 | out: |
@@ -984,3 +950,20 @@ void btrfs_add_ordered_operation(struct btrfs_trans_handle *trans, | |||
984 | } | 950 | } |
985 | spin_unlock(&root->fs_info->ordered_extent_lock); | 951 | spin_unlock(&root->fs_info->ordered_extent_lock); |
986 | } | 952 | } |
953 | |||
954 | int __init ordered_data_init(void) | ||
955 | { | ||
956 | btrfs_ordered_extent_cache = kmem_cache_create("btrfs_ordered_extent", | ||
957 | sizeof(struct btrfs_ordered_extent), 0, | ||
958 | SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, | ||
959 | NULL); | ||
960 | if (!btrfs_ordered_extent_cache) | ||
961 | return -ENOMEM; | ||
962 | return 0; | ||
963 | } | ||
964 | |||
965 | void ordered_data_exit(void) | ||
966 | { | ||
967 | if (btrfs_ordered_extent_cache) | ||
968 | kmem_cache_destroy(btrfs_ordered_extent_cache); | ||
969 | } | ||