diff mbox series

[v2] btrfs-progs: convert: Show more info when reserve_space fails

Message ID 20200924135502.19560-1-marcos@mpdesouza.com
State New, archived
Headers show
Series [v2] btrfs-progs: convert: Show more info when reserve_space fails | expand

Commit Message

Marcos Paulo de Souza Sept. 24, 2020, 1:55 p.m. UTC
From: Marcos Paulo de Souza <mpdesouza@suse.com>

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

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 (10Mb for example) end up being extended to 32Mb, 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

Link: https://github.com/kdave/btrfs-progs/issues/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>
---
 Changes from v1:
 * Added reviewed-by tag from Neal and Qu
 * Add largest free space portion available to the error message (Qu)

 convert/common.c | 32 +++++++++++++++++++++++++++++---
 1 file changed, 29 insertions(+), 3 deletions(-)

Comments

David Sterba Sept. 29, 2020, 8:51 p.m. UTC | #1
On Thu, Sep 24, 2020 at 10:55:02AM -0300, Marcos Paulo de Souza wrote:
> From: Marcos Paulo de Souza <mpdesouza@suse.com>
> 
> btrfs-convert currently can't handle more fragmented block groups when
> converting ext4 because the minimum size of a data chunk is 32Mb.
> 
> 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 (10Mb for example) end up being extended to 32Mb, 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
> 
> Link: https://github.com/kdave/btrfs-progs/issues/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>
> ---
>  Changes from v1:
>  * Added reviewed-by tag from Neal and Qu
>  * Add largest free space portion available to the error message (Qu)

Thanks, added to devel.
diff mbox series

Patch

diff --git a/convert/common.c b/convert/common.c
index 048629df..e636896b 100644
--- a/convert/common.c
+++ b/convert/common.c
@@ -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.