diff options
author | Zheng Yan <zheng.yan@oracle.com> | 2008-09-23 13:14:14 -0400 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2008-09-25 11:04:07 -0400 |
commit | 31840ae1a6b433ca0e6a8d341756ff478bbf959e (patch) | |
tree | 9343db596aec175e9640aa2800b80f01496d7047 /fs/btrfs/inode.c | |
parent | 1c2308f8e7d8491467e0095af2b01500f1b70819 (diff) |
Btrfs: Full back reference support
This patch makes the back reference system to explicit record the
location of parent node for all types of extents. The location of
parent node is placed into the offset field of backref key. Every
time a tree block is balanced, the back references for the affected
lower level extents are updated.
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 57 |
1 files changed, 39 insertions, 18 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 65b4f864b0df..2e7d82ec5d18 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -528,6 +528,9 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
528 | struct btrfs_trans_handle *trans; | 528 | struct btrfs_trans_handle *trans; |
529 | struct btrfs_ordered_extent *ordered_extent; | 529 | struct btrfs_ordered_extent *ordered_extent; |
530 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; | 530 | struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree; |
531 | struct btrfs_file_extent_item *extent_item; | ||
532 | struct btrfs_path *path = NULL; | ||
533 | struct extent_buffer *leaf; | ||
531 | u64 alloc_hint = 0; | 534 | u64 alloc_hint = 0; |
532 | struct list_head list; | 535 | struct list_head list; |
533 | struct btrfs_key ins; | 536 | struct btrfs_key ins; |
@@ -544,20 +547,15 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
544 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) | 547 | if (test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) |
545 | goto nocow; | 548 | goto nocow; |
546 | 549 | ||
550 | path = btrfs_alloc_path(); | ||
551 | BUG_ON(!path); | ||
552 | |||
547 | lock_extent(io_tree, ordered_extent->file_offset, | 553 | lock_extent(io_tree, ordered_extent->file_offset, |
548 | ordered_extent->file_offset + ordered_extent->len - 1, | 554 | ordered_extent->file_offset + ordered_extent->len - 1, |
549 | GFP_NOFS); | 555 | GFP_NOFS); |
550 | 556 | ||
551 | INIT_LIST_HEAD(&list); | 557 | INIT_LIST_HEAD(&list); |
552 | 558 | ||
553 | ins.objectid = ordered_extent->start; | ||
554 | ins.offset = ordered_extent->len; | ||
555 | ins.type = BTRFS_EXTENT_ITEM_KEY; | ||
556 | |||
557 | ret = btrfs_alloc_reserved_extent(trans, root, root->root_key.objectid, | ||
558 | trans->transid, inode->i_ino, | ||
559 | ordered_extent->file_offset, &ins); | ||
560 | BUG_ON(ret); | ||
561 | mutex_lock(&BTRFS_I(inode)->extent_mutex); | 559 | mutex_lock(&BTRFS_I(inode)->extent_mutex); |
562 | 560 | ||
563 | ret = btrfs_drop_extents(trans, root, inode, | 561 | ret = btrfs_drop_extents(trans, root, inode, |
@@ -566,18 +564,42 @@ static int btrfs_finish_ordered_io(struct inode *inode, u64 start, u64 end) | |||
566 | ordered_extent->len, | 564 | ordered_extent->len, |
567 | ordered_extent->file_offset, &alloc_hint); | 565 | ordered_extent->file_offset, &alloc_hint); |
568 | BUG_ON(ret); | 566 | BUG_ON(ret); |
569 | ret = btrfs_insert_file_extent(trans, root, inode->i_ino, | 567 | |
570 | ordered_extent->file_offset, | 568 | ins.objectid = inode->i_ino; |
571 | ordered_extent->start, | 569 | ins.offset = ordered_extent->file_offset; |
572 | ordered_extent->len, | 570 | ins.type = BTRFS_EXTENT_DATA_KEY; |
573 | ordered_extent->len, 0); | 571 | ret = btrfs_insert_empty_item(trans, root, path, &ins, |
572 | sizeof(*extent_item)); | ||
574 | BUG_ON(ret); | 573 | BUG_ON(ret); |
574 | leaf = path->nodes[0]; | ||
575 | extent_item = btrfs_item_ptr(leaf, path->slots[0], | ||
576 | struct btrfs_file_extent_item); | ||
577 | btrfs_set_file_extent_generation(leaf, extent_item, trans->transid); | ||
578 | btrfs_set_file_extent_type(leaf, extent_item, BTRFS_FILE_EXTENT_REG); | ||
579 | btrfs_set_file_extent_disk_bytenr(leaf, extent_item, | ||
580 | ordered_extent->start); | ||
581 | btrfs_set_file_extent_disk_num_bytes(leaf, extent_item, | ||
582 | ordered_extent->len); | ||
583 | btrfs_set_file_extent_offset(leaf, extent_item, 0); | ||
584 | btrfs_set_file_extent_num_bytes(leaf, extent_item, | ||
585 | ordered_extent->len); | ||
586 | btrfs_mark_buffer_dirty(leaf); | ||
575 | 587 | ||
576 | btrfs_drop_extent_cache(inode, ordered_extent->file_offset, | 588 | btrfs_drop_extent_cache(inode, ordered_extent->file_offset, |
577 | ordered_extent->file_offset + | 589 | ordered_extent->file_offset + |
578 | ordered_extent->len - 1); | 590 | ordered_extent->len - 1); |
579 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); | 591 | mutex_unlock(&BTRFS_I(inode)->extent_mutex); |
580 | 592 | ||
593 | ins.objectid = ordered_extent->start; | ||
594 | ins.offset = ordered_extent->len; | ||
595 | ins.type = BTRFS_EXTENT_ITEM_KEY; | ||
596 | ret = btrfs_alloc_reserved_extent(trans, root, leaf->start, | ||
597 | root->root_key.objectid, | ||
598 | trans->transid, inode->i_ino, | ||
599 | ordered_extent->file_offset, &ins); | ||
600 | BUG_ON(ret); | ||
601 | btrfs_release_path(root, path); | ||
602 | |||
581 | inode->i_blocks += ordered_extent->len >> 9; | 603 | inode->i_blocks += ordered_extent->len >> 9; |
582 | unlock_extent(io_tree, ordered_extent->file_offset, | 604 | unlock_extent(io_tree, ordered_extent->file_offset, |
583 | ordered_extent->file_offset + ordered_extent->len - 1, | 605 | ordered_extent->file_offset + ordered_extent->len - 1, |
@@ -596,6 +618,8 @@ nocow: | |||
596 | btrfs_put_ordered_extent(ordered_extent); | 618 | btrfs_put_ordered_extent(ordered_extent); |
597 | 619 | ||
598 | btrfs_end_transaction(trans, root); | 620 | btrfs_end_transaction(trans, root); |
621 | if (path) | ||
622 | btrfs_free_path(path); | ||
599 | return 0; | 623 | return 0; |
600 | } | 624 | } |
601 | 625 | ||
@@ -1433,10 +1457,7 @@ search_again: | |||
1433 | if (root->ref_cows) | 1457 | if (root->ref_cows) |
1434 | dec_i_blocks(inode, num_dec); | 1458 | dec_i_blocks(inode, num_dec); |
1435 | } | 1459 | } |
1436 | if (root->ref_cows) { | 1460 | root_gen = btrfs_header_generation(leaf); |
1437 | root_gen = | ||
1438 | btrfs_header_generation(leaf); | ||
1439 | } | ||
1440 | root_owner = btrfs_header_owner(leaf); | 1461 | root_owner = btrfs_header_owner(leaf); |
1441 | } | 1462 | } |
1442 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { | 1463 | } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) { |
@@ -1477,7 +1498,7 @@ delete: | |||
1477 | if (found_extent) { | 1498 | if (found_extent) { |
1478 | ret = btrfs_free_extent(trans, root, extent_start, | 1499 | ret = btrfs_free_extent(trans, root, extent_start, |
1479 | extent_num_bytes, | 1500 | extent_num_bytes, |
1480 | root_owner, | 1501 | leaf->start, root_owner, |
1481 | root_gen, inode->i_ino, | 1502 | root_gen, inode->i_ino, |
1482 | found_key.offset, 0); | 1503 | found_key.offset, 0); |
1483 | BUG_ON(ret); | 1504 | BUG_ON(ret); |