diff options
Diffstat (limited to 'fs/btrfs/file-item.c')
-rw-r--r-- | fs/btrfs/file-item.c | 144 |
1 files changed, 55 insertions, 89 deletions
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index b193bf324a41..a7bfc9541803 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -34,8 +34,7 @@ | |||
34 | 34 | ||
35 | #define MAX_ORDERED_SUM_BYTES(r) ((PAGE_SIZE - \ | 35 | #define MAX_ORDERED_SUM_BYTES(r) ((PAGE_SIZE - \ |
36 | sizeof(struct btrfs_ordered_sum)) / \ | 36 | sizeof(struct btrfs_ordered_sum)) / \ |
37 | sizeof(struct btrfs_sector_sum) * \ | 37 | sizeof(u32) * (r)->sectorsize) |
38 | (r)->sectorsize - (r)->sectorsize) | ||
39 | 38 | ||
40 | int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, | 39 | int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, |
41 | struct btrfs_root *root, | 40 | struct btrfs_root *root, |
@@ -297,7 +296,6 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, | |||
297 | struct btrfs_path *path; | 296 | struct btrfs_path *path; |
298 | struct extent_buffer *leaf; | 297 | struct extent_buffer *leaf; |
299 | struct btrfs_ordered_sum *sums; | 298 | struct btrfs_ordered_sum *sums; |
300 | struct btrfs_sector_sum *sector_sum; | ||
301 | struct btrfs_csum_item *item; | 299 | struct btrfs_csum_item *item; |
302 | LIST_HEAD(tmplist); | 300 | LIST_HEAD(tmplist); |
303 | unsigned long offset; | 301 | unsigned long offset; |
@@ -368,34 +366,28 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, | |||
368 | struct btrfs_csum_item); | 366 | struct btrfs_csum_item); |
369 | while (start < csum_end) { | 367 | while (start < csum_end) { |
370 | size = min_t(size_t, csum_end - start, | 368 | size = min_t(size_t, csum_end - start, |
371 | MAX_ORDERED_SUM_BYTES(root)); | 369 | MAX_ORDERED_SUM_BYTES(root)); |
372 | sums = kzalloc(btrfs_ordered_sum_size(root, size), | 370 | sums = kzalloc(btrfs_ordered_sum_size(root, size), |
373 | GFP_NOFS); | 371 | GFP_NOFS); |
374 | if (!sums) { | 372 | if (!sums) { |
375 | ret = -ENOMEM; | 373 | ret = -ENOMEM; |
376 | goto fail; | 374 | goto fail; |
377 | } | 375 | } |
378 | 376 | ||
379 | sector_sum = sums->sums; | ||
380 | sums->bytenr = start; | 377 | sums->bytenr = start; |
381 | sums->len = size; | 378 | sums->len = (int)size; |
382 | 379 | ||
383 | offset = (start - key.offset) >> | 380 | offset = (start - key.offset) >> |
384 | root->fs_info->sb->s_blocksize_bits; | 381 | root->fs_info->sb->s_blocksize_bits; |
385 | offset *= csum_size; | 382 | offset *= csum_size; |
383 | size >>= root->fs_info->sb->s_blocksize_bits; | ||
386 | 384 | ||
387 | while (size > 0) { | 385 | read_extent_buffer(path->nodes[0], |
388 | read_extent_buffer(path->nodes[0], | 386 | sums->sums, |
389 | §or_sum->sum, | 387 | ((unsigned long)item) + offset, |
390 | ((unsigned long)item) + | 388 | csum_size * size); |
391 | offset, csum_size); | 389 | |
392 | sector_sum->bytenr = start; | 390 | start += root->sectorsize * size; |
393 | |||
394 | size -= root->sectorsize; | ||
395 | start += root->sectorsize; | ||
396 | offset += csum_size; | ||
397 | sector_sum++; | ||
398 | } | ||
399 | list_add_tail(&sums->list, &tmplist); | 391 | list_add_tail(&sums->list, &tmplist); |
400 | } | 392 | } |
401 | path->slots[0]++; | 393 | path->slots[0]++; |
@@ -417,23 +409,20 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | |||
417 | struct bio *bio, u64 file_start, int contig) | 409 | struct bio *bio, u64 file_start, int contig) |
418 | { | 410 | { |
419 | struct btrfs_ordered_sum *sums; | 411 | struct btrfs_ordered_sum *sums; |
420 | struct btrfs_sector_sum *sector_sum; | ||
421 | struct btrfs_ordered_extent *ordered; | 412 | struct btrfs_ordered_extent *ordered; |
422 | char *data; | 413 | char *data; |
423 | struct bio_vec *bvec = bio->bi_io_vec; | 414 | struct bio_vec *bvec = bio->bi_io_vec; |
424 | int bio_index = 0; | 415 | int bio_index = 0; |
416 | int index; | ||
425 | unsigned long total_bytes = 0; | 417 | unsigned long total_bytes = 0; |
426 | unsigned long this_sum_bytes = 0; | 418 | unsigned long this_sum_bytes = 0; |
427 | u64 offset; | 419 | u64 offset; |
428 | u64 disk_bytenr; | ||
429 | 420 | ||
430 | WARN_ON(bio->bi_vcnt <= 0); | 421 | WARN_ON(bio->bi_vcnt <= 0); |
431 | sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS); | 422 | sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS); |
432 | if (!sums) | 423 | if (!sums) |
433 | return -ENOMEM; | 424 | return -ENOMEM; |
434 | 425 | ||
435 | sector_sum = sums->sums; | ||
436 | disk_bytenr = (u64)bio->bi_sector << 9; | ||
437 | sums->len = bio->bi_size; | 426 | sums->len = bio->bi_size; |
438 | INIT_LIST_HEAD(&sums->list); | 427 | INIT_LIST_HEAD(&sums->list); |
439 | 428 | ||
@@ -444,7 +433,8 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | |||
444 | 433 | ||
445 | ordered = btrfs_lookup_ordered_extent(inode, offset); | 434 | ordered = btrfs_lookup_ordered_extent(inode, offset); |
446 | BUG_ON(!ordered); /* Logic error */ | 435 | BUG_ON(!ordered); /* Logic error */ |
447 | sums->bytenr = ordered->start; | 436 | sums->bytenr = (u64)bio->bi_sector << 9; |
437 | index = 0; | ||
448 | 438 | ||
449 | while (bio_index < bio->bi_vcnt) { | 439 | while (bio_index < bio->bi_vcnt) { |
450 | if (!contig) | 440 | if (!contig) |
@@ -463,28 +453,27 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | |||
463 | sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left), | 453 | sums = kzalloc(btrfs_ordered_sum_size(root, bytes_left), |
464 | GFP_NOFS); | 454 | GFP_NOFS); |
465 | BUG_ON(!sums); /* -ENOMEM */ | 455 | BUG_ON(!sums); /* -ENOMEM */ |
466 | sector_sum = sums->sums; | ||
467 | sums->len = bytes_left; | 456 | sums->len = bytes_left; |
468 | ordered = btrfs_lookup_ordered_extent(inode, offset); | 457 | ordered = btrfs_lookup_ordered_extent(inode, offset); |
469 | BUG_ON(!ordered); /* Logic error */ | 458 | BUG_ON(!ordered); /* Logic error */ |
470 | sums->bytenr = ordered->start; | 459 | sums->bytenr = ((u64)bio->bi_sector << 9) + |
460 | total_bytes; | ||
461 | index = 0; | ||
471 | } | 462 | } |
472 | 463 | ||
473 | data = kmap_atomic(bvec->bv_page); | 464 | data = kmap_atomic(bvec->bv_page); |
474 | sector_sum->sum = ~(u32)0; | 465 | sums->sums[index] = ~(u32)0; |
475 | sector_sum->sum = btrfs_csum_data(data + bvec->bv_offset, | 466 | sums->sums[index] = btrfs_csum_data(data + bvec->bv_offset, |
476 | sector_sum->sum, | 467 | sums->sums[index], |
477 | bvec->bv_len); | 468 | bvec->bv_len); |
478 | kunmap_atomic(data); | 469 | kunmap_atomic(data); |
479 | btrfs_csum_final(sector_sum->sum, | 470 | btrfs_csum_final(sums->sums[index], |
480 | (char *)§or_sum->sum); | 471 | (char *)(sums->sums + index)); |
481 | sector_sum->bytenr = disk_bytenr; | ||
482 | 472 | ||
483 | sector_sum++; | ||
484 | bio_index++; | 473 | bio_index++; |
474 | index++; | ||
485 | total_bytes += bvec->bv_len; | 475 | total_bytes += bvec->bv_len; |
486 | this_sum_bytes += bvec->bv_len; | 476 | this_sum_bytes += bvec->bv_len; |
487 | disk_bytenr += bvec->bv_len; | ||
488 | offset += bvec->bv_len; | 477 | offset += bvec->bv_len; |
489 | bvec++; | 478 | bvec++; |
490 | } | 479 | } |
@@ -672,62 +661,46 @@ out: | |||
672 | return ret; | 661 | return ret; |
673 | } | 662 | } |
674 | 663 | ||
675 | static u64 btrfs_sector_sum_left(struct btrfs_ordered_sum *sums, | ||
676 | struct btrfs_sector_sum *sector_sum, | ||
677 | u64 total_bytes, u64 sectorsize) | ||
678 | { | ||
679 | u64 tmp = sectorsize; | ||
680 | u64 next_sector = sector_sum->bytenr; | ||
681 | struct btrfs_sector_sum *next = sector_sum + 1; | ||
682 | |||
683 | while ((tmp + total_bytes) < sums->len) { | ||
684 | if (next_sector + sectorsize != next->bytenr) | ||
685 | break; | ||
686 | tmp += sectorsize; | ||
687 | next_sector = next->bytenr; | ||
688 | next++; | ||
689 | } | ||
690 | return tmp; | ||
691 | } | ||
692 | |||
693 | int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, | 664 | int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, |
694 | struct btrfs_root *root, | 665 | struct btrfs_root *root, |
695 | struct btrfs_ordered_sum *sums) | 666 | struct btrfs_ordered_sum *sums) |
696 | { | 667 | { |
697 | u64 bytenr; | ||
698 | int ret; | ||
699 | struct btrfs_key file_key; | 668 | struct btrfs_key file_key; |
700 | struct btrfs_key found_key; | 669 | struct btrfs_key found_key; |
701 | u64 next_offset; | ||
702 | u64 total_bytes = 0; | ||
703 | int found_next; | ||
704 | struct btrfs_path *path; | 670 | struct btrfs_path *path; |
705 | struct btrfs_csum_item *item; | 671 | struct btrfs_csum_item *item; |
706 | struct btrfs_csum_item *item_end; | 672 | struct btrfs_csum_item *item_end; |
707 | struct extent_buffer *leaf = NULL; | 673 | struct extent_buffer *leaf = NULL; |
674 | u64 next_offset; | ||
675 | u64 total_bytes = 0; | ||
708 | u64 csum_offset; | 676 | u64 csum_offset; |
709 | struct btrfs_sector_sum *sector_sum; | 677 | u64 bytenr; |
710 | u32 nritems; | 678 | u32 nritems; |
711 | u32 ins_size; | 679 | u32 ins_size; |
680 | int index = 0; | ||
681 | int found_next; | ||
682 | int ret; | ||
712 | u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); | 683 | u16 csum_size = btrfs_super_csum_size(root->fs_info->super_copy); |
713 | 684 | ||
714 | path = btrfs_alloc_path(); | 685 | path = btrfs_alloc_path(); |
715 | if (!path) | 686 | if (!path) |
716 | return -ENOMEM; | 687 | return -ENOMEM; |
717 | |||
718 | sector_sum = sums->sums; | ||
719 | again: | 688 | again: |
720 | next_offset = (u64)-1; | 689 | next_offset = (u64)-1; |
721 | found_next = 0; | 690 | found_next = 0; |
691 | bytenr = sums->bytenr + total_bytes; | ||
722 | file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; | 692 | file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; |
723 | file_key.offset = sector_sum->bytenr; | 693 | file_key.offset = bytenr; |
724 | bytenr = sector_sum->bytenr; | ||
725 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY); | 694 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY); |
726 | 695 | ||
727 | item = btrfs_lookup_csum(trans, root, path, sector_sum->bytenr, 1); | 696 | item = btrfs_lookup_csum(trans, root, path, bytenr, 1); |
728 | if (!IS_ERR(item)) { | 697 | if (!IS_ERR(item)) { |
729 | leaf = path->nodes[0]; | ||
730 | ret = 0; | 698 | ret = 0; |
699 | leaf = path->nodes[0]; | ||
700 | item_end = btrfs_item_ptr(leaf, path->slots[0], | ||
701 | struct btrfs_csum_item); | ||
702 | item_end = (struct btrfs_csum_item *)((char *)item_end + | ||
703 | btrfs_item_size_nr(leaf, path->slots[0])); | ||
731 | goto found; | 704 | goto found; |
732 | } | 705 | } |
733 | ret = PTR_ERR(item); | 706 | ret = PTR_ERR(item); |
@@ -807,8 +780,7 @@ again: | |||
807 | 780 | ||
808 | free_space = btrfs_leaf_free_space(root, leaf) - | 781 | free_space = btrfs_leaf_free_space(root, leaf) - |
809 | sizeof(struct btrfs_item) - csum_size; | 782 | sizeof(struct btrfs_item) - csum_size; |
810 | tmp = btrfs_sector_sum_left(sums, sector_sum, total_bytes, | 783 | tmp = sums->len - total_bytes; |
811 | root->sectorsize); | ||
812 | tmp >>= root->fs_info->sb->s_blocksize_bits; | 784 | tmp >>= root->fs_info->sb->s_blocksize_bits; |
813 | WARN_ON(tmp < 1); | 785 | WARN_ON(tmp < 1); |
814 | 786 | ||
@@ -822,6 +794,7 @@ again: | |||
822 | diff *= csum_size; | 794 | diff *= csum_size; |
823 | 795 | ||
824 | btrfs_extend_item(root, path, diff); | 796 | btrfs_extend_item(root, path, diff); |
797 | ret = 0; | ||
825 | goto csum; | 798 | goto csum; |
826 | } | 799 | } |
827 | 800 | ||
@@ -831,8 +804,7 @@ insert: | |||
831 | if (found_next) { | 804 | if (found_next) { |
832 | u64 tmp; | 805 | u64 tmp; |
833 | 806 | ||
834 | tmp = btrfs_sector_sum_left(sums, sector_sum, total_bytes, | 807 | tmp = sums->len - total_bytes; |
835 | root->sectorsize); | ||
836 | tmp >>= root->fs_info->sb->s_blocksize_bits; | 808 | tmp >>= root->fs_info->sb->s_blocksize_bits; |
837 | tmp = min(tmp, (next_offset - file_key.offset) >> | 809 | tmp = min(tmp, (next_offset - file_key.offset) >> |
838 | root->fs_info->sb->s_blocksize_bits); | 810 | root->fs_info->sb->s_blocksize_bits); |
@@ -853,31 +825,25 @@ insert: | |||
853 | WARN_ON(1); | 825 | WARN_ON(1); |
854 | goto fail_unlock; | 826 | goto fail_unlock; |
855 | } | 827 | } |
856 | csum: | ||
857 | leaf = path->nodes[0]; | 828 | leaf = path->nodes[0]; |
829 | csum: | ||
858 | item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); | 830 | item = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); |
859 | ret = 0; | 831 | item_end = (struct btrfs_csum_item *)((unsigned char *)item + |
832 | btrfs_item_size_nr(leaf, path->slots[0])); | ||
860 | item = (struct btrfs_csum_item *)((unsigned char *)item + | 833 | item = (struct btrfs_csum_item *)((unsigned char *)item + |
861 | csum_offset * csum_size); | 834 | csum_offset * csum_size); |
862 | found: | 835 | found: |
863 | item_end = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_csum_item); | 836 | ins_size = (u32)(sums->len - total_bytes) >> |
864 | item_end = (struct btrfs_csum_item *)((unsigned char *)item_end + | 837 | root->fs_info->sb->s_blocksize_bits; |
865 | btrfs_item_size_nr(leaf, path->slots[0])); | 838 | ins_size *= csum_size; |
866 | next_sector: | 839 | ins_size = min_t(u32, (unsigned long)item_end - (unsigned long)item, |
867 | 840 | ins_size); | |
868 | write_extent_buffer(leaf, §or_sum->sum, (unsigned long)item, csum_size); | 841 | write_extent_buffer(leaf, sums->sums + index, (unsigned long)item, |
869 | 842 | ins_size); | |
870 | total_bytes += root->sectorsize; | 843 | |
871 | sector_sum++; | 844 | ins_size /= csum_size; |
872 | if (total_bytes < sums->len) { | 845 | total_bytes += ins_size * root->sectorsize; |
873 | item = (struct btrfs_csum_item *)((char *)item + | 846 | index += ins_size; |
874 | csum_size); | ||
875 | if (item < item_end && bytenr + PAGE_CACHE_SIZE == | ||
876 | sector_sum->bytenr) { | ||
877 | bytenr = sector_sum->bytenr; | ||
878 | goto next_sector; | ||
879 | } | ||
880 | } | ||
881 | 847 | ||
882 | btrfs_mark_buffer_dirty(path->nodes[0]); | 848 | btrfs_mark_buffer_dirty(path->nodes[0]); |
883 | if (total_bytes < sums->len) { | 849 | if (total_bytes < sums->len) { |