@@ -291,6 +291,81 @@ static int wipe_reserved_ranges(struct cache_tree *tree, u64 min_stripe_size,
return ret;
}
+static int calculate_available_space(struct cache_tree *used,
+ struct cache_tree *free,
+ struct btrfs_mkfs_config *cfg)
+{
+ struct cache_extent *cache;
+ u64 cur_off = 0;
+ /* Twice minimal chunk size */
+ u64 min_stripe_size = 2 * 16 * 1024 * 1024;
+ int ret;
+
+ for (cache = first_cache_extent(used); cache;
+ cache = next_cache_extent(cache)) {
+ u64 cur_len;
+
+ if (cache->start + cache->size < cur_off)
+ continue;
+ if (cache->start > cur_off + min_stripe_size)
+ cur_off = cache->start;
+ cur_len = max(cache->start + cache->size - cur_off,
+ min_stripe_size);
+ ret = add_merge_cache_extent(&cfg->convert_data_chunks,
+ cur_off, cur_len);
+ if (ret < 0)
+ goto out;
+ cur_off += cur_len;
+ }
+
+ /* remove reserved ranges and keep the size of chunks */
+ ret = wipe_reserved_ranges(&cfg->convert_data_chunks, min_stripe_size,
+ 1);
+ if (ret < 0)
+ goto out;
+
+ /*
+ * Now calculate the free space cache tree
+ * Always round up the start for insert, to avoid metadta extent cross
+ * stripe boundary
+ */
+ cur_off = 0;
+ for (cache = first_cache_extent(&cfg->convert_data_chunks); cache;
+ cache = next_cache_extent(cache)) {
+ if (cache->start < cur_off)
+ continue;
+ if (cache->start > cur_off) {
+ u64 insert_start;
+ u64 len;
+
+ len = cache->start - round_up(cur_off,
+ BTRFS_STRIPE_LEN);
+ insert_start = round_up(cur_off, BTRFS_STRIPE_LEN);
+
+ ret = add_merge_cache_extent(free, insert_start, len);
+ if (ret < 0)
+ goto out;
+ }
+ cur_off = cache->start + cache->size;
+ }
+ /* Don't forget the last range */
+ if (cfg->num_bytes > cur_off) {
+ u64 len = cfg->num_bytes - cur_off;
+ u64 insert_start;
+
+ insert_start = round_up(cur_off, BTRFS_STRIPE_LEN);
+
+ ret = add_merge_cache_extent(free, insert_start, len);
+ if (ret < 0)
+ goto out;
+ }
+
+ /* Remove reserved bytes */
+ ret = wipe_reserved_ranges(free, min_stripe_size, 0);
+out:
+ return ret;
+}
+
/*
* @fs_uuid - if NULL, generates a UUID, returns back the new filesystem UUID
*/
@@ -31,6 +31,8 @@
(BTRFS_FEATURE_INCOMPAT_EXTENDED_IREF \
| BTRFS_FEATURE_INCOMPAT_SKINNY_METADATA)
+#define BTRFS_CONVERT_META_GROUP_SIZE (32 * 1024 * 1024)
+
/*
* Avoid multi-device features (RAID56) and mixed block groups
*/
@@ -125,6 +127,14 @@ struct btrfs_mkfs_config {
struct cache_tree convert_used;
/*
+ * Ranges that should be covered by data chunk
+ * For convert use only.
+ *
+ * Optimized version of convert_used, without tiny chunks.
+ */
+ struct cache_tree convert_data_chunks;
+
+ /*
* Super block bytenr.
* For normal mkfs case, it shouldn't be used as mkfs doesn't support
* change super block bytenr anymore.
@@ -139,11 +149,13 @@ static inline void init_mkfs_config(struct btrfs_mkfs_config *cfg)
{
memset(cfg, 0, sizeof(*cfg));
cache_tree_init(&cfg->convert_used);
+ cache_tree_init(&cfg->convert_data_chunks);
}
static inline void free_mkfs_config(struct btrfs_mkfs_config *cfg)
{
free_extent_cache_tree(&cfg->convert_used);
+ free_extent_cache_tree(&cfg->convert_data_chunks);
}
int make_btrfs(int fd, struct btrfs_mkfs_config *cfg);
Introduce a new function, calculate_available_space() to get available space for convert. Unlike old implement, this function will do the new work: 1) batch used ext* data space. To ensure data chunks will recovery them all. And restore the result into mkfs_cfg->convert_data_chunks for later user. 2) avoid SB and reserved space Both batched data space or free space will not cover reserved space, like sb or the first 1M. Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com> --- utils.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ utils.h | 12 +++++++++++ 2 files changed, 87 insertions(+)