summaryrefslogtreecommitdiff
path: root/extent_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'extent_io.c')
-rw-r--r--extent_io.c87
1 files changed, 87 insertions, 0 deletions
diff --git a/extent_io.c b/extent_io.c
index 5093aeb2..592acd61 100644
--- a/extent_io.c
+++ b/extent_io.c
@@ -747,6 +747,93 @@ int read_data_from_disk(struct btrfs_fs_info *info, void *buf, u64 offset,
return 0;
}
+int write_data_to_disk(struct btrfs_fs_info *info, void *buf, u64 offset,
+ u64 bytes, int mirror)
+{
+ struct btrfs_multi_bio *multi = NULL;
+ struct btrfs_device *device;
+ u64 bytes_left = bytes;
+ u64 this_len;
+ u64 total_write = 0;
+ u64 *raid_map = NULL;
+ u64 dev_bytenr;
+ int dev_nr;
+ int ret = 0;
+
+ while (bytes_left > 0) {
+ this_len = bytes_left;
+ dev_nr = 0;
+
+ ret = btrfs_map_block(&info->mapping_tree, WRITE, offset,
+ &this_len, &multi, mirror, &raid_map);
+ if (ret) {
+ fprintf(stderr, "Couldn't map the block %Lu\n",
+ offset);
+ return -EIO;
+ }
+
+ if (raid_map) {
+ struct extent_buffer *eb;
+ u64 stripe_len = this_len;
+
+ this_len = min(this_len, bytes_left);
+ this_len = min(this_len, (u64)info->tree_root->leafsize);
+
+ eb = malloc(sizeof(struct extent_buffer) + this_len);
+ BUG_ON(!eb);
+
+ memset(eb, 0, sizeof(struct extent_buffer) + this_len);
+ eb->start = offset;
+ eb->len = this_len;
+
+ memcpy(eb->data, buf + total_write, this_len);
+ ret = write_raid56_with_parity(info, eb, multi,
+ stripe_len, raid_map);
+ BUG_ON(ret);
+
+ free(eb);
+ kfree(raid_map);
+ raid_map = NULL;
+ } else while (dev_nr < multi->num_stripes) {
+ device = multi->stripes[dev_nr].dev;
+ if (device->fd == 0) {
+ kfree(multi);
+ return -EIO;
+ }
+
+ dev_bytenr = multi->stripes[dev_nr].physical;
+ this_len = min(this_len, bytes_left);
+ dev_nr++;
+
+ ret = pwrite(device->fd, buf + total_write, this_len, dev_bytenr);
+ if (ret != this_len) {
+ if (ret < 0) {
+ fprintf(stderr, "Error writing to "
+ "device %d\n", errno);
+ ret = errno;
+ kfree(multi);
+ return ret;
+ } else {
+ fprintf(stderr, "Short write\n");
+ kfree(multi);
+ return -EIO;
+ }
+ }
+ }
+
+ BUG_ON(bytes_left < this_len);
+
+ bytes_left -= this_len;
+ offset += this_len;
+ total_write += this_len;
+
+ kfree(multi);
+ multi = NULL;
+ }
+ return 0;
+}
+
+
int set_extent_buffer_uptodate(struct extent_buffer *eb)
{
eb->flags |= EXTENT_UPTODATE;