Пример #1
0
int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
		     struct extent_buffer *eb)
{
	int ret;
	int dev_nr;
	u64 length;
	struct btrfs_multi_bio *multi = NULL;

	if (check_tree_block(root, eb))
		BUG();
	if (!btrfs_buffer_uptodate(eb, trans->transid))
		BUG();

	btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
	csum_tree_block(root, eb, 0);

	dev_nr = 0;
	length = eb->len;
	ret = btrfs_map_block(&root->fs_info->mapping_tree, WRITE,
			      eb->start, &length, &multi, 0);

	while(dev_nr < multi->num_stripes) {
		BUG_ON(ret);
		eb->fd = multi->stripes[dev_nr].dev->fd;
		eb->dev_bytenr = multi->stripes[dev_nr].physical;
		multi->stripes[dev_nr].dev->total_ios++;
		dev_nr++;
		ret = write_extent_to_disk(eb);
		BUG_ON(ret);
	}
	kfree(multi);
	return 0;
}
Пример #2
0
static int write_raid56_with_parity(struct btrfs_fs_info *info,
				    struct extent_buffer *eb,
				    struct btrfs_multi_bio *multi,
				    u64 stripe_len, u64 *raid_map)
{
	struct extent_buffer *ebs[multi->num_stripes], *p_eb = NULL, *q_eb = NULL;
	int i;
	int j;
	int ret;
	int alloc_size = eb->len;

	if (stripe_len > alloc_size)
		alloc_size = stripe_len;

	split_eb_for_raid56(info, eb, ebs, stripe_len, raid_map,
			    multi->num_stripes);

	for (i = 0; i < multi->num_stripes; i++) {
		struct extent_buffer *new_eb;
		if (raid_map[i] < BTRFS_RAID5_P_STRIPE) {
			ebs[i]->dev_bytenr = multi->stripes[i].physical;
			ebs[i]->fd = multi->stripes[i].dev->fd;
			multi->stripes[i].dev->total_ios++;
			BUG_ON(ebs[i]->start != raid_map[i]);
			continue;
		}
		new_eb = kmalloc(sizeof(*eb) + alloc_size, GFP_NOFS);
		BUG_ON(!new_eb);
		new_eb->dev_bytenr = multi->stripes[i].physical;
		new_eb->fd = multi->stripes[i].dev->fd;
		multi->stripes[i].dev->total_ios++;
		new_eb->len = stripe_len;

		if (raid_map[i] == BTRFS_RAID5_P_STRIPE)
			p_eb = new_eb;
		else if (raid_map[i] == BTRFS_RAID6_Q_STRIPE)
			q_eb = new_eb;
	}
	if (q_eb) {
		void *pointers[multi->num_stripes];
		ebs[multi->num_stripes - 2] = p_eb;
		ebs[multi->num_stripes - 1] = q_eb;

		for (i = 0; i < multi->num_stripes; i++)
			pointers[i] = ebs[i]->data;

		raid6_gen_syndrome(multi->num_stripes, stripe_len, pointers);
	} else {
		ebs[multi->num_stripes - 1] = p_eb;
		memcpy(p_eb->data, ebs[0]->data, stripe_len);
		for (j = 1; j < multi->num_stripes - 1; j++) {
			for (i = 0; i < stripe_len; i += sizeof(unsigned long)) {
				*(unsigned long *)(p_eb->data + i) ^=
					*(unsigned long *)(ebs[j]->data + i);
			}
		}
	}

	for (i = 0; i < multi->num_stripes; i++) {
		ret = write_extent_to_disk(ebs[i]);
		BUG_ON(ret);
		if (ebs[i] != eb)
			kfree(ebs[i]);
	}
	return 0;
}