Skip to content

Commit 7237f18

Browse files
Yan Zhengchrismason-xx
authored andcommitted
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 <[email protected]>
1 parent 7e66285 commit 7237f18

File tree

6 files changed

+248
-210
lines changed

6 files changed

+248
-210
lines changed

fs/btrfs/ctree.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -695,9 +695,7 @@ struct btrfs_fs_info {
695695
struct btrfs_transaction *running_transaction;
696696
wait_queue_head_t transaction_throttle;
697697
wait_queue_head_t transaction_wait;
698-
699698
wait_queue_head_t async_submit_wait;
700-
wait_queue_head_t tree_log_wait;
701699

702700
struct btrfs_super_block super_copy;
703701
struct btrfs_super_block super_for_commit;
@@ -724,10 +722,6 @@ struct btrfs_fs_info {
724722
atomic_t async_submit_draining;
725723
atomic_t nr_async_bios;
726724
atomic_t async_delalloc_pages;
727-
atomic_t tree_log_writers;
728-
atomic_t tree_log_commit;
729-
unsigned long tree_log_batch;
730-
u64 tree_log_transid;
731725

732726
/*
733727
* this is used by the balancing code to wait for all the pending
@@ -827,7 +821,14 @@ struct btrfs_root {
827821
struct kobject root_kobj;
828822
struct completion kobj_unregister;
829823
struct mutex objectid_mutex;
824+
830825
struct mutex log_mutex;
826+
wait_queue_head_t log_writer_wait;
827+
wait_queue_head_t log_commit_wait[2];
828+
atomic_t log_writers;
829+
atomic_t log_commit[2];
830+
unsigned long log_transid;
831+
unsigned long log_batch;
831832

832833
u64 objectid;
833834
u64 last_trans;

fs/btrfs/disk-io.c

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -849,6 +849,14 @@ static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
849849
spin_lock_init(&root->list_lock);
850850
mutex_init(&root->objectid_mutex);
851851
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;
852860
extent_io_tree_init(&root->dirty_log_pages,
853861
fs_info->btree_inode->i_mapping, GFP_NOFS);
854862

@@ -933,15 +941,16 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
933941
return 0;
934942
}
935943

936-
int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
937-
struct btrfs_fs_info *fs_info)
944+
static struct btrfs_root *alloc_log_tree(struct btrfs_trans_handle *trans,
945+
struct btrfs_fs_info *fs_info)
938946
{
939947
struct btrfs_root *root;
940948
struct btrfs_root *tree_root = fs_info->tree_root;
949+
struct extent_buffer *leaf;
941950

942951
root = kzalloc(sizeof(*root), GFP_NOFS);
943952
if (!root)
944-
return -ENOMEM;
953+
return ERR_PTR(-ENOMEM);
945954

946955
__setup_root(tree_root->nodesize, tree_root->leafsize,
947956
tree_root->sectorsize, tree_root->stripesize,
@@ -950,12 +959,23 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
950959
root->root_key.objectid = BTRFS_TREE_LOG_OBJECTID;
951960
root->root_key.type = BTRFS_ROOT_ITEM_KEY;
952961
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+
*/
953968
root->ref_cows = 0;
954969

955-
root->node = btrfs_alloc_free_block(trans, root, root->leafsize,
956-
0, BTRFS_TREE_LOG_OBJECTID,
957-
trans->transid, 0, 0, 0);
970+
leaf = btrfs_alloc_free_block(trans, root, root->leafsize,
971+
0, BTRFS_TREE_LOG_OBJECTID,
972+
trans->transid, 0, 0, 0);
973+
if (IS_ERR(leaf)) {
974+
kfree(root);
975+
return ERR_CAST(leaf);
976+
}
958977

978+
root->node = leaf;
959979
btrfs_set_header_nritems(root->node, 0);
960980
btrfs_set_header_level(root->node, 0);
961981
btrfs_set_header_bytenr(root->node, root->node->start);
@@ -967,7 +987,48 @@ int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
967987
BTRFS_FSID_SIZE);
968988
btrfs_mark_buffer_dirty(root->node);
969989
btrfs_tree_unlock(root->node);
970-
fs_info->log_root_tree = root;
990+
return root;
991+
}
992+
993+
int 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+
1006+
int 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;
9711032
return 0;
9721033
}
9731034

@@ -1530,10 +1591,6 @@ struct btrfs_root *open_ctree(struct super_block *sb,
15301591
init_waitqueue_head(&fs_info->transaction_throttle);
15311592
init_waitqueue_head(&fs_info->transaction_wait);
15321593
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;
15371594

15381595
__setup_root(4096, 4096, 4096, 4096, tree_root,
15391596
fs_info, BTRFS_ROOT_TREE_OBJECTID);

fs/btrfs/disk-io.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,7 @@ int btrfs_free_log_root_tree(struct btrfs_trans_handle *trans,
9898
struct btrfs_fs_info *fs_info);
9999
int btrfs_init_log_root_tree(struct btrfs_trans_handle *trans,
100100
struct btrfs_fs_info *fs_info);
101+
int btrfs_add_log_tree(struct btrfs_trans_handle *trans,
102+
struct btrfs_root *root);
101103
int btree_lock_page_hook(struct page *page);
102104
#endif

fs/btrfs/extent-tree.c

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2698,13 +2698,9 @@ static int __btrfs_free_extent(struct btrfs_trans_handle *trans,
26982698
/* if metadata always pin */
26992699
if (owner_objectid < BTRFS_FIRST_FREE_OBJECTID) {
27002700
if (root->root_key.objectid == BTRFS_TREE_LOG_OBJECTID) {
2701-
struct btrfs_block_group_cache *cache;
2702-
2703-
/* btrfs_free_reserved_extent */
2704-
cache = btrfs_lookup_block_group(root->fs_info, bytenr);
2705-
BUG_ON(!cache);
2706-
btrfs_add_free_space(cache, bytenr, num_bytes);
2707-
put_block_group(cache);
2701+
mutex_lock(&root->fs_info->pinned_mutex);
2702+
btrfs_update_pinned_extents(root, bytenr, num_bytes, 1);
2703+
mutex_unlock(&root->fs_info->pinned_mutex);
27082704
update_reserved_extents(root, bytenr, num_bytes, 0);
27092705
return 0;
27102706
}

fs/btrfs/file.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,10 +1214,10 @@ int btrfs_sync_file(struct file *file, struct dentry *dentry, int datasync)
12141214
}
12151215
mutex_unlock(&root->fs_info->trans_mutex);
12161216

1217-
root->fs_info->tree_log_batch++;
1217+
root->log_batch++;
12181218
filemap_fdatawrite(inode->i_mapping);
12191219
btrfs_wait_ordered_range(inode, 0, (u64)-1);
1220-
root->fs_info->tree_log_batch++;
1220+
root->log_batch++;
12211221

12221222
/*
12231223
* ok we haven't committed the transaction yet, lets do a commit

0 commit comments

Comments
 (0)