diff options
| -rw-r--r-- | fs/btrfs/compression.c | 124 | ||||
| -rw-r--r-- | fs/btrfs/ctree.h | 30 | ||||
| -rw-r--r-- | fs/btrfs/disk-io.c | 45 | ||||
| -rw-r--r-- | fs/btrfs/extent_io.c | 5 | ||||
| -rw-r--r-- | fs/btrfs/file-item.c | 185 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 45 | ||||
| -rw-r--r-- | fs/btrfs/ioctl.c | 55 | ||||
| -rw-r--r-- | fs/btrfs/ordered-data.c | 7 | ||||
| -rw-r--r-- | fs/btrfs/ordered-data.h | 10 | ||||
| -rw-r--r-- | fs/btrfs/tree-log.c | 121 | ||||
| -rw-r--r-- | fs/btrfs/volumes.c | 1 |
11 files changed, 387 insertions, 241 deletions
diff --git a/fs/btrfs/compression.c b/fs/btrfs/compression.c index 4febe2eb0b8..ad727413730 100644 --- a/fs/btrfs/compression.c +++ b/fs/btrfs/compression.c | |||
| @@ -69,11 +69,27 @@ struct compressed_bio { | |||
| 69 | 69 | ||
| 70 | /* IO errors */ | 70 | /* IO errors */ |
| 71 | int errors; | 71 | int errors; |
| 72 | int mirror_num; | ||
| 72 | 73 | ||
| 73 | /* for reads, this is the bio we are copying the data into */ | 74 | /* for reads, this is the bio we are copying the data into */ |
| 74 | struct bio *orig_bio; | 75 | struct bio *orig_bio; |
| 76 | |||
| 77 | /* | ||
| 78 | * the start of a variable length array of checksums only | ||
| 79 | * used by reads | ||
| 80 | */ | ||
| 81 | u32 sums; | ||
| 75 | }; | 82 | }; |
| 76 | 83 | ||
| 84 | static inline int compressed_bio_size(struct btrfs_root *root, | ||
| 85 | unsigned long disk_size) | ||
| 86 | { | ||
| 87 | u16 csum_size = btrfs_super_csum_size(&root->fs_info->super_copy); | ||
| 88 | return sizeof(struct compressed_bio) + | ||
| 89 | ((disk_size + root->sectorsize - 1) / root->sectorsize) * | ||
| 90 | csum_size; | ||
| 91 | } | ||
| 92 | |||
| 77 | static struct bio *compressed_bio_alloc(struct block_device *bdev, | 93 | static struct bio *compressed_bio_alloc(struct block_device *bdev, |
| 78 | u64 first_byte, gfp_t gfp_flags) | 94 | u64 first_byte, gfp_t gfp_flags) |
| 79 | { | 95 | { |
| @@ -96,6 +112,47 @@ static struct bio *compressed_bio_alloc(struct block_device *bdev, | |||
| 96 | return bio; | 112 | return bio; |
| 97 | } | 113 | } |
| 98 | 114 | ||
| 115 | static int check_compressed_csum(struct inode *inode, | ||
| 116 | struct compressed_bio *cb, | ||
| 117 | u64 disk_start) | ||
| 118 | { | ||
| 119 | int ret; | ||
| 120 | struct btrfs_root *root = BTRFS_I(inode)->root; | ||
| 121 | struct page *page; | ||
| 122 | unsigned long i; | ||
| 123 | char *kaddr; | ||
| 124 | u32 csum; | ||
| 125 | u32 *cb_sum = &cb->sums; | ||
| 126 | |||
| 127 | if (btrfs_test_opt(root, NODATASUM) || | ||
| 128 | btrfs_test_flag(inode, NODATASUM)) | ||
| 129 | return 0; | ||
| 130 | |||
| 131 | for (i = 0; i < cb->nr_pages; i++) { | ||
| 132 | page = cb->compressed_pages[i]; | ||
| 133 | csum = ~(u32)0; | ||
| 134 | |||
| 135 | kaddr = kmap_atomic(page, KM_USER0); | ||
| 136 | csum = btrfs_csum_data(root, kaddr, csum, PAGE_CACHE_SIZE); | ||
| 137 | btrfs_csum_final(csum, (char *)&csum); | ||
| 138 | kunmap_atomic(kaddr, KM_USER0); | ||
| 139 | |||
| 140 | if (csum != *cb_sum) { | ||
| 141 | printk("btrfs csum failed ino %lu extent %llu csum %u " | ||
| 142 | "wanted %u mirror %d\n", inode->i_ino, | ||
| 143 | (unsigned long long)disk_start, | ||
| 144 | csum, *cb_sum, cb->mirror_num); | ||
| 145 | ret = -EIO; | ||
| 146 | goto fail; | ||
| 147 | } | ||
| 148 | cb_sum++; | ||
| 149 | |||
| 150 | } | ||
| 151 | ret = 0; | ||
| 152 | fail: | ||
| 153 | return ret; | ||
| 154 | } | ||
| 155 | |||
| 99 | /* when we finish reading compressed pages from the disk, we | 156 | /* when we finish reading compressed pages from the disk, we |
| 100 | * decompress them and then run the bio end_io routines on the | 157 | * decompress them and then run the bio end_io routines on the |
| 101 | * decompressed pages (in the inode address space). | 158 | * decompressed pages (in the inode address space). |
| @@ -124,16 +181,21 @@ static void end_compressed_bio_read(struct bio *bio, int err) | |||
| 124 | if (!atomic_dec_and_test(&cb->pending_bios)) | 181 | if (!atomic_dec_and_test(&cb->pending_bios)) |
| 125 | goto out; | 182 | goto out; |
| 126 | 183 | ||
| 184 | inode = cb->inode; | ||
| 185 | ret = check_compressed_csum(inode, cb, (u64)bio->bi_sector << 9); | ||
| 186 | if (ret) | ||
| 187 | goto csum_failed; | ||
| 188 | |||
| 127 | /* ok, we're the last bio for this extent, lets start | 189 | /* ok, we're the last bio for this extent, lets start |
| 128 | * the decompression. | 190 | * the decompression. |
| 129 | */ | 191 | */ |
| 130 | inode = cb->inode; | ||
| 131 | tree = &BTRFS_I(inode)->io_tree; | 192 | tree = &BTRFS_I(inode)->io_tree; |
| 132 | ret = btrfs_zlib_decompress_biovec(cb->compressed_pages, | 193 | ret = btrfs_zlib_decompress_biovec(cb->compressed_pages, |
| 133 | cb->start, | 194 | cb->start, |
| 134 | cb->orig_bio->bi_io_vec, | 195 | cb->orig_bio->bi_io_vec, |
| 135 | cb->orig_bio->bi_vcnt, | 196 | cb->orig_bio->bi_vcnt, |
| 136 | cb->compressed_len); | 197 | cb->compressed_len); |
| 198 | csum_failed: | ||
| 137 | if (ret) | 199 | if (ret) |
| 138 | cb->errors = 1; | 200 | cb->errors = 1; |
| 139 | 201 | ||
| @@ -148,8 +210,21 @@ static void end_compressed_bio_read(struct bio *bio, int err) | |||
| 148 | /* do io completion on the original bio */ | 210 | /* do io completion on the original bio */ |
| 149 | if (cb->errors) { | 211 | if (cb->errors) { |
| 150 | bio_io_error(cb->orig_bio); | 212 | bio_io_error(cb->orig_bio); |
| 151 | } else | 213 | } else { |
| 214 | int bio_index = 0; | ||
| 215 | struct bio_vec *bvec = cb->orig_bio->bi_io_vec; | ||
| 216 | |||
| 217 | /* | ||
| 218 | * we have verified the checksum already, set page | ||
| 219 | * checked so the end_io handlers know about it | ||
| 220 | */ | ||
| 221 | while(bio_index < cb->orig_bio->bi_vcnt) { | ||
| 222 | SetPageChecked(bvec->bv_page); | ||
| 223 | bvec++; | ||
| 224 | bio_index++; | ||
| 225 | } | ||
| 152 | bio_endio(cb->orig_bio, 0); | 226 | bio_endio(cb->orig_bio, 0); |
| 227 | } | ||
| 153 | 228 | ||
| 154 | /* finally free the cb struct */ | 229 | /* finally free the cb struct */ |
| 155 | kfree(cb->compressed_pages); | 230 | kfree(cb->compressed_pages); |
| @@ -277,12 +352,13 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, | |||
| 277 | int ret; | 352 | int ret; |
| 278 | 353 | ||
| 279 | WARN_ON(start & ((u64)PAGE_CACHE_SIZE - 1)); | 354 | WARN_ON(start & ((u64)PAGE_CACHE_SIZE - 1)); |
| 280 | cb = kmalloc(sizeof(*cb), GFP_NOFS); | 355 | cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS); |
| 281 | atomic_set(&cb->pending_bios, 0); | 356 | atomic_set(&cb->pending_bios, 0); |
| 282 | cb->errors = 0; | 357 | cb->errors = 0; |
| 283 | cb->inode = inode; | 358 | cb->inode = inode; |
| 284 | cb->start = start; | 359 | cb->start = start; |
| 285 | cb->len = len; | 360 | cb->len = len; |
| 361 | cb->mirror_num = 0; | ||
| 286 | cb->compressed_pages = compressed_pages; | 362 | cb->compressed_pages = compressed_pages; |
| 287 | cb->compressed_len = compressed_len; | 363 | cb->compressed_len = compressed_len; |
| 288 | cb->orig_bio = NULL; | 364 | cb->orig_bio = NULL; |
| @@ -290,9 +366,6 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, | |||
| 290 | 366 | ||
| 291 | bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; | 367 | bdev = BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev; |
| 292 | 368 | ||
| 293 | ret = btrfs_csum_file_bytes(root, inode, start, len); | ||
| 294 | BUG_ON(ret); | ||
| 295 | |||
| 296 | bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS); | 369 | bio = compressed_bio_alloc(bdev, first_byte, GFP_NOFS); |
| 297 | bio->bi_private = cb; | 370 | bio->bi_private = cb; |
| 298 | bio->bi_end_io = end_compressed_bio_write; | 371 | bio->bi_end_io = end_compressed_bio_write; |
| @@ -325,6 +398,9 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, | |||
| 325 | ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0); | 398 | ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0); |
| 326 | BUG_ON(ret); | 399 | BUG_ON(ret); |
| 327 | 400 | ||
| 401 | ret = btrfs_csum_one_bio(root, inode, bio, start, 1); | ||
| 402 | BUG_ON(ret); | ||
| 403 | |||
| 328 | ret = btrfs_map_bio(root, WRITE, bio, 0, 1); | 404 | ret = btrfs_map_bio(root, WRITE, bio, 0, 1); |
| 329 | BUG_ON(ret); | 405 | BUG_ON(ret); |
| 330 | 406 | ||
| @@ -348,6 +424,9 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start, | |||
| 348 | ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0); | 424 | ret = btrfs_bio_wq_end_io(root->fs_info, bio, 0); |
| 349 | BUG_ON(ret); | 425 | BUG_ON(ret); |
| 350 | 426 | ||
| 427 | ret = btrfs_csum_one_bio(root, inode, bio, start, 1); | ||
| 428 | BUG_ON(ret); | ||
| 429 | |||
| 351 | ret = btrfs_map_bio(root, WRITE, bio, 0, 1); | 430 | ret = btrfs_map_bio(root, WRITE, bio, 0, 1); |
| 352 | BUG_ON(ret); | 431 | BUG_ON(ret); |
| 353 | 432 | ||
| @@ -510,6 +589,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
| 510 | u64 em_start; | 589 | u64 em_start; |
| 511 | struct extent_map *em; | 590 | struct extent_map *em; |
| 512 | int ret; | 591 | int ret; |
| 592 | u32 *sums; | ||
| 513 | 593 | ||
| 514 | tree = &BTRFS_I(inode)->io_tree; | 594 | tree = &BTRFS_I(inode)->io_tree; |
| 515 | em_tree = &BTRFS_I(inode)->extent_tree; | 595 | em_tree = &BTRFS_I(inode)->extent_tree; |
| @@ -521,15 +601,18 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
| 521 | PAGE_CACHE_SIZE); | 601 | PAGE_CACHE_SIZE); |
| 522 | spin_unlock(&em_tree->lock); | 602 | spin_unlock(&em_tree->lock); |
| 523 | 603 | ||
| 524 | cb = kmalloc(sizeof(*cb), GFP_NOFS); | 604 | compressed_len = em->block_len; |
| 605 | cb = kmalloc(compressed_bio_size(root, compressed_len), GFP_NOFS); | ||
| 525 | atomic_set(&cb->pending_bios, 0); | 606 | atomic_set(&cb->pending_bios, 0); |
| 526 | cb->errors = 0; | 607 | cb->errors = 0; |
| 527 | cb->inode = inode; | 608 | cb->inode = inode; |
| 609 | cb->mirror_num = mirror_num; | ||
| 610 | sums = &cb->sums; | ||
| 528 | 611 | ||
| 529 | cb->start = em->orig_start; | 612 | cb->start = em->orig_start; |
| 530 | compressed_len = em->block_len; | ||
| 531 | em_len = em->len; | 613 | em_len = em->len; |
| 532 | em_start = em->start; | 614 | em_start = em->start; |
| 615 | |||
| 533 | free_extent_map(em); | 616 | free_extent_map(em); |
| 534 | em = NULL; | 617 | em = NULL; |
| 535 | 618 | ||
| @@ -551,11 +634,6 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
| 551 | 634 | ||
| 552 | add_ra_bio_pages(inode, em_start + em_len, cb); | 635 | add_ra_bio_pages(inode, em_start + em_len, cb); |
| 553 | 636 | ||
| 554 | if (!btrfs_test_opt(root, NODATASUM) && | ||
| 555 | !btrfs_test_flag(inode, NODATASUM)) { | ||
| 556 | btrfs_lookup_bio_sums(root, inode, cb->orig_bio); | ||
| 557 | } | ||
| 558 | |||
| 559 | /* include any pages we added in add_ra-bio_pages */ | 637 | /* include any pages we added in add_ra-bio_pages */ |
| 560 | uncompressed_len = bio->bi_vcnt * PAGE_CACHE_SIZE; | 638 | uncompressed_len = bio->bi_vcnt * PAGE_CACHE_SIZE; |
| 561 | cb->len = uncompressed_len; | 639 | cb->len = uncompressed_len; |
| @@ -568,6 +646,8 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
| 568 | for (page_index = 0; page_index < nr_pages; page_index++) { | 646 | for (page_index = 0; page_index < nr_pages; page_index++) { |
| 569 | page = cb->compressed_pages[page_index]; | 647 | page = cb->compressed_pages[page_index]; |
| 570 | page->mapping = inode->i_mapping; | 648 | page->mapping = inode->i_mapping; |
| 649 | page->index = em_start >> PAGE_CACHE_SHIFT; | ||
| 650 | |||
| 571 | if (comp_bio->bi_size) | 651 | if (comp_bio->bi_size) |
| 572 | ret = tree->ops->merge_bio_hook(page, 0, | 652 | ret = tree->ops->merge_bio_hook(page, 0, |
| 573 | PAGE_CACHE_SIZE, | 653 | PAGE_CACHE_SIZE, |
| @@ -591,7 +671,16 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
| 591 | */ | 671 | */ |
| 592 | atomic_inc(&cb->pending_bios); | 672 | atomic_inc(&cb->pending_bios); |
| 593 | 673 | ||
| 594 | ret = btrfs_map_bio(root, READ, comp_bio, 0, 0); | 674 | if (!btrfs_test_opt(root, NODATASUM) && |
| 675 | !btrfs_test_flag(inode, NODATASUM)) { | ||
| 676 | btrfs_lookup_bio_sums(root, inode, comp_bio, | ||
| 677 | sums); | ||
| 678 | } | ||
| 679 | sums += (comp_bio->bi_size + root->sectorsize - 1) / | ||
| 680 | root->sectorsize; | ||
| 681 | |||
| 682 | ret = btrfs_map_bio(root, READ, comp_bio, | ||
| 683 | mirror_num, 0); | ||
| 595 | BUG_ON(ret); | 684 | BUG_ON(ret); |
| 596 | 685 | ||
| 597 | bio_put(comp_bio); | 686 | bio_put(comp_bio); |
| @@ -610,7 +699,12 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio, | |||
| 610 | ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, 0); | 699 | ret = btrfs_bio_wq_end_io(root->fs_info, comp_bio, 0); |
| 611 | BUG_ON(ret); | 700 | BUG_ON(ret); |
| 612 | 701 | ||
| 613 | ret = btrfs_map_bio(root, READ, comp_bio, 0, 0); | 702 | if (!btrfs_test_opt(root, NODATASUM) && |
| 703 | !btrfs_test_flag(inode, NODATASUM)) { | ||
| 704 | btrfs_lookup_bio_sums(root, inode, comp_bio, sums); | ||
| 705 | } | ||
| 706 | |||
| 707 | ret = btrfs_map_bio(root, READ, comp_bio, mirror_num, 0); | ||
| 614 | BUG_ON(ret); | 708 | BUG_ON(ret); |
| 615 | 709 | ||
| 616 | bio_put(comp_bio); | 710 | bio_put(comp_bio); |
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h index 96f2ec7ad5b..242b961ae6d 100644 --- a/fs/btrfs/ctree.h +++ b/fs/btrfs/ctree.h | |||
| @@ -73,6 +73,9 @@ struct btrfs_ordered_sum; | |||
| 73 | /* directory objectid inside the root tree */ | 73 | /* directory objectid inside the root tree */ |
| 74 | #define BTRFS_ROOT_TREE_DIR_OBJECTID 6ULL | 74 | #define BTRFS_ROOT_TREE_DIR_OBJECTID 6ULL |
| 75 | 75 | ||
| 76 | /* holds checksums of all the data extents */ | ||
| 77 | #define BTRFS_CSUM_TREE_OBJECTID 7ULL | ||
| 78 | |||
| 76 | /* orhpan objectid for tracking unlinked/truncated files */ | 79 | /* orhpan objectid for tracking unlinked/truncated files */ |
| 77 | #define BTRFS_ORPHAN_OBJECTID -5ULL | 80 | #define BTRFS_ORPHAN_OBJECTID -5ULL |
| 78 | 81 | ||
| @@ -84,6 +87,13 @@ struct btrfs_ordered_sum; | |||
| 84 | #define BTRFS_TREE_RELOC_OBJECTID -8ULL | 87 | #define BTRFS_TREE_RELOC_OBJECTID -8ULL |
| 85 | #define BTRFS_DATA_RELOC_TREE_OBJECTID -9ULL | 88 | #define BTRFS_DATA_RELOC_TREE_OBJECTID -9ULL |
| 86 | 89 | ||
| 90 | /* | ||
| 91 | * extent checksums all have this objectid | ||
| 92 | * this allows them to share the logging tree | ||
| 93 | * for fsyncs | ||
| 94 | */ | ||
| 95 | #define BTRFS_EXTENT_CSUM_OBJECTID -10ULL | ||
| 96 | |||
| 87 | /* dummy objectid represents multiple objectids */ | 97 | /* dummy objectid represents multiple objectids */ |
| 88 | #define BTRFS_MULTIPLE_OBJECTIDS -255ULL | 98 | #define BTRFS_MULTIPLE_OBJECTIDS -255ULL |
| 89 | 99 | ||
| @@ -634,6 +644,7 @@ struct btrfs_fs_info { | |||
| 634 | struct btrfs_root *chunk_root; | 644 | struct btrfs_root *chunk_root; |
| 635 | struct btrfs_root *dev_root; | 645 | struct btrfs_root *dev_root; |
| 636 | struct btrfs_root *fs_root; | 646 | struct btrfs_root *fs_root; |
| 647 | struct btrfs_root *csum_root; | ||
| 637 | 648 | ||
| 638 | /* the log root tree is a directory of all the other log roots */ | 649 | /* the log root tree is a directory of all the other log roots */ |
| 639 | struct btrfs_root *log_root_tree; | 650 | struct btrfs_root *log_root_tree; |
| @@ -716,6 +727,7 @@ struct btrfs_fs_info { | |||
| 716 | struct btrfs_workers workers; | 727 | struct btrfs_workers workers; |
| 717 | struct btrfs_workers delalloc_workers; | 728 | struct btrfs_workers delalloc_workers; |
| 718 | struct btrfs_workers endio_workers; | 729 | struct btrfs_workers endio_workers; |
| 730 | struct btrfs_workers endio_meta_workers; | ||
| 719 | struct btrfs_workers endio_write_workers; | 731 | struct btrfs_workers endio_write_workers; |
| 720 | struct btrfs_workers submit_workers; | 732 | struct btrfs_workers submit_workers; |
| 721 | /* | 733 | /* |
| @@ -858,13 +870,12 @@ struct btrfs_root { | |||
| 858 | * extent data is for file data | 870 | * extent data is for file data |
| 859 | */ | 871 | */ |
| 860 | #define BTRFS_EXTENT_DATA_KEY 108 | 872 | #define BTRFS_EXTENT_DATA_KEY 108 |
| 873 | |||
| 861 | /* | 874 | /* |
| 862 | * csum items have the checksums for data in the extents | 875 | * extent csums are stored in a separate tree and hold csums for |
| 876 | * an entire extent on disk. | ||
| 863 | */ | 877 | */ |
| 864 | #define BTRFS_CSUM_ITEM_KEY 120 | 878 | #define BTRFS_EXTENT_CSUM_KEY 128 |
| 865 | |||
| 866 | |||
| 867 | /* reserve 21-31 for other file/dir stuff */ | ||
| 868 | 879 | ||
| 869 | /* | 880 | /* |
| 870 | * root items point to tree roots. There are typically in the root | 881 | * root items point to tree roots. There are typically in the root |
| @@ -1917,7 +1928,7 @@ int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root | |||
| 1917 | 1928 | ||
| 1918 | /* file-item.c */ | 1929 | /* file-item.c */ |
| 1919 | int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, | 1930 | int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, |
| 1920 | struct bio *bio); | 1931 | struct bio *bio, u32 *dst); |
| 1921 | int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, | 1932 | int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, |
| 1922 | struct btrfs_root *root, | 1933 | struct btrfs_root *root, |
| 1923 | u64 objectid, u64 pos, | 1934 | u64 objectid, u64 pos, |
| @@ -1929,17 +1940,16 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, | |||
| 1929 | struct btrfs_path *path, u64 objectid, | 1940 | struct btrfs_path *path, u64 objectid, |
| 1930 | u64 bytenr, int mod); | 1941 | u64 bytenr, int mod); |
| 1931 | int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, | 1942 | int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, |
| 1932 | struct btrfs_root *root, struct inode *inode, | 1943 | struct btrfs_root *root, |
| 1933 | struct btrfs_ordered_sum *sums); | 1944 | struct btrfs_ordered_sum *sums); |
| 1934 | int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | 1945 | int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, |
| 1935 | struct bio *bio); | 1946 | struct bio *bio, u64 file_start, int contig); |
| 1936 | int btrfs_csum_file_bytes(struct btrfs_root *root, struct inode *inode, | 1947 | int btrfs_csum_file_bytes(struct btrfs_root *root, struct inode *inode, |
| 1937 | u64 start, unsigned long len); | 1948 | u64 start, unsigned long len); |
| 1938 | struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, | 1949 | struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, |
| 1939 | struct btrfs_root *root, | 1950 | struct btrfs_root *root, |
| 1940 | struct btrfs_path *path, | 1951 | struct btrfs_path *path, |
| 1941 | u64 objectid, u64 offset, | 1952 | u64 bytenr, int cow); |
| 1942 | int cow); | ||
| 1943 | int btrfs_csum_truncate(struct btrfs_trans_handle *trans, | 1953 | int btrfs_csum_truncate(struct btrfs_trans_handle *trans, |
| 1944 | struct btrfs_root *root, struct btrfs_path *path, | 1954 | struct btrfs_root *root, struct btrfs_path *path, |
| 1945 | u64 isize); | 1955 | u64 isize); |
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 3eb7c2576fe..61dc3b2c834 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -445,11 +445,18 @@ static void end_workqueue_bio(struct bio *bio, int err) | |||
| 445 | end_io_wq->error = err; | 445 | end_io_wq->error = err; |
| 446 | end_io_wq->work.func = end_workqueue_fn; | 446 | end_io_wq->work.func = end_workqueue_fn; |
| 447 | end_io_wq->work.flags = 0; | 447 | end_io_wq->work.flags = 0; |
| 448 | if (bio->bi_rw & (1 << BIO_RW)) | 448 | |
| 449 | if (bio->bi_rw & (1 << BIO_RW)) { | ||
| 449 | btrfs_queue_worker(&fs_info->endio_write_workers, | 450 | btrfs_queue_worker(&fs_info->endio_write_workers, |
| 450 | &end_io_wq->work); | 451 | &end_io_wq->work); |
| 451 | else | 452 | } else { |
| 452 | btrfs_queue_worker(&fs_info->endio_workers, &end_io_wq->work); | 453 | if (end_io_wq->metadata) |
| 454 | btrfs_queue_worker(&fs_info->endio_meta_workers, | ||
| 455 | &end_io_wq->work); | ||
| 456 | else | ||
| 457 | btrfs_queue_worker(&fs_info->endio_workers, | ||
| 458 | &end_io_wq->work); | ||
| 459 | } | ||
| 453 | } | 460 | } |
| 454 | 461 | ||
| 455 | int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio, | 462 | int btrfs_bio_wq_end_io(struct btrfs_fs_info *info, struct bio *bio, |
| @@ -1208,6 +1215,9 @@ static void __unplug_io_fn(struct backing_dev_info *bdi, struct page *page) | |||
| 1208 | info = (struct btrfs_fs_info *)bdi->unplug_io_data; | 1215 | info = (struct btrfs_fs_info *)bdi->unplug_io_data; |
| 1209 | list_for_each(cur, &info->fs_devices->devices) { | 1216 | list_for_each(cur, &info->fs_devices->devices) { |
| 1210 | device = list_entry(cur, struct btrfs_device, dev_list); | 1217 | device = list_entry(cur, struct btrfs_device, dev_list); |
| 1218 | if (!device->bdev) | ||
| 1219 | continue; | ||
| 1220 | |||
| 1211 | bdi = blk_get_backing_dev_info(device->bdev); | 1221 | bdi = blk_get_backing_dev_info(device->bdev); |
| 1212 | if (bdi->unplug_io_fn) { | 1222 | if (bdi->unplug_io_fn) { |
| 1213 | bdi->unplug_io_fn(bdi, page); | 1223 | bdi->unplug_io_fn(bdi, page); |
| @@ -1344,7 +1354,7 @@ static void end_workqueue_fn(struct btrfs_work *work) | |||
| 1344 | * blocksize <= pagesize, it is basically a noop | 1354 | * blocksize <= pagesize, it is basically a noop |
| 1345 | */ | 1355 | */ |
| 1346 | if (end_io_wq->metadata && !bio_ready_for_csum(bio)) { | 1356 | if (end_io_wq->metadata && !bio_ready_for_csum(bio)) { |
| 1347 | btrfs_queue_worker(&fs_info->endio_workers, | 1357 | btrfs_queue_worker(&fs_info->endio_meta_workers, |
| 1348 | &end_io_wq->work); | 1358 | &end_io_wq->work); |
| 1349 | return; | 1359 | return; |
| 1350 | } | 1360 | } |
| @@ -1454,6 +1464,8 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1454 | struct buffer_head *bh; | 1464 | struct buffer_head *bh; |
| 1455 | struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root), | 1465 | struct btrfs_root *extent_root = kzalloc(sizeof(struct btrfs_root), |
| 1456 | GFP_NOFS); | 1466 | GFP_NOFS); |
| 1467 | struct btrfs_root *csum_root = kzalloc(sizeof(struct btrfs_root), | ||
| 1468 | GFP_NOFS); | ||
| 1457 | struct btrfs_root *tree_root = kzalloc(sizeof(struct btrfs_root), | 1469 | struct btrfs_root *tree_root = kzalloc(sizeof(struct btrfs_root), |
| 1458 | GFP_NOFS); | 1470 | GFP_NOFS); |
| 1459 | struct btrfs_fs_info *fs_info = kzalloc(sizeof(*fs_info), | 1471 | struct btrfs_fs_info *fs_info = kzalloc(sizeof(*fs_info), |
| @@ -1470,7 +1482,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1470 | struct btrfs_super_block *disk_super; | 1482 | struct btrfs_super_block *disk_super; |
| 1471 | 1483 | ||
| 1472 | if (!extent_root || !tree_root || !fs_info || | 1484 | if (!extent_root || !tree_root || !fs_info || |
| 1473 | !chunk_root || !dev_root) { | 1485 | !chunk_root || !dev_root || !csum_root) { |
| 1474 | err = -ENOMEM; | 1486 | err = -ENOMEM; |
| 1475 | goto fail; | 1487 | goto fail; |
| 1476 | } | 1488 | } |
| @@ -1487,6 +1499,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1487 | init_completion(&fs_info->kobj_unregister); | 1499 | init_completion(&fs_info->kobj_unregister); |
| 1488 | fs_info->tree_root = tree_root; | 1500 | fs_info->tree_root = tree_root; |
| 1489 | fs_info->extent_root = extent_root; | 1501 | fs_info->extent_root = extent_root; |
| 1502 | fs_info->csum_root = csum_root; | ||
| 1490 | fs_info->chunk_root = chunk_root; | 1503 | fs_info->chunk_root = chunk_root; |
| 1491 | fs_info->dev_root = dev_root; | 1504 | fs_info->dev_root = dev_root; |
| 1492 | fs_info->fs_devices = fs_devices; | 1505 | fs_info->fs_devices = fs_devices; |
| @@ -1652,6 +1665,8 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1652 | btrfs_init_workers(&fs_info->fixup_workers, "fixup", 1); | 1665 | btrfs_init_workers(&fs_info->fixup_workers, "fixup", 1); |
| 1653 | btrfs_init_workers(&fs_info->endio_workers, "endio", | 1666 | btrfs_init_workers(&fs_info->endio_workers, "endio", |
| 1654 | fs_info->thread_pool_size); | 1667 | fs_info->thread_pool_size); |
| 1668 | btrfs_init_workers(&fs_info->endio_meta_workers, "endio-meta", | ||
| 1669 | fs_info->thread_pool_size); | ||
| 1655 | btrfs_init_workers(&fs_info->endio_write_workers, "endio-write", | 1670 | btrfs_init_workers(&fs_info->endio_write_workers, "endio-write", |
| 1656 | fs_info->thread_pool_size); | 1671 | fs_info->thread_pool_size); |
| 1657 | 1672 | ||
| @@ -1667,6 +1682,8 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1667 | btrfs_start_workers(&fs_info->delalloc_workers, 1); | 1682 | btrfs_start_workers(&fs_info->delalloc_workers, 1); |
| 1668 | btrfs_start_workers(&fs_info->fixup_workers, 1); | 1683 | btrfs_start_workers(&fs_info->fixup_workers, 1); |
| 1669 | btrfs_start_workers(&fs_info->endio_workers, fs_info->thread_pool_size); | 1684 | btrfs_start_workers(&fs_info->endio_workers, fs_info->thread_pool_size); |
| 1685 | btrfs_start_workers(&fs_info->endio_meta_workers, | ||
| 1686 | fs_info->thread_pool_size); | ||
| 1670 | btrfs_start_workers(&fs_info->endio_write_workers, | 1687 | btrfs_start_workers(&fs_info->endio_write_workers, |
| 1671 | fs_info->thread_pool_size); | 1688 | fs_info->thread_pool_size); |
| 1672 | 1689 | ||
| @@ -1751,6 +1768,13 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1751 | if (ret) | 1768 | if (ret) |
| 1752 | goto fail_extent_root; | 1769 | goto fail_extent_root; |
| 1753 | 1770 | ||
| 1771 | ret = find_and_setup_root(tree_root, fs_info, | ||
| 1772 | BTRFS_CSUM_TREE_OBJECTID, csum_root); | ||
| 1773 | if (ret) | ||
| 1774 | goto fail_extent_root; | ||
| 1775 | |||
| 1776 | csum_root->track_dirty = 1; | ||
| 1777 | |||
| 1754 | btrfs_read_block_groups(extent_root); | 1778 | btrfs_read_block_groups(extent_root); |
| 1755 | 1779 | ||
| 1756 | fs_info->generation = generation + 1; | 1780 | fs_info->generation = generation + 1; |
| @@ -1761,7 +1785,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
| 1761 | fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root, | 1785 | fs_info->cleaner_kthread = kthread_run(cleaner_kthread, tree_root, |
| 1762 | "btrfs-cleaner"); | 1786 | "btrfs-cleaner"); |
| 1763 | if (!fs_info->cleaner_kthread) | 1787 | if (!fs_info->cleaner_kthread) |
| 1764 | goto fail_extent_root; | 1788 | goto fail_csum_root; |
| 1765 | 1789 | ||
| 1766 | fs_info->transaction_kthread = kthread_run(transaction_kthread, | 1790 | fs_info->transaction_kthread = kthread_run(transaction_kthread, |
| 1767 | tree_root, | 1791 | tree_root, |
| @@ -1825,6 +1849,8 @@ fail_cleaner: | |||
| 1825 | filemap_write_and_wait(fs_info->btree_inode->i_mapping); | 1849 | filemap_write_and_wait(fs_info->btree_inode->i_mapping); |
| 1826 | invalidate_inode_pages2(fs_info->btree_inode->i_mapping); | 1850 | invalidate_inode_pages2(fs_info->btree_inode->i_mapping); |
| 1827 | 1851 | ||
| 1852 | fail_csum_root: | ||
| 1853 | free_extent_buffer(csum_root->node); | ||
| 1828 | fail_extent_root: | 1854 | fail_extent_root: |
| 1829 | free_extent_buffer(extent_root->node); | 1855 | free_extent_buffer(extent_root->node); |
| 1830 | fail_tree_root: | 1856 | fail_tree_root: |
| @@ -1838,6 +1864,7 @@ fail_sb_buffer: | |||
| 1838 | btrfs_stop_workers(&fs_info->delalloc_workers); | 1864 | btrfs_stop_workers(&fs_info->delalloc_workers); |
| 1839 | btrfs_stop_workers(&fs_info->workers); | 1865 | btrfs_stop_workers(&fs_info->workers); |
| 1840 | btrfs_stop_workers(&fs_info->endio_workers); | 1866 | btrfs_stop_workers(&fs_info->endio_workers); |
| 1867 | btrfs_stop_workers(&fs_info->endio_meta_workers); | ||
| 1841 | btrfs_stop_workers(&fs_info->endio_write_workers); | 1868 | btrfs_stop_workers(&fs_info->endio_write_workers); |
| 1842 | btrfs_stop_workers(&fs_info->submit_workers); | 1869 | btrfs_stop_workers(&fs_info->submit_workers); |
| 1843 | fail_iput: | 1870 | fail_iput: |
| @@ -1853,6 +1880,7 @@ fail: | |||
| 1853 | kfree(fs_info); | 1880 | kfree(fs_info); |
| 1854 | kfree(chunk_root); | 1881 | kfree(chunk_root); |
| 1855 | kfree(dev_root); | 1882 | kfree(dev_root); |
| 1883 | kfree(csum_root); | ||
| 1856 | return ERR_PTR(err); | 1884 | return ERR_PTR(err); |
| 1857 | } | 1885 | } |
| 1858 | 1886 | ||
| @@ -2131,6 +2159,9 @@ int close_ctree(struct btrfs_root *root) | |||
| 2131 | if (root->fs_info->dev_root->node); | 2159 | if (root->fs_info->dev_root->node); |
| 2132 | free_extent_buffer(root->fs_info->dev_root->node); | 2160 | free_extent_buffer(root->fs_info->dev_root->node); |
| 2133 | 2161 | ||
| 2162 | if (root->fs_info->csum_root->node); | ||
| 2163 | free_extent_buffer(root->fs_info->csum_root->node); | ||
| 2164 | |||
| 2134 | btrfs_free_block_groups(root->fs_info); | 2165 | btrfs_free_block_groups(root->fs_info); |
| 2135 | 2166 | ||
| 2136 | del_fs_roots(fs_info); | 2167 | del_fs_roots(fs_info); |
| @@ -2141,6 +2172,7 @@ int close_ctree(struct btrfs_root *root) | |||
| 2141 | btrfs_stop_workers(&fs_info->delalloc_workers); | 2172 | btrfs_stop_workers(&fs_info->delalloc_workers); |
| 2142 | btrfs_stop_workers(&fs_info->workers); | 2173 | btrfs_stop_workers(&fs_info->workers); |
| 2143 | btrfs_stop_workers(&fs_info->endio_workers); | 2174 | btrfs_stop_workers(&fs_info->endio_workers); |
| 2175 | btrfs_stop_workers(&fs_info->endio_meta_workers); | ||
| 2144 | btrfs_stop_workers(&fs_info->endio_write_workers); | 2176 | btrfs_stop_workers(&fs_info->endio_write_workers); |
| 2145 | btrfs_stop_workers(&fs_info->submit_workers); | 2177 | btrfs_stop_workers(&fs_info->submit_workers); |
| 2146 | 2178 | ||
| @@ -2163,6 +2195,7 @@ int close_ctree(struct btrfs_root *root) | |||
| 2163 | kfree(fs_info->tree_root); | 2195 | kfree(fs_info->tree_root); |
| 2164 | kfree(fs_info->chunk_root); | 2196 | kfree(fs_info->chunk_root); |
| 2165 | kfree(fs_info->dev_root); | 2197 | kfree(fs_info->dev_root); |
| 2198 | kfree(fs_info->csum_root); | ||
| 2166 | return 0; | 2199 | return 0; |
| 2167 | } | 2200 | } |
| 2168 | 2201 | ||
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index c3dfe2a0ec8..7449ecf32c5 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c | |||
| @@ -1732,6 +1732,9 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
| 1732 | int whole_page; | 1732 | int whole_page; |
| 1733 | int ret; | 1733 | int ret; |
| 1734 | 1734 | ||
| 1735 | if (err) | ||
| 1736 | uptodate = 0; | ||
| 1737 | |||
| 1735 | do { | 1738 | do { |
| 1736 | struct page *page = bvec->bv_page; | 1739 | struct page *page = bvec->bv_page; |
| 1737 | tree = &BTRFS_I(page->mapping->host)->io_tree; | 1740 | tree = &BTRFS_I(page->mapping->host)->io_tree; |
| @@ -1761,6 +1764,8 @@ static void end_bio_extent_readpage(struct bio *bio, int err) | |||
| 1761 | if (ret == 0) { | 1764 | if (ret == 0) { |
| 1762 | uptodate = | 1765 | uptodate = |
| 1763 | test_bit(BIO_UPTODATE, &bio->bi_flags); | 1766 | test_bit(BIO_UPTODATE, &bio->bi_flags); |
| 1767 | if (err) | ||
| 1768 | uptodate = 0; | ||
| 1764 | continue; | 1769 | continue; |
| 1765 | } | 1770 | } |
| 1766 | } | 1771 | } |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index 234ed441736..a3ad2ce0011 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
| @@ -74,8 +74,7 @@ out: | |||
| 74 | struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, | 74 | struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, |
| 75 | struct btrfs_root *root, | 75 | struct btrfs_root *root, |
| 76 | struct btrfs_path *path, | 76 | struct btrfs_path *path, |
| 77 | u64 objectid, u64 offset, | 77 | u64 bytenr, int cow) |
| 78 | int cow) | ||
| 79 | { | 78 | { |
| 80 | int ret; | 79 | int ret; |
| 81 | struct btrfs_key file_key; | 80 | struct btrfs_key file_key; |
| @@ -87,9 +86,9 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, | |||
| 87 | btrfs_super_csum_size(&root->fs_info->super_copy); | 86 | btrfs_super_csum_size(&root->fs_info->super_copy); |
| 88 | int csums_in_item; | 87 | int csums_in_item; |
| 89 | 88 | ||
| 90 | file_key.objectid = objectid; | 89 | file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; |
| 91 | file_key.offset = offset; | 90 | file_key.offset = bytenr; |
| 92 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); | 91 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY); |
| 93 | ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow); | 92 | ret = btrfs_search_slot(trans, root, &file_key, path, 0, cow); |
| 94 | if (ret < 0) | 93 | if (ret < 0) |
| 95 | goto fail; | 94 | goto fail; |
| @@ -100,11 +99,10 @@ struct btrfs_csum_item *btrfs_lookup_csum(struct btrfs_trans_handle *trans, | |||
| 100 | goto fail; | 99 | goto fail; |
| 101 | path->slots[0]--; | 100 | path->slots[0]--; |
| 102 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | 101 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
| 103 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || | 102 | if (btrfs_key_type(&found_key) != BTRFS_EXTENT_CSUM_KEY) |
| 104 | found_key.objectid != objectid) { | ||
| 105 | goto fail; | 103 | goto fail; |
| 106 | } | 104 | |
| 107 | csum_offset = (offset - found_key.offset) >> | 105 | csum_offset = (bytenr - found_key.offset) >> |
| 108 | root->fs_info->sb->s_blocksize_bits; | 106 | root->fs_info->sb->s_blocksize_bits; |
| 109 | csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]); | 107 | csums_in_item = btrfs_item_size_nr(leaf, path->slots[0]); |
| 110 | csums_in_item /= csum_size; | 108 | csums_in_item /= csum_size; |
| @@ -143,7 +141,7 @@ int btrfs_lookup_file_extent(struct btrfs_trans_handle *trans, | |||
| 143 | } | 141 | } |
| 144 | 142 | ||
| 145 | int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, | 143 | int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, |
| 146 | struct bio *bio) | 144 | struct bio *bio, u32 *dst) |
| 147 | { | 145 | { |
| 148 | u32 sum; | 146 | u32 sum; |
| 149 | struct bio_vec *bvec = bio->bi_io_vec; | 147 | struct bio_vec *bvec = bio->bi_io_vec; |
| @@ -151,6 +149,7 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, | |||
| 151 | u64 offset; | 149 | u64 offset; |
| 152 | u64 item_start_offset = 0; | 150 | u64 item_start_offset = 0; |
| 153 | u64 item_last_offset = 0; | 151 | u64 item_last_offset = 0; |
| 152 | u64 disk_bytenr; | ||
| 154 | u32 diff; | 153 | u32 diff; |
| 155 | u16 csum_size = | 154 | u16 csum_size = |
| 156 | btrfs_super_csum_size(&root->fs_info->super_copy); | 155 | btrfs_super_csum_size(&root->fs_info->super_copy); |
| @@ -165,21 +164,22 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, | |||
| 165 | 164 | ||
| 166 | WARN_ON(bio->bi_vcnt <= 0); | 165 | WARN_ON(bio->bi_vcnt <= 0); |
| 167 | 166 | ||
| 167 | disk_bytenr = (u64)bio->bi_sector << 9; | ||
| 168 | while(bio_index < bio->bi_vcnt) { | 168 | while(bio_index < bio->bi_vcnt) { |
| 169 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; | 169 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; |
| 170 | ret = btrfs_find_ordered_sum(inode, offset, &sum); | 170 | ret = btrfs_find_ordered_sum(inode, offset, disk_bytenr, &sum); |
| 171 | if (ret == 0) | 171 | if (ret == 0) |
| 172 | goto found; | 172 | goto found; |
| 173 | 173 | ||
| 174 | if (!item || offset < item_start_offset || | 174 | if (!item || disk_bytenr < item_start_offset || |
| 175 | offset >= item_last_offset) { | 175 | disk_bytenr >= item_last_offset) { |
| 176 | struct btrfs_key found_key; | 176 | struct btrfs_key found_key; |
| 177 | u32 item_size; | 177 | u32 item_size; |
| 178 | 178 | ||
| 179 | if (item) | 179 | if (item) |
| 180 | btrfs_release_path(root, path); | 180 | btrfs_release_path(root, path); |
| 181 | item = btrfs_lookup_csum(NULL, root, path, | 181 | item = btrfs_lookup_csum(NULL, root->fs_info->csum_root, |
| 182 | inode->i_ino, offset, 0); | 182 | path, disk_bytenr, 0); |
| 183 | if (IS_ERR(item)) { | 183 | if (IS_ERR(item)) { |
| 184 | ret = PTR_ERR(item); | 184 | ret = PTR_ERR(item); |
| 185 | if (ret == -ENOENT || ret == -EFBIG) | 185 | if (ret == -ENOENT || ret == -EFBIG) |
| @@ -208,7 +208,7 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, | |||
| 208 | * this byte range must be able to fit inside | 208 | * this byte range must be able to fit inside |
| 209 | * a single leaf so it will also fit inside a u32 | 209 | * a single leaf so it will also fit inside a u32 |
| 210 | */ | 210 | */ |
| 211 | diff = offset - item_start_offset; | 211 | diff = disk_bytenr - item_start_offset; |
| 212 | diff = diff / root->sectorsize; | 212 | diff = diff / root->sectorsize; |
| 213 | diff = diff * csum_size; | 213 | diff = diff * csum_size; |
| 214 | 214 | ||
| @@ -216,7 +216,11 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode, | |||
| 216 | ((unsigned long)item) + diff, | 216 | ((unsigned long)item) + diff, |
| 217 | csum_size); | 217 | csum_size); |
| 218 | found: | 218 | found: |
| 219 | set_state_private(io_tree, offset, sum); | 219 | if (dst) |
| 220 | *dst++ = sum; | ||
| 221 | else | ||
| 222 | set_state_private(io_tree, offset, sum); | ||
| 223 | disk_bytenr += bvec->bv_len; | ||
| 220 | bio_index++; | 224 | bio_index++; |
| 221 | bvec++; | 225 | bvec++; |
| 222 | } | 226 | } |
| @@ -224,75 +228,8 @@ found: | |||
| 224 | return 0; | 228 | return 0; |
| 225 | } | 229 | } |
| 226 | 230 | ||
| 227 | int btrfs_csum_file_bytes(struct btrfs_root *root, struct inode *inode, | ||
| 228 | u64 start, unsigned long len) | ||
| 229 | { | ||
| 230 | struct btrfs_ordered_sum *sums; | ||
| 231 | struct btrfs_sector_sum *sector_sum; | ||
| 232 | struct btrfs_ordered_extent *ordered; | ||
| 233 | char *data; | ||
| 234 | struct page *page; | ||
| 235 | unsigned long total_bytes = 0; | ||
| 236 | unsigned long this_sum_bytes = 0; | ||
| 237 | |||
| 238 | sums = kzalloc(btrfs_ordered_sum_size(root, len), GFP_NOFS); | ||
| 239 | if (!sums) | ||
| 240 | return -ENOMEM; | ||
| 241 | |||
| 242 | sector_sum = sums->sums; | ||
| 243 | sums->file_offset = start; | ||
| 244 | sums->len = len; | ||
| 245 | INIT_LIST_HEAD(&sums->list); | ||
| 246 | ordered = btrfs_lookup_ordered_extent(inode, sums->file_offset); | ||
| 247 | BUG_ON(!ordered); | ||
| 248 | |||
| 249 | while(len > 0) { | ||
| 250 | if (start >= ordered->file_offset + ordered->len || | ||
| 251 | start < ordered->file_offset) { | ||
| 252 | sums->len = this_sum_bytes; | ||
| 253 | this_sum_bytes = 0; | ||
| 254 | btrfs_add_ordered_sum(inode, ordered, sums); | ||
| 255 | btrfs_put_ordered_extent(ordered); | ||
| 256 | |||
| 257 | sums = kzalloc(btrfs_ordered_sum_size(root, len), | ||
| 258 | GFP_NOFS); | ||
| 259 | BUG_ON(!sums); | ||
| 260 | sector_sum = sums->sums; | ||
| 261 | sums->len = len; | ||
| 262 | sums->file_offset = start; | ||
| 263 | ordered = btrfs_lookup_ordered_extent(inode, | ||
| 264 | sums->file_offset); | ||
| 265 | BUG_ON(!ordered); | ||
| 266 | } | ||
| 267 | |||
| 268 | page = find_get_page(inode->i_mapping, | ||
| 269 | start >> PAGE_CACHE_SHIFT); | ||
| 270 | |||
| 271 | data = kmap_atomic(page, KM_USER0); | ||
| 272 | sector_sum->sum = ~(u32)0; | ||
| 273 | sector_sum->sum = btrfs_csum_data(root, data, sector_sum->sum, | ||
| 274 | PAGE_CACHE_SIZE); | ||
| 275 | kunmap_atomic(data, KM_USER0); | ||
| 276 | btrfs_csum_final(sector_sum->sum, | ||
| 277 | (char *)§or_sum->sum); | ||
| 278 | sector_sum->offset = page_offset(page); | ||
| 279 | page_cache_release(page); | ||
| 280 | |||
| 281 | sector_sum++; | ||
| 282 | total_bytes += PAGE_CACHE_SIZE; | ||
| 283 | this_sum_bytes += PAGE_CACHE_SIZE; | ||
| 284 | start += PAGE_CACHE_SIZE; | ||
| 285 | |||
| 286 | WARN_ON(len < PAGE_CACHE_SIZE); | ||
| 287 | len -= PAGE_CACHE_SIZE; | ||
| 288 | } | ||
| 289 | btrfs_add_ordered_sum(inode, ordered, sums); | ||
| 290 | btrfs_put_ordered_extent(ordered); | ||
| 291 | return 0; | ||
| 292 | } | ||
| 293 | |||
| 294 | int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | 231 | int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, |
| 295 | struct bio *bio) | 232 | struct bio *bio, u64 file_start, int contig) |
| 296 | { | 233 | { |
| 297 | struct btrfs_ordered_sum *sums; | 234 | struct btrfs_ordered_sum *sums; |
| 298 | struct btrfs_sector_sum *sector_sum; | 235 | struct btrfs_sector_sum *sector_sum; |
| @@ -303,6 +240,7 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | |||
| 303 | unsigned long total_bytes = 0; | 240 | unsigned long total_bytes = 0; |
| 304 | unsigned long this_sum_bytes = 0; | 241 | unsigned long this_sum_bytes = 0; |
| 305 | u64 offset; | 242 | u64 offset; |
| 243 | u64 disk_bytenr; | ||
| 306 | 244 | ||
| 307 | WARN_ON(bio->bi_vcnt <= 0); | 245 | WARN_ON(bio->bi_vcnt <= 0); |
| 308 | sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS); | 246 | sums = kzalloc(btrfs_ordered_sum_size(root, bio->bi_size), GFP_NOFS); |
| @@ -310,16 +248,25 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | |||
| 310 | return -ENOMEM; | 248 | return -ENOMEM; |
| 311 | 249 | ||
| 312 | sector_sum = sums->sums; | 250 | sector_sum = sums->sums; |
| 313 | sums->file_offset = page_offset(bvec->bv_page) + bvec->bv_offset; | 251 | disk_bytenr = (u64)bio->bi_sector << 9; |
| 314 | sums->len = bio->bi_size; | 252 | sums->len = bio->bi_size; |
| 315 | INIT_LIST_HEAD(&sums->list); | 253 | INIT_LIST_HEAD(&sums->list); |
| 316 | ordered = btrfs_lookup_ordered_extent(inode, sums->file_offset); | 254 | |
| 255 | if (contig) | ||
| 256 | offset = file_start; | ||
| 257 | else | ||
| 258 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; | ||
| 259 | |||
| 260 | ordered = btrfs_lookup_ordered_extent(inode, offset); | ||
| 317 | BUG_ON(!ordered); | 261 | BUG_ON(!ordered); |
| 262 | sums->bytenr = ordered->start; | ||
| 318 | 263 | ||
| 319 | while(bio_index < bio->bi_vcnt) { | 264 | while(bio_index < bio->bi_vcnt) { |
| 320 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; | 265 | if (!contig) |
| 321 | if (offset >= ordered->file_offset + ordered->len || | 266 | offset = page_offset(bvec->bv_page) + bvec->bv_offset; |
| 322 | offset < ordered->file_offset) { | 267 | |
| 268 | if (!contig && (offset >= ordered->file_offset + ordered->len || | ||
| 269 | offset < ordered->file_offset)) { | ||
| 323 | unsigned long bytes_left; | 270 | unsigned long bytes_left; |
| 324 | sums->len = this_sum_bytes; | 271 | sums->len = this_sum_bytes; |
| 325 | this_sum_bytes = 0; | 272 | this_sum_bytes = 0; |
| @@ -333,10 +280,9 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | |||
| 333 | BUG_ON(!sums); | 280 | BUG_ON(!sums); |
| 334 | sector_sum = sums->sums; | 281 | sector_sum = sums->sums; |
| 335 | sums->len = bytes_left; | 282 | sums->len = bytes_left; |
| 336 | sums->file_offset = offset; | 283 | ordered = btrfs_lookup_ordered_extent(inode, offset); |
| 337 | ordered = btrfs_lookup_ordered_extent(inode, | ||
| 338 | sums->file_offset); | ||
| 339 | BUG_ON(!ordered); | 284 | BUG_ON(!ordered); |
| 285 | sums->bytenr = ordered->start; | ||
| 340 | } | 286 | } |
| 341 | 287 | ||
| 342 | data = kmap_atomic(bvec->bv_page, KM_USER0); | 288 | data = kmap_atomic(bvec->bv_page, KM_USER0); |
| @@ -348,13 +294,14 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | |||
| 348 | kunmap_atomic(data, KM_USER0); | 294 | kunmap_atomic(data, KM_USER0); |
| 349 | btrfs_csum_final(sector_sum->sum, | 295 | btrfs_csum_final(sector_sum->sum, |
| 350 | (char *)§or_sum->sum); | 296 | (char *)§or_sum->sum); |
| 351 | sector_sum->offset = page_offset(bvec->bv_page) + | 297 | sector_sum->bytenr = disk_bytenr; |
| 352 | bvec->bv_offset; | ||
| 353 | 298 | ||
| 354 | sector_sum++; | 299 | sector_sum++; |
| 355 | bio_index++; | 300 | bio_index++; |
| 356 | total_bytes += bvec->bv_len; | 301 | total_bytes += bvec->bv_len; |
| 357 | this_sum_bytes += bvec->bv_len; | 302 | this_sum_bytes += bvec->bv_len; |
| 303 | disk_bytenr += bvec->bv_len; | ||
| 304 | offset += bvec->bv_len; | ||
| 358 | bvec++; | 305 | bvec++; |
| 359 | } | 306 | } |
| 360 | this_sum_bytes = 0; | 307 | this_sum_bytes = 0; |
| @@ -364,11 +311,10 @@ int btrfs_csum_one_bio(struct btrfs_root *root, struct inode *inode, | |||
| 364 | } | 311 | } |
| 365 | 312 | ||
| 366 | int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, | 313 | int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, |
| 367 | struct btrfs_root *root, struct inode *inode, | 314 | struct btrfs_root *root, |
| 368 | struct btrfs_ordered_sum *sums) | 315 | struct btrfs_ordered_sum *sums) |
| 369 | { | 316 | { |
| 370 | u64 objectid = inode->i_ino; | 317 | u64 bytenr; |
| 371 | u64 offset; | ||
| 372 | int ret; | 318 | int ret; |
| 373 | struct btrfs_key file_key; | 319 | struct btrfs_key file_key; |
| 374 | struct btrfs_key found_key; | 320 | struct btrfs_key found_key; |
| @@ -396,13 +342,12 @@ int btrfs_csum_file_blocks(struct btrfs_trans_handle *trans, | |||
| 396 | again: | 342 | again: |
| 397 | next_offset = (u64)-1; | 343 | next_offset = (u64)-1; |
| 398 | found_next = 0; | 344 | found_next = 0; |
| 399 | offset = sector_sum->offset; | 345 | file_key.objectid = BTRFS_EXTENT_CSUM_OBJECTID; |
| 400 | file_key.objectid = objectid; | 346 | file_key.offset = sector_sum->bytenr; |
| 401 | file_key.offset = offset; | 347 | bytenr = sector_sum->bytenr; |
| 402 | btrfs_set_key_type(&file_key, BTRFS_CSUM_ITEM_KEY); | 348 | btrfs_set_key_type(&file_key, BTRFS_EXTENT_CSUM_KEY); |
| 403 | 349 | ||
| 404 | mutex_lock(&BTRFS_I(inode)->csum_mutex); | 350 | item = btrfs_lookup_csum(trans, root, path, sector_sum->bytenr, 1); |
| 405 | item = btrfs_lookup_csum(trans, root, path, objectid, offset, 1); | ||
| 406 | if (!IS_ERR(item)) { | 351 | if (!IS_ERR(item)) { |
| 407 | leaf = path->nodes[0]; | 352 | leaf = path->nodes[0]; |
| 408 | ret = 0; | 353 | ret = 0; |
| @@ -432,8 +377,8 @@ again: | |||
| 432 | slot = 0; | 377 | slot = 0; |
| 433 | } | 378 | } |
| 434 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot); | 379 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, slot); |
| 435 | if (found_key.objectid != objectid || | 380 | if (found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || |
| 436 | found_key.type != BTRFS_CSUM_ITEM_KEY) { | 381 | found_key.type != BTRFS_EXTENT_CSUM_KEY) { |
| 437 | found_next = 1; | 382 | found_next = 1; |
| 438 | goto insert; | 383 | goto insert; |
| 439 | } | 384 | } |
| @@ -460,10 +405,10 @@ again: | |||
| 460 | path->slots[0]--; | 405 | path->slots[0]--; |
| 461 | leaf = path->nodes[0]; | 406 | leaf = path->nodes[0]; |
| 462 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); | 407 | btrfs_item_key_to_cpu(leaf, &found_key, path->slots[0]); |
| 463 | csum_offset = (offset - found_key.offset) >> | 408 | csum_offset = (bytenr - found_key.offset) >> |
| 464 | root->fs_info->sb->s_blocksize_bits; | 409 | root->fs_info->sb->s_blocksize_bits; |
| 465 | if (btrfs_key_type(&found_key) != BTRFS_CSUM_ITEM_KEY || | 410 | if (btrfs_key_type(&found_key) != BTRFS_EXTENT_CSUM_KEY || |
| 466 | found_key.objectid != objectid || | 411 | found_key.objectid != BTRFS_EXTENT_CSUM_OBJECTID || |
| 467 | csum_offset >= MAX_CSUM_ITEMS(root, csum_size)) { | 412 | csum_offset >= MAX_CSUM_ITEMS(root, csum_size)) { |
| 468 | goto insert; | 413 | goto insert; |
| 469 | } | 414 | } |
| @@ -482,8 +427,18 @@ insert: | |||
| 482 | btrfs_release_path(root, path); | 427 | btrfs_release_path(root, path); |
| 483 | csum_offset = 0; | 428 | csum_offset = 0; |
| 484 | if (found_next) { | 429 | if (found_next) { |
| 485 | u64 tmp = min((u64)i_size_read(inode), next_offset); | 430 | u64 tmp = total_bytes + root->sectorsize; |
| 486 | tmp -= offset & ~((u64)root->sectorsize -1); | 431 | u64 next_sector = sector_sum->bytenr; |
| 432 | struct btrfs_sector_sum *next = sector_sum + 1; | ||
| 433 | |||
| 434 | while(tmp < sums->len) { | ||
| 435 | if (next_sector + root->sectorsize != next->bytenr) | ||
| 436 | break; | ||
| 437 | tmp += root->sectorsize; | ||
| 438 | next_sector = next->bytenr; | ||
| 439 | next++; | ||
| 440 | } | ||
| 441 | tmp = min(tmp, next_offset - file_key.offset); | ||
| 487 | tmp >>= root->fs_info->sb->s_blocksize_bits; | 442 | tmp >>= root->fs_info->sb->s_blocksize_bits; |
| 488 | tmp = max((u64)1, tmp); | 443 | tmp = max((u64)1, tmp); |
| 489 | tmp = min(tmp, (u64)MAX_CSUM_ITEMS(root, csum_size)); | 444 | tmp = min(tmp, (u64)MAX_CSUM_ITEMS(root, csum_size)); |
| @@ -510,7 +465,6 @@ found: | |||
| 510 | item_end = (struct btrfs_csum_item *)((unsigned char *)item_end + | 465 | item_end = (struct btrfs_csum_item *)((unsigned char *)item_end + |
| 511 | btrfs_item_size_nr(leaf, path->slots[0])); | 466 | btrfs_item_size_nr(leaf, path->slots[0])); |
| 512 | eb_token = NULL; | 467 | eb_token = NULL; |
| 513 | mutex_unlock(&BTRFS_I(inode)->csum_mutex); | ||
| 514 | cond_resched(); | 468 | cond_resched(); |
| 515 | next_sector: | 469 | next_sector: |
| 516 | 470 | ||
| @@ -541,9 +495,9 @@ next_sector: | |||
| 541 | if (total_bytes < sums->len) { | 495 | if (total_bytes < sums->len) { |
| 542 | item = (struct btrfs_csum_item *)((char *)item + | 496 | item = (struct btrfs_csum_item *)((char *)item + |
| 543 | csum_size); | 497 | csum_size); |
| 544 | if (item < item_end && offset + PAGE_CACHE_SIZE == | 498 | if (item < item_end && bytenr + PAGE_CACHE_SIZE == |
| 545 | sector_sum->offset) { | 499 | sector_sum->bytenr) { |
| 546 | offset = sector_sum->offset; | 500 | bytenr = sector_sum->bytenr; |
| 547 | goto next_sector; | 501 | goto next_sector; |
| 548 | } | 502 | } |
| 549 | } | 503 | } |
| @@ -562,7 +516,6 @@ out: | |||
| 562 | return ret; | 516 | return ret; |
| 563 | 517 | ||
| 564 | fail_unlock: | 518 | fail_unlock: |
| 565 | mutex_unlock(&BTRFS_I(inode)->csum_mutex); | ||
| 566 | goto out; | 519 | goto out; |
| 567 | } | 520 | } |
| 568 | 521 | ||
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 09efc9473a3..c03d847b8c4 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
| @@ -1221,7 +1221,7 @@ static int __btrfs_submit_bio_start(struct inode *inode, int rw, struct bio *bio | |||
| 1221 | struct btrfs_root *root = BTRFS_I(inode)->root; | 1221 | struct btrfs_root *root = BTRFS_I(inode)->root; |
| 1222 | int ret = 0; | 1222 | int ret = 0; |
| 1223 | 1223 | ||
| 1224 | ret = btrfs_csum_one_bio(root, inode, bio); | 1224 | ret = btrfs_csum_one_bio(root, inode, bio, 0, 0); |
| 1225 | BUG_ON(ret); | 1225 | BUG_ON(ret); |
| 1226 | return 0; | 1226 | return 0; |
| 1227 | } | 1227 | } |
| @@ -1259,12 +1259,11 @@ static int btrfs_submit_bio_hook(struct inode *inode, int rw, struct bio *bio, | |||
| 1259 | btrfs_test_flag(inode, NODATASUM); | 1259 | btrfs_test_flag(inode, NODATASUM); |
| 1260 | 1260 | ||
| 1261 | if (!(rw & (1 << BIO_RW))) { | 1261 | if (!(rw & (1 << BIO_RW))) { |
| 1262 | 1262 | if (bio_flags & EXTENT_BIO_COMPRESSED) { | |
| 1263 | if (bio_flags & EXTENT_BIO_COMPRESSED) | ||
| 1264 | return btrfs_submit_compressed_read(inode, bio, | 1263 | return btrfs_submit_compressed_read(inode, bio, |
| 1265 | mirror_num, bio_flags); | 1264 | mirror_num, bio_flags); |
| 1266 | else if (!skip_sum) | 1265 | } else if (!skip_sum) |
| 1267 | btrfs_lookup_bio_sums(root, inode, bio); | 1266 | btrfs_lookup_bio_sums(root, inode, bio, NULL); |
| 1268 | goto mapit; | 1267 | goto mapit; |
| 1269 | } else if (!skip_sum) { | 1268 | } else if (!skip_sum) { |
| 1270 | /* we're doing a write, do the async checksumming */ | 1269 | /* we're doing a write, do the async checksumming */ |
| @@ -1292,8 +1291,8 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans, | |||
| 1292 | btrfs_set_trans_block_group(trans, inode); | 1291 | btrfs_set_trans_block_group(trans, inode); |
| 1293 | list_for_each(cur, list) { | 1292 | list_for_each(cur, list) { |
| 1294 | sum = list_entry(cur, struct btrfs_ordered_sum, list); | 1293 | sum = list_entry(cur, struct btrfs_ordered_sum, list); |
| 1295 | btrfs_csum_file_blocks(trans, BTRFS_I(inode)->root, | 1294 | btrfs_csum_file_blocks(trans, |
| 1296 | inode, sum); | 1295 | BTRFS_I(inode)->root->fs_info->csum_root, sum); |
| 1297 | } | 1296 | } |
| 1298 | return 0; | 1297 | return 0; |
| 1299 | } | 1298 | } |
| @@ -1545,6 +1544,7 @@ struct io_failure_record { | |||
| 1545 | u64 start; | 1544 | u64 start; |
| 1546 | u64 len; | 1545 | u64 len; |
| 1547 | u64 logical; | 1546 | u64 logical; |
| 1547 | unsigned long bio_flags; | ||
| 1548 | int last_mirror; | 1548 | int last_mirror; |
| 1549 | }; | 1549 | }; |
| 1550 | 1550 | ||
| @@ -1563,7 +1563,6 @@ static int btrfs_io_failed_hook(struct bio *failed_bio, | |||
| 1563 | int ret; | 1563 | int ret; |
| 1564 | int rw; | 1564 | int rw; |
| 1565 | u64 logical; | 1565 | u64 logical; |
| 1566 | unsigned long bio_flags = 0; | ||
| 1567 | 1566 | ||
| 1568 | ret = get_state_private(failure_tree, start, &private); | 1567 | ret = get_state_private(failure_tree, start, &private); |
| 1569 | if (ret) { | 1568 | if (ret) { |
| @@ -1573,6 +1572,7 @@ static int btrfs_io_failed_hook(struct bio *failed_bio, | |||
| 1573 | failrec->start = start; | 1572 | failrec->start = start; |
| 1574 | failrec->len = end - start + 1; | 1573 | failrec->len = end - start + 1; |
| 1575 | failrec->last_mirror = 0; | 1574 | failrec->last_mirror = 0; |
| 1575 | failrec->bio_flags = 0; | ||
| 1576 | 1576 | ||
| 1577 | spin_lock(&em_tree->lock); | 1577 | spin_lock(&em_tree->lock); |
| 1578 | em = lookup_extent_mapping(em_tree, start, failrec->len); | 1578 | em = lookup_extent_mapping(em_tree, start, failrec->len); |
| @@ -1588,8 +1588,10 @@ static int btrfs_io_failed_hook(struct bio *failed_bio, | |||
| 1588 | } | 1588 | } |
| 1589 | logical = start - em->start; | 1589 | logical = start - em->start; |
| 1590 | logical = em->block_start + logical; | 1590 | logical = em->block_start + logical; |
| 1591 | if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) | 1591 | if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags)) { |
| 1592 | bio_flags = EXTENT_BIO_COMPRESSED; | 1592 | logical = em->block_start; |
| 1593 | failrec->bio_flags = EXTENT_BIO_COMPRESSED; | ||
| 1594 | } | ||
| 1593 | failrec->logical = logical; | 1595 | failrec->logical = logical; |
| 1594 | free_extent_map(em); | 1596 | free_extent_map(em); |
| 1595 | set_extent_bits(failure_tree, start, end, EXTENT_LOCKED | | 1597 | set_extent_bits(failure_tree, start, end, EXTENT_LOCKED | |
| @@ -1626,6 +1628,7 @@ static int btrfs_io_failed_hook(struct bio *failed_bio, | |||
| 1626 | bio->bi_sector = failrec->logical >> 9; | 1628 | bio->bi_sector = failrec->logical >> 9; |
| 1627 | bio->bi_bdev = failed_bio->bi_bdev; | 1629 | bio->bi_bdev = failed_bio->bi_bdev; |
| 1628 | bio->bi_size = 0; | 1630 | bio->bi_size = 0; |
| 1631 | |||
| 1629 | bio_add_page(bio, page, failrec->len, start - page_offset(page)); | 1632 | bio_add_page(bio, page, failrec->len, start - page_offset(page)); |
| 1630 | if (failed_bio->bi_rw & (1 << BIO_RW)) | 1633 | if (failed_bio->bi_rw & (1 << BIO_RW)) |
| 1631 | rw = WRITE; | 1634 | rw = WRITE; |
| @@ -1634,7 +1637,7 @@ static int btrfs_io_failed_hook(struct bio *failed_bio, | |||
| 1634 | 1637 | ||
| 1635 | BTRFS_I(inode)->io_tree.ops->submit_bio_hook(inode, rw, bio, | 1638 | BTRFS_I(inode)->io_tree.ops->submit_bio_hook(inode, rw, bio, |
| 1636 | failrec->last_mirror, | 1639 | failrec->last_mirror, |
| 1637 | bio_flags); | 1640 | failrec->bio_flags); |
| 1638 | return 0; | 1641 | return 0; |
| 1639 | } | 1642 | } |
| 1640 | 1643 | ||
| @@ -1688,9 +1691,14 @@ static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end, | |||
| 1688 | u32 csum = ~(u32)0; | 1691 | u32 csum = ~(u32)0; |
| 1689 | unsigned long flags; | 1692 | unsigned long flags; |
| 1690 | 1693 | ||
| 1694 | if (PageChecked(page)) { | ||
| 1695 | ClearPageChecked(page); | ||
| 1696 | goto good; | ||
| 1697 | } | ||
| 1691 | if (btrfs_test_opt(root, NODATASUM) || | 1698 | if (btrfs_test_opt(root, NODATASUM) || |
| 1692 | btrfs_test_flag(inode, NODATASUM)) | 1699 | btrfs_test_flag(inode, NODATASUM)) |
| 1693 | return 0; | 1700 | return 0; |
| 1701 | |||
| 1694 | if (state && state->start == start) { | 1702 | if (state && state->start == start) { |
| 1695 | private = state->private; | 1703 | private = state->private; |
| 1696 | ret = 0; | 1704 | ret = 0; |
| @@ -1709,7 +1717,7 @@ static int btrfs_readpage_end_io_hook(struct page *page, u64 start, u64 end, | |||
| 1709 | } | 1717 | } |
| 1710 | kunmap_atomic(kaddr, KM_IRQ0); | 1718 | kunmap_atomic(kaddr, KM_IRQ0); |
| 1711 | local_irq_restore(flags); | 1719 | local_irq_restore(flags); |
| 1712 | 1720 | good: | |
| 1713 | /* if the io failure tree for this inode is non-empty, | 1721 | /* if the io failure tree for this inode is non-empty, |
| 1714 | * check to see if we've recovered from a failed IO | 1722 | * check to see if we've recovered from a failed IO |
| 1715 | */ | 1723 | */ |
| @@ -2243,6 +2251,7 @@ fail: | |||
| 2243 | return err; | 2251 | return err; |
| 2244 | } | 2252 | } |
| 2245 | 2253 | ||
| 2254 | #if 0 | ||
| 2246 | /* | 2255 | /* |
| 2247 | * when truncating bytes in a file, it is possible to avoid reading | 2256 | * when truncating bytes in a file, it is possible to avoid reading |
| 2248 | * the leaves that contain only checksum items. This can be the | 2257 | * the leaves that contain only checksum items. This can be the |
| @@ -2410,6 +2419,8 @@ out: | |||
| 2410 | return ret; | 2419 | return ret; |
| 2411 | } | 2420 | } |
| 2412 | 2421 | ||
| 2422 | #endif | ||
| 2423 | |||
| 2413 | /* | 2424 | /* |
| 2414 | * this can truncate away extent items, csum items and directory items. | 2425 | * this can truncate away extent items, csum items and directory items. |
| 2415 | * It starts at a high offset and removes keys until it can't find | 2426 | * It starts at a high offset and removes keys until it can't find |
| @@ -2459,9 +2470,6 @@ noinline int btrfs_truncate_inode_items(struct btrfs_trans_handle *trans, | |||
| 2459 | 2470 | ||
| 2460 | btrfs_init_path(path); | 2471 | btrfs_init_path(path); |
| 2461 | 2472 | ||
| 2462 | ret = drop_csum_leaves(trans, root, path, inode, new_size); | ||
| 2463 | BUG_ON(ret); | ||
| 2464 | |||
| 2465 | search_again: | 2473 | search_again: |
| 2466 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); | 2474 | ret = btrfs_search_slot(trans, root, &key, path, -1, 1); |
| 2467 | if (ret < 0) { | 2475 | if (ret < 0) { |
| @@ -2509,16 +2517,11 @@ search_again: | |||
| 2509 | } | 2517 | } |
| 2510 | item_end--; | 2518 | item_end--; |
| 2511 | } | 2519 | } |
| 2512 | if (found_type == BTRFS_CSUM_ITEM_KEY) { | ||
| 2513 | ret = btrfs_csum_truncate(trans, root, path, | ||
| 2514 | new_size); | ||
| 2515 | BUG_ON(ret); | ||
| 2516 | } | ||
| 2517 | if (item_end < new_size) { | 2520 | if (item_end < new_size) { |
| 2518 | if (found_type == BTRFS_DIR_ITEM_KEY) { | 2521 | if (found_type == BTRFS_DIR_ITEM_KEY) { |
| 2519 | found_type = BTRFS_INODE_ITEM_KEY; | 2522 | found_type = BTRFS_INODE_ITEM_KEY; |
| 2520 | } else if (found_type == BTRFS_EXTENT_ITEM_KEY) { | 2523 | } else if (found_type == BTRFS_EXTENT_ITEM_KEY) { |
| 2521 | found_type = BTRFS_CSUM_ITEM_KEY; | 2524 | found_type = BTRFS_EXTENT_DATA_KEY; |
| 2522 | } else if (found_type == BTRFS_EXTENT_DATA_KEY) { | 2525 | } else if (found_type == BTRFS_EXTENT_DATA_KEY) { |
| 2523 | found_type = BTRFS_XATTR_ITEM_KEY; | 2526 | found_type = BTRFS_XATTR_ITEM_KEY; |
| 2524 | } else if (found_type == BTRFS_XATTR_ITEM_KEY) { | 2527 | } else if (found_type == BTRFS_XATTR_ITEM_KEY) { |
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c index b4da53d55c8..6228b69c2b9 100644 --- a/fs/btrfs/ioctl.c +++ b/fs/btrfs/ioctl.c | |||
| @@ -714,8 +714,7 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 714 | u64 len = olen; | 714 | u64 len = olen; |
| 715 | u64 bs = root->fs_info->sb->s_blocksize; | 715 | u64 bs = root->fs_info->sb->s_blocksize; |
| 716 | u64 hint_byte; | 716 | u64 hint_byte; |
| 717 | u16 csum_size = | 717 | |
| 718 | btrfs_super_csum_size(&root->fs_info->super_copy); | ||
| 719 | /* | 718 | /* |
| 720 | * TODO: | 719 | * TODO: |
| 721 | * - split compressed inline extents. annoying: we need to | 720 | * - split compressed inline extents. annoying: we need to |
| @@ -833,7 +832,7 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 833 | slot = path->slots[0]; | 832 | slot = path->slots[0]; |
| 834 | 833 | ||
| 835 | btrfs_item_key_to_cpu(leaf, &key, slot); | 834 | btrfs_item_key_to_cpu(leaf, &key, slot); |
| 836 | if (btrfs_key_type(&key) > BTRFS_CSUM_ITEM_KEY || | 835 | if (btrfs_key_type(&key) > BTRFS_EXTENT_DATA_KEY || |
| 837 | key.objectid != src->i_ino) | 836 | key.objectid != src->i_ino) |
| 838 | break; | 837 | break; |
| 839 | 838 | ||
| @@ -958,56 +957,6 @@ static long btrfs_ioctl_clone(struct file *file, unsigned long srcfd, | |||
| 958 | btrfs_mark_buffer_dirty(leaf); | 957 | btrfs_mark_buffer_dirty(leaf); |
| 959 | } | 958 | } |
| 960 | 959 | ||
| 961 | if (btrfs_key_type(&key) == BTRFS_CSUM_ITEM_KEY) { | ||
| 962 | u32 size; | ||
| 963 | struct btrfs_key new_key; | ||
| 964 | u64 coverslen; | ||
| 965 | int coff, clen; | ||
| 966 | |||
| 967 | size = btrfs_item_size_nr(leaf, slot); | ||
| 968 | coverslen = (size / csum_size) << | ||
| 969 | root->fs_info->sb->s_blocksize_bits; | ||
| 970 | printk("csums for %llu~%llu\n", | ||
| 971 | key.offset, coverslen); | ||
| 972 | if (key.offset + coverslen < off || | ||
| 973 | key.offset >= off+len) | ||
| 974 | goto next; | ||
| 975 | |||
| 976 | read_extent_buffer(leaf, buf, | ||
| 977 | btrfs_item_ptr_offset(leaf, slot), | ||
| 978 | size); | ||
| 979 | btrfs_release_path(root, path); | ||
| 980 | |||
| 981 | coff = 0; | ||
| 982 | if (off > key.offset) | ||
| 983 | coff = ((off - key.offset) >> | ||
| 984 | root->fs_info->sb->s_blocksize_bits) * | ||
| 985 | csum_size; | ||
| 986 | clen = size - coff; | ||
| 987 | if (key.offset + coverslen > off+len) | ||
| 988 | clen -= ((key.offset+coverslen-off-len) >> | ||
| 989 | root->fs_info->sb->s_blocksize_bits) * | ||
| 990 | csum_size; | ||
| 991 | printk(" will dup %d~%d of %d\n", | ||
| 992 | coff, clen, size); | ||
| 993 | |||
| 994 | memcpy(&new_key, &key, sizeof(new_key)); | ||
| 995 | new_key.objectid = inode->i_ino; | ||
| 996 | new_key.offset = key.offset + destoff - off; | ||
| 997 | |||
| 998 | ret = btrfs_insert_empty_item(trans, root, path, | ||
| 999 | &new_key, clen); | ||
| 1000 | if (ret) | ||
| 1001 | goto out; | ||
| 1002 | |||
| 1003 | leaf = path->nodes[0]; | ||
| 1004 | slot = path->slots[0]; | ||
| 1005 | write_extent_buffer(leaf, buf + coff, | ||
| 1006 | btrfs_item_ptr_offset(leaf, slot), | ||
| 1007 | clen); | ||
| 1008 | btrfs_mark_buffer_dirty(leaf); | ||
| 1009 | } | ||
| 1010 | |||
| 1011 | next: | 960 | next: |
| 1012 | btrfs_release_path(root, path); | 961 | btrfs_release_path(root, path); |
| 1013 | key.offset++; | 962 | key.offset++; |
diff --git a/fs/btrfs/ordered-data.c b/fs/btrfs/ordered-data.c index 027ad6b3839..d9e232227da 100644 --- a/fs/btrfs/ordered-data.c +++ b/fs/btrfs/ordered-data.c | |||
| @@ -610,7 +610,8 @@ out: | |||
| 610 | * try to find a checksum. This is used because we allow pages to | 610 | * try to find a checksum. This is used because we allow pages to |
| 611 | * be reclaimed before their checksum is actually put into the btree | 611 | * be reclaimed before their checksum is actually put into the btree |
| 612 | */ | 612 | */ |
| 613 | int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u32 *sum) | 613 | int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, |
| 614 | u32 *sum) | ||
| 614 | { | 615 | { |
| 615 | struct btrfs_ordered_sum *ordered_sum; | 616 | struct btrfs_ordered_sum *ordered_sum; |
| 616 | struct btrfs_sector_sum *sector_sums; | 617 | struct btrfs_sector_sum *sector_sums; |
| @@ -629,11 +630,11 @@ int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u32 *sum) | |||
| 629 | mutex_lock(&tree->mutex); | 630 | mutex_lock(&tree->mutex); |
| 630 | list_for_each_prev(cur, &ordered->list) { | 631 | list_for_each_prev(cur, &ordered->list) { |
| 631 | ordered_sum = list_entry(cur, struct btrfs_ordered_sum, list); | 632 | ordered_sum = list_entry(cur, struct btrfs_ordered_sum, list); |
| 632 | if (offset >= ordered_sum->file_offset) { | 633 | if (disk_bytenr >= ordered_sum->bytenr) { |
| 633 | num_sectors = ordered_sum->len / sectorsize; | 634 | num_sectors = ordered_sum->len / sectorsize; |
| 634 | sector_sums = ordered_sum->sums; | 635 | sector_sums = ordered_sum->sums; |
| 635 | for (i = 0; i < num_sectors; i++) { | 636 | for (i = 0; i < num_sectors; i++) { |
| 636 | if (sector_sums[i].offset == offset) { | 637 | if (sector_sums[i].bytenr == disk_bytenr) { |
| 637 | *sum = sector_sums[i].sum; | 638 | *sum = sector_sums[i].sum; |
| 638 | ret = 0; | 639 | ret = 0; |
| 639 | goto out; | 640 | goto out; |
diff --git a/fs/btrfs/ordered-data.h b/fs/btrfs/ordered-data.h index 260bf95dfe0..ab66d5e8d6d 100644 --- a/fs/btrfs/ordered-data.h +++ b/fs/btrfs/ordered-data.h | |||
| @@ -33,15 +33,17 @@ struct btrfs_ordered_inode_tree { | |||
| 33 | * the ordered extent are on disk | 33 | * the ordered extent are on disk |
| 34 | */ | 34 | */ |
| 35 | struct btrfs_sector_sum { | 35 | struct btrfs_sector_sum { |
| 36 | u64 offset; | 36 | /* bytenr on disk */ |
| 37 | u64 bytenr; | ||
| 37 | u32 sum; | 38 | u32 sum; |
| 38 | }; | 39 | }; |
| 39 | 40 | ||
| 40 | struct btrfs_ordered_sum { | 41 | struct btrfs_ordered_sum { |
| 41 | u64 file_offset; | 42 | /* bytenr is the start of this extent on disk */ |
| 43 | u64 bytenr; | ||
| 44 | |||
| 42 | /* | 45 | /* |
| 43 | * this is the length in bytes covered by the sums array below. | 46 | * this is the length in bytes covered by the sums array below. |
| 44 | * But, the sums array may not be contiguous in the file. | ||
| 45 | */ | 47 | */ |
| 46 | unsigned long len; | 48 | unsigned long len; |
| 47 | struct list_head list; | 49 | struct list_head list; |
| @@ -147,7 +149,7 @@ struct btrfs_ordered_extent * | |||
| 147 | btrfs_lookup_first_ordered_extent(struct inode * inode, u64 file_offset); | 149 | btrfs_lookup_first_ordered_extent(struct inode * inode, u64 file_offset); |
| 148 | int btrfs_ordered_update_i_size(struct inode *inode, | 150 | int btrfs_ordered_update_i_size(struct inode *inode, |
| 149 | struct btrfs_ordered_extent *ordered); | 151 | struct btrfs_ordered_extent *ordered); |
| 150 | int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u32 *sum); | 152 | int btrfs_find_ordered_sum(struct inode *inode, u64 offset, u64 disk_bytenr, u32 *sum); |
| 151 | int btrfs_wait_on_page_writeback_range(struct address_space *mapping, | 153 | int btrfs_wait_on_page_writeback_range(struct address_space *mapping, |
| 152 | pgoff_t start, pgoff_t end); | 154 | pgoff_t start, pgoff_t end); |
| 153 | int btrfs_fdatawrite_range(struct address_space *mapping, loff_t start, | 155 | int btrfs_fdatawrite_range(struct address_space *mapping, loff_t start, |
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index c766649ad45..08469ec0585 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
| @@ -934,24 +934,17 @@ static noinline int replay_one_csum(struct btrfs_trans_handle *trans, | |||
| 934 | unsigned long file_bytes; | 934 | unsigned long file_bytes; |
| 935 | struct btrfs_ordered_sum *sums; | 935 | struct btrfs_ordered_sum *sums; |
| 936 | struct btrfs_sector_sum *sector_sum; | 936 | struct btrfs_sector_sum *sector_sum; |
| 937 | struct inode *inode; | ||
| 938 | unsigned long ptr; | 937 | unsigned long ptr; |
| 939 | 938 | ||
| 940 | file_bytes = (item_size / csum_size) * root->sectorsize; | 939 | file_bytes = (item_size / csum_size) * root->sectorsize; |
| 941 | inode = read_one_inode(root, key->objectid); | ||
| 942 | if (!inode) { | ||
| 943 | return -EIO; | ||
| 944 | } | ||
| 945 | |||
| 946 | sums = kzalloc(btrfs_ordered_sum_size(root, file_bytes), GFP_NOFS); | 940 | sums = kzalloc(btrfs_ordered_sum_size(root, file_bytes), GFP_NOFS); |
| 947 | if (!sums) { | 941 | if (!sums) { |
| 948 | iput(inode); | ||
| 949 | return -ENOMEM; | 942 | return -ENOMEM; |
| 950 | } | 943 | } |
| 951 | 944 | ||
| 952 | INIT_LIST_HEAD(&sums->list); | 945 | INIT_LIST_HEAD(&sums->list); |
| 953 | sums->len = file_bytes; | 946 | sums->len = file_bytes; |
| 954 | sums->file_offset = key->offset; | 947 | sums->bytenr = key->offset; |
| 955 | 948 | ||
| 956 | /* | 949 | /* |
| 957 | * copy all the sums into the ordered sum struct | 950 | * copy all the sums into the ordered sum struct |
| @@ -960,7 +953,7 @@ static noinline int replay_one_csum(struct btrfs_trans_handle *trans, | |||
| 960 | cur_offset = key->offset; | 953 | cur_offset = key->offset; |
| 961 | ptr = btrfs_item_ptr_offset(eb, slot); | 954 | ptr = btrfs_item_ptr_offset(eb, slot); |
| 962 | while(item_size > 0) { | 955 | while(item_size > 0) { |
| 963 | sector_sum->offset = cur_offset; | 956 | sector_sum->bytenr = cur_offset; |
| 964 | read_extent_buffer(eb, §or_sum->sum, ptr, csum_size); | 957 | read_extent_buffer(eb, §or_sum->sum, ptr, csum_size); |
| 965 | sector_sum++; | 958 | sector_sum++; |
| 966 | item_size -= csum_size; | 959 | item_size -= csum_size; |
| @@ -969,11 +962,9 @@ static noinline int replay_one_csum(struct btrfs_trans_handle *trans, | |||
| 969 | } | 962 | } |
| 970 | 963 | ||
| 971 | /* let btrfs_csum_file_blocks add them into the file */ | 964 | /* let btrfs_csum_file_blocks add them into the file */ |
| 972 | ret = btrfs_csum_file_blocks(trans, root, inode, sums); | 965 | ret = btrfs_csum_file_blocks(trans, root->fs_info->csum_root, sums); |
| 973 | BUG_ON(ret); | 966 | BUG_ON(ret); |
| 974 | kfree(sums); | 967 | kfree(sums); |
| 975 | iput(inode); | ||
| 976 | |||
| 977 | return 0; | 968 | return 0; |
| 978 | } | 969 | } |
| 979 | /* | 970 | /* |
| @@ -1670,7 +1661,7 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
| 1670 | ret = replay_one_extent(wc->trans, root, path, | 1661 | ret = replay_one_extent(wc->trans, root, path, |
| 1671 | eb, i, &key); | 1662 | eb, i, &key); |
| 1672 | BUG_ON(ret); | 1663 | BUG_ON(ret); |
| 1673 | } else if (key.type == BTRFS_CSUM_ITEM_KEY) { | 1664 | } else if (key.type == BTRFS_EXTENT_CSUM_KEY) { |
| 1674 | ret = replay_one_csum(wc->trans, root, path, | 1665 | ret = replay_one_csum(wc->trans, root, path, |
| 1675 | eb, i, &key); | 1666 | eb, i, &key); |
| 1676 | BUG_ON(ret); | 1667 | BUG_ON(ret); |
| @@ -2466,6 +2457,85 @@ static int drop_objectid_items(struct btrfs_trans_handle *trans, | |||
| 2466 | return 0; | 2457 | return 0; |
| 2467 | } | 2458 | } |
| 2468 | 2459 | ||
| 2460 | static noinline int copy_extent_csums(struct btrfs_trans_handle *trans, | ||
| 2461 | struct list_head *list, | ||
| 2462 | struct btrfs_root *root, | ||
| 2463 | u64 disk_bytenr, u64 len) | ||
| 2464 | { | ||
| 2465 | struct btrfs_ordered_sum *sums; | ||
| 2466 | struct btrfs_sector_sum *sector_sum; | ||
| 2467 | int ret; | ||
| 2468 | struct btrfs_path *path; | ||
| 2469 | struct btrfs_csum_item *item = NULL; | ||
| 2470 | u64 end = disk_bytenr + len; | ||
| 2471 | u64 item_start_offset = 0; | ||
| 2472 | u64 item_last_offset = 0; | ||
| 2473 | u32 diff; | ||
| 2474 | u32 sum; | ||
| 2475 | u16 csum_size = btrfs_super_csum_size(&root->fs_info->super_copy); | ||
| 2476 | |||
| 2477 | sums = kzalloc(btrfs_ordered_sum_size(root, len), GFP_NOFS); | ||
| 2478 | |||
| 2479 | sector_sum = sums->sums; | ||
| 2480 | sums->bytenr = disk_bytenr; | ||
| 2481 | sums->len = len; | ||
| 2482 | list_add_tail(&sums->list, list); | ||
| 2483 | |||
| 2484 | path = btrfs_alloc_path(); | ||
| 2485 | while(disk_bytenr < end) { | ||
| 2486 | if (!item || disk_bytenr < item_start_offset || | ||
| 2487 | disk_bytenr >= item_last_offset) { | ||
| 2488 | struct btrfs_key found_key; | ||
| 2489 | u32 item_size; | ||
| 2490 | |||
| 2491 | if (item) | ||
| 2492 | btrfs_release_path(root, path); | ||
| 2493 | item = btrfs_lookup_csum(NULL, root, path, | ||
| 2494 | disk_bytenr, 0); | ||
| 2495 | if (IS_ERR(item)) { | ||
| 2496 | ret = PTR_ERR(item); | ||
| 2497 | if (ret == -ENOENT || ret == -EFBIG) | ||
| 2498 | ret = 0; | ||
| 2499 | sum = 0; | ||
| 2500 | printk("log no csum found for byte %llu\n", | ||
| 2501 | (unsigned long long)disk_bytenr); | ||
| 2502 | item = NULL; | ||
| 2503 | btrfs_release_path(root, path); | ||
| 2504 | goto found; | ||
| 2505 | } | ||
| 2506 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, | ||
| 2507 | path->slots[0]); | ||
| 2508 | |||
| 2509 | item_start_offset = found_key.offset; | ||
| 2510 | item_size = btrfs_item_size_nr(path->nodes[0], | ||
| 2511 | path->slots[0]); | ||
| 2512 | item_last_offset = item_start_offset + | ||
| 2513 | (item_size / csum_size) * | ||
| 2514 | root->sectorsize; | ||
| 2515 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], | ||
| 2516 | struct btrfs_csum_item); | ||
| 2517 | } | ||
| 2518 | /* | ||
| 2519 | * this byte range must be able to fit inside | ||
| 2520 | * a single leaf so it will also fit inside a u32 | ||
| 2521 | */ | ||
| 2522 | diff = disk_bytenr - item_start_offset; | ||
| 2523 | diff = diff / root->sectorsize; | ||
| 2524 | diff = diff * csum_size; | ||
| 2525 | |||
| 2526 | read_extent_buffer(path->nodes[0], &sum, | ||
| 2527 | ((unsigned long)item) + diff, | ||
| 2528 | csum_size); | ||
| 2529 | found: | ||
| 2530 | sector_sum->bytenr = disk_bytenr; | ||
| 2531 | sector_sum->sum = sum; | ||
| 2532 | disk_bytenr += root->sectorsize; | ||
| 2533 | sector_sum++; | ||
| 2534 | } | ||
| 2535 | btrfs_free_path(path); | ||
| 2536 | return 0; | ||
| 2537 | } | ||
| 2538 | |||
| 2469 | static noinline int copy_items(struct btrfs_trans_handle *trans, | 2539 | static noinline int copy_items(struct btrfs_trans_handle *trans, |
| 2470 | struct btrfs_root *log, | 2540 | struct btrfs_root *log, |
| 2471 | struct btrfs_path *dst_path, | 2541 | struct btrfs_path *dst_path, |
| @@ -2481,6 +2551,9 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, | |||
| 2481 | u32 *ins_sizes; | 2551 | u32 *ins_sizes; |
| 2482 | char *ins_data; | 2552 | char *ins_data; |
| 2483 | int i; | 2553 | int i; |
| 2554 | struct list_head ordered_sums; | ||
| 2555 | |||
| 2556 | INIT_LIST_HEAD(&ordered_sums); | ||
| 2484 | 2557 | ||
| 2485 | ins_data = kmalloc(nr * sizeof(struct btrfs_key) + | 2558 | ins_data = kmalloc(nr * sizeof(struct btrfs_key) + |
| 2486 | nr * sizeof(u32), GFP_NOFS); | 2559 | nr * sizeof(u32), GFP_NOFS); |
| @@ -2535,6 +2608,9 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, | |||
| 2535 | extent); | 2608 | extent); |
| 2536 | u64 dl = btrfs_file_extent_disk_num_bytes(src, | 2609 | u64 dl = btrfs_file_extent_disk_num_bytes(src, |
| 2537 | extent); | 2610 | extent); |
| 2611 | u64 cs = btrfs_file_extent_offset(src, extent); | ||
| 2612 | u64 cl = btrfs_file_extent_num_bytes(src, | ||
| 2613 | extent);; | ||
| 2538 | /* ds == 0 is a hole */ | 2614 | /* ds == 0 is a hole */ |
| 2539 | if (ds != 0) { | 2615 | if (ds != 0) { |
| 2540 | ret = btrfs_inc_extent_ref(trans, log, | 2616 | ret = btrfs_inc_extent_ref(trans, log, |
| @@ -2544,6 +2620,11 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, | |||
| 2544 | trans->transid, | 2620 | trans->transid, |
| 2545 | ins_keys[i].objectid); | 2621 | ins_keys[i].objectid); |
| 2546 | BUG_ON(ret); | 2622 | BUG_ON(ret); |
| 2623 | ret = copy_extent_csums(trans, | ||
| 2624 | &ordered_sums, | ||
| 2625 | log->fs_info->csum_root, | ||
| 2626 | ds + cs, cl); | ||
| 2627 | BUG_ON(ret); | ||
| 2547 | } | 2628 | } |
| 2548 | } | 2629 | } |
| 2549 | } | 2630 | } |
| @@ -2553,6 +2634,20 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, | |||
| 2553 | btrfs_mark_buffer_dirty(dst_path->nodes[0]); | 2634 | btrfs_mark_buffer_dirty(dst_path->nodes[0]); |
| 2554 | btrfs_release_path(log, dst_path); | 2635 | btrfs_release_path(log, dst_path); |
| 2555 | kfree(ins_data); | 2636 | kfree(ins_data); |
| 2637 | |||
| 2638 | /* | ||
| 2639 | * we have to do this after the loop above to avoid changing the | ||
| 2640 | * log tree while trying to change the log tree. | ||
| 2641 | */ | ||
| 2642 | while(!list_empty(&ordered_sums)) { | ||
| 2643 | struct btrfs_ordered_sum *sums = list_entry(ordered_sums.next, | ||
| 2644 | struct btrfs_ordered_sum, | ||
| 2645 | list); | ||
| 2646 | ret = btrfs_csum_file_blocks(trans, log, sums); | ||
| 2647 | BUG_ON(ret); | ||
| 2648 | list_del(&sums->list); | ||
| 2649 | kfree(sums); | ||
| 2650 | } | ||
| 2556 | return 0; | 2651 | return 0; |
| 2557 | } | 2652 | } |
| 2558 | 2653 | ||
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 6c523b3360f..2049d179ccd 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c | |||
| @@ -2771,6 +2771,7 @@ static struct btrfs_device *add_missing_dev(struct btrfs_root *root, | |||
| 2771 | device->work.func = pending_bios_fn; | 2771 | device->work.func = pending_bios_fn; |
| 2772 | fs_devices->num_devices++; | 2772 | fs_devices->num_devices++; |
| 2773 | spin_lock_init(&device->io_lock); | 2773 | spin_lock_init(&device->io_lock); |
| 2774 | INIT_LIST_HEAD(&device->dev_alloc_list); | ||
| 2774 | memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE); | 2775 | memcpy(device->uuid, dev_uuid, BTRFS_UUID_SIZE); |
| 2775 | return device; | 2776 | return device; |
| 2776 | } | 2777 | } |
