diff options
-rw-r--r-- | fs/btrfs/extent-tree.c | 61 |
1 files changed, 33 insertions, 28 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index b074ad1416dd..9151850266b0 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -39,6 +39,7 @@ static int cache_block_group(struct btrfs_root *root, | |||
39 | u64 i; | 39 | u64 i; |
40 | u64 last = 0; | 40 | u64 last = 0; |
41 | u64 hole_size; | 41 | u64 hole_size; |
42 | u64 first_free; | ||
42 | int found = 0; | 43 | int found = 0; |
43 | 44 | ||
44 | root = root->fs_info->extent_root; | 45 | root = root->fs_info->extent_root; |
@@ -51,16 +52,22 @@ static int cache_block_group(struct btrfs_root *root, | |||
51 | path = btrfs_alloc_path(); | 52 | path = btrfs_alloc_path(); |
52 | if (!path) | 53 | if (!path) |
53 | return -ENOMEM; | 54 | return -ENOMEM; |
55 | |||
54 | path->reada = 2; | 56 | path->reada = 2; |
57 | first_free = block_group->key.objectid; | ||
55 | key.objectid = block_group->key.objectid; | 58 | key.objectid = block_group->key.objectid; |
56 | key.flags = 0; | 59 | key.flags = 0; |
57 | key.offset = 0; | 60 | key.offset = 0; |
61 | |||
58 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); | 62 | btrfs_set_key_type(&key, BTRFS_EXTENT_ITEM_KEY); |
59 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 63 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
64 | |||
60 | if (ret < 0) | 65 | if (ret < 0) |
61 | return ret; | 66 | return ret; |
67 | |||
62 | if (ret && path->slots[0] > 0) | 68 | if (ret && path->slots[0] > 0) |
63 | path->slots[0]--; | 69 | path->slots[0]--; |
70 | |||
64 | while(1) { | 71 | while(1) { |
65 | leaf = btrfs_buffer_leaf(path->nodes[0]); | 72 | leaf = btrfs_buffer_leaf(path->nodes[0]); |
66 | slot = path->slots[0]; | 73 | slot = path->slots[0]; |
@@ -71,50 +78,48 @@ static int cache_block_group(struct btrfs_root *root, | |||
71 | if (ret == 0) { | 78 | if (ret == 0) { |
72 | continue; | 79 | continue; |
73 | } else { | 80 | } else { |
74 | if (found) { | ||
75 | hole_size = block_group->key.objectid + | ||
76 | block_group->key.offset - last; | ||
77 | } else { | ||
78 | last = block_group->key.objectid; | ||
79 | hole_size = block_group->key.offset; | ||
80 | } | ||
81 | for (i = 0; i < hole_size; i++) { | ||
82 | set_radix_bit(extent_radix, | ||
83 | last + i); | ||
84 | } | ||
85 | break; | 81 | break; |
86 | } | 82 | } |
87 | } | 83 | } |
84 | |||
88 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); | 85 | btrfs_disk_key_to_cpu(&key, &leaf->items[slot].key); |
86 | if (key.objectid < block_group->key.objectid) { | ||
87 | if (key.objectid + key.offset > first_free) | ||
88 | first_free = key.objectid + key.offset; | ||
89 | goto next; | ||
90 | } | ||
91 | |||
89 | if (key.objectid >= block_group->key.objectid + | 92 | if (key.objectid >= block_group->key.objectid + |
90 | block_group->key.offset) { | 93 | block_group->key.offset) { |
91 | if (found) { | ||
92 | hole_size = block_group->key.objectid + | ||
93 | block_group->key.offset - last; | ||
94 | } else { | ||
95 | last = block_group->key.objectid; | ||
96 | hole_size = block_group->key.offset; | ||
97 | } | ||
98 | for (i = 0; i < hole_size; i++) { | ||
99 | set_radix_bit(extent_radix, last + i); | ||
100 | } | ||
101 | break; | 94 | break; |
102 | } | 95 | } |
96 | |||
103 | if (btrfs_key_type(&key) == BTRFS_EXTENT_ITEM_KEY) { | 97 | if (btrfs_key_type(&key) == BTRFS_EXTENT_ITEM_KEY) { |
104 | if (!found) { | 98 | if (!found) { |
105 | last = key.objectid + key.offset; | 99 | last = first_free; |
106 | found = 1; | 100 | found = 1; |
107 | } else { | ||
108 | hole_size = key.objectid - last; | ||
109 | for (i = 0; i < hole_size; i++) { | ||
110 | set_radix_bit(extent_radix, last + i); | ||
111 | } | ||
112 | last = key.objectid + key.offset; | ||
113 | } | 101 | } |
102 | hole_size = key.objectid - last; | ||
103 | for (i = 0; i < hole_size; i++) { | ||
104 | set_radix_bit(extent_radix, last + i); | ||
105 | } | ||
106 | last = key.objectid + key.offset; | ||
114 | } | 107 | } |
108 | next: | ||
115 | path->slots[0]++; | 109 | path->slots[0]++; |
116 | } | 110 | } |
117 | 111 | ||
112 | if (!found) | ||
113 | last = first_free; | ||
114 | if (block_group->key.objectid + | ||
115 | block_group->key.offset > last) { | ||
116 | hole_size = block_group->key.objectid + | ||
117 | block_group->key.offset - last; | ||
118 | for (i = 0; i < hole_size; i++) { | ||
119 | set_radix_bit(extent_radix, | ||
120 | last + i); | ||
121 | } | ||
122 | } | ||
118 | block_group->cached = 1; | 123 | block_group->cached = 1; |
119 | err: | 124 | err: |
120 | btrfs_free_path(path); | 125 | btrfs_free_path(path); |