mirror of
https://github.com/kdave/btrfs-progs
synced 2025-01-22 21:43:35 +00:00
btrfs-progs: convert: report available space before conversion happens
Now if an ENOSPC error happened, the free space report would help user to determine if it's a real ENOSPC or a bug in convert. The reported free space is the calculated free space, which doesn't include super block space, nor merged data chunks. The free space is always smaller than the reported available space of the original fs, as we need extra padding space for used space to avoid too fragmented data chunks. The output would be: $ ./btrfs-convert /dev/sda create btrfs filesystem: blocksize: 4096 nodesize: 16384 features: extref, skinny-metadata (default) checksum: crc32c free space report: total: 10737418240 free: 0 (0.00%) ERROR: unable to create initial ctree: No space left on device WARNING: an error occurred during conversion, the original filesystem is not modified Signed-off-by: Qu Wenruo <wqu@suse.com> [ put total, free to separate lines ] Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
5587635716
commit
d353a5b3c2
@ -35,6 +35,7 @@ struct btrfs_convert_context {
|
||||
u64 inodes_count;
|
||||
u64 free_inodes_count;
|
||||
u64 total_bytes;
|
||||
u64 free_bytes_initial;
|
||||
char *volume_name;
|
||||
const struct btrfs_convert_operations *convert_ops;
|
||||
|
||||
@ -47,6 +48,13 @@ struct btrfs_convert_context {
|
||||
/* Free space which is not covered by data_chunks */
|
||||
struct cache_tree free_space;
|
||||
|
||||
/*
|
||||
* Free space reserved for ENOSPC report, it's just a copy free_space.
|
||||
* But after initial calculation, free_space_initial is no longer
|
||||
* updated, so we have a good idea on how much free space we really
|
||||
* have for btrfs.
|
||||
*/
|
||||
struct cache_tree free_space_initial;
|
||||
void *fs_data;
|
||||
};
|
||||
|
||||
|
@ -727,6 +727,24 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int copy_free_space_tree(struct btrfs_convert_context *cctx)
|
||||
{
|
||||
struct cache_tree *src = &cctx->free_space;
|
||||
struct cache_tree *dst = &cctx->free_space_initial;
|
||||
struct cache_extent *cache;
|
||||
int ret = 0;
|
||||
|
||||
for (cache = search_cache_extent(src, 0);
|
||||
cache;
|
||||
cache = next_cache_extent(cache)) {
|
||||
ret = add_merge_cache_extent(dst, cache->start, cache->size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
cctx->free_bytes_initial += cache->size;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read used space, and since we have the used space,
|
||||
* calculate data_chunks and free for later mkfs
|
||||
@ -740,7 +758,10 @@ static int convert_read_used_space(struct btrfs_convert_context *cctx)
|
||||
return ret;
|
||||
|
||||
ret = calculate_available_space(cctx);
|
||||
return ret;
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return copy_free_space_tree(cctx);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1165,7 +1186,10 @@ static int do_convert(const char *devname, u32 convert_flags, u32 nodesize,
|
||||
printf("\tnodesize: %u\n", nodesize);
|
||||
printf("\tfeatures: %s\n", features_buf);
|
||||
printf("\tchecksum: %s\n", btrfs_super_csum_name(csum_type));
|
||||
|
||||
printf("free space report:\n");
|
||||
printf("\ttotal: %llu\n",cctx.total_bytes);
|
||||
printf("\tfree: %llu (%.2f%%)\n", cctx.free_bytes_initial,
|
||||
100.0 * cctx.free_bytes_initial / cctx.total_bytes);
|
||||
memset(&mkfs_cfg, 0, sizeof(mkfs_cfg));
|
||||
mkfs_cfg.csum_type = csum_type;
|
||||
mkfs_cfg.label = cctx.volume_name;
|
||||
|
@ -74,6 +74,7 @@ void init_convert_context(struct btrfs_convert_context *cctx)
|
||||
cache_tree_init(&cctx->used_space);
|
||||
cache_tree_init(&cctx->data_chunks);
|
||||
cache_tree_init(&cctx->free_space);
|
||||
cache_tree_init(&cctx->free_space_initial);
|
||||
}
|
||||
|
||||
void clean_convert_context(struct btrfs_convert_context *cctx)
|
||||
@ -81,6 +82,7 @@ void clean_convert_context(struct btrfs_convert_context *cctx)
|
||||
free_extent_cache_tree(&cctx->used_space);
|
||||
free_extent_cache_tree(&cctx->data_chunks);
|
||||
free_extent_cache_tree(&cctx->free_space);
|
||||
free_extent_cache_tree(&cctx->free_space_initial);
|
||||
}
|
||||
|
||||
int block_iterate_proc(u64 disk_block, u64 file_block,
|
||||
|
Loading…
Reference in New Issue
Block a user