diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-12-11 09:25:06 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:03:58 -0400 |
commit | 7bb86316c3961d1bc401ef184fd996f999556c7f (patch) | |
tree | e67de3b594cf680f295010095a71ed7e825cb757 /fs/btrfs/extent-tree.c | |
parent | 74493f7a59bfd4d1c7029c74ab2cd0e400612c6b (diff) |
Btrfs: Add back pointers from extents to the btree or file referencing them
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 373 |
1 files changed, 311 insertions, 62 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 0f1ebdd4e925..32991f73e9db 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -17,6 +17,7 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/sched.h> | 19 | #include <linux/sched.h> |
20 | #include <linux/crc32c.h> | ||
20 | #include "hash.h" | 21 | #include "hash.h" |
21 | #include "ctree.h" | 22 | #include "ctree.h" |
22 | #include "disk-io.h" | 23 | #include "disk-io.h" |
@@ -89,7 +90,8 @@ static int cache_block_group(struct btrfs_root *root, | |||
89 | 90 | ||
90 | btrfs_item_key_to_cpu(leaf, &key, slot); | 91 | btrfs_item_key_to_cpu(leaf, &key, slot); |
91 | if (key.objectid < block_group->key.objectid) { | 92 | if (key.objectid < block_group->key.objectid) { |
92 | if (key.objectid + key.offset > first_free) | 93 | if (btrfs_key_type(&key) != BTRFS_EXTENT_REF_KEY && |
94 | key.objectid + key.offset > first_free) | ||
93 | first_free = key.objectid + key.offset; | 95 | first_free = key.objectid + key.offset; |
94 | goto next; | 96 | goto next; |
95 | } | 97 | } |
@@ -353,7 +355,7 @@ found: | |||
353 | return found_group; | 355 | return found_group; |
354 | } | 356 | } |
355 | 357 | ||
356 | static u64 hash_extent_ref(u64 root_objectid, u64 root_generation, | 358 | static u64 hash_extent_ref(u64 root_objectid, u64 ref_generation, |
357 | u64 owner, u64 owner_offset) | 359 | u64 owner, u64 owner_offset) |
358 | { | 360 | { |
359 | u32 high_crc = ~(u32)0; | 361 | u32 high_crc = ~(u32)0; |
@@ -362,53 +364,149 @@ static u64 hash_extent_ref(u64 root_objectid, u64 root_generation, | |||
362 | 364 | ||
363 | lenum = cpu_to_le64(root_objectid); | 365 | lenum = cpu_to_le64(root_objectid); |
364 | high_crc = crc32c(high_crc, &lenum, sizeof(lenum)); | 366 | high_crc = crc32c(high_crc, &lenum, sizeof(lenum)); |
365 | lenum = cpu_to_le64(root_generation); | 367 | lenum = cpu_to_le64(ref_generation); |
366 | high_crc = crc32c(high_crc, &lenum, sizeof(lenum)); | 368 | low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); |
367 | 369 | ||
370 | #if 0 | ||
368 | lenum = cpu_to_le64(owner); | 371 | lenum = cpu_to_le64(owner); |
369 | low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); | 372 | low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); |
370 | |||
371 | lenum = cpu_to_le64(owner_offset); | 373 | lenum = cpu_to_le64(owner_offset); |
372 | low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); | 374 | low_crc = crc32c(low_crc, &lenum, sizeof(lenum)); |
373 | 375 | #endif | |
374 | return ((u64)high_crc << 32) | (u64)low_crc; | 376 | return ((u64)high_crc << 32) | (u64)low_crc; |
375 | } | 377 | } |
376 | 378 | ||
377 | int insert_extent_ref(struct btrfs_trans_handle *trans, | 379 | static int match_extent_ref(struct extent_buffer *leaf, |
378 | struct btrfs_root *root, | 380 | struct btrfs_extent_ref *disk_ref, |
379 | struct btrfs_path *path, | 381 | struct btrfs_extent_ref *cpu_ref) |
380 | u64 bytenr, | 382 | { |
381 | u64 root_objectid, u64 root_generation, | 383 | int ret; |
382 | u64 owner, u64 owner_offset) | 384 | int len; |
385 | |||
386 | if (cpu_ref->objectid) | ||
387 | len = sizeof(*cpu_ref); | ||
388 | else | ||
389 | len = 2 * sizeof(u64); | ||
390 | ret = memcmp_extent_buffer(leaf, cpu_ref, (unsigned long)disk_ref, | ||
391 | len); | ||
392 | return ret == 0; | ||
393 | } | ||
394 | |||
395 | static int lookup_extent_backref(struct btrfs_trans_handle *trans, | ||
396 | struct btrfs_root *root, | ||
397 | struct btrfs_path *path, u64 bytenr, | ||
398 | u64 root_objectid, u64 ref_generation, | ||
399 | u64 owner, u64 owner_offset, int del) | ||
383 | { | 400 | { |
384 | u64 hash; | 401 | u64 hash; |
385 | struct btrfs_key key; | 402 | struct btrfs_key key; |
403 | struct btrfs_key found_key; | ||
386 | struct btrfs_extent_ref ref; | 404 | struct btrfs_extent_ref ref; |
387 | struct extent_buffer *l; | 405 | struct extent_buffer *leaf; |
388 | struct btrfs_extent_item *item; | 406 | struct btrfs_extent_ref *disk_ref; |
407 | int ret; | ||
408 | int ret2; | ||
409 | |||
410 | btrfs_set_stack_ref_root(&ref, root_objectid); | ||
411 | btrfs_set_stack_ref_generation(&ref, ref_generation); | ||
412 | btrfs_set_stack_ref_objectid(&ref, owner); | ||
413 | btrfs_set_stack_ref_offset(&ref, owner_offset); | ||
414 | |||
415 | hash = hash_extent_ref(root_objectid, ref_generation, owner, | ||
416 | owner_offset); | ||
417 | key.offset = hash; | ||
418 | key.objectid = bytenr; | ||
419 | key.type = BTRFS_EXTENT_REF_KEY; | ||
420 | |||
421 | while (1) { | ||
422 | ret = btrfs_search_slot(trans, root, &key, path, | ||
423 | del ? -1 : 0, del); | ||
424 | if (ret < 0) | ||
425 | goto out; | ||
426 | leaf = path->nodes[0]; | ||
427 | if (ret != 0) { | ||
428 | u32 nritems = btrfs_header_nritems(leaf); | ||
429 | if (path->slots[0] >= nritems) { | ||
430 | ret2 = btrfs_next_leaf(root, path); | ||
431 | if (ret2) | ||
432 | goto out; | ||
433 | leaf = path->nodes[0]; | ||
434 | } | ||
435 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | ||
436 | if (found_key.objectid != bytenr || | ||
437 | found_key.type != BTRFS_EXTENT_REF_KEY) | ||
438 | goto out; | ||
439 | key.offset = found_key.offset; | ||
440 | if (del) { | ||
441 | btrfs_release_path(root, path); | ||
442 | continue; | ||
443 | } | ||
444 | } | ||
445 | disk_ref = btrfs_item_ptr(path->nodes[0], | ||
446 | path->slots[0], | ||
447 | struct btrfs_extent_ref); | ||
448 | if (match_extent_ref(path->nodes[0], disk_ref, &ref)) { | ||
449 | ret = 0; | ||
450 | goto out; | ||
451 | } | ||
452 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | ||
453 | key.offset = found_key.offset + 1; | ||
454 | btrfs_release_path(root, path); | ||
455 | } | ||
456 | out: | ||
457 | return ret; | ||
458 | } | ||
459 | |||
460 | int btrfs_insert_extent_backref(struct btrfs_trans_handle *trans, | ||
461 | struct btrfs_root *root, | ||
462 | struct btrfs_path *path, u64 bytenr, | ||
463 | u64 root_objectid, u64 ref_generation, | ||
464 | u64 owner, u64 owner_offset) | ||
465 | { | ||
466 | u64 hash; | ||
467 | struct btrfs_key key; | ||
468 | struct btrfs_extent_ref ref; | ||
469 | struct btrfs_extent_ref *disk_ref; | ||
389 | int ret; | 470 | int ret; |
390 | 471 | ||
391 | btrfs_set_stack_ref_root(&ref, root_objectid); | 472 | btrfs_set_stack_ref_root(&ref, root_objectid); |
392 | btrfs_set_stack_ref_generation(&ref, root_generation); | 473 | btrfs_set_stack_ref_generation(&ref, ref_generation); |
393 | btrfs_set_stack_ref_objectid(&ref, owner); | 474 | btrfs_set_stack_ref_objectid(&ref, owner); |
394 | btrfs_set_stack_ref_offset(&ref, owner_offset); | 475 | btrfs_set_stack_ref_offset(&ref, owner_offset); |
395 | 476 | ||
396 | ret = btrfs_name_hash(&ref, sizeof(ref), &hash); | 477 | hash = hash_extent_ref(root_objectid, ref_generation, owner, |
478 | owner_offset); | ||
397 | key.offset = hash; | 479 | key.offset = hash; |
398 | key.objectid = bytenr; | 480 | key.objectid = bytenr; |
399 | key.type = BTRFS_EXTENT_REF_KEY; | 481 | key.type = BTRFS_EXTENT_REF_KEY; |
400 | 482 | ||
401 | ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(ref)); | 483 | ret = btrfs_insert_empty_item(trans, root, path, &key, sizeof(ref)); |
402 | while (ret == -EEXIST) { | 484 | while (ret == -EEXIST) { |
403 | 485 | disk_ref = btrfs_item_ptr(path->nodes[0], path->slots[0], | |
486 | struct btrfs_extent_ref); | ||
487 | if (match_extent_ref(path->nodes[0], disk_ref, &ref)) | ||
488 | goto out; | ||
489 | key.offset++; | ||
490 | btrfs_release_path(root, path); | ||
491 | ret = btrfs_insert_empty_item(trans, root, path, &key, | ||
492 | sizeof(ref)); | ||
404 | } | 493 | } |
405 | 494 | if (ret) | |
495 | goto out; | ||
496 | disk_ref = btrfs_item_ptr(path->nodes[0], path->slots[0], | ||
497 | struct btrfs_extent_ref); | ||
498 | write_extent_buffer(path->nodes[0], &ref, (unsigned long)disk_ref, | ||
499 | sizeof(ref)); | ||
500 | btrfs_mark_buffer_dirty(path->nodes[0]); | ||
501 | out: | ||
502 | btrfs_release_path(root, path); | ||
503 | return ret; | ||
406 | } | 504 | } |
407 | 505 | ||
408 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | 506 | int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, |
409 | struct btrfs_root *root, | 507 | struct btrfs_root *root, |
410 | u64 bytenr, u64 num_bytes, | 508 | u64 bytenr, u64 num_bytes, |
411 | u64 root_objectid, u64 root_generation, | 509 | u64 root_objectid, u64 ref_generation, |
412 | u64 owner, u64 owner_offset) | 510 | u64 owner, u64 owner_offset) |
413 | { | 511 | { |
414 | struct btrfs_path *path; | 512 | struct btrfs_path *path; |
@@ -441,6 +539,11 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | |||
441 | btrfs_mark_buffer_dirty(path->nodes[0]); | 539 | btrfs_mark_buffer_dirty(path->nodes[0]); |
442 | 540 | ||
443 | btrfs_release_path(root->fs_info->extent_root, path); | 541 | btrfs_release_path(root->fs_info->extent_root, path); |
542 | |||
543 | ret = btrfs_insert_extent_backref(trans, root->fs_info->extent_root, | ||
544 | path, bytenr, root_objectid, | ||
545 | ref_generation, owner, owner_offset); | ||
546 | BUG_ON(ret); | ||
444 | finish_current_insert(trans, root->fs_info->extent_root); | 547 | finish_current_insert(trans, root->fs_info->extent_root); |
445 | del_pending_extents(trans, root->fs_info->extent_root); | 548 | del_pending_extents(trans, root->fs_info->extent_root); |
446 | 549 | ||
@@ -489,10 +592,29 @@ out: | |||
489 | } | 592 | } |
490 | 593 | ||
491 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, | 594 | int btrfs_inc_root_ref(struct btrfs_trans_handle *trans, |
492 | struct btrfs_root *root) | 595 | struct btrfs_root *root, u64 owner_objectid) |
493 | { | 596 | { |
597 | u64 generation; | ||
598 | u64 key_objectid; | ||
599 | u64 level; | ||
600 | u32 nritems; | ||
601 | struct btrfs_disk_key disk_key; | ||
602 | |||
603 | level = btrfs_header_level(root->node); | ||
604 | generation = trans->transid; | ||
605 | nritems = btrfs_header_nritems(root->node); | ||
606 | if (nritems > 0) { | ||
607 | if (level == 0) | ||
608 | btrfs_item_key(root->node, &disk_key, 0); | ||
609 | else | ||
610 | btrfs_node_key(root->node, &disk_key, 0); | ||
611 | key_objectid = btrfs_disk_key_objectid(&disk_key); | ||
612 | } else { | ||
613 | key_objectid = 0; | ||
614 | } | ||
494 | return btrfs_inc_extent_ref(trans, root, root->node->start, | 615 | return btrfs_inc_extent_ref(trans, root, root->node->start, |
495 | root->node->len); | 616 | root->node->len, owner_objectid, |
617 | generation, 0, 0); | ||
496 | } | 618 | } |
497 | 619 | ||
498 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 620 | int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
@@ -506,7 +628,6 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
506 | int level; | 628 | int level; |
507 | int ret; | 629 | int ret; |
508 | int faili; | 630 | int faili; |
509 | int err; | ||
510 | 631 | ||
511 | if (!root->ref_cows) | 632 | if (!root->ref_cows) |
512 | return 0; | 633 | return 0; |
@@ -528,7 +649,9 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
528 | if (disk_bytenr == 0) | 649 | if (disk_bytenr == 0) |
529 | continue; | 650 | continue; |
530 | ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, | 651 | ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, |
531 | btrfs_file_extent_disk_num_bytes(buf, fi)); | 652 | btrfs_file_extent_disk_num_bytes(buf, fi), |
653 | root->root_key.objectid, trans->transid, | ||
654 | key.objectid, key.offset); | ||
532 | if (ret) { | 655 | if (ret) { |
533 | faili = i; | 656 | faili = i; |
534 | goto fail; | 657 | goto fail; |
@@ -536,7 +659,9 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
536 | } else { | 659 | } else { |
537 | bytenr = btrfs_node_blockptr(buf, i); | 660 | bytenr = btrfs_node_blockptr(buf, i); |
538 | ret = btrfs_inc_extent_ref(trans, root, bytenr, | 661 | ret = btrfs_inc_extent_ref(trans, root, bytenr, |
539 | btrfs_level_size(root, level - 1)); | 662 | btrfs_level_size(root, level - 1), |
663 | root->root_key.objectid, | ||
664 | trans->transid, 0, 0); | ||
540 | if (ret) { | 665 | if (ret) { |
541 | faili = i; | 666 | faili = i; |
542 | goto fail; | 667 | goto fail; |
@@ -546,6 +671,7 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
546 | return 0; | 671 | return 0; |
547 | fail: | 672 | fail: |
548 | WARN_ON(1); | 673 | WARN_ON(1); |
674 | #if 0 | ||
549 | for (i =0; i < faili; i++) { | 675 | for (i =0; i < faili; i++) { |
550 | if (level == 0) { | 676 | if (level == 0) { |
551 | u64 disk_bytenr; | 677 | u64 disk_bytenr; |
@@ -571,6 +697,7 @@ fail: | |||
571 | BUG_ON(err); | 697 | BUG_ON(err); |
572 | } | 698 | } |
573 | } | 699 | } |
700 | #endif | ||
574 | return ret; | 701 | return ret; |
575 | } | 702 | } |
576 | 703 | ||
@@ -809,18 +936,18 @@ int btrfs_finish_extent_commit(struct btrfs_trans_handle *trans, | |||
809 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct | 936 | static int finish_current_insert(struct btrfs_trans_handle *trans, struct |
810 | btrfs_root *extent_root) | 937 | btrfs_root *extent_root) |
811 | { | 938 | { |
939 | u64 start; | ||
940 | u64 end; | ||
941 | struct btrfs_fs_info *info = extent_root->fs_info; | ||
942 | struct btrfs_path *path; | ||
812 | struct btrfs_key ins; | 943 | struct btrfs_key ins; |
813 | struct btrfs_extent_item extent_item; | 944 | struct btrfs_extent_item extent_item; |
814 | int ret; | 945 | int ret; |
815 | int err = 0; | 946 | int err = 0; |
816 | u64 start; | ||
817 | u64 end; | ||
818 | struct btrfs_fs_info *info = extent_root->fs_info; | ||
819 | 947 | ||
820 | btrfs_set_stack_extent_refs(&extent_item, 1); | 948 | btrfs_set_stack_extent_refs(&extent_item, 1); |
821 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); | 949 | btrfs_set_key_type(&ins, BTRFS_EXTENT_ITEM_KEY); |
822 | btrfs_set_stack_extent_owner(&extent_item, | 950 | path = btrfs_alloc_path(); |
823 | extent_root->root_key.objectid); | ||
824 | 951 | ||
825 | while(1) { | 952 | while(1) { |
826 | ret = find_first_extent_bit(&info->extent_ins, 0, &start, | 953 | ret = find_first_extent_bit(&info->extent_ins, 0, &start, |
@@ -834,7 +961,12 @@ static int finish_current_insert(struct btrfs_trans_handle *trans, struct | |||
834 | &extent_item, sizeof(extent_item)); | 961 | &extent_item, sizeof(extent_item)); |
835 | clear_extent_bits(&info->extent_ins, start, end, EXTENT_LOCKED, | 962 | clear_extent_bits(&info->extent_ins, start, end, EXTENT_LOCKED, |
836 | GFP_NOFS); | 963 | GFP_NOFS); |
964 | err = btrfs_insert_extent_backref(trans, extent_root, path, | ||
965 | start, extent_root->root_key.objectid, | ||
966 | 0, 0, 0); | ||
967 | BUG_ON(err); | ||
837 | } | 968 | } |
969 | btrfs_free_path(path); | ||
838 | return 0; | 970 | return 0; |
839 | } | 971 | } |
840 | 972 | ||
@@ -871,7 +1003,9 @@ static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes, | |||
871 | * remove an extent from the root, returns 0 on success | 1003 | * remove an extent from the root, returns 0 on success |
872 | */ | 1004 | */ |
873 | static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 1005 | static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
874 | *root, u64 bytenr, u64 num_bytes, int pin, | 1006 | *root, u64 bytenr, u64 num_bytes, |
1007 | u64 root_objectid, u64 ref_generation, | ||
1008 | u64 owner_objectid, u64 owner_offset, int pin, | ||
875 | int mark_free) | 1009 | int mark_free) |
876 | { | 1010 | { |
877 | struct btrfs_path *path; | 1011 | struct btrfs_path *path; |
@@ -891,6 +1025,24 @@ static int __free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | |||
891 | if (!path) | 1025 | if (!path) |
892 | return -ENOMEM; | 1026 | return -ENOMEM; |
893 | 1027 | ||
1028 | if (ref_generation && owner_objectid == 0 && root_objectid == 3) { | ||
1029 | //printk("drop backref root %Lu gen %Lu byte %Lu\n", root_objectid, ref_generation, bytenr ); | ||
1030 | } | ||
1031 | ret = lookup_extent_backref(trans, extent_root, path, | ||
1032 | bytenr, root_objectid, | ||
1033 | ref_generation, | ||
1034 | owner_objectid, owner_offset, 1); | ||
1035 | if (ret == 0) { | ||
1036 | ret = btrfs_del_item(trans, extent_root, path); | ||
1037 | } else { | ||
1038 | btrfs_print_leaf(extent_root, path->nodes[0]); | ||
1039 | WARN_ON(1); | ||
1040 | printk("Unable to find ref byte nr %Lu root %Lu " | ||
1041 | " gen %Lu owner %Lu offset %Lu\n", bytenr, | ||
1042 | root_objectid, ref_generation, owner_objectid, | ||
1043 | owner_offset); | ||
1044 | } | ||
1045 | btrfs_release_path(extent_root, path); | ||
894 | ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1); | 1046 | ret = btrfs_search_slot(trans, extent_root, &key, path, -1, 1); |
895 | if (ret < 0) | 1047 | if (ret < 0) |
896 | return ret; | 1048 | return ret; |
@@ -965,7 +1117,9 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
965 | clear_extent_bits(pending_del, start, end, EXTENT_LOCKED, | 1117 | clear_extent_bits(pending_del, start, end, EXTENT_LOCKED, |
966 | GFP_NOFS); | 1118 | GFP_NOFS); |
967 | ret = __free_extent(trans, extent_root, | 1119 | ret = __free_extent(trans, extent_root, |
968 | start, end + 1 - start, 0, 0); | 1120 | start, end + 1 - start, |
1121 | extent_root->root_key.objectid, | ||
1122 | 0, 0, 0, 0, 0); | ||
969 | if (ret) | 1123 | if (ret) |
970 | err = ret; | 1124 | err = ret; |
971 | } | 1125 | } |
@@ -976,18 +1130,25 @@ static int del_pending_extents(struct btrfs_trans_handle *trans, struct | |||
976 | * remove an extent from the root, returns 0 on success | 1130 | * remove an extent from the root, returns 0 on success |
977 | */ | 1131 | */ |
978 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root | 1132 | int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root |
979 | *root, u64 bytenr, u64 num_bytes, int pin) | 1133 | *root, u64 bytenr, u64 num_bytes, |
1134 | u64 root_objectid, u64 ref_generation, | ||
1135 | u64 owner_objectid, u64 owner_offset, int pin) | ||
980 | { | 1136 | { |
981 | struct btrfs_root *extent_root = root->fs_info->extent_root; | 1137 | struct btrfs_root *extent_root = root->fs_info->extent_root; |
982 | int pending_ret; | 1138 | int pending_ret; |
983 | int ret; | 1139 | int ret; |
984 | 1140 | ||
985 | WARN_ON(num_bytes < root->sectorsize); | 1141 | WARN_ON(num_bytes < root->sectorsize); |
1142 | if (!root->ref_cows) | ||
1143 | ref_generation = 0; | ||
1144 | |||
986 | if (root == extent_root) { | 1145 | if (root == extent_root) { |
987 | pin_down_bytes(root, bytenr, num_bytes, 1); | 1146 | pin_down_bytes(root, bytenr, num_bytes, 1); |
988 | return 0; | 1147 | return 0; |
989 | } | 1148 | } |
990 | ret = __free_extent(trans, root, bytenr, num_bytes, pin, pin == 0); | 1149 | ret = __free_extent(trans, root, bytenr, num_bytes, root_objectid, |
1150 | ref_generation, owner_objectid, owner_offset, | ||
1151 | pin, pin == 0); | ||
991 | pending_ret = del_pending_extents(trans, root->fs_info->extent_root); | 1152 | pending_ret = del_pending_extents(trans, root->fs_info->extent_root); |
992 | return ret ? ret : pending_ret; | 1153 | return ret ? ret : pending_ret; |
993 | } | 1154 | } |
@@ -1080,23 +1241,26 @@ check_failed: | |||
1080 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); | 1241 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); |
1081 | 1242 | ||
1082 | /* | 1243 | /* |
1083 | * a rare case, go back one key if we hit a block group item | 1244 | * walk backwards to find the first extent item key |
1084 | * instead of an extent item | ||
1085 | */ | 1245 | */ |
1086 | if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY && | 1246 | while(btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY) { |
1087 | key.objectid + key.offset >= search_start) { | 1247 | if (path->slots[0] == 0) { |
1088 | ins->objectid = key.objectid; | 1248 | ret = btrfs_prev_leaf(root, path); |
1089 | ins->offset = key.offset - 1; | 1249 | if (ret != 0) { |
1090 | btrfs_release_path(root, path); | 1250 | ret = btrfs_search_slot(trans, root, ins, |
1091 | ret = btrfs_search_slot(trans, root, ins, path, 0, 0); | 1251 | path, 0, 0); |
1092 | if (ret < 0) | 1252 | if (ret < 0) |
1093 | goto error; | 1253 | goto error; |
1094 | 1254 | if (path->slots[0] > 0) | |
1095 | if (path->slots[0] > 0) { | 1255 | path->slots[0]--; |
1256 | break; | ||
1257 | } | ||
1258 | } else { | ||
1096 | path->slots[0]--; | 1259 | path->slots[0]--; |
1097 | } | 1260 | } |
1261 | l = path->nodes[0]; | ||
1262 | btrfs_item_key_to_cpu(l, &key, path->slots[0]); | ||
1098 | } | 1263 | } |
1099 | |||
1100 | while (1) { | 1264 | while (1) { |
1101 | l = path->nodes[0]; | 1265 | l = path->nodes[0]; |
1102 | slot = path->slots[0]; | 1266 | slot = path->slots[0]; |
@@ -1146,7 +1310,8 @@ check_failed: | |||
1146 | } | 1310 | } |
1147 | } | 1311 | } |
1148 | if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY) { | 1312 | if (btrfs_key_type(&key) != BTRFS_EXTENT_ITEM_KEY) { |
1149 | if (!start_found) { | 1313 | if (!start_found && btrfs_key_type(&key) == |
1314 | BTRFS_BLOCK_GROUP_ITEM_KEY) { | ||
1150 | last_byte = key.objectid; | 1315 | last_byte = key.objectid; |
1151 | start_found = 1; | 1316 | start_found = 1; |
1152 | } | 1317 | } |
@@ -1244,8 +1409,10 @@ error: | |||
1244 | * returns 0 if everything worked, non-zero otherwise. | 1409 | * returns 0 if everything worked, non-zero otherwise. |
1245 | */ | 1410 | */ |
1246 | int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | 1411 | int btrfs_alloc_extent(struct btrfs_trans_handle *trans, |
1247 | struct btrfs_root *root, u64 owner, | 1412 | struct btrfs_root *root, |
1248 | u64 num_bytes, u64 empty_size, u64 hint_byte, | 1413 | u64 num_bytes, u64 root_objectid, u64 ref_generation, |
1414 | u64 owner, u64 owner_offset, | ||
1415 | u64 empty_size, u64 hint_byte, | ||
1249 | u64 search_end, struct btrfs_key *ins, int data) | 1416 | u64 search_end, struct btrfs_key *ins, int data) |
1250 | { | 1417 | { |
1251 | int ret; | 1418 | int ret; |
@@ -1255,9 +1422,9 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1255 | struct btrfs_fs_info *info = root->fs_info; | 1422 | struct btrfs_fs_info *info = root->fs_info; |
1256 | struct btrfs_root *extent_root = info->extent_root; | 1423 | struct btrfs_root *extent_root = info->extent_root; |
1257 | struct btrfs_extent_item extent_item; | 1424 | struct btrfs_extent_item extent_item; |
1425 | struct btrfs_path *path; | ||
1258 | 1426 | ||
1259 | btrfs_set_stack_extent_refs(&extent_item, 1); | 1427 | btrfs_set_stack_extent_refs(&extent_item, 1); |
1260 | btrfs_set_stack_extent_owner(&extent_item, owner); | ||
1261 | 1428 | ||
1262 | WARN_ON(num_bytes < root->sectorsize); | 1429 | WARN_ON(num_bytes < root->sectorsize); |
1263 | ret = find_free_extent(trans, root, num_bytes, empty_size, | 1430 | ret = find_free_extent(trans, root, num_bytes, empty_size, |
@@ -1296,8 +1463,16 @@ int btrfs_alloc_extent(struct btrfs_trans_handle *trans, | |||
1296 | 1463 | ||
1297 | trans->alloc_exclude_start = 0; | 1464 | trans->alloc_exclude_start = 0; |
1298 | trans->alloc_exclude_nr = 0; | 1465 | trans->alloc_exclude_nr = 0; |
1466 | BUG_ON(ret); | ||
1467 | |||
1468 | path = btrfs_alloc_path(); | ||
1469 | BUG_ON(!path); | ||
1470 | ret = btrfs_insert_extent_backref(trans, extent_root, path, | ||
1471 | ins->objectid, root_objectid, | ||
1472 | ref_generation, owner, owner_offset); | ||
1299 | 1473 | ||
1300 | BUG_ON(ret); | 1474 | BUG_ON(ret); |
1475 | btrfs_free_path(path); | ||
1301 | finish_current_insert(trans, extent_root); | 1476 | finish_current_insert(trans, extent_root); |
1302 | pending_ret = del_pending_extents(trans, extent_root); | 1477 | pending_ret = del_pending_extents(trans, extent_root); |
1303 | 1478 | ||
@@ -1321,15 +1496,43 @@ update_block: | |||
1321 | */ | 1496 | */ |
1322 | struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | 1497 | struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, |
1323 | struct btrfs_root *root, | 1498 | struct btrfs_root *root, |
1324 | u32 blocksize, u64 hint, | 1499 | u32 blocksize, |
1500 | u64 root_objectid, u64 hint, | ||
1501 | u64 empty_size) | ||
1502 | { | ||
1503 | u64 ref_generation; | ||
1504 | |||
1505 | if (root->ref_cows) | ||
1506 | ref_generation = trans->transid; | ||
1507 | else | ||
1508 | ref_generation = 0; | ||
1509 | |||
1510 | |||
1511 | return __btrfs_alloc_free_block(trans, root, blocksize, root_objectid, | ||
1512 | ref_generation, 0, 0, hint, empty_size); | ||
1513 | } | ||
1514 | |||
1515 | /* | ||
1516 | * helper function to allocate a block for a given tree | ||
1517 | * returns the tree buffer or NULL. | ||
1518 | */ | ||
1519 | struct extent_buffer *__btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | ||
1520 | struct btrfs_root *root, | ||
1521 | u32 blocksize, | ||
1522 | u64 root_objectid, | ||
1523 | u64 ref_generation, | ||
1524 | u64 first_objectid, | ||
1525 | int level, | ||
1526 | u64 hint, | ||
1325 | u64 empty_size) | 1527 | u64 empty_size) |
1326 | { | 1528 | { |
1327 | struct btrfs_key ins; | 1529 | struct btrfs_key ins; |
1328 | int ret; | 1530 | int ret; |
1329 | struct extent_buffer *buf; | 1531 | struct extent_buffer *buf; |
1330 | 1532 | ||
1331 | ret = btrfs_alloc_extent(trans, root, root->root_key.objectid, | 1533 | ret = btrfs_alloc_extent(trans, root, blocksize, |
1332 | blocksize, empty_size, hint, | 1534 | root_objectid, ref_generation, |
1535 | first_objectid, level, empty_size, hint, | ||
1333 | (u64)-1, &ins, 0); | 1536 | (u64)-1, &ins, 0); |
1334 | if (ret) { | 1537 | if (ret) { |
1335 | BUG_ON(ret > 0); | 1538 | BUG_ON(ret > 0); |
@@ -1337,7 +1540,9 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
1337 | } | 1540 | } |
1338 | buf = btrfs_find_create_tree_block(root, ins.objectid, blocksize); | 1541 | buf = btrfs_find_create_tree_block(root, ins.objectid, blocksize); |
1339 | if (!buf) { | 1542 | if (!buf) { |
1340 | btrfs_free_extent(trans, root, ins.objectid, blocksize, 0); | 1543 | btrfs_free_extent(trans, root, ins.objectid, blocksize, |
1544 | root->root_key.objectid, ref_generation, | ||
1545 | 0, 0, 0); | ||
1341 | return ERR_PTR(-ENOMEM); | 1546 | return ERR_PTR(-ENOMEM); |
1342 | } | 1547 | } |
1343 | btrfs_set_buffer_uptodate(buf); | 1548 | btrfs_set_buffer_uptodate(buf); |
@@ -1355,6 +1560,8 @@ struct extent_buffer *btrfs_alloc_free_block(struct btrfs_trans_handle *trans, | |||
1355 | static int drop_leaf_ref(struct btrfs_trans_handle *trans, | 1560 | static int drop_leaf_ref(struct btrfs_trans_handle *trans, |
1356 | struct btrfs_root *root, struct extent_buffer *leaf) | 1561 | struct btrfs_root *root, struct extent_buffer *leaf) |
1357 | { | 1562 | { |
1563 | u64 leaf_owner; | ||
1564 | u64 leaf_generation; | ||
1358 | struct btrfs_key key; | 1565 | struct btrfs_key key; |
1359 | struct btrfs_file_extent_item *fi; | 1566 | struct btrfs_file_extent_item *fi; |
1360 | int i; | 1567 | int i; |
@@ -1363,6 +1570,9 @@ static int drop_leaf_ref(struct btrfs_trans_handle *trans, | |||
1363 | 1570 | ||
1364 | BUG_ON(!btrfs_is_leaf(leaf)); | 1571 | BUG_ON(!btrfs_is_leaf(leaf)); |
1365 | nritems = btrfs_header_nritems(leaf); | 1572 | nritems = btrfs_header_nritems(leaf); |
1573 | leaf_owner = btrfs_header_owner(leaf); | ||
1574 | leaf_generation = btrfs_header_generation(leaf); | ||
1575 | |||
1366 | for (i = 0; i < nritems; i++) { | 1576 | for (i = 0; i < nritems; i++) { |
1367 | u64 disk_bytenr; | 1577 | u64 disk_bytenr; |
1368 | 1578 | ||
@@ -1381,7 +1591,9 @@ static int drop_leaf_ref(struct btrfs_trans_handle *trans, | |||
1381 | if (disk_bytenr == 0) | 1591 | if (disk_bytenr == 0) |
1382 | continue; | 1592 | continue; |
1383 | ret = btrfs_free_extent(trans, root, disk_bytenr, | 1593 | ret = btrfs_free_extent(trans, root, disk_bytenr, |
1384 | btrfs_file_extent_disk_num_bytes(leaf, fi), 0); | 1594 | btrfs_file_extent_disk_num_bytes(leaf, fi), |
1595 | leaf_owner, leaf_generation, | ||
1596 | key.objectid, key.offset, 0); | ||
1385 | BUG_ON(ret); | 1597 | BUG_ON(ret); |
1386 | } | 1598 | } |
1387 | return 0; | 1599 | return 0; |
@@ -1423,9 +1635,12 @@ static void reada_walk_down(struct btrfs_root *root, | |||
1423 | static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | 1635 | static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root |
1424 | *root, struct btrfs_path *path, int *level) | 1636 | *root, struct btrfs_path *path, int *level) |
1425 | { | 1637 | { |
1638 | u64 root_owner; | ||
1639 | u64 root_gen; | ||
1640 | u64 bytenr; | ||
1426 | struct extent_buffer *next; | 1641 | struct extent_buffer *next; |
1427 | struct extent_buffer *cur; | 1642 | struct extent_buffer *cur; |
1428 | u64 bytenr; | 1643 | struct extent_buffer *parent; |
1429 | u32 blocksize; | 1644 | u32 blocksize; |
1430 | int ret; | 1645 | int ret; |
1431 | u32 refs; | 1646 | u32 refs; |
@@ -1466,9 +1681,13 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1466 | ret = lookup_extent_ref(trans, root, bytenr, blocksize, &refs); | 1681 | ret = lookup_extent_ref(trans, root, bytenr, blocksize, &refs); |
1467 | BUG_ON(ret); | 1682 | BUG_ON(ret); |
1468 | if (refs != 1) { | 1683 | if (refs != 1) { |
1684 | parent = path->nodes[*level]; | ||
1685 | root_owner = btrfs_header_owner(parent); | ||
1686 | root_gen = btrfs_header_generation(parent); | ||
1469 | path->slots[*level]++; | 1687 | path->slots[*level]++; |
1470 | ret = btrfs_free_extent(trans, root, bytenr, | 1688 | ret = btrfs_free_extent(trans, root, bytenr, |
1471 | blocksize, 1); | 1689 | blocksize, root_owner, |
1690 | root_gen, 0, 0, 1); | ||
1472 | BUG_ON(ret); | 1691 | BUG_ON(ret); |
1473 | continue; | 1692 | continue; |
1474 | } | 1693 | } |
@@ -1484,10 +1703,16 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1484 | blocksize, &refs); | 1703 | blocksize, &refs); |
1485 | BUG_ON(ret); | 1704 | BUG_ON(ret); |
1486 | if (refs != 1) { | 1705 | if (refs != 1) { |
1706 | parent = path->nodes[*level]; | ||
1707 | root_owner = btrfs_header_owner(parent); | ||
1708 | root_gen = btrfs_header_generation(parent); | ||
1709 | |||
1487 | path->slots[*level]++; | 1710 | path->slots[*level]++; |
1488 | free_extent_buffer(next); | 1711 | free_extent_buffer(next); |
1489 | ret = btrfs_free_extent(trans, root, | 1712 | ret = btrfs_free_extent(trans, root, bytenr, |
1490 | bytenr, blocksize, 1); | 1713 | blocksize, |
1714 | root_owner, | ||
1715 | root_gen, 0, 0, 1); | ||
1491 | BUG_ON(ret); | 1716 | BUG_ON(ret); |
1492 | continue; | 1717 | continue; |
1493 | } | 1718 | } |
@@ -1502,8 +1727,19 @@ static int walk_down_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1502 | out: | 1727 | out: |
1503 | WARN_ON(*level < 0); | 1728 | WARN_ON(*level < 0); |
1504 | WARN_ON(*level >= BTRFS_MAX_LEVEL); | 1729 | WARN_ON(*level >= BTRFS_MAX_LEVEL); |
1730 | |||
1731 | if (path->nodes[*level] == root->node) { | ||
1732 | root_owner = root->root_key.objectid; | ||
1733 | parent = path->nodes[*level]; | ||
1734 | } else { | ||
1735 | parent = path->nodes[*level + 1]; | ||
1736 | root_owner = btrfs_header_owner(parent); | ||
1737 | } | ||
1738 | |||
1739 | root_gen = btrfs_header_generation(parent); | ||
1505 | ret = btrfs_free_extent(trans, root, path->nodes[*level]->start, | 1740 | ret = btrfs_free_extent(trans, root, path->nodes[*level]->start, |
1506 | path->nodes[*level]->len, 1); | 1741 | path->nodes[*level]->len, |
1742 | root_owner, root_gen, 0, 0, 1); | ||
1507 | free_extent_buffer(path->nodes[*level]); | 1743 | free_extent_buffer(path->nodes[*level]); |
1508 | path->nodes[*level] = NULL; | 1744 | path->nodes[*level] = NULL; |
1509 | *level += 1; | 1745 | *level += 1; |
@@ -1519,10 +1755,12 @@ out: | |||
1519 | static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root | 1755 | static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root |
1520 | *root, struct btrfs_path *path, int *level) | 1756 | *root, struct btrfs_path *path, int *level) |
1521 | { | 1757 | { |
1758 | u64 root_owner; | ||
1759 | u64 root_gen; | ||
1760 | struct btrfs_root_item *root_item = &root->root_item; | ||
1522 | int i; | 1761 | int i; |
1523 | int slot; | 1762 | int slot; |
1524 | int ret; | 1763 | int ret; |
1525 | struct btrfs_root_item *root_item = &root->root_item; | ||
1526 | 1764 | ||
1527 | for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { | 1765 | for(i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { |
1528 | slot = path->slots[i]; | 1766 | slot = path->slots[i]; |
@@ -1539,9 +1777,20 @@ static int walk_up_tree(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1539 | root_item->drop_level = i; | 1777 | root_item->drop_level = i; |
1540 | return 0; | 1778 | return 0; |
1541 | } else { | 1779 | } else { |
1780 | if (path->nodes[*level] == root->node) { | ||
1781 | root_owner = root->root_key.objectid; | ||
1782 | root_gen = | ||
1783 | btrfs_header_generation(path->nodes[*level]); | ||
1784 | } else { | ||
1785 | struct extent_buffer *node; | ||
1786 | node = path->nodes[*level + 1]; | ||
1787 | root_owner = btrfs_header_owner(node); | ||
1788 | root_gen = btrfs_header_generation(node); | ||
1789 | } | ||
1542 | ret = btrfs_free_extent(trans, root, | 1790 | ret = btrfs_free_extent(trans, root, |
1543 | path->nodes[*level]->start, | 1791 | path->nodes[*level]->start, |
1544 | path->nodes[*level]->len, 1); | 1792 | path->nodes[*level]->len, |
1793 | root_owner, root_gen, 0, 0, 1); | ||
1545 | BUG_ON(ret); | 1794 | BUG_ON(ret); |
1546 | free_extent_buffer(path->nodes[*level]); | 1795 | free_extent_buffer(path->nodes[*level]); |
1547 | path->nodes[*level] = NULL; | 1796 | path->nodes[*level] = NULL; |