diff options
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 429 |
1 files changed, 115 insertions, 314 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index ebfd304138ca..2cd957d6e8d8 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -24,37 +24,19 @@ | |||
24 | #include "disk-io.h" | 24 | #include "disk-io.h" |
25 | #include "print-tree.h" | 25 | #include "print-tree.h" |
26 | #include "transaction.h" | 26 | #include "transaction.h" |
27 | #include "volumes.h" | ||
27 | 28 | ||
28 | #define BLOCK_GROUP_DATA EXTENT_WRITEBACK | 29 | #define BLOCK_GROUP_DATA EXTENT_WRITEBACK |
29 | #define BLOCK_GROUP_METADATA EXTENT_UPTODATE | 30 | #define BLOCK_GROUP_METADATA EXTENT_UPTODATE |
31 | #define BLOCK_GROUP_SYSTEM EXTENT_NEW | ||
32 | |||
30 | #define BLOCK_GROUP_DIRTY EXTENT_DIRTY | 33 | #define BLOCK_GROUP_DIRTY EXTENT_DIRTY |
31 | 34 | ||
32 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct | 35 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct |
33 | btrfs_root *extent_root); | 36 | btrfs_root *extent_root); |
34 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct | 37 | static int del_pending_extents(struct btrfs_trans_handle *trans, struct |
35 | btrfs_root *extent_root); | 38 | 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 | 39 | ||
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 | } | ||
58 | 40 | ||
59 | static int cache_block_group(struct btrfs_root *root, | 41 | static int cache_block_group(struct btrfs_root *root, |
60 | struct btrfs_block_group_cache *block_group) | 42 | struct btrfs_block_group_cache *block_group) |
@@ -91,7 +73,7 @@ static int cache_block_group(struct btrfs_root *root, | |||
91 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); | 73 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
92 | if (ret < 0) | 74 | if (ret < 0) |
93 | return ret; | 75 | return ret; |
94 | ret = find_previous_extent(root, path); | 76 | ret = btrfs_previous_item(root, path, 0, BTRFS_EXTENT_ITEM_KEY); |
95 | if (ret < 0) | 77 | if (ret < 0) |
96 | return ret; | 78 | return ret; |
97 | if (ret == 0) { | 79 | if (ret == 0) { |
@@ -168,7 +150,8 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct | |||
168 | block_group_cache = &info->block_group_cache; | 150 | block_group_cache = &info->block_group_cache; |
169 | ret = find_first_extent_bit(block_group_cache, | 151 | ret = find_first_extent_bit(block_group_cache, |
170 | bytenr, &start, &end, | 152 | bytenr, &start, &end, |
171 | BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA); | 153 | BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA | |
154 | BLOCK_GROUP_SYSTEM); | ||
172 | if (ret) { | 155 | if (ret) { |
173 | return NULL; | 156 | return NULL; |
174 | } | 157 | } |
@@ -182,23 +165,38 @@ struct btrfs_block_group_cache *btrfs_lookup_block_group(struct | |||
182 | return block_group; | 165 | return block_group; |
183 | return NULL; | 166 | return NULL; |
184 | } | 167 | } |
185 | static u64 noinline find_search_start(struct btrfs_root *root, | 168 | |
169 | static int block_group_bits(struct btrfs_block_group_cache *cache, u64 bits) | ||
170 | { | ||
171 | if ((bits & BLOCK_GROUP_DATA) && | ||
172 | (cache->flags & BTRFS_BLOCK_GROUP_DATA)) | ||
173 | return 1; | ||
174 | if ((bits & BLOCK_GROUP_METADATA) && | ||
175 | (cache->flags & BTRFS_BLOCK_GROUP_METADATA)) | ||
176 | return 1; | ||
177 | if ((bits & BLOCK_GROUP_SYSTEM) && | ||
178 | (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM)) | ||
179 | return 1; | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static int noinline find_search_start(struct btrfs_root *root, | ||
186 | struct btrfs_block_group_cache **cache_ret, | 184 | struct btrfs_block_group_cache **cache_ret, |
187 | u64 search_start, int num, int data) | 185 | u64 *start_ret, int num, int data) |
188 | { | 186 | { |
189 | int ret; | 187 | int ret; |
190 | struct btrfs_block_group_cache *cache = *cache_ret; | 188 | struct btrfs_block_group_cache *cache = *cache_ret; |
191 | struct extent_io_tree *free_space_cache; | 189 | struct extent_io_tree *free_space_cache; |
192 | struct extent_state *state; | ||
193 | u64 last; | 190 | u64 last; |
194 | u64 start = 0; | 191 | u64 start = 0; |
192 | u64 end = 0; | ||
195 | u64 cache_miss = 0; | 193 | u64 cache_miss = 0; |
196 | u64 total_fs_bytes; | 194 | u64 total_fs_bytes; |
195 | u64 search_start = *start_ret; | ||
197 | int wrapped = 0; | 196 | int wrapped = 0; |
198 | 197 | ||
199 | if (!cache) { | 198 | if (!cache) |
200 | goto out; | 199 | goto out; |
201 | } | ||
202 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | 200 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); |
203 | free_space_cache = &root->fs_info->free_space_cache; | 201 | free_space_cache = &root->fs_info->free_space_cache; |
204 | 202 | ||
@@ -208,6 +206,9 @@ again: | |||
208 | goto out; | 206 | goto out; |
209 | 207 | ||
210 | last = max(search_start, cache->key.objectid); | 208 | last = max(search_start, cache->key.objectid); |
209 | if (!block_group_bits(cache, data)) { | ||
210 | goto new_group; | ||
211 | } | ||
211 | 212 | ||
212 | while(1) { | 213 | while(1) { |
213 | ret = find_first_extent_bit(&root->fs_info->free_space_cache, | 214 | ret = find_first_extent_bit(&root->fs_info->free_space_cache, |
@@ -225,22 +226,20 @@ again: | |||
225 | cache_miss = start; | 226 | cache_miss = start; |
226 | continue; | 227 | continue; |
227 | } | 228 | } |
228 | if (data != BTRFS_BLOCK_GROUP_MIXED && | 229 | if (start + num > cache->key.objectid + cache->key.offset) |
229 | start + num > cache->key.objectid + cache->key.offset) | ||
230 | goto new_group; | 230 | goto new_group; |
231 | if (start + num > total_fs_bytes) | 231 | if (start + num > total_fs_bytes) |
232 | goto new_group; | 232 | goto new_group; |
233 | return start; | 233 | *start_ret = start; |
234 | return 0; | ||
234 | } | 235 | } |
235 | out: | 236 | out: |
236 | cache = btrfs_lookup_block_group(root->fs_info, search_start); | 237 | cache = btrfs_lookup_block_group(root->fs_info, search_start); |
237 | if (!cache) { | 238 | if (!cache) { |
238 | printk("Unable to find block group for %Lu\n", | 239 | printk("Unable to find block group for %Lu\n", search_start); |
239 | search_start); | ||
240 | WARN_ON(1); | 240 | WARN_ON(1); |
241 | return search_start; | ||
242 | } | 241 | } |
243 | return search_start; | 242 | return -ENOSPC; |
244 | 243 | ||
245 | new_group: | 244 | new_group: |
246 | last = cache->key.objectid + cache->key.offset; | 245 | last = cache->key.objectid + cache->key.offset; |
@@ -251,7 +250,6 @@ no_cache: | |||
251 | if (!wrapped) { | 250 | if (!wrapped) { |
252 | wrapped = 1; | 251 | wrapped = 1; |
253 | last = search_start; | 252 | last = search_start; |
254 | data = BTRFS_BLOCK_GROUP_MIXED; | ||
255 | goto wrapped; | 253 | goto wrapped; |
256 | } | 254 | } |
257 | goto out; | 255 | goto out; |
@@ -299,7 +297,6 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
299 | int ret; | 297 | int ret; |
300 | int full_search = 0; | 298 | int full_search = 0; |
301 | int factor = 8; | 299 | int factor = 8; |
302 | int data_swap = 0; | ||
303 | 300 | ||
304 | block_group_cache = &info->block_group_cache; | 301 | block_group_cache = &info->block_group_cache; |
305 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); | 302 | total_fs_bytes = btrfs_super_total_bytes(&root->fs_info->super_copy); |
@@ -307,19 +304,12 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
307 | if (!owner) | 304 | if (!owner) |
308 | factor = 8; | 305 | factor = 8; |
309 | 306 | ||
310 | if (data == BTRFS_BLOCK_GROUP_MIXED) { | 307 | bit = data; |
311 | bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA; | ||
312 | factor = 10; | ||
313 | } else if (data) | ||
314 | bit = BLOCK_GROUP_DATA; | ||
315 | else | ||
316 | bit = BLOCK_GROUP_METADATA; | ||
317 | 308 | ||
318 | if (search_start && search_start < total_fs_bytes) { | 309 | if (search_start && search_start < total_fs_bytes) { |
319 | struct btrfs_block_group_cache *shint; | 310 | struct btrfs_block_group_cache *shint; |
320 | shint = btrfs_lookup_block_group(info, search_start); | 311 | shint = btrfs_lookup_block_group(info, search_start); |
321 | if (shint && (shint->data == data || | 312 | if (shint && block_group_bits(shint, data)) { |
322 | shint->data == BTRFS_BLOCK_GROUP_MIXED)) { | ||
323 | used = btrfs_block_group_used(&shint->item); | 313 | used = btrfs_block_group_used(&shint->item); |
324 | if (used + shint->pinned < | 314 | if (used + shint->pinned < |
325 | div_factor(shint->key.offset, factor)) { | 315 | div_factor(shint->key.offset, factor)) { |
@@ -327,8 +317,8 @@ struct btrfs_block_group_cache *btrfs_find_block_group(struct btrfs_root *root, | |||
327 | } | 317 | } |
328 | } | 318 | } |
329 | } | 319 | } |
330 | if (hint && hint->key.objectid < total_fs_bytes && | 320 | if (hint && block_group_bits(hint, data) && |
331 | (hint->data == data || hint->data == BTRFS_BLOCK_GROUP_MIXED)) { | 321 | hint->key.objectid < total_fs_bytes) { |
332 | used = btrfs_block_group_used(&hint->item); | 322 | used = btrfs_block_group_used(&hint->item); |
333 | if (used + hint->pinned < | 323 | if (used + hint->pinned < |
334 | div_factor(hint->key.offset, factor)) { | 324 | div_factor(hint->key.offset, factor)) { |
@@ -379,12 +369,6 @@ again: | |||
379 | full_search = 1; | 369 | full_search = 1; |
380 | goto again; | 370 | goto again; |
381 | } | 371 | } |
382 | if (!data_swap) { | ||
383 | data_swap = 1; | ||
384 | bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA; | ||
385 | last = search_start; | ||
386 | goto again; | ||
387 | } | ||
388 | found: | 372 | found: |
389 | return found_group; | 373 | return found_group; |
390 | } | 374 | } |
@@ -1002,7 +986,7 @@ int btrfs_write_dirty_block_groups(struct btrfs_trans_handle *trans, | |||
1002 | static int update_block_group(struct btrfs_trans_handle *trans, | 986 | static int update_block_group(struct btrfs_trans_handle *trans, |
1003 | struct btrfs_root *root, | 987 | struct btrfs_root *root, |
1004 | u64 bytenr, u64 num_bytes, int alloc, | 988 | u64 bytenr, u64 num_bytes, int alloc, |
1005 | int mark_free, int data) | 989 | int mark_free) |
1006 | { | 990 | { |
1007 | struct btrfs_block_group_cache *cache; | 991 | struct btrfs_block_group_cache *cache; |
1008 | struct btrfs_fs_info *info = root->fs_info; | 992 | struct btrfs_fs_info *info = root->fs_info; |
@@ -1027,41 +1011,6 @@ static int update_block_group(struct btrfs_trans_handle *trans, | |||
1027 | old_val = btrfs_block_group_used(&cache->item); | 1011 | old_val = btrfs_block_group_used(&cache->item); |
1028 | num_bytes = min(total, cache->key.offset - byte_in_group); | 1012 | num_bytes = min(total, cache->key.offset - byte_in_group); |
1029 | if (alloc) { | 1013 | if (alloc) { |
1030 | if (cache->data != data && | ||
1031 | old_val < (cache->key.offset >> 1)) { | ||
1032 | int bit_to_clear; | ||
1033 | int bit_to_set; | ||
1034 | cache->data = data; | ||
1035 | if (data) { | ||
1036 | bit_to_clear = BLOCK_GROUP_METADATA; | ||
1037 | bit_to_set = BLOCK_GROUP_DATA; | ||
1038 | cache->item.flags &= | ||
1039 | ~BTRFS_BLOCK_GROUP_MIXED; | ||
1040 | cache->item.flags |= | ||
1041 | BTRFS_BLOCK_GROUP_DATA; | ||
1042 | } else { | ||
1043 | bit_to_clear = BLOCK_GROUP_DATA; | ||
1044 | bit_to_set = BLOCK_GROUP_METADATA; | ||
1045 | cache->item.flags &= | ||
1046 | ~BTRFS_BLOCK_GROUP_MIXED; | ||
1047 | cache->item.flags &= | ||
1048 | ~BTRFS_BLOCK_GROUP_DATA; | ||
1049 | } | ||
1050 | clear_extent_bits(&info->block_group_cache, | ||
1051 | start, end, bit_to_clear, | ||
1052 | GFP_NOFS); | ||
1053 | set_extent_bits(&info->block_group_cache, | ||
1054 | start, end, bit_to_set, | ||
1055 | GFP_NOFS); | ||
1056 | } else if (cache->data != data && | ||
1057 | cache->data != BTRFS_BLOCK_GROUP_MIXED) { | ||
1058 | cache->data = BTRFS_BLOCK_GROUP_MIXED; | ||
1059 | set_extent_bits(&info->block_group_cache, | ||
1060 | start, end, | ||
1061 | BLOCK_GROUP_DATA | | ||
1062 | BLOCK_GROUP_METADATA, | ||
1063 | GFP_NOFS); | ||
1064 | } | ||
1065 | old_val += num_bytes; | 1014 | old_val += num_bytes; |
1066 | } else { | 1015 | } else { |
1067 | old_val -= num_bytes; | 1016 | old_val -= num_bytes; |
@@ -1357,7 +1306,7 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1357 | return ret; | 1306 | return ret; |
1358 | } | 1307 | } |
1359 | ret = update_block_group(trans, root, bytenr, num_bytes, 0, | 1308 | ret = update_block_group(trans, root, bytenr, num_bytes, 0, |
1360 | mark_free, 0); | 1309 | mark_free); |
1361 | BUG_ON(ret); | 1310 | BUG_ON(ret); |
1362 | } | 1311 | } |
1363 | btrfs_free_path(path); | 1312 | btrfs_free_path(path); |
@@ -1450,38 +1399,21 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
1450 | u64 exclude_start, u64 exclude_nr, | 1399 | u64 exclude_start, u64 exclude_nr, |
1451 | int data) | 1400 | int data) |
1452 | { | 1401 | { |
1453 | struct btrfs_path *path; | ||
1454 | struct btrfs_key key; | ||
1455 | u64 hole_size = 0; | ||
1456 | u64 aligned; | ||
1457 | int ret; | 1402 | int ret; |
1458 | int slot = 0; | ||
1459 | u64 last_byte = 0; | ||
1460 | u64 *last_ptr = NULL; | ||
1461 | u64 orig_search_start = search_start; | 1403 | u64 orig_search_start = search_start; |
1462 | int start_found; | ||
1463 | struct extent_buffer *l; | ||
1464 | struct btrfs_root * root = orig_root->fs_info->extent_root; | 1404 | struct btrfs_root * root = orig_root->fs_info->extent_root; |
1465 | struct btrfs_fs_info *info = root->fs_info; | 1405 | struct btrfs_fs_info *info = root->fs_info; |
1466 | u64 total_needed = num_bytes; | 1406 | u64 total_needed = num_bytes; |
1467 | int level; | ||
1468 | struct btrfs_block_group_cache *block_group; | 1407 | struct btrfs_block_group_cache *block_group; |
1469 | int full_scan = 0; | 1408 | int full_scan = 0; |
1470 | int wrapped = 0; | 1409 | int wrapped = 0; |
1471 | int empty_cluster; | ||
1472 | u64 cached_start; | ||
1473 | 1410 | ||
1474 | WARN_ON(num_bytes < root->sectorsize); | 1411 | WARN_ON(num_bytes < root->sectorsize); |
1475 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); | 1412 | btrfs_set_key_type(ins, BTRFS_EXTENT_ITEM_KEY); |
1476 | 1413 | ||
1477 | level = btrfs_header_level(root->node); | ||
1478 | |||
1479 | if (num_bytes >= 32 * 1024 * 1024 && hint_byte) { | ||
1480 | data = BTRFS_BLOCK_GROUP_MIXED; | ||
1481 | } | ||
1482 | |||
1483 | if (search_end == (u64)-1) | 1414 | if (search_end == (u64)-1) |
1484 | search_end = btrfs_super_total_bytes(&info->super_copy); | 1415 | search_end = btrfs_super_total_bytes(&info->super_copy); |
1416 | |||
1485 | if (hint_byte) { | 1417 | if (hint_byte) { |
1486 | block_group = btrfs_lookup_block_group(info, hint_byte); | 1418 | block_group = btrfs_lookup_block_group(info, hint_byte); |
1487 | if (!block_group) | 1419 | if (!block_group) |
@@ -1495,7 +1427,7 @@ static int noinline find_free_extent(struct btrfs_trans_handle *trans, | |||
1495 | } | 1427 | } |
1496 | 1428 | ||
1497 | total_needed += empty_size; | 1429 | total_needed += empty_size; |
1498 | path = btrfs_alloc_path(); | 1430 | |
1499 | check_failed: | 1431 | check_failed: |
1500 | if (!block_group) { | 1432 | if (!block_group) { |
1501 | block_group = btrfs_lookup_block_group(info, search_start); | 1433 | block_group = btrfs_lookup_block_group(info, search_start); |
@@ -1503,135 +1435,49 @@ check_failed: | |||
1503 | block_group = btrfs_lookup_block_group(info, | 1435 | block_group = btrfs_lookup_block_group(info, |
1504 | orig_search_start); | 1436 | orig_search_start); |
1505 | } | 1437 | } |
1506 | search_start = find_search_start(root, &block_group, search_start, | 1438 | ret = find_search_start(root, &block_group, &search_start, |
1507 | total_needed, data); | 1439 | total_needed, data); |
1508 | search_start = stripe_align(root, search_start); | 1440 | if (ret) |
1509 | cached_start = search_start; | ||
1510 | btrfs_init_path(path); | ||
1511 | ins->objectid = search_start; | ||
1512 | ins->offset = 0; | ||
1513 | start_found = 0; | ||
1514 | path->reada = 2; | ||
1515 | |||
1516 | ret = btrfs_search_slot(trans, root, ins, path, 0, 0); | ||
1517 | if (ret < 0) | ||
1518 | goto error; | ||
1519 | ret = find_previous_extent(root, path); | ||
1520 | if (ret < 0) | ||
1521 | goto error; | 1441 | goto error; |
1522 | l = path->nodes[0]; | ||
1523 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); | ||
1524 | while (1) { | ||
1525 | l = path->nodes[0]; | ||
1526 | slot = path->slots[0]; | ||
1527 | if (slot >= btrfs_header_nritems(l)) { | ||
1528 | ret = btrfs_next_leaf(root, path); | ||
1529 | if (ret == 0) | ||
1530 | continue; | ||
1531 | if (ret < 0) | ||
1532 | goto error; | ||
1533 | 1442 | ||
1534 | search_start = max(search_start, | 1443 | search_start = stripe_align(root, search_start); |
1535 | block_group->key.objectid); | 1444 | ins->objectid = search_start; |
1536 | if (!start_found) { | 1445 | ins->offset = num_bytes; |
1537 | aligned = stripe_align(root, search_start); | ||
1538 | ins->objectid = aligned; | ||
1539 | if (aligned >= search_end) { | ||
1540 | ret = -ENOSPC; | ||
1541 | goto error; | ||
1542 | } | ||
1543 | ins->offset = search_end - aligned; | ||
1544 | start_found = 1; | ||
1545 | goto check_pending; | ||
1546 | } | ||
1547 | ins->objectid = stripe_align(root, | ||
1548 | last_byte > search_start ? | ||
1549 | last_byte : search_start); | ||
1550 | if (search_end <= ins->objectid) { | ||
1551 | ret = -ENOSPC; | ||
1552 | goto error; | ||
1553 | } | ||
1554 | ins->offset = search_end - ins->objectid; | ||
1555 | BUG_ON(ins->objectid >= search_end); | ||
1556 | goto check_pending; | ||
1557 | } | ||
1558 | btrfs_item_key_to_cpu(l, &key, slot); | ||
1559 | |||
1560 | if (key.objectid >= search_start && key.objectid > last_byte && | ||
1561 | start_found) { | ||
1562 | if (last_byte < search_start) | ||
1563 | last_byte = search_start; | ||
1564 | aligned = stripe_align(root, last_byte); | ||
1565 | hole_size = key.objectid - aligned; | ||
1566 | if (key.objectid > aligned && hole_size >= num_bytes) { | ||
1567 | ins->objectid = aligned; | ||
1568 | ins->offset = hole_size; | ||
1569 | goto check_pending; | ||
1570 | } | ||
1571 | } | ||
1572 | if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY) { | ||
1573 | if (!start_found && btrfs_key_type(&key) == | ||
1574 | BTRFS_BLOCK_GROUP_ITEM_KEY) { | ||
1575 | last_byte = key.objectid; | ||
1576 | start_found = 1; | ||
1577 | } | ||
1578 | goto next; | ||
1579 | } | ||
1580 | |||
1581 | |||
1582 | start_found = 1; | ||
1583 | last_byte = key.objectid + key.offset; | ||
1584 | |||
1585 | if (!full_scan && data != BTRFS_BLOCK_GROUP_MIXED && | ||
1586 | last_byte >= block_group->key.objectid + | ||
1587 | block_group->key.offset) { | ||
1588 | btrfs_release_path(root, path); | ||
1589 | search_start = block_group->key.objectid + | ||
1590 | block_group->key.offset; | ||
1591 | goto new_group; | ||
1592 | } | ||
1593 | next: | ||
1594 | path->slots[0]++; | ||
1595 | cond_resched(); | ||
1596 | } | ||
1597 | check_pending: | ||
1598 | /* we have to make sure we didn't find an extent that has already | ||
1599 | * been allocated by the map tree or the original allocation | ||
1600 | */ | ||
1601 | btrfs_release_path(root, path); | ||
1602 | BUG_ON(ins->objectid < search_start); | ||
1603 | 1446 | ||
1604 | if (ins->objectid + num_bytes >= search_end) | 1447 | if (ins->objectid + num_bytes >= search_end) |
1605 | goto enospc; | 1448 | goto enospc; |
1606 | if (!full_scan && data != BTRFS_BLOCK_GROUP_MIXED && | 1449 | |
1607 | ins->objectid + num_bytes > block_group-> | 1450 | if (ins->objectid + num_bytes > |
1608 | key.objectid + block_group->key.offset) { | 1451 | block_group->key.objectid + block_group->key.offset) { |
1609 | search_start = block_group->key.objectid + | 1452 | search_start = block_group->key.objectid + |
1610 | block_group->key.offset; | 1453 | block_group->key.offset; |
1611 | goto new_group; | 1454 | goto new_group; |
1612 | } | 1455 | } |
1456 | |||
1613 | if (test_range_bit(&info->extent_ins, ins->objectid, | 1457 | if (test_range_bit(&info->extent_ins, ins->objectid, |
1614 | ins->objectid + num_bytes -1, EXTENT_LOCKED, 0)) { | 1458 | ins->objectid + num_bytes -1, EXTENT_LOCKED, 0)) { |
1615 | search_start = ins->objectid + num_bytes; | 1459 | search_start = ins->objectid + num_bytes; |
1616 | goto new_group; | 1460 | goto new_group; |
1617 | } | 1461 | } |
1462 | |||
1618 | if (test_range_bit(&info->pinned_extents, ins->objectid, | 1463 | if (test_range_bit(&info->pinned_extents, ins->objectid, |
1619 | ins->objectid + num_bytes -1, EXTENT_DIRTY, 0)) { | 1464 | ins->objectid + num_bytes -1, EXTENT_DIRTY, 0)) { |
1620 | search_start = ins->objectid + num_bytes; | 1465 | search_start = ins->objectid + num_bytes; |
1621 | goto new_group; | 1466 | goto new_group; |
1622 | } | 1467 | } |
1468 | |||
1623 | if (exclude_nr > 0 && (ins->objectid + num_bytes > exclude_start && | 1469 | if (exclude_nr > 0 && (ins->objectid + num_bytes > exclude_start && |
1624 | ins->objectid < exclude_start + exclude_nr)) { | 1470 | ins->objectid < exclude_start + exclude_nr)) { |
1625 | search_start = exclude_start + exclude_nr; | 1471 | search_start = exclude_start + exclude_nr; |
1626 | goto new_group; | 1472 | goto new_group; |
1627 | } | 1473 | } |
1628 | if (!data) { | 1474 | |
1475 | if (!(data & BLOCK_GROUP_DATA)) { | ||
1629 | block_group = btrfs_lookup_block_group(info, ins->objectid); | 1476 | block_group = btrfs_lookup_block_group(info, ins->objectid); |
1630 | if (block_group) | 1477 | if (block_group) |
1631 | trans->block_group = block_group; | 1478 | trans->block_group = block_group; |
1632 | } | 1479 | } |
1633 | ins->offset = num_bytes; | 1480 | ins->offset = num_bytes; |
1634 | btrfs_free_path(path); | ||
1635 | return 0; | 1481 | return 0; |
1636 | 1482 | ||
1637 | new_group: | 1483 | new_group: |
@@ -1646,7 +1492,6 @@ enospc: | |||
1646 | if (!full_scan) | 1492 | if (!full_scan) |
1647 | total_needed -= empty_size; | 1493 | total_needed -= empty_size; |
1648 | full_scan = 1; | 1494 | full_scan = 1; |
1649 | data = BTRFS_BLOCK_GROUP_MIXED; | ||
1650 | } else | 1495 | } else |
1651 | wrapped = 1; | 1496 | wrapped = 1; |
1652 | } | 1497 | } |
@@ -1657,8 +1502,6 @@ enospc: | |||
1657 | goto check_failed; | 1502 | goto check_failed; |
1658 | 1503 | ||
1659 | error: | 1504 | error: |
1660 | btrfs_release_path(root, path); | ||
1661 | btrfs_free_path(path); | ||
1662 | return ret; | 1505 | return ret; |
1663 | } | 1506 | } |
1664 | /* | 1507 | /* |
@@ -1689,6 +1532,13 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1689 | struct btrfs_path *path; | 1532 | struct btrfs_path *path; |
1690 | struct btrfs_key keys[2]; | 1533 | struct btrfs_key keys[2]; |
1691 | 1534 | ||
1535 | if (data) | ||
1536 | data = BLOCK_GROUP_DATA; | ||
1537 | else if (root == root->fs_info->chunk_root) | ||
1538 | data = BLOCK_GROUP_SYSTEM; | ||
1539 | else | ||
1540 | data = BLOCK_GROUP_METADATA; | ||
1541 | |||
1692 | new_hint = max(hint_byte, root->fs_info->alloc_start); | 1542 | new_hint = max(hint_byte, root->fs_info->alloc_start); |
1693 | if (new_hint < btrfs_super_total_bytes(&info->super_copy)) | 1543 | if (new_hint < btrfs_super_total_bytes(&info->super_copy)) |
1694 | hint_byte = new_hint; | 1544 | hint_byte = new_hint; |
@@ -1718,7 +1568,6 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1718 | set_extent_bits(&root->fs_info->extent_ins, ins->objectid, | 1568 | set_extent_bits(&root->fs_info->extent_ins, ins->objectid, |
1719 | ins->objectid + ins->offset - 1, | 1569 | ins->objectid + ins->offset - 1, |
1720 | EXTENT_LOCKED, GFP_NOFS); | 1570 | EXTENT_LOCKED, GFP_NOFS); |
1721 | WARN_ON(data == 1); | ||
1722 | goto update_block; | 1571 | goto update_block; |
1723 | } | 1572 | } |
1724 | 1573 | ||
@@ -1768,8 +1617,7 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1768 | } | 1617 | } |
1769 | 1618 | ||
1770 | update_block: | 1619 | update_block: |
1771 | ret = update_block_group(trans, root, ins->objectid, ins->offset, 1, 0, | 1620 | ret = update_block_group(trans, root, ins->objectid, ins->offset, 1, 0); |
1772 | data); | ||
1773 | if (ret) { | 1621 | if (ret) { |
1774 | printk("update block group failed for %Lu %Lu\n", | 1622 | printk("update block group failed for %Lu %Lu\n", |
1775 | ins->objectid, ins->offset); | 1623 | ins->objectid, ins->offset); |
@@ -2457,7 +2305,7 @@ again: | |||
2457 | if (ret < 0) | 2305 | if (ret < 0) |
2458 | goto out; | 2306 | goto out; |
2459 | 2307 | ||
2460 | ret = find_previous_extent(root, path); | 2308 | ret = btrfs_previous_item(root, path, 0, BTRFS_EXTENT_ITEM_KEY); |
2461 | if (ret < 0) | 2309 | if (ret < 0) |
2462 | goto out; | 2310 | goto out; |
2463 | if (ret == 0) { | 2311 | if (ret == 0) { |
@@ -2604,95 +2452,48 @@ out: | |||
2604 | int btrfs_grow_extent_tree(struct btrfs_trans_handle *trans, | 2452 | int btrfs_grow_extent_tree(struct btrfs_trans_handle *trans, |
2605 | struct btrfs_root *root, u64 new_size) | 2453 | struct btrfs_root *root, u64 new_size) |
2606 | { | 2454 | { |
2607 | struct btrfs_path *path; | 2455 | btrfs_set_super_total_bytes(&root->fs_info->super_copy, new_size); |
2608 | u64 nr = 0; | 2456 | return 0; |
2609 | u64 cur_byte; | 2457 | } |
2610 | u64 old_size; | ||
2611 | unsigned long rem; | ||
2612 | struct btrfs_block_group_cache *cache; | ||
2613 | struct btrfs_block_group_item *item; | ||
2614 | struct btrfs_fs_info *info = root->fs_info; | ||
2615 | struct extent_io_tree *block_group_cache; | ||
2616 | struct btrfs_key key; | ||
2617 | struct extent_buffer *leaf; | ||
2618 | int ret; | ||
2619 | int bit; | ||
2620 | |||
2621 | old_size = btrfs_super_total_bytes(&info->super_copy); | ||
2622 | block_group_cache = &info->block_group_cache; | ||
2623 | |||
2624 | root = info->extent_root; | ||
2625 | |||
2626 | cache = btrfs_lookup_block_group(root->fs_info, old_size - 1); | ||
2627 | |||
2628 | cur_byte = cache->key.objectid + cache->key.offset; | ||
2629 | if (cur_byte >= new_size) | ||
2630 | goto set_size; | ||
2631 | |||
2632 | key.offset = BTRFS_BLOCK_GROUP_SIZE; | ||
2633 | btrfs_set_key_type(&key, BTRFS_BLOCK_GROUP_ITEM_KEY); | ||
2634 | 2458 | ||
2635 | path = btrfs_alloc_path(); | 2459 | int find_first_block_group(struct btrfs_root *root, struct btrfs_path *path, |
2636 | if (!path) | 2460 | struct btrfs_key *key) |
2637 | return -ENOMEM; | 2461 | { |
2462 | int ret; | ||
2463 | struct btrfs_key found_key; | ||
2464 | struct extent_buffer *leaf; | ||
2465 | int slot; | ||
2638 | 2466 | ||
2639 | while(cur_byte < new_size) { | 2467 | ret = btrfs_search_slot(NULL, root, key, path, 0, 0); |
2640 | key.objectid = cur_byte; | 2468 | if (ret < 0) |
2641 | ret = btrfs_insert_empty_item(trans, root, path, &key, | 2469 | return ret; |
2642 | sizeof(struct btrfs_block_group_item)); | 2470 | while(1) { |
2643 | BUG_ON(ret); | 2471 | slot = path->slots[0]; |
2644 | leaf = path->nodes[0]; | 2472 | leaf = path->nodes[0]; |
2645 | item = btrfs_item_ptr(leaf, path->slots[0], | 2473 | if (slot >= btrfs_header_nritems(leaf)) { |
2646 | struct btrfs_block_group_item); | 2474 | ret = btrfs_next_leaf(root, path); |
2647 | 2475 | if (ret == 0) | |
2648 | btrfs_set_disk_block_group_used(leaf, item, 0); | 2476 | continue; |
2649 | div_long_long_rem(nr, 3, &rem); | 2477 | if (ret < 0) |
2650 | if (rem) { | 2478 | goto error; |
2651 | btrfs_set_disk_block_group_flags(leaf, item, | 2479 | break; |
2652 | BTRFS_BLOCK_GROUP_DATA); | ||
2653 | } else { | ||
2654 | btrfs_set_disk_block_group_flags(leaf, item, 0); | ||
2655 | } | ||
2656 | nr++; | ||
2657 | |||
2658 | cache = kmalloc(sizeof(*cache), GFP_NOFS); | ||
2659 | BUG_ON(!cache); | ||
2660 | |||
2661 | read_extent_buffer(leaf, &cache->item, (unsigned long)item, | ||
2662 | sizeof(cache->item)); | ||
2663 | |||
2664 | memcpy(&cache->key, &key, sizeof(key)); | ||
2665 | cache->cached = 0; | ||
2666 | cache->pinned = 0; | ||
2667 | cur_byte = key.objectid + key.offset; | ||
2668 | btrfs_release_path(root, path); | ||
2669 | |||
2670 | if (cache->item.flags & BTRFS_BLOCK_GROUP_DATA) { | ||
2671 | bit = BLOCK_GROUP_DATA; | ||
2672 | cache->data = BTRFS_BLOCK_GROUP_DATA; | ||
2673 | } else { | ||
2674 | bit = BLOCK_GROUP_METADATA; | ||
2675 | cache->data = 0; | ||
2676 | } | 2480 | } |
2481 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | ||
2677 | 2482 | ||
2678 | /* use EXTENT_LOCKED to prevent merging */ | 2483 | if (found_key.objectid >= key->objectid && |
2679 | set_extent_bits(block_group_cache, key.objectid, | 2484 | found_key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) |
2680 | key.objectid + key.offset - 1, | 2485 | return 0; |
2681 | bit | EXTENT_LOCKED, GFP_NOFS); | 2486 | path->slots[0]++; |
2682 | set_state_private(block_group_cache, key.objectid, | ||
2683 | (unsigned long)cache); | ||
2684 | } | 2487 | } |
2685 | btrfs_free_path(path); | 2488 | ret = -ENOENT; |
2686 | set_size: | 2489 | error: |
2687 | btrfs_set_super_total_bytes(&info->super_copy, new_size); | 2490 | return ret; |
2688 | return 0; | ||
2689 | } | 2491 | } |
2690 | 2492 | ||
2691 | int btrfs_read_block_groups(struct btrfs_root *root) | 2493 | int btrfs_read_block_groups(struct btrfs_root *root) |
2692 | { | 2494 | { |
2693 | struct btrfs_path *path; | 2495 | struct btrfs_path *path; |
2694 | int ret; | 2496 | int ret; |
2695 | int err = 0; | ||
2696 | int bit; | 2497 | int bit; |
2697 | struct btrfs_block_group_cache *cache; | 2498 | struct btrfs_block_group_cache *cache; |
2698 | struct btrfs_fs_info *info = root->fs_info; | 2499 | struct btrfs_fs_info *info = root->fs_info; |
@@ -2702,28 +2503,28 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
2702 | struct extent_buffer *leaf; | 2503 | struct extent_buffer *leaf; |
2703 | 2504 | ||
2704 | block_group_cache = &info->block_group_cache; | 2505 | block_group_cache = &info->block_group_cache; |
2705 | |||
2706 | root = info->extent_root; | 2506 | root = info->extent_root; |
2707 | key.objectid = 0; | 2507 | key.objectid = 0; |
2708 | key.offset = BTRFS_BLOCK_GROUP_SIZE; | 2508 | key.offset = 0; |
2709 | btrfs_set_key_type(&key, BTRFS_BLOCK_GROUP_ITEM_KEY); | 2509 | btrfs_set_key_type(&key, BTRFS_BLOCK_GROUP_ITEM_KEY); |
2710 | |||
2711 | path = btrfs_alloc_path(); | 2510 | path = btrfs_alloc_path(); |
2712 | if (!path) | 2511 | if (!path) |
2713 | return -ENOMEM; | 2512 | return -ENOMEM; |
2714 | 2513 | ||
2715 | while(1) { | 2514 | while(1) { |
2716 | ret = btrfs_search_slot(NULL, info->extent_root, | 2515 | ret = find_first_block_group(root, path, &key); |
2717 | &key, path, 0, 0); | 2516 | if (ret > 0) { |
2718 | if (ret != 0) { | 2517 | ret = 0; |
2719 | err = ret; | 2518 | goto error; |
2720 | break; | ||
2721 | } | 2519 | } |
2520 | if (ret != 0) | ||
2521 | goto error; | ||
2522 | |||
2722 | leaf = path->nodes[0]; | 2523 | leaf = path->nodes[0]; |
2723 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | 2524 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
2724 | cache = kmalloc(sizeof(*cache), GFP_NOFS); | 2525 | cache = kmalloc(sizeof(*cache), GFP_NOFS); |
2725 | if (!cache) { | 2526 | if (!cache) { |
2726 | err = -1; | 2527 | ret = -ENOMEM; |
2727 | break; | 2528 | break; |
2728 | } | 2529 | } |
2729 | 2530 | ||
@@ -2733,18 +2534,17 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
2733 | memcpy(&cache->key, &found_key, sizeof(found_key)); | 2534 | memcpy(&cache->key, &found_key, sizeof(found_key)); |
2734 | cache->cached = 0; | 2535 | cache->cached = 0; |
2735 | cache->pinned = 0; | 2536 | cache->pinned = 0; |
2537 | |||
2736 | key.objectid = found_key.objectid + found_key.offset; | 2538 | key.objectid = found_key.objectid + found_key.offset; |
2737 | btrfs_release_path(root, path); | 2539 | btrfs_release_path(root, path); |
2738 | 2540 | cache->flags = btrfs_block_group_flags(&cache->item); | |
2739 | if (cache->item.flags & BTRFS_BLOCK_GROUP_MIXED) { | 2541 | bit = 0; |
2740 | bit = BLOCK_GROUP_DATA | BLOCK_GROUP_METADATA; | 2542 | if (cache->flags & BTRFS_BLOCK_GROUP_DATA) { |
2741 | cache->data = BTRFS_BLOCK_GROUP_MIXED; | ||
2742 | } else if (cache->item.flags & BTRFS_BLOCK_GROUP_DATA) { | ||
2743 | bit = BLOCK_GROUP_DATA; | 2543 | bit = BLOCK_GROUP_DATA; |
2744 | cache->data = BTRFS_BLOCK_GROUP_DATA; | 2544 | } else if (cache->flags & BTRFS_BLOCK_GROUP_SYSTEM) { |
2745 | } else { | 2545 | bit = BLOCK_GROUP_SYSTEM; |
2546 | } else if (cache->flags & BTRFS_BLOCK_GROUP_METADATA) { | ||
2746 | bit = BLOCK_GROUP_METADATA; | 2547 | bit = BLOCK_GROUP_METADATA; |
2747 | cache->data = 0; | ||
2748 | } | 2548 | } |
2749 | 2549 | ||
2750 | /* use EXTENT_LOCKED to prevent merging */ | 2550 | /* use EXTENT_LOCKED to prevent merging */ |
@@ -2758,7 +2558,8 @@ int btrfs_read_block_groups(struct btrfs_root *root) | |||
2758 | btrfs_super_total_bytes(&info->super_copy)) | 2558 | btrfs_super_total_bytes(&info->super_copy)) |
2759 | break; | 2559 | break; |
2760 | } | 2560 | } |
2761 | 2561 | ret = 0; | |
2562 | error: | ||
2762 | btrfs_free_path(path); | 2563 | btrfs_free_path(path); |
2763 | return 0; | 2564 | return ret; |
2764 | } | 2565 | } |