aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/extent-tree.c61
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 }
108next:
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;
119err: 124err:
120 btrfs_free_path(path); 125 btrfs_free_path(path);