Exemple #1
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)
{
	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;
}
Exemple #2
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)) {