diff options
| -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); |
