diff options
Diffstat (limited to 'fs/btrfs/free-space-cache.c')
-rw-r--r-- | fs/btrfs/free-space-cache.c | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c index 4ba0aedc878b..74aa552f4793 100644 --- a/fs/btrfs/free-space-cache.c +++ b/fs/btrfs/free-space-cache.c | |||
@@ -75,7 +75,8 @@ static struct inode *__lookup_free_space_inode(struct btrfs_root *root, | |||
75 | * sure NOFS is set to keep us from deadlocking. | 75 | * sure NOFS is set to keep us from deadlocking. |
76 | */ | 76 | */ |
77 | nofs_flag = memalloc_nofs_save(); | 77 | nofs_flag = memalloc_nofs_save(); |
78 | inode = btrfs_iget(fs_info->sb, &location, root, NULL); | 78 | inode = btrfs_iget_path(fs_info->sb, &location, root, NULL, path); |
79 | btrfs_release_path(path); | ||
79 | memalloc_nofs_restore(nofs_flag); | 80 | memalloc_nofs_restore(nofs_flag); |
80 | if (IS_ERR(inode)) | 81 | if (IS_ERR(inode)) |
81 | return inode; | 82 | return inode; |
@@ -838,6 +839,25 @@ int load_free_space_cache(struct btrfs_fs_info *fs_info, | |||
838 | path->search_commit_root = 1; | 839 | path->search_commit_root = 1; |
839 | path->skip_locking = 1; | 840 | path->skip_locking = 1; |
840 | 841 | ||
842 | /* | ||
843 | * We must pass a path with search_commit_root set to btrfs_iget in | ||
844 | * order to avoid a deadlock when allocating extents for the tree root. | ||
845 | * | ||
846 | * When we are COWing an extent buffer from the tree root, when looking | ||
847 | * for a free extent, at extent-tree.c:find_free_extent(), we can find | ||
848 | * block group without its free space cache loaded. When we find one | ||
849 | * we must load its space cache which requires reading its free space | ||
850 | * cache's inode item from the root tree. If this inode item is located | ||
851 | * in the same leaf that we started COWing before, then we end up in | ||
852 | * deadlock on the extent buffer (trying to read lock it when we | ||
853 | * previously write locked it). | ||
854 | * | ||
855 | * It's safe to read the inode item using the commit root because | ||
856 | * block groups, once loaded, stay in memory forever (until they are | ||
857 | * removed) as well as their space caches once loaded. New block groups | ||
858 | * once created get their ->cached field set to BTRFS_CACHE_FINISHED so | ||
859 | * we will never try to read their inode item while the fs is mounted. | ||
860 | */ | ||
841 | inode = lookup_free_space_inode(fs_info, block_group, path); | 861 | inode = lookup_free_space_inode(fs_info, block_group, path); |
842 | if (IS_ERR(inode)) { | 862 | if (IS_ERR(inode)) { |
843 | btrfs_free_path(path); | 863 | btrfs_free_path(path); |