aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQu Wenruo <wqu@suse.com>2018-09-27 02:42:35 -0400
committerDavid Sterba <dsterba@suse.com>2018-10-15 11:23:36 -0400
commit3d0174f78e72301324a5b0ba7d67676474e36fff (patch)
tree3396913881f8828eb65f82ed9e06719f8e5dd3f5
parent2cd86d309bd1203241ceb833effe90787f3564a1 (diff)
btrfs: qgroup: Only trace data extents in leaves if we're relocating data block group
For qgroup_trace_extent_swap(), if we find one leaf that needs to be traced, we will also iterate all file extents and trace them. This is OK if we're relocating data block groups, but if we're relocating metadata block groups, balance code itself has ensured that both subtree of file tree and reloc tree contain the same contents. That's to say, if we're relocating metadata block groups, all file extents in reloc and file tree should match, thus no need to trace them. This should reduce the total number of dirty extents processed in metadata block group balance. [[Benchmark]] (with all previous enhancement) Hardware: VM 4G vRAM, 8 vCPUs, disk is using 'unsafe' cache mode, backing device is SAMSUNG 850 evo SSD. Host has 16G ram. Mkfs parameter: --nodesize 4K (To bump up tree size) Initial subvolume contents: 4G data copied from /usr and /lib. (With enough regular small files) Snapshots: 16 snapshots of the original subvolume. each snapshot has 3 random files modified. balance parameter: -m So the content should be pretty similar to a real world root fs layout. | v4.19-rc1 | w/ patchset | diff (*) --------------------------------------------------------------- relocated extents | 22929 | 22851 | -0.3% qgroup dirty extents | 227757 | 140886 | -38.1% time (sys) | 65.253s | 37.464s | -42.6% time (real) | 74.032s | 44.722s | -39.6% Signed-off-by: Qu Wenruo <wqu@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
-rw-r--r--fs/btrfs/qgroup.c21
-rw-r--r--fs/btrfs/qgroup.h1
-rw-r--r--fs/btrfs/relocation.c10
3 files changed, 21 insertions, 11 deletions
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index 6b35b3481085..ac9690f36a94 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1761,7 +1761,8 @@ static int adjust_slots_upwards(struct btrfs_path *path, int root_level)
1761static int qgroup_trace_extent_swap(struct btrfs_trans_handle* trans, 1761static int qgroup_trace_extent_swap(struct btrfs_trans_handle* trans,
1762 struct extent_buffer *src_eb, 1762 struct extent_buffer *src_eb,
1763 struct btrfs_path *dst_path, 1763 struct btrfs_path *dst_path,
1764 int dst_level, int root_level) 1764 int dst_level, int root_level,
1765 bool trace_leaf)
1765{ 1766{
1766 struct btrfs_key key; 1767 struct btrfs_key key;
1767 struct btrfs_path *src_path; 1768 struct btrfs_path *src_path;
@@ -1863,7 +1864,7 @@ static int qgroup_trace_extent_swap(struct btrfs_trans_handle* trans,
1863 goto out; 1864 goto out;
1864 1865
1865 /* Record leaf file extents */ 1866 /* Record leaf file extents */
1866 if (dst_level == 0) { 1867 if (dst_level == 0 && trace_leaf) {
1867 ret = btrfs_qgroup_trace_leaf_items(trans, src_path->nodes[0]); 1868 ret = btrfs_qgroup_trace_leaf_items(trans, src_path->nodes[0]);
1868 if (ret < 0) 1869 if (ret < 0)
1869 goto out; 1870 goto out;
@@ -1900,7 +1901,7 @@ static int qgroup_trace_new_subtree_blocks(struct btrfs_trans_handle* trans,
1900 struct extent_buffer *src_eb, 1901 struct extent_buffer *src_eb,
1901 struct btrfs_path *dst_path, 1902 struct btrfs_path *dst_path,
1902 int cur_level, int root_level, 1903 int cur_level, int root_level,
1903 u64 last_snapshot) 1904 u64 last_snapshot, bool trace_leaf)
1904{ 1905{
1905 struct btrfs_fs_info *fs_info = trans->fs_info; 1906 struct btrfs_fs_info *fs_info = trans->fs_info;
1906 struct extent_buffer *eb; 1907 struct extent_buffer *eb;
@@ -1972,7 +1973,7 @@ static int qgroup_trace_new_subtree_blocks(struct btrfs_trans_handle* trans,
1972 1973
1973 /* Now record this tree block and its counter part for qgroups */ 1974 /* Now record this tree block and its counter part for qgroups */
1974 ret = qgroup_trace_extent_swap(trans, src_eb, dst_path, cur_level, 1975 ret = qgroup_trace_extent_swap(trans, src_eb, dst_path, cur_level,
1975 root_level); 1976 root_level, trace_leaf);
1976 if (ret < 0) 1977 if (ret < 0)
1977 goto cleanup; 1978 goto cleanup;
1978 1979
@@ -1989,7 +1990,7 @@ static int qgroup_trace_new_subtree_blocks(struct btrfs_trans_handle* trans,
1989 /* Recursive call (at most 7 times) */ 1990 /* Recursive call (at most 7 times) */
1990 ret = qgroup_trace_new_subtree_blocks(trans, src_eb, 1991 ret = qgroup_trace_new_subtree_blocks(trans, src_eb,
1991 dst_path, cur_level - 1, root_level, 1992 dst_path, cur_level - 1, root_level,
1992 last_snapshot); 1993 last_snapshot, trace_leaf);
1993 if (ret < 0) 1994 if (ret < 0)
1994 goto cleanup; 1995 goto cleanup;
1995 } 1996 }
@@ -2028,6 +2029,7 @@ out:
2028 * @dst_parent, @dst_slot: pointer to dst (reloc tree) eb. 2029 * @dst_parent, @dst_slot: pointer to dst (reloc tree) eb.
2029 */ 2030 */
2030int btrfs_qgroup_trace_subtree_swap(struct btrfs_trans_handle *trans, 2031int btrfs_qgroup_trace_subtree_swap(struct btrfs_trans_handle *trans,
2032 struct btrfs_block_group_cache *bg_cache,
2031 struct extent_buffer *src_parent, int src_slot, 2033 struct extent_buffer *src_parent, int src_slot,
2032 struct extent_buffer *dst_parent, int dst_slot, 2034 struct extent_buffer *dst_parent, int dst_slot,
2033 u64 last_snapshot) 2035 u64 last_snapshot)
@@ -2037,6 +2039,7 @@ int btrfs_qgroup_trace_subtree_swap(struct btrfs_trans_handle *trans,
2037 struct btrfs_key first_key; 2039 struct btrfs_key first_key;
2038 struct extent_buffer *src_eb = NULL; 2040 struct extent_buffer *src_eb = NULL;
2039 struct extent_buffer *dst_eb = NULL; 2041 struct extent_buffer *dst_eb = NULL;
2042 bool trace_leaf = false;
2040 u64 child_gen; 2043 u64 child_gen;
2041 u64 child_bytenr; 2044 u64 child_bytenr;
2042 int level; 2045 int level;
@@ -2055,6 +2058,12 @@ int btrfs_qgroup_trace_subtree_swap(struct btrfs_trans_handle *trans,
2055 return -EUCLEAN; 2058 return -EUCLEAN;
2056 } 2059 }
2057 2060
2061 /*
2062 * Only trace leaf if we're relocating data block groups, this could
2063 * reduce tons of data extents tracing for meta/sys bg relocation.
2064 */
2065 if (bg_cache->flags & BTRFS_BLOCK_GROUP_DATA)
2066 trace_leaf = true;
2058 /* Read out real @src_eb, pointed by @src_parent and @src_slot */ 2067 /* Read out real @src_eb, pointed by @src_parent and @src_slot */
2059 child_bytenr = btrfs_node_blockptr(src_parent, src_slot); 2068 child_bytenr = btrfs_node_blockptr(src_parent, src_slot);
2060 child_gen = btrfs_node_ptr_generation(src_parent, src_slot); 2069 child_gen = btrfs_node_ptr_generation(src_parent, src_slot);
@@ -2099,7 +2108,7 @@ int btrfs_qgroup_trace_subtree_swap(struct btrfs_trans_handle *trans,
2099 2108
2100 /* Do the generation-aware breadth-first search */ 2109 /* Do the generation-aware breadth-first search */
2101 ret = qgroup_trace_new_subtree_blocks(trans, src_eb, dst_path, level, 2110 ret = qgroup_trace_new_subtree_blocks(trans, src_eb, dst_path, level,
2102 level, last_snapshot); 2111 level, last_snapshot, trace_leaf);
2103 if (ret < 0) 2112 if (ret < 0)
2104 goto out; 2113 goto out;
2105 ret = 0; 2114 ret = 0;
diff --git a/fs/btrfs/qgroup.h b/fs/btrfs/qgroup.h
index 1aaf4c276900..80ebeb3ab5ba 100644
--- a/fs/btrfs/qgroup.h
+++ b/fs/btrfs/qgroup.h
@@ -238,6 +238,7 @@ int btrfs_qgroup_trace_subtree(struct btrfs_trans_handle *trans,
238 u64 root_gen, int root_level); 238 u64 root_gen, int root_level);
239 239
240int btrfs_qgroup_trace_subtree_swap(struct btrfs_trans_handle *trans, 240int btrfs_qgroup_trace_subtree_swap(struct btrfs_trans_handle *trans,
241 struct btrfs_block_group_cache *bg_cache,
241 struct extent_buffer *src_parent, int src_slot, 242 struct extent_buffer *src_parent, int src_slot,
242 struct extent_buffer *dst_parent, int dst_slot, 243 struct extent_buffer *dst_parent, int dst_slot,
243 u64 last_snapshot); 244 u64 last_snapshot);
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index d10357122aa1..3e6e3d93caad 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -1744,7 +1744,7 @@ int memcmp_node_keys(struct extent_buffer *eb, int slot,
1744 * errors, a negative error number is returned. 1744 * errors, a negative error number is returned.
1745 */ 1745 */
1746static noinline_for_stack 1746static noinline_for_stack
1747int replace_path(struct btrfs_trans_handle *trans, 1747int replace_path(struct btrfs_trans_handle *trans, struct reloc_control *rc,
1748 struct btrfs_root *dest, struct btrfs_root *src, 1748 struct btrfs_root *dest, struct btrfs_root *src,
1749 struct btrfs_path *path, struct btrfs_key *next_key, 1749 struct btrfs_path *path, struct btrfs_key *next_key,
1750 int lowest_level, int max_level) 1750 int lowest_level, int max_level)
@@ -1888,9 +1888,9 @@ again:
1888 * and tree block numbers, if current trans doesn't free 1888 * and tree block numbers, if current trans doesn't free
1889 * data reloc tree inode. 1889 * data reloc tree inode.
1890 */ 1890 */
1891 ret = btrfs_qgroup_trace_subtree_swap(trans, parent, slot, 1891 ret = btrfs_qgroup_trace_subtree_swap(trans, rc->block_group,
1892 path->nodes[level], path->slots[level], 1892 parent, slot, path->nodes[level],
1893 last_snapshot); 1893 path->slots[level], last_snapshot);
1894 if (ret < 0) 1894 if (ret < 0)
1895 break; 1895 break;
1896 1896
@@ -2209,7 +2209,7 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
2209 btrfs_comp_cpu_keys(&next_key, &key) >= 0) { 2209 btrfs_comp_cpu_keys(&next_key, &key) >= 0) {
2210 ret = 0; 2210 ret = 0;
2211 } else { 2211 } else {
2212 ret = replace_path(trans, root, reloc_root, path, 2212 ret = replace_path(trans, rc, root, reloc_root, path,
2213 &next_key, level, max_level); 2213 &next_key, level, max_level);
2214 } 2214 }
2215 if (ret < 0) { 2215 if (ret < 0) {