提交 6baa4293 编写于 作者: F Filipe Manana 提交者: Josef Bacik

Btrfs: correctly determine if blocks are shared in btrfs_compare_trees

Just comparing the pointers (logical disk addresses) of the btree nodes is
not completely bullet proof, we have to check if their generation numbers
match too.

It is guaranteed that a COW operation will result in a block with a different
logical disk address than the original block's address, but over time we can
reuse that former logical disk address.

For example, creating a 2Gb filesystem on a loop device, and having a script
running in a loop always updating the access timestamp of a file, resulted in
the same logical disk address being reused for the same fs btree block in about
only 4 minutes.

This could make us skip entire subtrees when doing an incremental send (which
is currently the only user of btrfs_compare_trees). However the odds of getting
2 blocks at the same tree level, with the same logical disk address, equal first
slot keys and different generations, should hopefully be very low.
Signed-off-by: NFilipe David Borba Manana <fdmanana@gmail.com>
Signed-off-by: NJosef Bacik <jbacik@fb.com>
上级 9dc44214
...@@ -5376,6 +5376,8 @@ int btrfs_compare_trees(struct btrfs_root *left_root, ...@@ -5376,6 +5376,8 @@ int btrfs_compare_trees(struct btrfs_root *left_root,
int advance_right; int advance_right;
u64 left_blockptr; u64 left_blockptr;
u64 right_blockptr; u64 right_blockptr;
u64 left_gen;
u64 right_gen;
u64 left_start_ctransid; u64 left_start_ctransid;
u64 right_start_ctransid; u64 right_start_ctransid;
u64 ctransid; u64 ctransid;
...@@ -5640,7 +5642,14 @@ int btrfs_compare_trees(struct btrfs_root *left_root, ...@@ -5640,7 +5642,14 @@ int btrfs_compare_trees(struct btrfs_root *left_root,
right_blockptr = btrfs_node_blockptr( right_blockptr = btrfs_node_blockptr(
right_path->nodes[right_level], right_path->nodes[right_level],
right_path->slots[right_level]); right_path->slots[right_level]);
if (left_blockptr == right_blockptr) { left_gen = btrfs_node_ptr_generation(
left_path->nodes[left_level],
left_path->slots[left_level]);
right_gen = btrfs_node_ptr_generation(
right_path->nodes[right_level],
right_path->slots[right_level]);
if (left_blockptr == right_blockptr &&
left_gen == right_gen) {
/* /*
* As we're on a shared block, don't * As we're on a shared block, don't
* allow to go deeper. * allow to go deeper.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册