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 metadata_profile_opt, int mixed, int ssd) { u64 num_devices = btrfs_super_num_devices(root->fs_info->super_copy); int ret; if (metadata_profile) { u64 meta_flags = BTRFS_BLOCK_GROUP_METADATA; ret = create_one_raid_group(trans, root, BTRFS_BLOCK_GROUP_SYSTEM | metadata_profile); BUG_ON(ret); if (mixed) meta_flags |= BTRFS_BLOCK_GROUP_DATA; ret = create_one_raid_group(trans, root, meta_flags | metadata_profile); BUG_ON(ret); } if (!mixed && num_devices > 1 && data_profile) { ret = create_one_raid_group(trans, root, BTRFS_BLOCK_GROUP_DATA | data_profile); BUG_ON(ret); } recow_roots(trans, root); return 0; }
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 metadata_profile_opt, int mixed, int ssd, int enospc_log) { u64 num_devices = btrfs_super_num_devices(root->fs_info->super_copy); u64 allowed = 0; u64 devices_for_raid = num_devices; int ret; root = root->fs_info->extent_root; /* * Set default profiles according to number of added devices. * For mixed groups defaults are single/single. */ if (!metadata_profile_opt && !mixed) { if (num_devices == 1 && ssd) printf("Detected a SSD, turning off metadata " "duplication. Mkfs with -m dup if you want to " "force metadata duplication.\n"); metadata_profile = (num_devices > 1) ? BTRFS_BLOCK_GROUP_RAID1 : (ssd) ? 0: BTRFS_BLOCK_GROUP_DUP; } if (!data_profile_opt && !mixed) { data_profile = (num_devices > 1) ? BTRFS_BLOCK_GROUP_RAID0 : 0; /* raid0 or single */ } if (devices_for_raid > 4) devices_for_raid = 4; switch (devices_for_raid) { default: case 4: allowed |= BTRFS_BLOCK_GROUP_RAID10; case 3: allowed |= BTRFS_BLOCK_GROUP_RAID6; case 2: allowed |= BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_RAID5; break; case 1: allowed |= BTRFS_BLOCK_GROUP_DUP; } if (metadata_profile & ~allowed) { fprintf(stderr, "unable to create FS with metadata " "profile %llu (have %llu devices)\n", metadata_profile, num_devices); exit(1); } if (data_profile & ~allowed) { fprintf(stderr, "unable to create FS with data " "profile %llu (have %llu devices)\n", data_profile, num_devices); exit(1); } /* allow dup'ed data chunks only in mixed mode */ if (!mixed && (data_profile & BTRFS_BLOCK_GROUP_DUP)) { fprintf(stderr, "dup for data is allowed only in mixed mode\n"); exit(1); } if (allowed & metadata_profile) { u64 meta_flags = BTRFS_BLOCK_GROUP_METADATA; ret = create_one_raid_group(trans, root, BTRFS_BLOCK_GROUP_SYSTEM | (allowed & metadata_profile)); BUG_ON(ret); if (mixed) meta_flags |= BTRFS_BLOCK_GROUP_DATA; ret = create_one_raid_group(trans, root, meta_flags | (allowed & metadata_profile)); BUG_ON(ret); ret = recow_roots(trans, root); BUG_ON(ret); } if (!mixed && enospc_log) { u64 total_bytes = btrfs_super_total_bytes(root->fs_info->super_copy); u64 alloced_bytes = 0; u64 alloc_flags = BTRFS_BLOCK_GROUP_ENOSPC | (allowed & metadata_profile); if (alloc_flags & (BTRFS_BLOCK_GROUP_RAID1 | BTRFS_BLOCK_GROUP_DUP)) { total_bytes >>= 1; } else if (alloc_flags & (BTRFS_BLOCK_GROUP_RAID10)) {