diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/disk-io.c | 4 | ||||
-rw-r--r-- | fs/btrfs/extent-tree.c | 5 | ||||
-rw-r--r-- | fs/btrfs/extent_io.c | 43 | ||||
-rw-r--r-- | fs/btrfs/extent_io.h | 6 | ||||
-rw-r--r-- | fs/btrfs/free-space-cache.c | 2 | ||||
-rw-r--r-- | fs/btrfs/relocation.c | 2 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 14 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 3 |
8 files changed, 63 insertions, 16 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index aa02eab8c40b..c69995556f61 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -3572,7 +3572,7 @@ static int btrfs_destroy_marked_extents(struct btrfs_root *root, | |||
3572 | 3572 | ||
3573 | while (1) { | 3573 | while (1) { |
3574 | ret = find_first_extent_bit(dirty_pages, start, &start, &end, | 3574 | ret = find_first_extent_bit(dirty_pages, start, &start, &end, |
3575 | mark); | 3575 | mark, NULL); |
3576 | if (ret) | 3576 | if (ret) |
3577 | break; | 3577 | break; |
3578 | 3578 | ||
@@ -3627,7 +3627,7 @@ static int btrfs_destroy_pinned_extent(struct btrfs_root *root, | |||
3627 | again: | 3627 | again: |
3628 | while (1) { | 3628 | while (1) { |
3629 | ret = find_first_extent_bit(unpin, 0, &start, &end, | 3629 | ret = find_first_extent_bit(unpin, 0, &start, &end, |
3630 | EXTENT_DIRTY); | 3630 | EXTENT_DIRTY, NULL); |
3631 | if (ret) | 3631 | if (ret) |
3632 | break; | 3632 | break; |
3633 | 3633 | ||
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 3270b1087850..ca4aad96f814 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -312,7 +312,8 @@ static u64 add_new_free_space(struct btrfs_block_group_cache *block_group, | |||
312 | while (start < end) { | 312 | while (start < end) { |
313 | ret = find_first_extent_bit(info->pinned_extents, start, | 313 | ret = find_first_extent_bit(info->pinned_extents, start, |
314 | &extent_start, &extent_end, | 314 | &extent_start, &extent_end, |
315 | EXTENT_DIRTY | EXTENT_UPTODATE); | 315 | EXTENT_DIRTY | EXTENT_UPTODATE, |
316 | NULL); | ||
316 | if (ret) | 317 | if (ret) |
317 | break; | 318 | break; |
318 | 319 | ||
@@ -5045,7 +5046,7 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
5045 | 5046 | ||
5046 | while (1) { | 5047 | while (1) { |
5047 | ret = find_first_extent_bit(unpin, 0, &start, &end, | 5048 | ret = find_first_extent_bit(unpin, 0, &start, &end, |
5048 | EXTENT_DIRTY); | 5049 | EXTENT_DIRTY, NULL); |
5049 | if (ret) | 5050 | if (ret) |
5050 | break; | 5051 | break; |
5051 | 5052 | ||
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 979fa0d6bfee..e8ee39b73356 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
@@ -937,6 +937,7 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int bits, | |||
937 | * @end: the end offset in bytes (inclusive) | 937 | * @end: the end offset in bytes (inclusive) |
938 | * @bits: the bits to set in this range | 938 | * @bits: the bits to set in this range |
939 | * @clear_bits: the bits to clear in this range | 939 | * @clear_bits: the bits to clear in this range |
940 | * @cached_state: state that we're going to cache | ||
940 | * @mask: the allocation mask | 941 | * @mask: the allocation mask |
941 | * | 942 | * |
942 | * This will go through and set bits for the given range. If any states exist | 943 | * This will go through and set bits for the given range. If any states exist |
@@ -946,7 +947,8 @@ int set_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, int bits, | |||
946 | * boundary bits like LOCK. | 947 | * boundary bits like LOCK. |
947 | */ | 948 | */ |
948 | int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, | 949 | int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, |
949 | int bits, int clear_bits, gfp_t mask) | 950 | int bits, int clear_bits, |
951 | struct extent_state **cached_state, gfp_t mask) | ||
950 | { | 952 | { |
951 | struct extent_state *state; | 953 | struct extent_state *state; |
952 | struct extent_state *prealloc = NULL; | 954 | struct extent_state *prealloc = NULL; |
@@ -963,6 +965,15 @@ again: | |||
963 | } | 965 | } |
964 | 966 | ||
965 | spin_lock(&tree->lock); | 967 | spin_lock(&tree->lock); |
968 | if (cached_state && *cached_state) { | ||
969 | state = *cached_state; | ||
970 | if (state->start <= start && state->end > start && | ||
971 | state->tree) { | ||
972 | node = &state->rb_node; | ||
973 | goto hit_next; | ||
974 | } | ||
975 | } | ||
976 | |||
966 | /* | 977 | /* |
967 | * this search will find all the extents that end after | 978 | * this search will find all the extents that end after |
968 | * our range starts. | 979 | * our range starts. |
@@ -993,6 +1004,7 @@ hit_next: | |||
993 | */ | 1004 | */ |
994 | if (state->start == start && state->end <= end) { | 1005 | if (state->start == start && state->end <= end) { |
995 | set_state_bits(tree, state, &bits); | 1006 | set_state_bits(tree, state, &bits); |
1007 | cache_state(state, cached_state); | ||
996 | state = clear_state_bit(tree, state, &clear_bits, 0); | 1008 | state = clear_state_bit(tree, state, &clear_bits, 0); |
997 | if (last_end == (u64)-1) | 1009 | if (last_end == (u64)-1) |
998 | goto out; | 1010 | goto out; |
@@ -1033,6 +1045,7 @@ hit_next: | |||
1033 | goto out; | 1045 | goto out; |
1034 | if (state->end <= end) { | 1046 | if (state->end <= end) { |
1035 | set_state_bits(tree, state, &bits); | 1047 | set_state_bits(tree, state, &bits); |
1048 | cache_state(state, cached_state); | ||
1036 | state = clear_state_bit(tree, state, &clear_bits, 0); | 1049 | state = clear_state_bit(tree, state, &clear_bits, 0); |
1037 | if (last_end == (u64)-1) | 1050 | if (last_end == (u64)-1) |
1038 | goto out; | 1051 | goto out; |
@@ -1071,6 +1084,7 @@ hit_next: | |||
1071 | &bits); | 1084 | &bits); |
1072 | if (err) | 1085 | if (err) |
1073 | extent_io_tree_panic(tree, err); | 1086 | extent_io_tree_panic(tree, err); |
1087 | cache_state(prealloc, cached_state); | ||
1074 | prealloc = NULL; | 1088 | prealloc = NULL; |
1075 | start = this_end + 1; | 1089 | start = this_end + 1; |
1076 | goto search_again; | 1090 | goto search_again; |
@@ -1093,6 +1107,7 @@ hit_next: | |||
1093 | extent_io_tree_panic(tree, err); | 1107 | extent_io_tree_panic(tree, err); |
1094 | 1108 | ||
1095 | set_state_bits(tree, prealloc, &bits); | 1109 | set_state_bits(tree, prealloc, &bits); |
1110 | cache_state(prealloc, cached_state); | ||
1096 | clear_state_bit(tree, prealloc, &clear_bits, 0); | 1111 | clear_state_bit(tree, prealloc, &clear_bits, 0); |
1097 | prealloc = NULL; | 1112 | prealloc = NULL; |
1098 | goto out; | 1113 | goto out; |
@@ -1297,18 +1312,42 @@ out: | |||
1297 | * If nothing was found, 1 is returned. If found something, return 0. | 1312 | * If nothing was found, 1 is returned. If found something, return 0. |
1298 | */ | 1313 | */ |
1299 | int find_first_extent_bit(struct extent_io_tree *tree, u64 start, | 1314 | int find_first_extent_bit(struct extent_io_tree *tree, u64 start, |
1300 | u64 *start_ret, u64 *end_ret, int bits) | 1315 | u64 *start_ret, u64 *end_ret, int bits, |
1316 | struct extent_state **cached_state) | ||
1301 | { | 1317 | { |
1302 | struct extent_state *state; | 1318 | struct extent_state *state; |
1319 | struct rb_node *n; | ||
1303 | int ret = 1; | 1320 | int ret = 1; |
1304 | 1321 | ||
1305 | spin_lock(&tree->lock); | 1322 | spin_lock(&tree->lock); |
1323 | if (cached_state && *cached_state) { | ||
1324 | state = *cached_state; | ||
1325 | if (state->end == start - 1 && state->tree) { | ||
1326 | n = rb_next(&state->rb_node); | ||
1327 | while (n) { | ||
1328 | state = rb_entry(n, struct extent_state, | ||
1329 | rb_node); | ||
1330 | if (state->state & bits) | ||
1331 | goto got_it; | ||
1332 | n = rb_next(n); | ||
1333 | } | ||
1334 | free_extent_state(*cached_state); | ||
1335 | *cached_state = NULL; | ||
1336 | goto out; | ||
1337 | } | ||
1338 | free_extent_state(*cached_state); | ||
1339 | *cached_state = NULL; | ||
1340 | } | ||
1341 | |||
1306 | state = find_first_extent_bit_state(tree, start, bits); | 1342 | state = find_first_extent_bit_state(tree, start, bits); |
1343 | got_it: | ||
1307 | if (state) { | 1344 | if (state) { |
1345 | cache_state(state, cached_state); | ||
1308 | *start_ret = state->start; | 1346 | *start_ret = state->start; |
1309 | *end_ret = state->end; | 1347 | *end_ret = state->end; |
1310 | ret = 0; | 1348 | ret = 0; |
1311 | } | 1349 | } |
1350 | out: | ||
1312 | spin_unlock(&tree->lock); | 1351 | spin_unlock(&tree->lock); |
1313 | return ret; | 1352 | return ret; |
1314 | } | 1353 | } |
diff --git a/fs/btrfs/extent_io.h b/fs/btrfs/extent_io.h index a69dea219044..7aeb31087f88 100644 --- a/fs/btrfs/extent_io.h +++ b/fs/btrfs/extent_io.h | |||
@@ -233,13 +233,15 @@ int set_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, | |||
233 | int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, | 233 | int clear_extent_dirty(struct extent_io_tree *tree, u64 start, u64 end, |
234 | gfp_t mask); | 234 | gfp_t mask); |
235 | int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, | 235 | int convert_extent_bit(struct extent_io_tree *tree, u64 start, u64 end, |
236 | int bits, int clear_bits, gfp_t mask); | 236 | int bits, int clear_bits, |
237 | struct extent_state **cached_state, gfp_t mask); | ||
237 | int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end, | 238 | int set_extent_delalloc(struct extent_io_tree *tree, u64 start, u64 end, |
238 | struct extent_state **cached_state, gfp_t mask); | 239 | struct extent_state **cached_state, gfp_t mask); |
239 | int set_extent_defrag(struct extent_io_tree *tree, u64 start, u64 end, | 240 | int set_extent_defrag(struct extent_io_tree *tree, u64 start, u64 end, |
240 | struct extent_state **cached_state, gfp_t mask); | 241 | struct extent_state **cached_state, gfp_t mask); |
241 | int find_first_extent_bit(struct extent_io_tree *tree, u64 start, | 242 | int find_first_extent_bit(struct extent_io_tree *tree, u64 start, |
242 | u64 *start_ret, u64 *end_ret, int bits); | 243 | u64 *start_ret, u64 *end_ret, int bits, |
244 | struct extent_state **cached_state); | ||
243 | struct extent_state *find_first_extent_bit_state(struct extent_io_tree *tree, | 245 | struct extent_state *find_first_extent_bit_state(struct extent_io_tree *tree, |
244 | u64 start, int bits); | 246 | u64 start, int bits); |
245 | int extent_invalidatepage(struct extent_io_tree *tree, | 247 | int extent_invalidatepage(struct extent_io_tree *tree, |
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index b107e68797f4..1027b854b90c 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -966,7 +966,7 @@ int __btrfs_write_out_cache(struct btrfs_root *root, struct inode *inode, | |||
966 | block_group->key.offset)) { | 966 | block_group->key.offset)) { |
967 | ret = find_first_extent_bit(unpin, start, | 967 | ret = find_first_extent_bit(unpin, start, |
968 | &extent_start, &extent_end, | 968 | &extent_start, &extent_end, |
969 | EXTENT_DIRTY); | 969 | EXTENT_DIRTY, NULL); |
970 | if (ret) { | 970 | if (ret) { |
971 | ret = 0; | 971 | ret = 0; |
972 | break; | 972 | break; |
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 6e530bb86c94..776f0aa128fc 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c | |||
@@ -3621,7 +3621,7 @@ next: | |||
3621 | 3621 | ||
3622 | ret = find_first_extent_bit(&rc->processed_blocks, | 3622 | ret = find_first_extent_bit(&rc->processed_blocks, |
3623 | key.objectid, &start, &end, | 3623 | key.objectid, &start, &end, |
3624 | EXTENT_DIRTY); | 3624 | EXTENT_DIRTY, NULL); |
3625 | 3625 | ||
3626 | if (ret == 0 && start <= key.objectid) { | 3626 | if (ret == 0 && start <= key.objectid) { |
3627 | btrfs_release_path(path); | 3627 | btrfs_release_path(path); |
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c index 69139a356f71..77db875b5116 100644 --- a/fs/btrfs/transaction.c +++ b/fs/btrfs/transaction.c | |||
@@ -687,13 +687,15 @@ int btrfs_write_marked_extents(struct btrfs_root *root, | |||
687 | int err = 0; | 687 | int err = 0; |
688 | int werr = 0; | 688 | int werr = 0; |
689 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; | 689 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; |
690 | struct extent_state *cached_state = NULL; | ||
690 | u64 start = 0; | 691 | u64 start = 0; |
691 | u64 end; | 692 | u64 end; |
692 | 693 | ||
693 | while (!find_first_extent_bit(dirty_pages, start, &start, &end, | 694 | while (!find_first_extent_bit(dirty_pages, start, &start, &end, |
694 | mark)) { | 695 | mark, &cached_state)) { |
695 | convert_extent_bit(dirty_pages, start, end, EXTENT_NEED_WAIT, mark, | 696 | convert_extent_bit(dirty_pages, start, end, EXTENT_NEED_WAIT, |
696 | GFP_NOFS); | 697 | mark, &cached_state, GFP_NOFS); |
698 | cached_state = NULL; | ||
697 | err = filemap_fdatawrite_range(mapping, start, end); | 699 | err = filemap_fdatawrite_range(mapping, start, end); |
698 | if (err) | 700 | if (err) |
699 | werr = err; | 701 | werr = err; |
@@ -717,12 +719,14 @@ int btrfs_wait_marked_extents(struct btrfs_root *root, | |||
717 | int err = 0; | 719 | int err = 0; |
718 | int werr = 0; | 720 | int werr = 0; |
719 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; | 721 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; |
722 | struct extent_state *cached_state = NULL; | ||
720 | u64 start = 0; | 723 | u64 start = 0; |
721 | u64 end; | 724 | u64 end; |
722 | 725 | ||
723 | while (!find_first_extent_bit(dirty_pages, start, &start, &end, | 726 | while (!find_first_extent_bit(dirty_pages, start, &start, &end, |
724 | EXTENT_NEED_WAIT)) { | 727 | EXTENT_NEED_WAIT, &cached_state)) { |
725 | clear_extent_bits(dirty_pages, start, end, EXTENT_NEED_WAIT, GFP_NOFS); | 728 | clear_extent_bit(dirty_pages, start, end, EXTENT_NEED_WAIT, |
729 | 0, 0, &cached_state, GFP_NOFS); | ||
726 | err = filemap_fdatawait_range(mapping, start, end); | 730 | err = filemap_fdatawait_range(mapping, start, end); |
727 | if (err) | 731 | if (err) |
728 | werr = err; | 732 | werr = err; |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 1d7b34844323..f4b9e54b1da2 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -2463,7 +2463,8 @@ static void free_log_tree(struct btrfs_trans_handle *trans, | |||
2463 | 2463 | ||
2464 | while (1) { | 2464 | while (1) { |
2465 | ret = find_first_extent_bit(&log->dirty_log_pages, | 2465 | ret = find_first_extent_bit(&log->dirty_log_pages, |
2466 | 0, &start, &end, EXTENT_DIRTY | EXTENT_NEW); | 2466 | 0, &start, &end, EXTENT_DIRTY | EXTENT_NEW, |
2467 | NULL); | ||
2467 | if (ret) | 2468 | if (ret) |
2468 | break; | 2469 | break; |
2469 | 2470 | ||