forked from Mirrors/btrfs-progs
btrfs-progs: move transaction code out of disk-io
Temporarily export the low-level helpers. Signed-off-by: David Sterba <dsterba@suse.com>master
parent
37c271b216
commit
f2b0cbe8e8
123
disk-io.c
123
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)
|
||||
|
|
|
@ -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);
|
||||
|
|
125
transaction.c
125
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue