diff --git a/disk-io.c b/disk-io.c index f969c9b5..29aec0ba 100644 --- a/disk-io.c +++ b/disk-io.c @@ -481,129 +481,6 @@ void btrfs_setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info, root->root_key.objectid = objectid; } -static int update_cowonly_root(struct btrfs_trans_handle *trans, - struct btrfs_root *root) -{ - int ret; - u64 old_root_bytenr; - struct btrfs_root *tree_root = root->fs_info->tree_root; - - btrfs_write_dirty_block_groups(trans, root); - while(1) { - old_root_bytenr = btrfs_root_bytenr(&root->root_item); - if (old_root_bytenr == root->node->start) - break; - btrfs_set_root_bytenr(&root->root_item, - root->node->start); - btrfs_set_root_generation(&root->root_item, - trans->transid); - root->root_item.level = btrfs_header_level(root->node); - ret = btrfs_update_root(trans, tree_root, - &root->root_key, - &root->root_item); - BUG_ON(ret); - btrfs_write_dirty_block_groups(trans, root); - } - return 0; -} - -static int commit_tree_roots(struct btrfs_trans_handle *trans, - struct btrfs_fs_info *fs_info) -{ - struct btrfs_root *root; - struct list_head *next; - struct extent_buffer *eb; - int ret; - - if (fs_info->readonly) - return 0; - - eb = fs_info->tree_root->node; - extent_buffer_get(eb); - ret = btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb); - free_extent_buffer(eb); - if (ret) - return ret; - - while(!list_empty(&fs_info->dirty_cowonly_roots)) { - next = fs_info->dirty_cowonly_roots.next; - list_del_init(next); - root = list_entry(next, struct btrfs_root, dirty_list); - update_cowonly_root(trans, root); - free_extent_buffer(root->commit_root); - root->commit_root = NULL; - } - - return 0; -} - -static int __commit_transaction(struct btrfs_trans_handle *trans, - struct btrfs_root *root) -{ - u64 start; - u64 end; - struct btrfs_fs_info *fs_info = root->fs_info; - struct extent_buffer *eb; - struct extent_io_tree *tree = &fs_info->extent_cache; - int ret; - - while(1) { - ret = find_first_extent_bit(tree, 0, &start, &end, - EXTENT_DIRTY); - if (ret) - break; - while(start <= end) { - eb = find_first_extent_buffer(tree, start); - BUG_ON(!eb || eb->start != start); - ret = write_tree_block(trans, fs_info, eb); - BUG_ON(ret); - start += eb->len; - clear_extent_buffer_dirty(eb); - free_extent_buffer(eb); - } - } - return 0; -} - -int btrfs_commit_transaction(struct btrfs_trans_handle *trans, - struct btrfs_root *root) -{ - u64 transid = trans->transid; - int ret = 0; - struct btrfs_fs_info *fs_info = root->fs_info; - - if (root->commit_root == root->node) - goto commit_tree; - if (root == root->fs_info->tree_root) - goto commit_tree; - if (root == root->fs_info->chunk_root) - goto commit_tree; - - free_extent_buffer(root->commit_root); - root->commit_root = NULL; - - btrfs_set_root_bytenr(&root->root_item, root->node->start); - btrfs_set_root_generation(&root->root_item, trans->transid); - root->root_item.level = btrfs_header_level(root->node); - ret = btrfs_update_root(trans, root->fs_info->tree_root, - &root->root_key, &root->root_item); - BUG_ON(ret); -commit_tree: - ret = commit_tree_roots(trans, fs_info); - BUG_ON(ret); - ret = __commit_transaction(trans, root); - BUG_ON(ret); - write_ctree_super(trans, fs_info); - btrfs_finish_extent_commit(trans, fs_info->extent_root, - &fs_info->pinned_extents); - kfree(trans); - free_extent_buffer(root->commit_root); - root->commit_root = NULL; - fs_info->running_transaction = NULL; - fs_info->last_trans_committed = transid; - return 0; -} - static int find_and_setup_root(struct btrfs_root *tree_root, struct btrfs_fs_info *fs_info, u64 objectid, struct btrfs_root *root) diff --git a/disk-io.h b/disk-io.h index 6e42eced..f6a422f2 100644 --- a/disk-io.h +++ b/disk-io.h @@ -180,8 +180,6 @@ int btrfs_set_buffer_uptodate(struct extent_buffer *buf); u32 btrfs_csum_data(char *data, u32 seed, size_t len); void btrfs_csum_final(u32 crc, u8 *result); -int btrfs_commit_transaction(struct btrfs_trans_handle *trans, - struct btrfs_root *root); int btrfs_open_device(struct btrfs_device *dev); int csum_tree_block_size(struct extent_buffer *buf, u16 csum_sectorsize, int verify); diff --git a/transaction.c b/transaction.c index b9280015..80aa7bc4 100644 --- a/transaction.c +++ b/transaction.c @@ -15,6 +15,7 @@ */ #include "kerncompat.h" +#include "disk-io.h" #include "transaction.h" #include "messages.h" @@ -47,3 +48,127 @@ struct btrfs_trans_handle* btrfs_start_transaction(struct btrfs_root *root, return h; } + +static int update_cowonly_root(struct btrfs_trans_handle *trans, + struct btrfs_root *root) +{ + int ret; + u64 old_root_bytenr; + struct btrfs_root *tree_root = root->fs_info->tree_root; + + btrfs_write_dirty_block_groups(trans, root); + while(1) { + old_root_bytenr = btrfs_root_bytenr(&root->root_item); + if (old_root_bytenr == root->node->start) + break; + btrfs_set_root_bytenr(&root->root_item, + root->node->start); + btrfs_set_root_generation(&root->root_item, + trans->transid); + root->root_item.level = btrfs_header_level(root->node); + ret = btrfs_update_root(trans, tree_root, + &root->root_key, + &root->root_item); + BUG_ON(ret); + btrfs_write_dirty_block_groups(trans, root); + } + return 0; +} + +int commit_tree_roots(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info) +{ + struct btrfs_root *root; + struct list_head *next; + struct extent_buffer *eb; + int ret; + + if (fs_info->readonly) + return 0; + + eb = fs_info->tree_root->node; + extent_buffer_get(eb); + ret = btrfs_cow_block(trans, fs_info->tree_root, eb, NULL, 0, &eb); + free_extent_buffer(eb); + if (ret) + return ret; + + while(!list_empty(&fs_info->dirty_cowonly_roots)) { + next = fs_info->dirty_cowonly_roots.next; + list_del_init(next); + root = list_entry(next, struct btrfs_root, dirty_list); + update_cowonly_root(trans, root); + free_extent_buffer(root->commit_root); + root->commit_root = NULL; + } + + return 0; +} + +int __commit_transaction(struct btrfs_trans_handle *trans, + struct btrfs_root *root) +{ + u64 start; + u64 end; + struct btrfs_fs_info *fs_info = root->fs_info; + struct extent_buffer *eb; + struct extent_io_tree *tree = &fs_info->extent_cache; + int ret; + + while(1) { + ret = find_first_extent_bit(tree, 0, &start, &end, + EXTENT_DIRTY); + if (ret) + break; + while(start <= end) { + eb = find_first_extent_buffer(tree, start); + BUG_ON(!eb || eb->start != start); + ret = write_tree_block(trans, fs_info, eb); + BUG_ON(ret); + start += eb->len; + clear_extent_buffer_dirty(eb); + free_extent_buffer(eb); + } + } + return 0; +} + +int btrfs_commit_transaction(struct btrfs_trans_handle *trans, + struct btrfs_root *root) +{ + u64 transid = trans->transid; + int ret = 0; + struct btrfs_fs_info *fs_info = root->fs_info; + + if (root->commit_root == root->node) + goto commit_tree; + if (root == root->fs_info->tree_root) + goto commit_tree; + if (root == root->fs_info->chunk_root) + goto commit_tree; + + free_extent_buffer(root->commit_root); + root->commit_root = NULL; + + btrfs_set_root_bytenr(&root->root_item, root->node->start); + btrfs_set_root_generation(&root->root_item, trans->transid); + root->root_item.level = btrfs_header_level(root->node); + ret = btrfs_update_root(trans, root->fs_info->tree_root, + &root->root_key, &root->root_item); + BUG_ON(ret); +commit_tree: + ret = commit_tree_roots(trans, fs_info); + BUG_ON(ret); + ret = __commit_transaction(trans, root); + BUG_ON(ret); + write_ctree_super(trans, fs_info); + btrfs_finish_extent_commit(trans, fs_info->extent_root, + &fs_info->pinned_extents); + kfree(trans); + free_extent_buffer(root->commit_root); + root->commit_root = NULL; + fs_info->running_transaction = NULL; + fs_info->last_trans_committed = transid; + return 0; +} + diff --git a/transaction.h b/transaction.h index 7f6be051..fe6704e6 100644 --- a/transaction.h +++ b/transaction.h @@ -33,5 +33,11 @@ struct btrfs_trans_handle { struct btrfs_trans_handle* btrfs_start_transaction(struct btrfs_root *root, int num_blocks); +int __commit_transaction(struct btrfs_trans_handle *trans, + struct btrfs_root *root); +int commit_tree_roots(struct btrfs_trans_handle *trans, + struct btrfs_fs_info *fs_info); +int btrfs_commit_transaction(struct btrfs_trans_handle *trans, + struct btrfs_root *root); #endif