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;
|
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,
|
static int find_and_setup_root(struct btrfs_root *tree_root,
|
||||||
struct btrfs_fs_info *fs_info,
|
struct btrfs_fs_info *fs_info,
|
||||||
u64 objectid, struct btrfs_root *root)
|
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);
|
u32 btrfs_csum_data(char *data, u32 seed, size_t len);
|
||||||
void btrfs_csum_final(u32 crc, u8 *result);
|
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 btrfs_open_device(struct btrfs_device *dev);
|
||||||
int csum_tree_block_size(struct extent_buffer *buf, u16 csum_sectorsize,
|
int csum_tree_block_size(struct extent_buffer *buf, u16 csum_sectorsize,
|
||||||
int verify);
|
int verify);
|
||||||
|
|
125
transaction.c
125
transaction.c
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "kerncompat.h"
|
#include "kerncompat.h"
|
||||||
|
#include "disk-io.h"
|
||||||
#include "transaction.h"
|
#include "transaction.h"
|
||||||
|
|
||||||
#include "messages.h"
|
#include "messages.h"
|
||||||
|
@ -47,3 +48,127 @@ struct btrfs_trans_handle* btrfs_start_transaction(struct btrfs_root *root,
|
||||||
|
|
||||||
return h;
|
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,
|
struct btrfs_trans_handle* btrfs_start_transaction(struct btrfs_root *root,
|
||||||
int num_blocks);
|
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
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue