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 6cff69f..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);
@@ -290,9 +312,7 @@ static int create_data_reloc_tree(struct btrfs_trans_handle *trans,
        return 0;
 }
 
-
-static void print_usage(void) __attribute__((noreturn));
-static void print_usage(void)
+static void print_usage(int ret)
 {
        fprintf(stderr, "usage: mkfs.btrfs [options] dev [ dev ... ]\n");
        fprintf(stderr, "options:\n");
@@ -313,7 +333,7 @@ static void print_usage(void)
        fprintf(stderr, "\t-q|--quiet              no messages except errors\n");
        fprintf(stderr, "\t-V|--version            print the mkfs.btrfs version and exit\n");
        fprintf(stderr, "%s\n", PACKAGE_STRING);
-       exit(1);
+       exit(ret);
 }
 
 static void print_version(void) __attribute__((noreturn));
@@ -341,7 +361,6 @@ static u64 parse_profile(char *s)
                return 0;
        } else {
                fprintf(stderr, "Unknown profile %s\n", s);
-               print_usage();
        }
        /* not reached */
        return 0;
@@ -1144,23 +1163,23 @@ static void list_all_devices(struct btrfs_root *root)
        list_for_each_entry(device, &fs_devices->devices, dev_list)
                number_of_devices++;
 
-       printf("  Number of devices:\t%d\n", number_of_devices);
-       printf("    UUID                                  ID    SIZE    PATH\n");
-       printf("    ------------------------------------  --  --------- -----------\n");
+       printf("Number of devices:  %d\n", number_of_devices);
+       /* printf("Total devices size: %10s\n", */
+               /* pretty_size(total_block_count)); */
+       printf("Devices:\n");
+       printf("   ID        SIZE  PATH\n");
        list_for_each_entry_reverse(device, &fs_devices->devices, dev_list) {
                char dev_uuid[BTRFS_UUID_UNPARSED_SIZE];
 
                uuid_unparse(device->uuid, dev_uuid);
-               printf("    %s %3llu %10s %s\n",
-                       dev_uuid, device->devid,
+               printf("  %3llu  %10s  %s\n",
+                       device->devid,
                        pretty_size(device->total_bytes),
                        device->name);
                total_block_count += device->total_bytes;
        }
 
        printf("\n");
-       printf("  Total devices size: %10s\n",
-               pretty_size(total_block_count));
 }
 
 int main(int ac, char **av)
@@ -1175,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;
@@ -1190,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;
@@ -1198,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;
@@ -1222,6 +1242,7 @@ int main(int ac, char **av)
                        { "features", required_argument, NULL, 'O' },
                        { "uuid", required_argument, NULL, 'U' },
                        { "quiet", 0, NULL, 'q' },
+                       { "help", no_argument, NULL, GETOPT_VAL_HELP },
                        { NULL, 0, NULL, 0}
                };
 
@@ -1302,8 +1323,9 @@ int main(int ac, char **av)
                        case 'q':
                                verbose = 0;
                                break;
+                       case GETOPT_VAL_HELP:
                        default:
-                               print_usage();
+                               print_usage(c != GETOPT_VAL_HELP);
                }
        }
        sectorsize = max(sectorsize, (u32)sysconf(_SC_PAGESIZE));
@@ -1312,7 +1334,7 @@ int main(int ac, char **av)
        saved_optind = optind;
        dev_cnt = ac - optind;
        if (dev_cnt == 0)
-               print_usage();
+               print_usage(1);
 
        if (source_dir_set && dev_cnt > 1) {
                fprintf(stderr,
@@ -1336,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;
@@ -1427,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) {
@@ -1513,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);
@@ -1528,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;
@@ -1590,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);
@@ -1618,33 +1673,31 @@ raid_groups:
        if (verbose) {
                char features_buf[64];
 
-               printf("BTRFS filesystem summary:\n");
-               printf("  Label:\t\t%s\n", label);
-               printf("  UUID:\t\t\t%s\n", fs_uuid);
-               printf("\n");
-
-               printf("  Node size:\t\t%u\n", nodesize);
-               printf("  Sector size:\t\t%u\n", sectorsize);
-               printf("  Initial chunks:\n");
+               printf("Label:              %s\n", label);
+               printf("UUID:               %s\n", fs_uuid);
+               printf("Node size:          %u\n", nodesize);
+               printf("Sector size:        %u\n", sectorsize);
+               printf("Filesystem size:    %s\n",
+                       pretty_size(btrfs_super_total_bytes(root->fs_info->super_copy)));
+               printf("Block group profiles:\n");
                if (allocation.data)
-                       printf("    Data:\t\t%s\n",
+                       printf("  Data:             %-8s %16s\n",
+                               btrfs_group_profile_str(data_profile),
                                pretty_size(allocation.data));
                if (allocation.metadata)
-                       printf("    Metadata:\t\t%s\n",
+                       printf("  Metadata:         %-8s %16s\n",
+                               btrfs_group_profile_str(metadata_profile),
                                pretty_size(allocation.metadata));
                if (allocation.mixed)
-                       printf("    Data+Metadata:\t%s\n",
+                       printf("  Data+Metadata:    %-8s %16s\n",
+                               btrfs_group_profile_str(data_profile),
                                pretty_size(allocation.mixed));
-               printf("    System:\t\t%s\n",
+               printf("  System:           %-8s %16s\n",
+                       btrfs_group_profile_str(metadata_profile),
                        pretty_size(allocation.system));
-               printf("  Metadata profile:\t%s\n",
-                       btrfs_group_profile_str(metadata_profile));
-               printf("  Data profile:\t\t%s\n",
-                       btrfs_group_profile_str(data_profile));
-               printf("  Mixed mode:\t\t%s\n", mixed ? "YES" : "NO");
-               printf("  SSD detected:\t\t%s\n", ssd ? "YES" : "NO");
+               printf("SSD detected:       %s\n", ssd ? "yes" : "no");
                btrfs_parse_features_to_string(features_buf, features);
-               printf("  Incompat features:\t%s", features_buf);
+               printf("Incompat features:  %s", features_buf);
                printf("\n");
 
                list_all_devices(root);