diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 80 |
1 files changed, 36 insertions, 44 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index b801eb4b3eef..cc89df4493ab 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -33,6 +33,28 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
33 | btrfs_root *extent_root); | 33 | btrfs_root *extent_root); |
34 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct | 34 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct |
35 | btrfs_root *extent_root); | 35 | btrfs_root *extent_root); |
36 | static int find_previous_extent(struct btrfs_root *root, | ||
37 | struct btrfs_path *path) | ||
38 | { | ||
39 | struct btrfs_key found_key; | ||
40 | struct extent_buffer *leaf; | ||
41 | int ret; | ||
42 | |||
43 | while(1) { | ||
44 | if (path->slots[0] == 0) { | ||
45 | ret = btrfs_prev_leaf(root, path); | ||
46 | if (ret != 0) | ||
47 | return ret; | ||
48 | } else { | ||
49 | path->slots[0]--; | ||
50 | } | ||
51 | leaf = path->nodes[0]; | ||
52 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | ||
53 | if (found_key.type == BTRFS_EXTENT_ITEM_KEY) | ||
54 | return 0; | ||
55 | } | ||
56 | return 1; | ||
57 | } | ||
36 | 58 | ||
37 | static int cache_block_group(struct btrfs_root *root, | 59 | static int cache_block_group(struct btrfs_root *root, |
38 | struct btrfs_block_group_cache *block_group) | 60 | struct btrfs_block_group_cache *block_group) |
@@ -65,16 +87,19 @@ static int cache_block_group(struct btrfs_root *root, | |||
65 | first_free = block_group->key.objectid; | 87 | first_free = block_group->key.objectid; |
66 | key.objectid = block_group->key.objectid; | 88 | key.objectid = block_group->key.objectid; |
67 | key.offset = 0; | 89 | key.offset = 0; |
68 | |||
69 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 90 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
70 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 91 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
71 | |||
72 | if (ret < 0) | 92 | if (ret < 0) |
73 | return ret; | 93 | return ret; |
74 | 94 | ret = find_previous_extent(root, path); | |
75 | if (ret && path->slots[0] > 0) | 95 | if (ret < 0) |
76 | path->slots[0]--; | 96 | return ret; |
77 | 97 | if (ret == 0) { | |
98 | leaf = path->nodes[0]; | ||
99 | btrfs_item_key_to_cpu(leaf, &key, path->slots[0]); | ||
100 | if (key.objectid + key.offset > first_free) | ||
101 | first_free = key.objectid + key.offset; | ||
102 | } | ||
78 | while(1) { | 103 | while(1) { |
79 | leaf = path->nodes[0]; | 104 | leaf = path->nodes[0]; |
80 | slot = path->slots[0]; | 105 | slot = path->slots[0]; |
@@ -88,15 +113,10 @@ static int cache_block_group(struct btrfs_root *root, | |||
88 | break; | 113 | break; |
89 | } | 114 | } |
90 | } | 115 | } |
91 | |||
92 | btrfs_item_key_to_cpu(leaf, &key, slot); | 116 | btrfs_item_key_to_cpu(leaf, &key, slot); |
93 | if (key.objectid < block_group->key.objectid) { | 117 | if (key.objectid < block_group->key.objectid) { |
94 | if (btrfs_key_type(&key) != BTRFS_EXTENT_REF_KEY && | ||
95 | key.objectid + key.offset > first_free) | ||
96 | first_free = key.objectid + key.offset; | ||
97 | goto next; | 118 | goto next; |
98 | } | 119 | } |
99 | |||
100 | if (key.objectid >= block_group->key.objectid + | 120 | if (key.objectid >= block_group->key.objectid + |
101 | block_group->key.offset) { | 121 | block_group->key.offset) { |
102 | break; | 122 | break; |
@@ -162,11 +182,9 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct | |||
162 | return block_group; | 182 | return block_group; |
163 | return NULL; | 183 | return NULL; |
164 | } | 184 | } |
165 | |||
166 | static u64 noinline find_search_start(struct btrfs_root *root, | 185 | static u64 noinline find_search_start(struct btrfs_root *root, |
167 | struct btrfs_block_group_cache **cache_ret, | 186 | struct btrfs_block_group_cache **cache_ret, |
168 | u64 search_start, int num, | 187 | u64 search_start, int num, int data) |
169 | int data, int full_scan) | ||
170 | { | 188 | { |
171 | int ret; | 189 | int ret; |
172 | struct btrfs_block_group_cache *cache = *cache_ret; | 190 | struct btrfs_block_group_cache *cache = *cache_ret; |
@@ -771,9 +789,7 @@ again: | |||
771 | out: | 789 | out: |
772 | btrfs_free_path(path); | 790 | btrfs_free_path(path); |
773 | return total_count; | 791 | return total_count; |
774 | |||
775 | } | 792 | } |
776 | |||
777 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, | 793 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, |
778 | struct btrfs_root *root, u64 owner_objectid) | 794 | struct btrfs_root *root, u64 owner_objectid) |
779 | { | 795 | { |
@@ -1422,7 +1438,7 @@ check_failed: | |||
1422 | orig_search_start); | 1438 | orig_search_start); |
1423 | } | 1439 | } |
1424 | search_start = find_search_start(root, &block_group, search_start, | 1440 | search_start = find_search_start(root, &block_group, search_start, |
1425 | total_needed, data, full_scan); | 1441 | total_needed, data); |
1426 | search_start = stripe_align(root, search_start); | 1442 | search_start = stripe_align(root, search_start); |
1427 | cached_start = search_start; | 1443 | cached_start = search_start; |
1428 | btrfs_init_path(path); | 1444 | btrfs_init_path(path); |
@@ -1434,35 +1450,11 @@ check_failed: | |||
1434 | ret = btrfs_search_slot(trans, root, ins, path, 0, 0); | 1450 | ret = btrfs_search_slot(trans, root, ins, path, 0, 0); |
1435 | if (ret < 0) | 1451 | if (ret < 0) |
1436 | goto error; | 1452 | goto error; |
1437 | 1453 | ret = find_previous_extent(root, path); | |
1438 | if (path->slots[0] > 0) { | 1454 | if (ret < 0) |
1439 | path->slots[0]--; | 1455 | goto error; |
1440 | } | ||
1441 | |||
1442 | l = path->nodes[0]; | 1456 | l = path->nodes[0]; |
1443 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); | 1457 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); |
1444 | |||
1445 | /* | ||
1446 | * walk backwards to find the first extent item key | ||
1447 | */ | ||
1448 | while(btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY) { | ||
1449 | if (path->slots[0] == 0) { | ||
1450 | ret = btrfs_prev_leaf(root, path); | ||
1451 | if (ret != 0) { | ||
1452 | ret = btrfs_search_slot(trans, root, ins, | ||
1453 | path, 0, 0); | ||
1454 | if (ret < 0) | ||
1455 | goto error; | ||
1456 | if (path->slots[0] > 0) | ||
1457 | path->slots[0]--; | ||
1458 | break; | ||
1459 | } | ||
1460 | } else { | ||
1461 | path->slots[0]--; | ||
1462 | } | ||
1463 | l = path->nodes[0]; | ||
1464 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); | ||
1465 | } | ||
1466 | while (1) { | 1458 | while (1) { |
1467 | l = path->nodes[0]; | 1459 | l = path->nodes[0]; |
1468 | slot = path->slots[0]; | 1460 | slot = path->slots[0]; |