diff options
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 5f3544e5f3cb..1b9b87870f51 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -2778,6 +2778,8 @@ int btrfs_check_metadata_free_space(struct btrfs_root *root) | |||
2778 | /* get the space info for where the metadata will live */ | 2778 | /* get the space info for where the metadata will live */ |
2779 | alloc_target = btrfs_get_alloc_profile(root, 0); | 2779 | alloc_target = btrfs_get_alloc_profile(root, 0); |
2780 | meta_sinfo = __find_space_info(info, alloc_target); | 2780 | meta_sinfo = __find_space_info(info, alloc_target); |
2781 | if (!meta_sinfo) | ||
2782 | goto alloc; | ||
2781 | 2783 | ||
2782 | again: | 2784 | again: |
2783 | spin_lock(&meta_sinfo->lock); | 2785 | spin_lock(&meta_sinfo->lock); |
@@ -2795,7 +2797,7 @@ again: | |||
2795 | if (!meta_sinfo->full) { | 2797 | if (!meta_sinfo->full) { |
2796 | meta_sinfo->force_alloc = 1; | 2798 | meta_sinfo->force_alloc = 1; |
2797 | spin_unlock(&meta_sinfo->lock); | 2799 | spin_unlock(&meta_sinfo->lock); |
2798 | 2800 | alloc: | |
2799 | trans = btrfs_start_transaction(root, 1); | 2801 | trans = btrfs_start_transaction(root, 1); |
2800 | if (!trans) | 2802 | if (!trans) |
2801 | return -ENOMEM; | 2803 | return -ENOMEM; |
@@ -2803,6 +2805,10 @@ again: | |||
2803 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, | 2805 | ret = do_chunk_alloc(trans, root->fs_info->extent_root, |
2804 | 2 * 1024 * 1024, alloc_target, 0); | 2806 | 2 * 1024 * 1024, alloc_target, 0); |
2805 | btrfs_end_transaction(trans, root); | 2807 | btrfs_end_transaction(trans, root); |
2808 | if (!meta_sinfo) { | ||
2809 | meta_sinfo = __find_space_info(info, | ||
2810 | alloc_target); | ||
2811 | } | ||
2806 | goto again; | 2812 | goto again; |
2807 | } | 2813 | } |
2808 | spin_unlock(&meta_sinfo->lock); | 2814 | spin_unlock(&meta_sinfo->lock); |
@@ -2838,6 +2844,9 @@ int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode, | |||
2838 | bytes = (bytes + root->sectorsize - 1) & ~((u64)root->sectorsize - 1); | 2844 | bytes = (bytes + root->sectorsize - 1) & ~((u64)root->sectorsize - 1); |
2839 | 2845 | ||
2840 | data_sinfo = BTRFS_I(inode)->space_info; | 2846 | data_sinfo = BTRFS_I(inode)->space_info; |
2847 | if (!data_sinfo) | ||
2848 | goto alloc; | ||
2849 | |||
2841 | again: | 2850 | again: |
2842 | /* make sure we have enough space to handle the data first */ | 2851 | /* make sure we have enough space to handle the data first */ |
2843 | spin_lock(&data_sinfo->lock); | 2852 | spin_lock(&data_sinfo->lock); |
@@ -2856,7 +2865,7 @@ again: | |||
2856 | 2865 | ||
2857 | data_sinfo->force_alloc = 1; | 2866 | data_sinfo->force_alloc = 1; |
2858 | spin_unlock(&data_sinfo->lock); | 2867 | spin_unlock(&data_sinfo->lock); |
2859 | 2868 | alloc: | |
2860 | alloc_target = btrfs_get_alloc_profile(root, 1); | 2869 | alloc_target = btrfs_get_alloc_profile(root, 1); |
2861 | trans = btrfs_start_transaction(root, 1); | 2870 | trans = btrfs_start_transaction(root, 1); |
2862 | if (!trans) | 2871 | if (!trans) |
@@ -2868,6 +2877,11 @@ again: | |||
2868 | btrfs_end_transaction(trans, root); | 2877 | btrfs_end_transaction(trans, root); |
2869 | if (ret) | 2878 | if (ret) |
2870 | return ret; | 2879 | return ret; |
2880 | |||
2881 | if (!data_sinfo) { | ||
2882 | btrfs_set_inode_space_info(root, inode); | ||
2883 | data_sinfo = BTRFS_I(inode)->space_info; | ||
2884 | } | ||
2871 | goto again; | 2885 | goto again; |
2872 | } | 2886 | } |
2873 | spin_unlock(&data_sinfo->lock); | 2887 | spin_unlock(&data_sinfo->lock); |