aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2009-09-22 14:45:50 -0400
committerChris Mason <chris.mason@oracle.com>2009-09-22 14:45:50 -0400
commit33b4d47f5e24b986f486d7de9a2df915ad1fdfbc (patch)
tree198fb5c7d48bfd9e4010eb253e9e7573172a7680 /fs
parent1b2da372b0324b5c604fc8790e70a7efbeacb0b6 (diff)
Btrfs: deal with NULL space info
After a balance it is briefly possible for the space info field in the inode to be NULL. This adds some checks to make sure things properly deal with the NULL value. Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/extent-tree.c18
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
2782again: 2784again:
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 2800alloc:
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
2841again: 2850again:
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 2868alloc:
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);