btrfs-progs: convert: show more info when reserve_space fails

btrfs-convert currently can't handle more fragmented block groups when
converting ext4 because the minimum size of a data chunk is 32MiB.

When converting an ext4 fs with more fragmented block group with the disk
almost full, we can end up hitting a ENOSPC problem [1] since smaller
block groups (10MiB for example) end up being extended to 32MiB, leaving
the free space tree smaller when converting it to btrfs.

This patch adds error messages telling which needed bytes couldn't be
allocated from the free space tree and shows the largest portion available:

  create btrfs filesystem:
	  blocksize: 4096
	  nodesize:  16384
	  features:  extref, skinny-metadata (default)
	  checksum:  crc32c
  free space report:
	  total:     1073741824
	  free:      39124992 (3.64%)
  ERROR: failed to reserve 33554432 bytes for metadata chunk, largest available: 33488896 bytes
  ERROR: unable to create initial ctree: No space left on device

Issue: #251
Reviewed-by: Neal Gompa <ngompa13@gmail.com>
Reviewed-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: Marcos Paulo de Souza <mpdesouza@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Marcos Paulo de Souza 2020-09-24 10:55:02 -03:00 committed by David Sterba
parent 92d92e99b7
commit 65ecbc7e0e

View File

@ -774,6 +774,20 @@ out:
return ret;
}
static u64 largest_free_space(struct cache_tree *free_space)
{
struct cache_extent *cache;
u64 largest_free_space = 0;
for (cache = first_cache_extent(free_space); cache;
cache = next_cache_extent(cache)) {
if (cache->size > largest_free_space)
largest_free_space = cache->size;
}
return largest_free_space;
}
/*
* Improved version of make_btrfs().
*
@ -812,8 +826,12 @@ int make_convert_btrfs(int fd, struct btrfs_mkfs_config *cfg,
*/
ret = reserve_free_space(free_space, BTRFS_STRIPE_LEN,
&cfg->super_bytenr);
if (ret < 0)
if (ret < 0) {
error(
"failed to reserve %d bytes for temporary superblock, largest available: %llu bytes",
BTRFS_STRIPE_LEN, largest_free_space(free_space));
goto out;
}
/*
* Then reserve system chunk space
@ -823,12 +841,20 @@ int make_convert_btrfs(int fd, struct btrfs_mkfs_config *cfg,
*/
ret = reserve_free_space(free_space, BTRFS_MKFS_SYSTEM_GROUP_SIZE,
&sys_chunk_start);
if (ret < 0)
if (ret < 0) {
error(
"failed to reserve %d bytes for system chunk, largest available: %llu bytes",
BTRFS_MKFS_SYSTEM_GROUP_SIZE, largest_free_space(free_space));
goto out;
}
ret = reserve_free_space(free_space, BTRFS_CONVERT_META_GROUP_SIZE,
&meta_chunk_start);
if (ret < 0)
if (ret < 0) {
error(
"failed to reserve %d bytes for metadata chunk, largest available: %llu bytes",
BTRFS_CONVERT_META_GROUP_SIZE, largest_free_space(free_space));
goto out;
}
/*
* Allocated meta/sys chunks will be mapped 1:1 with device offset.