From: Wang Xiaoguang <wangxg.f...@cn.fujitsu.com> When running inband dedup with balance, it's possible that inband dedup still increase ref on extents which are in RO chunk.
This may cause either find_data_references() gives warning, or make run_delayed_refs() return -EIO and cause trans abort. The cause is, normal dedup_del() is only called at run_delayed_ref() time, which is too late for balance case. This patch fixes this bug by calling dedup_del() at extent searching time of balance. Signed-off-by: Wang Xiaoguang <wangxg.f...@cn.fujitsu.com> --- fs/btrfs/relocation.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 2bd0011..913a7b1 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -31,6 +31,7 @@ #include "async-thread.h" #include "free-space-cache.h" #include "inode-map.h" +#include "dedup.h" /* * backref_node, mapping_node and tree_block start with this @@ -3909,6 +3910,7 @@ static noinline_for_stack int relocate_block_group(struct reloc_control *rc) struct btrfs_trans_handle *trans = NULL; struct btrfs_path *path; struct btrfs_extent_item *ei; + struct btrfs_fs_info *fs_info = rc->extent_root->fs_info; u64 flags; u32 item_size; int ret; @@ -4039,6 +4041,17 @@ restart: if (rc->stage == MOVE_DATA_EXTENTS && (flags & BTRFS_EXTENT_FLAG_DATA)) { rc->found_file_extent = 1; + /* + * This data extent will be replaced, but normal + * dedup_del() will only happen at run_delayed_ref() + * time, which is too late, so delete dedup hash early + * to prevent its ref get increased. + */ + ret = btrfs_dedup_del(trans, fs_info, key.objectid); + if (ret < 0) { + err = ret; + break; + } ret = relocate_data_extent(rc->data_inode, &key, &rc->cluster); if (ret < 0) { -- 2.7.1 -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html