Btrfs: deal with NULL space info
[linux-2.6.git] / fs / btrfs / extent-tree.c
index 5f3544e..1b9b878 100644 (file)
@@ -2778,6 +2778,8 @@ int btrfs_check_metadata_free_space(struct btrfs_root *root)
        /* get the space info for where the metadata will live */
        alloc_target = btrfs_get_alloc_profile(root, 0);
        meta_sinfo = __find_space_info(info, alloc_target);
+       if (!meta_sinfo)
+               goto alloc;
 
 again:
        spin_lock(&meta_sinfo->lock);
@@ -2795,7 +2797,7 @@ again:
                if (!meta_sinfo->full) {
                        meta_sinfo->force_alloc = 1;
                        spin_unlock(&meta_sinfo->lock);
-
+alloc:
                        trans = btrfs_start_transaction(root, 1);
                        if (!trans)
                                return -ENOMEM;
@@ -2803,6 +2805,10 @@ again:
                        ret = do_chunk_alloc(trans, root->fs_info->extent_root,
                                             2 * 1024 * 1024, alloc_target, 0);
                        btrfs_end_transaction(trans, root);
+                       if (!meta_sinfo) {
+                               meta_sinfo = __find_space_info(info,
+                                                              alloc_target);
+                       }
                        goto again;
                }
                spin_unlock(&meta_sinfo->lock);
@@ -2838,6 +2844,9 @@ int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode,
        bytes = (bytes + root->sectorsize - 1) & ~((u64)root->sectorsize - 1);
 
        data_sinfo = BTRFS_I(inode)->space_info;
+       if (!data_sinfo)
+               goto alloc;
+
 again:
        /* make sure we have enough space to handle the data first */
        spin_lock(&data_sinfo->lock);
@@ -2856,7 +2865,7 @@ again:
 
                        data_sinfo->force_alloc = 1;
                        spin_unlock(&data_sinfo->lock);
-
+alloc:
                        alloc_target = btrfs_get_alloc_profile(root, 1);
                        trans = btrfs_start_transaction(root, 1);
                        if (!trans)
@@ -2868,6 +2877,11 @@ again:
                        btrfs_end_transaction(trans, root);
                        if (ret)
                                return ret;
+
+                       if (!data_sinfo) {
+                               btrfs_set_inode_space_info(root, inode);
+                               data_sinfo = BTRFS_I(inode)->space_info;
+                       }
                        goto again;
                }
                spin_unlock(&data_sinfo->lock);