aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorYan Zheng <zheng.yan@oracle.com>2009-01-21 12:54:03 -0500
committerChris Mason <chris.mason@oracle.com>2009-01-21 12:54:03 -0500
commit7237f1833601dcc435a64176c2c347ec4bd959f9 (patch)
tree5e12b9a7655f03181605e02fd91b42e68ee92c2e /fs/btrfs/disk-io.c
parent7e6628544abad773222d8b177f738ac2db1859de (diff)
Btrfs: fix tree logs parallel sync
To improve performance, btrfs_sync_log merges tree log sync requests. But it wrongly merges sync requests for different tree logs. If multiple tree logs are synced at the same time, only one of them actually gets synced. This patch has following changes to fix the bug: Move most tree log related fields in btrfs_fs_info to btrfs_root. This allows merging sync requests separately for each tree log. Don't insert root item into the log root tree immediately after log tree is allocated. Root item for log tree is inserted when log tree get synced for the first time. This allows syncing the log root tree without first syncing all log trees. At tree-log sync, btrfs_sync_log first sync the log tree; then updates corresponding root item in the log root tree; sync the log root tree; then update the super block. Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c79
1 files changed, 68 insertions, 11 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 3cf17257f89d..7feac5a475e9 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -849,6 +849,14 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
849 spin_lock_init(&root->list_lock); 849 spin_lock_init(&root->list_lock);
850 mutex_init(&root->objectid_mutex); 850 mutex_init(&root->objectid_mutex);
851 mutex_init(&root->log_mutex); 851 mutex_init(&root->log_mutex);
852 init_waitqueue_head(&root->log_writer_wait);
853 init_waitqueue_head(&root->log_commit_wait[0]);
854 init_waitqueue_head(&root->log_commit_wait[1]);
855 atomic_set(&root->log_commit[0], 0);
856 atomic_set(&root->log_commit[1], 0);
857 atomic_set(&root->log_writers, 0);
858 root->log_batch = 0;
859 root->log_transid = 0;
852 extent_io_tree_init(&root->dirty_log_pages, 860 extent_io_tree_init(&root->dirty_log_pages,
853 fs_info->btree_inode->i_mapping, GFP_NOFS); 861 fs_info->btree_inode->i_mapping, GFP_NOFS);
854 862
@@ -933,15 +941,16 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
933 return 0; 941 return 0;
934} 942}
935 943
936int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans, 944static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans,
937 struct btrfs_fs_info *fs_info) 945 struct btrfs_fs_info *fs_info)
938{ 946{
939 struct btrfs_root *root; 947 struct btrfs_root *root;
940 struct btrfs_root *tree_root = fs_info->tree_root; 948 struct btrfs_root *tree_root = fs_info->tree_root;
949 struct extent_buffer *leaf;
941 950
942 root = kzalloc(sizeof(*root), GFP_NOFS); 951 root = kzalloc(sizeof(*root), GFP_NOFS);
943 if (!root) 952 if (!root)
944 return -ENOMEM; 953 return ERR_PTR(-ENOMEM);
945 954
946 __setup_root(tree_root->nodesize, tree_root->leafsize, 955 __setup_root(tree_root->nodesize, tree_root->leafsize,
947 tree_root->sectorsize, tree_root->stripesize, 956 tree_root->sectorsize, tree_root->stripesize,
@@ -950,12 +959,23 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
950 root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID; 959 root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID;
951 root->root_key.type = BTRFS_ROOT_ITEM_KEY; 960 root->root_key.type = BTRFS_ROOT_ITEM_KEY;
952 root->root_key.offset = BTRFS_TREE_LOG_OBJECTID; 961 root->root_key.offset = BTRFS_TREE_LOG_OBJECTID;
962 /*
963 * log trees do not get reference counted because they go away
964 * before a real commit is actually done. They do store pointers
965 * to file data extents, and those reference counts still get
966 * updated (along with back refs to the log tree).
967 */
953 root->ref_cows = 0; 968 root->ref_cows = 0;
954 969
955 root->node = btrfs_alloc_free_block(trans, root, root->leafsize, 970 leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
956 0, BTRFS_TREE_LOG_OBJECTID, 971 0, BTRFS_TREE_LOG_OBJECTID,
957 trans->transid, 0, 0, 0); 972 trans->transid, 0, 0, 0);
973 if (IS_ERR(leaf)) {
974 kfree(root);
975 return ERR_CAST(leaf);
976 }
958 977
978 root->node = leaf;
959 btrfs_set_header_nritems(root->node, 0); 979 btrfs_set_header_nritems(root->node, 0);
960 btrfs_set_header_level(root->node, 0); 980 btrfs_set_header_level(root->node, 0);
961 btrfs_set_header_bytenr(root->node, root->node->start); 981 btrfs_set_header_bytenr(root->node, root->node->start);
@@ -967,7 +987,48 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
967 BTRFS_FSID_SIZE); 987 BTRFS_FSID_SIZE);
968 btrfs_mark_buffer_dirty(root->node); 988 btrfs_mark_buffer_dirty(root->node);
969 btrfs_tree_unlock(root->node); 989 btrfs_tree_unlock(root->node);
970 fs_info->log_root_tree = root; 990 return root;
991}
992
993int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
994 struct btrfs_fs_info *fs_info)
995{
996 struct btrfs_root *log_root;
997
998 log_root = alloc_log_tree(trans, fs_info);
999 if (IS_ERR(log_root))
1000 return PTR_ERR(log_root);
1001 WARN_ON(fs_info->log_root_tree);
1002 fs_info->log_root_tree = log_root;
1003 return 0;
1004}
1005
1006int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
1007 struct btrfs_root *root)
1008{
1009 struct btrfs_root *log_root;
1010 struct btrfs_inode_item *inode_item;
1011
1012 log_root = alloc_log_tree(trans, root->fs_info);
1013 if (IS_ERR(log_root))
1014 return PTR_ERR(log_root);
1015
1016 log_root->last_trans = trans->transid;
1017 log_root->root_key.offset = root->root_key.objectid;
1018
1019 inode_item = &log_root->root_item.inode;
1020 inode_item->generation = cpu_to_le64(1);
1021 inode_item->size = cpu_to_le64(3);
1022 inode_item->nlink = cpu_to_le32(1);
1023 inode_item->nbytes = cpu_to_le64(root->leafsize);
1024 inode_item->mode = cpu_to_le32(S_IFDIR | 0755);
1025
1026 btrfs_set_root_bytenr(&log_root->root_item, log_root->node->start);
1027 btrfs_set_root_generation(&log_root->root_item, trans->transid);
1028
1029 WARN_ON(root->log_root);
1030 root->log_root = log_root;
1031 root->log_transid = 0;
971 return 0; 1032 return 0;
972} 1033}
973 1034
@@ -1530,10 +1591,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1530 init_waitqueue_head(&fs_info->transaction_throttle); 1591 init_waitqueue_head(&fs_info->transaction_throttle);
1531 init_waitqueue_head(&fs_info->transaction_wait); 1592 init_waitqueue_head(&fs_info->transaction_wait);
1532 init_waitqueue_head(&fs_info->async_submit_wait); 1593 init_waitqueue_head(&fs_info->async_submit_wait);
1533 init_waitqueue_head(&fs_info->tree_log_wait);
1534 atomic_set(&fs_info->tree_log_commit, 0);
1535 atomic_set(&fs_info->tree_log_writers, 0);
1536 fs_info->tree_log_transid = 0;
1537 1594
1538 __setup_root(4096, 4096, 4096, 4096, tree_root, 1595 __setup_root(4096, 4096, 4096, 4096, tree_root,
1539 fs_info, BTRFS_ROOT_TREE_OBJECTID); 1596 fs_info, BTRFS_ROOT_TREE_OBJECTID);