btrfs-progs: extent-tree: Introduce functions to free in-memory block group cache
[platform/upstream/btrfs-progs.git] / mkfs.c
diff --git a/mkfs.c b/mkfs.c
index 14b75bc..b60fc5a 100644 (file)
--- a/mkfs.c
+++ b/mkfs.c
@@ -59,11 +59,11 @@ struct mkfs_allocation {
        u64 system;
 };
 
-static int make_root_dir(struct btrfs_root *root, int mixed,
-                               struct mkfs_allocation *allocation)
+static int create_metadata_block_groups(struct btrfs_root *root,
+               u64 metadata_profile, int mixed,
+               struct mkfs_allocation *allocation)
 {
        struct btrfs_trans_handle *trans;
-       struct btrfs_key location;
        u64 bytes_used;
        u64 chunk_start = 0;
        u64 chunk_size = 0;
@@ -74,6 +74,7 @@ static int make_root_dir(struct btrfs_root *root, int mixed,
 
        root->fs_info->system_allocs = 1;
        ret = btrfs_make_block_group(trans, root, bytes_used,
+                                    metadata_profile |
                                     BTRFS_BLOCK_GROUP_SYSTEM,
                                     BTRFS_FIRST_CHUNK_TREE_OBJECTID,
                                     0, BTRFS_MKFS_SYSTEM_GROUP_SIZE);
@@ -92,6 +93,7 @@ static int make_root_dir(struct btrfs_root *root, int mixed,
                }
                BUG_ON(ret);
                ret = btrfs_make_block_group(trans, root, 0,
+                                            metadata_profile |
                                             BTRFS_BLOCK_GROUP_METADATA |
                                             BTRFS_BLOCK_GROUP_DATA,
                                             BTRFS_FIRST_CHUNK_TREE_OBJECTID,
@@ -108,6 +110,7 @@ static int make_root_dir(struct btrfs_root *root, int mixed,
                }
                BUG_ON(ret);
                ret = btrfs_make_block_group(trans, root, 0,
+                                            metadata_profile |
                                             BTRFS_BLOCK_GROUP_METADATA,
                                             BTRFS_FIRST_CHUNK_TREE_OBJECTID,
                                             chunk_start, chunk_size);
@@ -117,8 +120,18 @@ static int make_root_dir(struct btrfs_root *root, int mixed,
 
        root->fs_info->system_allocs = 0;
        btrfs_commit_transaction(trans, root);
-       trans = btrfs_start_transaction(root, 1);
-       BUG_ON(!trans);
+
+err:
+       return ret;
+}
+
+static int create_data_block_groups(struct btrfs_trans_handle *trans,
+               struct btrfs_root *root, u64 data_profile, int mixed,
+               struct mkfs_allocation *allocation)
+{
+       u64 chunk_start = 0;
+       u64 chunk_size = 0;
+       int ret = 0;
 
        if (!mixed) {
                ret = btrfs_alloc_chunk(trans, root->fs_info->extent_root,
@@ -130,6 +143,7 @@ static int make_root_dir(struct btrfs_root *root, int mixed,
                }
                BUG_ON(ret);
                ret = btrfs_make_block_group(trans, root, 0,
+                                            data_profile |
                                             BTRFS_BLOCK_GROUP_DATA,
                                             BTRFS_FIRST_CHUNK_TREE_OBJECTID,
                                             chunk_start, chunk_size);
@@ -137,6 +151,16 @@ static int make_root_dir(struct btrfs_root *root, int mixed,
                BUG_ON(ret);
        }
 
+err:
+       return ret;
+}
+
+static int make_root_dir(struct btrfs_trans_handle *trans, struct btrfs_root *root,
+               int mixed, struct mkfs_allocation *allocation)
+{
+       struct btrfs_key location;
+       int ret;
+
        ret = btrfs_make_root_dir(trans, root->fs_info->tree_root,
                              BTRFS_ROOT_TREE_DIR_OBJECTID);
        if (ret)
@@ -159,7 +183,6 @@ static int make_root_dir(struct btrfs_root *root, int mixed,
        if (ret)
                goto err;
 
-       btrfs_commit_transaction(trans, root);
 err:
        return ret;
 }
@@ -229,8 +252,7 @@ static int create_one_raid_group(struct btrfs_trans_handle *trans,
 
 static int create_raid_groups(struct btrfs_trans_handle *trans,
                              struct btrfs_root *root, u64 data_profile,
-                             int data_profile_opt, u64 metadata_profile,
-                             int mixed,
+                             u64 metadata_profile, int mixed,
                              struct mkfs_allocation *allocation)
 {
        u64 num_devices = btrfs_super_num_devices(root->fs_info->super_copy);
@@ -1172,6 +1194,8 @@ int main(int ac, char **av)
        u64 alloc_start = 0;
        u64 metadata_profile = 0;
        u64 data_profile = 0;
+       u64 default_metadata_profile = 0;
+       u64 default_data_profile = 0;
        u32 nodesize = max_t(u32, sysconf(_SC_PAGESIZE),
                        BTRFS_MKFS_DEFAULT_NODE_SIZE);
        u32 sectorsize = 4096;
@@ -1187,7 +1211,6 @@ int main(int ac, char **av)
        int discard = 1;
        int ssd = 0;
        int force_overwrite = 0;
-
        char *source_dir = NULL;
        int source_dir_set = 0;
        u64 num_of_meta_chunks = 0;
@@ -1195,10 +1218,10 @@ int main(int ac, char **av)
        u64 source_dir_size = 0;
        int dev_cnt = 0;
        int saved_optind;
-       char estr[100];
        char fs_uuid[BTRFS_UUID_UNPARSED_SIZE] = { 0 };
        u64 features = BTRFS_MKFS_DEFAULT_FEATURES;
        struct mkfs_allocation allocation = { 0 };
+       struct btrfs_mkfs_config mkfs_cfg;
 
        while(1) {
                int c;
@@ -1335,10 +1358,8 @@ int main(int ac, char **av)
        while (dev_cnt-- > 0) {
                file = av[optind++];
                if (is_block_device(file))
-                       if (test_dev_for_mkfs(file, force_overwrite, estr)) {
-                               fprintf(stderr, "Error: %s", estr);
+                       if (test_dev_for_mkfs(file, force_overwrite))
                                exit(1);
-                       }
        }
 
        optind = saved_optind;
@@ -1426,11 +1447,9 @@ int main(int ac, char **av)
                }
        }
        ret = test_num_disk_vs_raid(metadata_profile, data_profile,
-                       dev_cnt, mixed, estr);
-       if (ret) {
-               fprintf(stderr, "Error: %s\n", estr);
+                       dev_cnt, mixed);
+       if (ret)
                exit(1);
-       }
 
        /* if we are here that means all devs are good to btrfsify */
        if (verbose) {
@@ -1512,8 +1531,16 @@ int main(int ac, char **av)
                features |= BTRFS_FEATURE_INCOMPAT_RAID56;
        }
 
-       ret = make_btrfs(fd, file, label, fs_uuid, blocks, dev_block_count,
-                        nodesize, sectorsize, stripesize, features);
+       mkfs_cfg.label = label;
+       mkfs_cfg.fs_uuid = fs_uuid;
+       memcpy(mkfs_cfg.blocks, blocks, sizeof(blocks));
+       mkfs_cfg.num_bytes = dev_block_count;
+       mkfs_cfg.nodesize = nodesize;
+       mkfs_cfg.sectorsize = sectorsize;
+       mkfs_cfg.stripesize = stripesize;
+       mkfs_cfg.features = features;
+
+       ret = make_btrfs(fd, &mkfs_cfg);
        if (ret) {
                fprintf(stderr, "error during mkfs: %s\n", strerror(-ret));
                exit(1);
@@ -1527,19 +1554,49 @@ int main(int ac, char **av)
        }
        root->fs_info->alloc_start = alloc_start;
 
-       ret = make_root_dir(root, mixed, &allocation);
+       if (dev_cnt == 0) {
+               default_metadata_profile = metadata_profile;
+               default_data_profile = data_profile;
+       } else {
+               /*
+                * Temporary groups to store new device entries
+                */
+               default_metadata_profile = 0;
+               default_data_profile = 0;
+       }
+
+       ret = create_metadata_block_groups(root, default_metadata_profile,
+                       mixed, &allocation);
+       if (ret) {
+               fprintf(stderr, "failed to create default block groups\n");
+               exit(1);
+       }
+
+       trans = btrfs_start_transaction(root, 1);
+       BUG_ON(!trans);
+
+       ret = create_data_block_groups(trans, root, default_data_profile,
+                       mixed, &allocation);
+       if (ret) {
+               fprintf(stderr, "failed to create default data block groups\n");
+               exit(1);
+       }
+
+       ret = make_root_dir(trans, root, mixed, &allocation);
        if (ret) {
                fprintf(stderr, "failed to setup the root directory\n");
                exit(1);
        }
 
+       btrfs_commit_transaction(trans, root);
+
        trans = btrfs_start_transaction(root, 1);
 
        if (is_block_device(file))
                btrfs_register_one_device(file);
 
        if (dev_cnt == 0)
-               goto raid_groups;
+               goto skip_multidev;
 
        while (dev_cnt-- > 0) {
                int old_mixed = mixed;
@@ -1589,13 +1646,12 @@ int main(int ac, char **av)
                        btrfs_register_one_device(file);
        }
 
-raid_groups:
        if (!source_dir_set) {
                ret = create_raid_groups(trans, root, data_profile,
-                                data_profile_opt, metadata_profile,
-                                mixed, &allocation);
+                                metadata_profile, mixed, &allocation);
                BUG_ON(ret);
        }
+skip_multidev:
 
        ret = create_data_reloc_tree(trans, root);
        BUG_ON(ret);