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) { |
