diff options
Diffstat (limited to 'fs/btrfs/file-item.c')
-rw-r--r-- | fs/btrfs/file-item.c | 103 |
1 files changed, 70 insertions, 33 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index a67e1c828d0f..b5baf5bdc8e1 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "transaction.h" | 25 | #include "transaction.h" |
26 | #include "volumes.h" | 26 | #include "volumes.h" |
27 | #include "print-tree.h" | 27 | #include "print-tree.h" |
28 | #include "compression.h" | ||
28 | 29 | ||
29 | #define __MAX_CSUM_ITEMS(r, size) ((unsigned long)(((BTRFS_LEAF_DATA_SIZE(r) - \ | 30 | #define __MAX_CSUM_ITEMS(r, size) ((unsigned long)(((BTRFS_LEAF_DATA_SIZE(r) - \ |
30 | sizeof(struct btrfs_item) * 2) / \ | 31 | sizeof(struct btrfs_item) * 2) / \ |
@@ -172,6 +173,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, | |||
172 | u64 item_start_offset = 0; | 173 | u64 item_start_offset = 0; |
173 | u64 item_last_offset = 0; | 174 | u64 item_last_offset = 0; |
174 | u64 disk_bytenr; | 175 | u64 disk_bytenr; |
176 | u64 page_bytes_left; | ||
175 | u32 diff; | 177 | u32 diff; |
176 | int nblocks; | 178 | int nblocks; |
177 | int bio_index = 0; | 179 | int bio_index = 0; |
@@ -220,6 +222,8 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, | |||
220 | disk_bytenr = (u64)bio->bi_iter.bi_sector << 9; | 222 | disk_bytenr = (u64)bio->bi_iter.bi_sector << 9; |
221 | if (dio) | 223 | if (dio) |
222 | offset = logical_offset; | 224 | offset = logical_offset; |
225 | |||
226 | page_bytes_left = bvec->bv_len; | ||
223 | while (bio_index < bio->bi_vcnt) { | 227 | while (bio_index < bio->bi_vcnt) { |
224 | if (!dio) | 228 | if (!dio) |
225 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; | 229 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; |
@@ -243,7 +247,7 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, | |||
243 | if (BTRFS_I(inode)->root->root_key.objectid == | 247 | if (BTRFS_I(inode)->root->root_key.objectid == |
244 | BTRFS_DATA_RELOC_TREE_OBJECTID) { | 248 | BTRFS_DATA_RELOC_TREE_OBJECTID) { |
245 | set_extent_bits(io_tree, offset, | 249 | set_extent_bits(io_tree, offset, |
246 | offset + bvec->bv_len - 1, | 250 | offset + root->sectorsize - 1, |
247 | EXTENT_NODATASUM, GFP_NOFS); | 251 | EXTENT_NODATASUM, GFP_NOFS); |
248 | } else { | 252 | } else { |
249 | btrfs_info(BTRFS_I(inode)->root->fs_info, | 253 | btrfs_info(BTRFS_I(inode)->root->fs_info, |
@@ -281,13 +285,29 @@ static int __btrfs_lookup_bio_sums(struct btrfs_root *root, | |||
281 | found: | 285 | found: |
282 | csum += count * csum_size; | 286 | csum += count * csum_size; |
283 | nblocks -= count; | 287 | nblocks -= count; |
284 | bio_index += count; | 288 | |
285 | while (count--) { | 289 | while (count--) { |
286 | disk_bytenr += bvec->bv_len; | 290 | disk_bytenr += root->sectorsize; |
287 | offset += bvec->bv_len; | 291 | offset += root->sectorsize; |
288 | bvec++; | 292 | page_bytes_left -= root->sectorsize; |
293 | if (!page_bytes_left) { | ||
294 | bio_index++; | ||
295 | /* | ||
296 | * make sure we're still inside the | ||
297 | * bio before we update page_bytes_left | ||
298 | */ | ||
299 | if (bio_index >= bio->bi_vcnt) { | ||
300 | WARN_ON_ONCE(count); | ||
301 | goto done; | ||
302 | } | ||
303 | bvec++; | ||
304 | page_bytes_left = bvec->bv_len; | ||
305 | } | ||
306 | |||
289 | } | 307 | } |
290 | } | 308 | } |
309 | |||
310 | done: | ||
291 | btrfs_free_path(path); | 311 | btrfs_free_path(path); |
292 | return 0; | 312 | return 0; |
293 | } | 313 | } |
@@ -432,6 +452,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | |||
432 | struct bio_vec *bvec = bio->bi_io_vec; | 452 | struct bio_vec *bvec = bio->bi_io_vec; |
433 | int bio_index = 0; | 453 | int bio_index = 0; |
434 | int index; | 454 | int index; |
455 | int nr_sectors; | ||
456 | int i; | ||
435 | unsigned long total_bytes = 0; | 457 | unsigned long total_bytes = 0; |
436 | unsigned long this_sum_bytes = 0; | 458 | unsigned long this_sum_bytes = 0; |
437 | u64 offset; | 459 | u64 offset; |
@@ -459,41 +481,56 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | |||
459 | if (!contig) | 481 | if (!contig) |
460 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; | 482 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; |
461 | 483 | ||
462 | if (offset >= ordered->file_offset + ordered->len || | 484 | data = kmap_atomic(bvec->bv_page); |
463 | offset < ordered->file_offset) { | ||
464 | unsigned long bytes_left; | ||
465 | sums->len = this_sum_bytes; | ||
466 | this_sum_bytes = 0; | ||
467 | btrfs_add_ordered_sum(inode, ordered, sums); | ||
468 | btrfs_put_ordered_extent(ordered); | ||
469 | 485 | ||
470 | bytes_left = bio->bi_iter.bi_size - total_bytes; | 486 | nr_sectors = BTRFS_BYTES_TO_BLKS(root->fs_info, |
487 | bvec->bv_len + root->sectorsize | ||
488 | - 1); | ||
489 | |||
490 | for (i = 0; i < nr_sectors; i++) { | ||
491 | if (offset >= ordered->file_offset + ordered->len || | ||
492 | offset < ordered->file_offset) { | ||
493 | unsigned long bytes_left; | ||
494 | |||
495 | kunmap_atomic(data); | ||
496 | sums->len = this_sum_bytes; | ||
497 | this_sum_bytes = 0; | ||
498 | btrfs_add_ordered_sum(inode, ordered, sums); | ||
499 | btrfs_put_ordered_extent(ordered); | ||
500 | |||
501 | bytes_left = bio->bi_iter.bi_size - total_bytes; | ||
502 | |||
503 | sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left), | ||
504 | GFP_NOFS); | ||
505 | BUG_ON(!sums); /* -ENOMEM */ | ||
506 | sums->len = bytes_left; | ||
507 | ordered = btrfs_lookup_ordered_extent(inode, | ||
508 | offset); | ||
509 | ASSERT(ordered); /* Logic error */ | ||
510 | sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9) | ||
511 | + total_bytes; | ||
512 | index = 0; | ||
513 | |||
514 | data = kmap_atomic(bvec->bv_page); | ||
515 | } | ||
471 | 516 | ||
472 | sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left), | 517 | sums->sums[index] = ~(u32)0; |
473 | GFP_NOFS); | 518 | sums->sums[index] |
474 | BUG_ON(!sums); /* -ENOMEM */ | 519 | = btrfs_csum_data(data + bvec->bv_offset |
475 | sums->len = bytes_left; | 520 | + (i * root->sectorsize), |
476 | ordered = btrfs_lookup_ordered_extent(inode, offset); | 521 | sums->sums[index], |
477 | BUG_ON(!ordered); /* Logic error */ | 522 | root->sectorsize); |
478 | sums->bytenr = ((u64)bio->bi_iter.bi_sector << 9) + | 523 | btrfs_csum_final(sums->sums[index], |
479 | total_bytes; | 524 | (char *)(sums->sums + index)); |
480 | index = 0; | 525 | index++; |
526 | offset += root->sectorsize; | ||
527 | this_sum_bytes += root->sectorsize; | ||
528 | total_bytes += root->sectorsize; | ||
481 | } | 529 | } |
482 | 530 | ||
483 | data = kmap_atomic(bvec->bv_page); | ||
484 | sums->sums[index] = ~(u32)0; | ||
485 | sums->sums[index] = btrfs_csum_data(data + bvec->bv_offset, | ||
486 | sums->sums[index], | ||
487 | bvec->bv_len); | ||
488 | kunmap_atomic(data); | 531 | kunmap_atomic(data); |
489 | btrfs_csum_final(sums->sums[index], | ||
490 | (char *)(sums->sums + index)); | ||
491 | 532 | ||
492 | bio_index++; | 533 | bio_index++; |
493 | index++; | ||
494 | total_bytes += bvec->bv_len; | ||
495 | this_sum_bytes += bvec->bv_len; | ||
496 | offset += bvec->bv_len; | ||
497 | bvec++; | 534 | bvec++; |
498 | } | 535 | } |
499 | this_sum_bytes = 0; | 536 | this_sum_bytes = 0; |