Skip to content

Commit a9b3311

Browse files
jeffmahoneykdave
authored andcommitted
btrfs: fix race with relocation recovery and fs_root setup
If we have to recover relocation during mount, we'll ultimately have to evict the orphan inode. That goes through the reservation dance, where priority_reclaim_metadata_space and flush_space expect fs_info->fs_root to be valid. That's the next thing to be set up during mount, so we crash, almost always in flush_space trying to join the transaction but priority_reclaim_metadata_space is possible as well. This call path has been problematic in the past WRT whether ->fs_root is valid yet. Commit 957780e (Btrfs: introduce ticketed enospc infrastructure) added new users that are called in the direct path instead of the async path that had already been worked around. The thing is that we don't actually need the fs_root, specifically, for anything. We either use it to determine whether the root is the chunk_root for use in choosing an allocation profile or as a root to pass btrfs_join_transaction before immediately committing it. Anything that isn't the chunk root works in the former case and any root works in the latter. A simple fix is to use a root we know will always be there: the extent_root. Cc: <[email protected]> # v4.8+ Fixes: 957780e (Btrfs: introduce ticketed enospc infrastructure) Signed-off-by: Jeff Mahoney <[email protected]> Reviewed-by: Liu Bo <[email protected]> Signed-off-by: David Sterba <[email protected]>
1 parent 896533a commit a9b3311

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

fs/btrfs/extent-tree.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4845,7 +4845,7 @@ static int may_commit_transaction(struct btrfs_fs_info *fs_info,
48454845
spin_unlock(&delayed_rsv->lock);
48464846

48474847
commit:
4848-
trans = btrfs_join_transaction(fs_info->fs_root);
4848+
trans = btrfs_join_transaction(fs_info->extent_root);
48494849
if (IS_ERR(trans))
48504850
return -ENOSPC;
48514851

@@ -4863,7 +4863,7 @@ static int flush_space(struct btrfs_fs_info *fs_info,
48634863
struct btrfs_space_info *space_info, u64 num_bytes,
48644864
u64 orig_bytes, int state)
48654865
{
4866-
struct btrfs_root *root = fs_info->fs_root;
4866+
struct btrfs_root *root = fs_info->extent_root;
48674867
struct btrfs_trans_handle *trans;
48684868
int nr;
48694869
int ret = 0;
@@ -5063,7 +5063,7 @@ static void priority_reclaim_metadata_space(struct btrfs_fs_info *fs_info,
50635063
int flush_state = FLUSH_DELAYED_ITEMS_NR;
50645064

50655065
spin_lock(&space_info->lock);
5066-
to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->fs_root,
5066+
to_reclaim = btrfs_calc_reclaim_metadata_size(fs_info->extent_root,
50675067
space_info);
50685068
if (!to_reclaim) {
50695069
spin_unlock(&space_info->lock);

0 commit comments

Comments
 (0)