diff options
author | Qu Wenruo <quwenruo@cn.fujitsu.com> | 2015-10-26 02:11:18 -0400 |
---|---|---|
committer | Chris Mason <clm@fb.com> | 2015-10-26 22:44:39 -0400 |
commit | 5846a3c26873e86b034c702a8bc202aa76082369 (patch) | |
tree | 8495bf1ae8236d363579751a63414ba31c498a0d /fs/btrfs/extent-tree.c | |
parent | 696249132158014d594896df3a81390616069c5c (diff) |
btrfs: qgroup: Fix a race in delayed_ref which leads to abort trans
Between btrfs_allocerved_file_extent() and
btrfs_add_delayed_qgroup_reserve(), there is a window that delayed_refs
are run and delayed ref head maybe freed before
btrfs_add_delayed_qgroup_reserve().
This will cause btrfs_dad_delayed_qgroup_reserve() to return -ENOENT,
and cause transaction to be aborted.
This patch will record qgroup reserve space info into delayed_ref_head
at btrfs_add_delayed_ref(), to eliminate the race window.
Reported-by: Filipe Manana <fdmanana@suse.com>
Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: Chris Mason <clm@fb.com>
Diffstat (limited to 'fs/btrfs/extent-tree.c')
-rw-r--r-- | fs/btrfs/extent-tree.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index c1f8c7e27a6d..f50c7c2e2b59 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2087,8 +2087,8 @@ int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, | |||
2087 | BTRFS_ADD_DELAYED_REF, NULL); | 2087 | BTRFS_ADD_DELAYED_REF, NULL); |
2088 | } else { | 2088 | } else { |
2089 | ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr, | 2089 | ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr, |
2090 | num_bytes, | 2090 | num_bytes, parent, root_objectid, |
2091 | parent, root_objectid, owner, offset, | 2091 | owner, offset, 0, |
2092 | BTRFS_ADD_DELAYED_REF, NULL); | 2092 | BTRFS_ADD_DELAYED_REF, NULL); |
2093 | } | 2093 | } |
2094 | return ret; | 2094 | return ret; |
@@ -6832,8 +6832,8 @@ int btrfs_free_extent(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
6832 | ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr, | 6832 | ret = btrfs_add_delayed_data_ref(fs_info, trans, bytenr, |
6833 | num_bytes, | 6833 | num_bytes, |
6834 | parent, root_objectid, owner, | 6834 | parent, root_objectid, owner, |
6835 | offset, BTRFS_DROP_DELAYED_REF, | 6835 | offset, 0, |
6836 | NULL); | 6836 | BTRFS_DROP_DELAYED_REF, NULL); |
6837 | } | 6837 | } |
6838 | return ret; | 6838 | return ret; |
6839 | } | 6839 | } |
@@ -7759,7 +7759,8 @@ static int alloc_reserved_tree_block(struct btrfs_trans_handle *trans, | |||
7759 | int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans, | 7759 | int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans, |
7760 | struct btrfs_root *root, | 7760 | struct btrfs_root *root, |
7761 | u64 root_objectid, u64 owner, | 7761 | u64 root_objectid, u64 owner, |
7762 | u64 offset, struct btrfs_key *ins) | 7762 | u64 offset, u64 ram_bytes, |
7763 | struct btrfs_key *ins) | ||
7763 | { | 7764 | { |
7764 | int ret; | 7765 | int ret; |
7765 | 7766 | ||
@@ -7768,7 +7769,8 @@ int btrfs_alloc_reserved_file_extent(struct btrfs_trans_handle *trans, | |||
7768 | ret = btrfs_add_delayed_data_ref(root->fs_info, trans, ins->objectid, | 7769 | ret = btrfs_add_delayed_data_ref(root->fs_info, trans, ins->objectid, |
7769 | ins->offset, 0, | 7770 | ins->offset, 0, |
7770 | root_objectid, owner, offset, | 7771 | root_objectid, owner, offset, |
7771 | BTRFS_ADD_DELAYED_EXTENT, NULL); | 7772 | ram_bytes, BTRFS_ADD_DELAYED_EXTENT, |
7773 | NULL); | ||
7772 | return ret; | 7774 | return ret; |
7773 | } | 7775 | } |
7774 | 7776 | ||