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; }
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; }