Currently only relocation code cares about btrfs_root::reloc_root, and
they have the method to sync btrfs_root::reloc_root without screwing
things up.
However qgroup code doesn't really have the ability to keep
btrfs_root::reloc_root reliable.
Currently if someone outside of relocation code want to access
btrfs_root::reloc_root, it's highly possible some race could make
@reloc_root unreliable.
Thankfully, we only need to make qgroup code access
btrfs_root::reloc_root, and due to the nature of qgroup, it only needs
it before committing a transaction.
So alter the timming of transaction commit for merge_reloc_root(). For
every successful root merge, commit transaction before dropping
btrfs_root::reloc_root, making qgroup code happy with it.
Signed-off-by: Qu Wenruo <wqu@xxxxxxxx>
---
fs/btrfs/relocation.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index 44efde9886fc..a8b62323f60b 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2251,6 +2251,17 @@ static noinline_for_stack int merge_reloc_root(struct reloc_control *rc,
btrfs_free_path(path);
if (err == 0) {
+ /*
+ * Commit current trans before we reset root->reloc_root
+ * pointer, since qgroup code still needs root->reloc_root
+ * to trace post-swap CoWs until we commit transaction.
+ */
+ err = btrfs_commit_transaction(trans);
+ if (err < 0)
+ return err;
+ trans = btrfs_start_transaction(root, 0);
+ if (IS_ERR(trans))
+ return PTR_ERR(trans);
memset(&root_item->drop_progress, 0,
sizeof(root_item->drop_progress));
root_item->drop_level = 0;
--
2.19.1