Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 33b4d47f authored by Chris Mason's avatar Chris Mason
Browse files

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: default avatarChris Mason <chris.mason@oracle.com>
parent 1b2da372
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -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 @@ int btrfs_check_metadata_free_space(struct btrfs_root *root)
		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 @@ int btrfs_check_metadata_free_space(struct btrfs_root *root)
			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 @@ int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode,

			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 @@ int btrfs_check_data_free_space(struct btrfs_root *root, struct inode *inode,
			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);