diff options
author | Yan Zheng <zheng.yan@oracle.com> | 2009-01-06 11:42:00 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2009-01-06 11:42:00 -0500 |
commit | 07d400a6df4767a90d49a153fdb7f4cfa1e3f23e (patch) | |
tree | 8ca61bb87ffb72343b8d392a26fb7a6265f6fa3d /fs/btrfs | |
parent | 1ba12553f3600ffebad226c5204ab0e46df98161 (diff) |
Btrfs: tree logging checksum fixes
This patch contains following things.
1) Limit the max size of btrfs_ordered_sum structure to PAGE_SIZE. This
struct is kmalloced so we want to keep it reasonable.
2) Replace copy_extent_csums by btrfs_lookup_csums_range. This was
duplicated code in tree-log.c
3) Remove replay_one_csum. csum items are replayed at the same time as
replaying file extents. This guarantees we only replay useful csums.
4) nbytes accounting fix.
Signed-off-by: Yan Zheng <zheng.yan@oracle.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/extent-tree.c | 2 | ||||
-rw-r--r-- | fs/btrfs/file-item.c | 62 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 5 | ||||
-rw-r--r-- | fs/btrfs/tree-log.c | 293 |
4 files changed, 130 insertions, 232 deletions
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c index 171ca30a3755..293da650873f 100644 --- a/fs/btrfs/extent-tree.c +++ b/fs/btrfs/extent-tree.c | |||
@@ -5579,7 +5579,7 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len) | |||
5579 | BUG_ON(ordered->file_offset != file_pos || ordered->len != len); | 5579 | BUG_ON(ordered->file_offset != file_pos || ordered->len != len); |
5580 | 5580 | ||
5581 | disk_bytenr = file_pos + BTRFS_I(inode)->index_cnt; | 5581 | disk_bytenr = file_pos + BTRFS_I(inode)->index_cnt; |
5582 | ret = btrfs_lookup_csums_range(root, disk_bytenr, | 5582 | ret = btrfs_lookup_csums_range(root->fs_info->csum_root, disk_bytenr, |
5583 | disk_bytenr + len - 1, &list); | 5583 | disk_bytenr + len - 1, &list); |
5584 | 5584 | ||
5585 | while (!list_empty(&list)) { | 5585 | while (!list_empty(&list)) { |
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c index b11abfad81a5..964652435fd1 100644 --- a/fs/btrfs/file-item.c +++ b/fs/btrfs/file-item.c | |||
@@ -27,6 +27,12 @@ | |||
27 | #define MAX_CSUM_ITEMS(r, size) ((((BTRFS_LEAF_DATA_SIZE(r) - \ | 27 | #define MAX_CSUM_ITEMS(r, size) ((((BTRFS_LEAF_DATA_SIZE(r) - \ |
28 | sizeof(struct btrfs_item) * 2) / \ | 28 | sizeof(struct btrfs_item) * 2) / \ |
29 | size) - 1)) | 29 | size) - 1)) |
30 | |||
31 | #define MAX_ORDERED_SUM_BYTES(r) ((PAGE_SIZE - \ | ||
32 | sizeof(struct btrfs_ordered_sum)) / \ | ||
33 | sizeof(struct btrfs_sector_sum) * \ | ||
34 | (r)->sectorsize - (r)->sectorsize) | ||
35 | |||
30 | int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, | 36 | int btrfs_insert_file_extent(struct btrfs_trans_handle *trans, |
31 | struct btrfs_root *root, | 37 | struct btrfs_root *root, |
32 | u64 objectid, u64 pos, | 38 | u64 objectid, u64 pos, |
@@ -259,8 +265,7 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, | |||
259 | key.offset = start; | 265 | key.offset = start; |
260 | key.type = BTRFS_EXTENT_CSUM_KEY; | 266 | key.type = BTRFS_EXTENT_CSUM_KEY; |
261 | 267 | ||
262 | ret = btrfs_search_slot(NULL, root->fs_info->csum_root, | 268 | ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); |
263 | &key, path, 0, 0); | ||
264 | if (ret < 0) | 269 | if (ret < 0) |
265 | goto fail; | 270 | goto fail; |
266 | if (ret > 0 && path->slots[0] > 0) { | 271 | if (ret > 0 && path->slots[0] > 0) { |
@@ -279,7 +284,7 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, | |||
279 | while (start <= end) { | 284 | while (start <= end) { |
280 | leaf = path->nodes[0]; | 285 | leaf = path->nodes[0]; |
281 | if (path->slots[0] >= btrfs_header_nritems(leaf)) { | 286 | if (path->slots[0] >= btrfs_header_nritems(leaf)) { |
282 | ret = btrfs_next_leaf(root->fs_info->csum_root, path); | 287 | ret = btrfs_next_leaf(root, path); |
283 | if (ret < 0) | 288 | if (ret < 0) |
284 | goto fail; | 289 | goto fail; |
285 | if (ret > 0) | 290 | if (ret > 0) |
@@ -306,33 +311,38 @@ int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end, | |||
306 | continue; | 311 | continue; |
307 | } | 312 | } |
308 | 313 | ||
309 | size = min(csum_end, end + 1) - start; | 314 | csum_end = min(csum_end, end + 1); |
310 | sums = kzalloc(btrfs_ordered_sum_size(root, size), GFP_NOFS); | 315 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], |
311 | BUG_ON(!sums); | 316 | struct btrfs_csum_item); |
317 | while (start < csum_end) { | ||
318 | size = min_t(size_t, csum_end - start, | ||
319 | MAX_ORDERED_SUM_BYTES(root)); | ||
320 | sums = kzalloc(btrfs_ordered_sum_size(root, size), | ||
321 | GFP_NOFS); | ||
322 | BUG_ON(!sums); | ||
312 | 323 | ||
313 | sector_sum = sums->sums; | 324 | sector_sum = sums->sums; |
314 | sums->bytenr = start; | 325 | sums->bytenr = start; |
315 | sums->len = size; | 326 | sums->len = size; |
316 | 327 | ||
317 | offset = (start - key.offset) >> | 328 | offset = (start - key.offset) >> |
318 | root->fs_info->sb->s_blocksize_bits; | 329 | root->fs_info->sb->s_blocksize_bits; |
319 | offset *= csum_size; | 330 | offset *= csum_size; |
320 | 331 | ||
321 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], | 332 | while (size > 0) { |
322 | struct btrfs_csum_item); | 333 | read_extent_buffer(path->nodes[0], |
323 | while (size > 0) { | 334 | §or_sum->sum, |
324 | read_extent_buffer(path->nodes[0], §or_sum->sum, | 335 | ((unsigned long)item) + |
325 | ((unsigned long)item) + offset, | 336 | offset, csum_size); |
326 | csum_size); | 337 | sector_sum->bytenr = start; |
327 | sector_sum->bytenr = start; | 338 | |
328 | 339 | size -= root->sectorsize; | |
329 | size -= root->sectorsize; | 340 | start += root->sectorsize; |
330 | start += root->sectorsize; | 341 | offset += csum_size; |
331 | offset += csum_size; | 342 | sector_sum++; |
332 | sector_sum++; | 343 | } |
344 | list_add_tail(&sums->list, list); | ||
333 | } | 345 | } |
334 | list_add_tail(&sums->list, list); | ||
335 | |||
336 | path->slots[0]++; | 346 | path->slots[0]++; |
337 | } | 347 | } |
338 | ret = 0; | 348 | ret = 0; |
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index c0ca9c3723c0..4e57fe68e4b9 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -157,7 +157,6 @@ static noinline int insert_inline_extent(struct btrfs_trans_handle *trans, | |||
157 | key.objectid = inode->i_ino; | 157 | key.objectid = inode->i_ino; |
158 | key.offset = start; | 158 | key.offset = start; |
159 | btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY); | 159 | btrfs_set_key_type(&key, BTRFS_EXTENT_DATA_KEY); |
160 | inode_add_bytes(inode, size); | ||
161 | datasize = btrfs_file_extent_calc_inline_size(cur_size); | 160 | datasize = btrfs_file_extent_calc_inline_size(cur_size); |
162 | 161 | ||
163 | inode_add_bytes(inode, size); | 162 | inode_add_bytes(inode, size); |
@@ -920,8 +919,8 @@ static noinline int csum_exist_in_range(struct btrfs_root *root, | |||
920 | struct btrfs_ordered_sum *sums; | 919 | struct btrfs_ordered_sum *sums; |
921 | LIST_HEAD(list); | 920 | LIST_HEAD(list); |
922 | 921 | ||
923 | ret = btrfs_lookup_csums_range(root, bytenr, bytenr + num_bytes - 1, | 922 | ret = btrfs_lookup_csums_range(root->fs_info->csum_root, bytenr, |
924 | &list); | 923 | bytenr + num_bytes - 1, &list); |
925 | if (ret == 0 && list_empty(&list)) | 924 | if (ret == 0 && list_empty(&list)) |
926 | return 0; | 925 | return 0; |
927 | 926 | ||
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 3a72a1b6c247..332ec35d2c08 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c | |||
@@ -433,49 +433,6 @@ insert: | |||
433 | trans->transid); | 433 | trans->transid); |
434 | } | 434 | } |
435 | } | 435 | } |
436 | |||
437 | if (overwrite_root && | ||
438 | key->type == BTRFS_EXTENT_DATA_KEY) { | ||
439 | int extent_type; | ||
440 | struct btrfs_file_extent_item *fi; | ||
441 | |||
442 | fi = (struct btrfs_file_extent_item *)dst_ptr; | ||
443 | extent_type = btrfs_file_extent_type(path->nodes[0], fi); | ||
444 | if (extent_type == BTRFS_FILE_EXTENT_REG || | ||
445 | extent_type == BTRFS_FILE_EXTENT_PREALLOC) { | ||
446 | struct btrfs_key ins; | ||
447 | ins.objectid = btrfs_file_extent_disk_bytenr( | ||
448 | path->nodes[0], fi); | ||
449 | ins.offset = btrfs_file_extent_disk_num_bytes( | ||
450 | path->nodes[0], fi); | ||
451 | ins.type = BTRFS_EXTENT_ITEM_KEY; | ||
452 | |||
453 | /* | ||
454 | * is this extent already allocated in the extent | ||
455 | * allocation tree? If so, just add a reference | ||
456 | */ | ||
457 | ret = btrfs_lookup_extent(root, ins.objectid, | ||
458 | ins.offset); | ||
459 | if (ret == 0) { | ||
460 | ret = btrfs_inc_extent_ref(trans, root, | ||
461 | ins.objectid, ins.offset, | ||
462 | path->nodes[0]->start, | ||
463 | root->root_key.objectid, | ||
464 | trans->transid, key->objectid); | ||
465 | } else { | ||
466 | /* | ||
467 | * insert the extent pointer in the extent | ||
468 | * allocation tree | ||
469 | */ | ||
470 | ret = btrfs_alloc_logged_extent(trans, root, | ||
471 | path->nodes[0]->start, | ||
472 | root->root_key.objectid, | ||
473 | trans->transid, key->objectid, | ||
474 | &ins); | ||
475 | BUG_ON(ret); | ||
476 | } | ||
477 | } | ||
478 | } | ||
479 | no_copy: | 436 | no_copy: |
480 | btrfs_mark_buffer_dirty(path->nodes[0]); | 437 | btrfs_mark_buffer_dirty(path->nodes[0]); |
481 | btrfs_release_path(root, path); | 438 | btrfs_release_path(root, path); |
@@ -530,6 +487,7 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
530 | u64 extent_end; | 487 | u64 extent_end; |
531 | u64 alloc_hint; | 488 | u64 alloc_hint; |
532 | u64 start = key->offset; | 489 | u64 start = key->offset; |
490 | u64 saved_nbytes; | ||
533 | struct btrfs_file_extent_item *item; | 491 | struct btrfs_file_extent_item *item; |
534 | struct inode *inode = NULL; | 492 | struct inode *inode = NULL; |
535 | unsigned long size; | 493 | unsigned long size; |
@@ -591,17 +549,95 @@ static noinline int replay_one_extent(struct btrfs_trans_handle *trans, | |||
591 | } | 549 | } |
592 | btrfs_release_path(root, path); | 550 | btrfs_release_path(root, path); |
593 | 551 | ||
552 | saved_nbytes = inode_get_bytes(inode); | ||
594 | /* drop any overlapping extents */ | 553 | /* drop any overlapping extents */ |
595 | ret = btrfs_drop_extents(trans, root, inode, | 554 | ret = btrfs_drop_extents(trans, root, inode, |
596 | start, extent_end, start, &alloc_hint); | 555 | start, extent_end, start, &alloc_hint); |
597 | BUG_ON(ret); | 556 | BUG_ON(ret); |
598 | 557 | ||
599 | /* insert the extent */ | 558 | if (found_type == BTRFS_FILE_EXTENT_REG || |
600 | ret = overwrite_item(trans, root, path, eb, slot, key); | 559 | found_type == BTRFS_FILE_EXTENT_PREALLOC) { |
601 | BUG_ON(ret); | 560 | unsigned long dest_offset; |
561 | struct btrfs_key ins; | ||
562 | |||
563 | ret = btrfs_insert_empty_item(trans, root, path, key, | ||
564 | sizeof(*item)); | ||
565 | BUG_ON(ret); | ||
566 | dest_offset = btrfs_item_ptr_offset(path->nodes[0], | ||
567 | path->slots[0]); | ||
568 | copy_extent_buffer(path->nodes[0], eb, dest_offset, | ||
569 | (unsigned long)item, sizeof(*item)); | ||
570 | |||
571 | ins.objectid = btrfs_file_extent_disk_bytenr(eb, item); | ||
572 | ins.offset = btrfs_file_extent_disk_num_bytes(eb, item); | ||
573 | ins.type = BTRFS_EXTENT_ITEM_KEY; | ||
574 | |||
575 | if (ins.objectid > 0) { | ||
576 | u64 csum_start; | ||
577 | u64 csum_end; | ||
578 | LIST_HEAD(ordered_sums); | ||
579 | /* | ||
580 | * is this extent already allocated in the extent | ||
581 | * allocation tree? If so, just add a reference | ||
582 | */ | ||
583 | ret = btrfs_lookup_extent(root, ins.objectid, | ||
584 | ins.offset); | ||
585 | if (ret == 0) { | ||
586 | ret = btrfs_inc_extent_ref(trans, root, | ||
587 | ins.objectid, ins.offset, | ||
588 | path->nodes[0]->start, | ||
589 | root->root_key.objectid, | ||
590 | trans->transid, key->objectid); | ||
591 | } else { | ||
592 | /* | ||
593 | * insert the extent pointer in the extent | ||
594 | * allocation tree | ||
595 | */ | ||
596 | ret = btrfs_alloc_logged_extent(trans, root, | ||
597 | path->nodes[0]->start, | ||
598 | root->root_key.objectid, | ||
599 | trans->transid, key->objectid, | ||
600 | &ins); | ||
601 | BUG_ON(ret); | ||
602 | } | ||
603 | btrfs_release_path(root, path); | ||
604 | |||
605 | if (btrfs_file_extent_compression(eb, item)) { | ||
606 | csum_start = ins.objectid; | ||
607 | csum_end = csum_start + ins.offset; | ||
608 | } else { | ||
609 | csum_start = ins.objectid + | ||
610 | btrfs_file_extent_offset(eb, item); | ||
611 | csum_end = csum_start + | ||
612 | btrfs_file_extent_num_bytes(eb, item); | ||
613 | } | ||
614 | |||
615 | ret = btrfs_lookup_csums_range(root->log_root, | ||
616 | csum_start, csum_end - 1, | ||
617 | &ordered_sums); | ||
618 | BUG_ON(ret); | ||
619 | while (!list_empty(&ordered_sums)) { | ||
620 | struct btrfs_ordered_sum *sums; | ||
621 | sums = list_entry(ordered_sums.next, | ||
622 | struct btrfs_ordered_sum, | ||
623 | list); | ||
624 | ret = btrfs_csum_file_blocks(trans, | ||
625 | root->fs_info->csum_root, | ||
626 | sums); | ||
627 | BUG_ON(ret); | ||
628 | list_del(&sums->list); | ||
629 | kfree(sums); | ||
630 | } | ||
631 | } else { | ||
632 | btrfs_release_path(root, path); | ||
633 | } | ||
634 | } else if (found_type == BTRFS_FILE_EXTENT_INLINE) { | ||
635 | /* inline extents are easy, we just overwrite them */ | ||
636 | ret = overwrite_item(trans, root, path, eb, slot, key); | ||
637 | BUG_ON(ret); | ||
638 | } | ||
602 | 639 | ||
603 | /* btrfs_drop_extents changes i_bytes & i_blocks, update it here */ | 640 | inode_set_bytes(inode, saved_nbytes); |
604 | inode_add_bytes(inode, extent_end - start); | ||
605 | btrfs_update_inode(trans, root, inode); | 641 | btrfs_update_inode(trans, root, inode); |
606 | out: | 642 | out: |
607 | if (inode) | 643 | if (inode) |
@@ -903,70 +939,6 @@ out_nowrite: | |||
903 | } | 939 | } |
904 | 940 | ||
905 | /* | 941 | /* |
906 | * replay one csum item from the log tree into the subvolume 'root' | ||
907 | * eb, slot and key all refer to the log tree | ||
908 | * path is for temp use by this function and should be released on return | ||
909 | * | ||
910 | * This copies the checksums out of the log tree and inserts them into | ||
911 | * the subvolume. Any existing checksums for this range in the file | ||
912 | * are overwritten, and new items are added where required. | ||
913 | * | ||
914 | * We keep this simple by reusing the btrfs_ordered_sum code from | ||
915 | * the data=ordered mode. This basically means making a copy | ||
916 | * of all the checksums in ram, which we have to do anyway for kmap | ||
917 | * rules. | ||
918 | * | ||
919 | * The copy is then sent down to btrfs_csum_file_blocks, which | ||
920 | * does all the hard work of finding existing items in the file | ||
921 | * or adding new ones. | ||
922 | */ | ||
923 | static noinline int replay_one_csum(struct btrfs_trans_handle *trans, | ||
924 | struct btrfs_root *root, | ||
925 | struct btrfs_path *path, | ||
926 | struct extent_buffer *eb, int slot, | ||
927 | struct btrfs_key *key) | ||
928 | { | ||
929 | int ret; | ||
930 | u32 item_size = btrfs_item_size_nr(eb, slot); | ||
931 | u64 cur_offset; | ||
932 | u16 csum_size = | ||
933 | btrfs_super_csum_size(&root->fs_info->super_copy); | ||
934 | unsigned long file_bytes; | ||
935 | struct btrfs_ordered_sum *sums; | ||
936 | struct btrfs_sector_sum *sector_sum; | ||
937 | unsigned long ptr; | ||
938 | |||
939 | file_bytes = (item_size / csum_size) * root->sectorsize; | ||
940 | sums = kzalloc(btrfs_ordered_sum_size(root, file_bytes), GFP_NOFS); | ||
941 | if (!sums) | ||
942 | return -ENOMEM; | ||
943 | |||
944 | INIT_LIST_HEAD(&sums->list); | ||
945 | sums->len = file_bytes; | ||
946 | sums->bytenr = key->offset; | ||
947 | |||
948 | /* | ||
949 | * copy all the sums into the ordered sum struct | ||
950 | */ | ||
951 | sector_sum = sums->sums; | ||
952 | cur_offset = key->offset; | ||
953 | ptr = btrfs_item_ptr_offset(eb, slot); | ||
954 | while (item_size > 0) { | ||
955 | sector_sum->bytenr = cur_offset; | ||
956 | read_extent_buffer(eb, §or_sum->sum, ptr, csum_size); | ||
957 | sector_sum++; | ||
958 | item_size -= csum_size; | ||
959 | ptr += csum_size; | ||
960 | cur_offset += root->sectorsize; | ||
961 | } | ||
962 | |||
963 | /* let btrfs_csum_file_blocks add them into the file */ | ||
964 | ret = btrfs_csum_file_blocks(trans, root->fs_info->csum_root, sums); | ||
965 | BUG_ON(ret); | ||
966 | kfree(sums); | ||
967 | return 0; | ||
968 | } | ||
969 | /* | ||
970 | * There are a few corners where the link count of the file can't | 942 | * There are a few corners where the link count of the file can't |
971 | * be properly maintained during replay. So, instead of adding | 943 | * be properly maintained during replay. So, instead of adding |
972 | * lots of complexity to the log code, we just scan the backrefs | 944 | * lots of complexity to the log code, we just scan the backrefs |
@@ -1659,10 +1631,6 @@ static int replay_one_buffer(struct btrfs_root *log, struct extent_buffer *eb, | |||
1659 | ret = replay_one_extent(wc->trans, root, path, | 1631 | ret = replay_one_extent(wc->trans, root, path, |
1660 | eb, i, &key); | 1632 | eb, i, &key); |
1661 | BUG_ON(ret); | 1633 | BUG_ON(ret); |
1662 | } else if (key.type == BTRFS_EXTENT_CSUM_KEY) { | ||
1663 | ret = replay_one_csum(wc->trans, root, path, | ||
1664 | eb, i, &key); | ||
1665 | BUG_ON(ret); | ||
1666 | } else if (key.type == BTRFS_DIR_ITEM_KEY || | 1634 | } else if (key.type == BTRFS_DIR_ITEM_KEY || |
1667 | key.type == BTRFS_DIR_INDEX_KEY) { | 1635 | key.type == BTRFS_DIR_INDEX_KEY) { |
1668 | ret = replay_one_dir_item(wc->trans, root, path, | 1636 | ret = replay_one_dir_item(wc->trans, root, path, |
@@ -2021,7 +1989,7 @@ int btrfs_free_log(struct btrfs_trans_handle *trans, struct btrfs_root *root) | |||
2021 | .process_func = process_one_buffer | 1989 | .process_func = process_one_buffer |
2022 | }; | 1990 | }; |
2023 | 1991 | ||
2024 | if (!root->log_root) | 1992 | if (!root->log_root || root->fs_info->log_root_recovering) |
2025 | return 0; | 1993 | return 0; |
2026 | 1994 | ||
2027 | log = root->log_root; | 1995 | log = root->log_root; |
@@ -2453,86 +2421,6 @@ static int drop_objectid_items(struct btrfs_trans_handle *trans, | |||
2453 | return 0; | 2421 | return 0; |
2454 | } | 2422 | } |
2455 | 2423 | ||
2456 | static noinline int copy_extent_csums(struct btrfs_trans_handle *trans, | ||
2457 | struct list_head *list, | ||
2458 | struct btrfs_root *root, | ||
2459 | u64 disk_bytenr, u64 len) | ||
2460 | { | ||
2461 | struct btrfs_ordered_sum *sums; | ||
2462 | struct btrfs_sector_sum *sector_sum; | ||
2463 | int ret; | ||
2464 | struct btrfs_path *path; | ||
2465 | struct btrfs_csum_item *item = NULL; | ||
2466 | u64 end = disk_bytenr + len; | ||
2467 | u64 item_start_offset = 0; | ||
2468 | u64 item_last_offset = 0; | ||
2469 | u32 diff; | ||
2470 | u32 sum; | ||
2471 | u16 csum_size = btrfs_super_csum_size(&root->fs_info->super_copy); | ||
2472 | |||
2473 | sums = kzalloc(btrfs_ordered_sum_size(root, len), GFP_NOFS); | ||
2474 | |||
2475 | sector_sum = sums->sums; | ||
2476 | sums->bytenr = disk_bytenr; | ||
2477 | sums->len = len; | ||
2478 | list_add_tail(&sums->list, list); | ||
2479 | |||
2480 | path = btrfs_alloc_path(); | ||
2481 | while (disk_bytenr < end) { | ||
2482 | if (!item || disk_bytenr < item_start_offset || | ||
2483 | disk_bytenr >= item_last_offset) { | ||
2484 | struct btrfs_key found_key; | ||
2485 | u32 item_size; | ||
2486 | |||
2487 | if (item) | ||
2488 | btrfs_release_path(root, path); | ||
2489 | item = btrfs_lookup_csum(NULL, root, path, | ||
2490 | disk_bytenr, 0); | ||
2491 | if (IS_ERR(item)) { | ||
2492 | ret = PTR_ERR(item); | ||
2493 | if (ret == -ENOENT || ret == -EFBIG) | ||
2494 | ret = 0; | ||
2495 | sum = 0; | ||
2496 | printk(KERN_INFO "log no csum found for " | ||
2497 | "byte %llu\n", | ||
2498 | (unsigned long long)disk_bytenr); | ||
2499 | item = NULL; | ||
2500 | btrfs_release_path(root, path); | ||
2501 | goto found; | ||
2502 | } | ||
2503 | btrfs_item_key_to_cpu(path->nodes[0], &found_key, | ||
2504 | path->slots[0]); | ||
2505 | |||
2506 | item_start_offset = found_key.offset; | ||
2507 | item_size = btrfs_item_size_nr(path->nodes[0], | ||
2508 | path->slots[0]); | ||
2509 | item_last_offset = item_start_offset + | ||
2510 | (item_size / csum_size) * | ||
2511 | root->sectorsize; | ||
2512 | item = btrfs_item_ptr(path->nodes[0], path->slots[0], | ||
2513 | struct btrfs_csum_item); | ||
2514 | } | ||
2515 | /* | ||
2516 | * this byte range must be able to fit inside | ||
2517 | * a single leaf so it will also fit inside a u32 | ||
2518 | */ | ||
2519 | diff = disk_bytenr - item_start_offset; | ||
2520 | diff = diff / root->sectorsize; | ||
2521 | diff = diff * csum_size; | ||
2522 | |||
2523 | read_extent_buffer(path->nodes[0], &sum, | ||
2524 | ((unsigned long)item) + diff, | ||
2525 | csum_size); | ||
2526 | found: | ||
2527 | sector_sum->bytenr = disk_bytenr; | ||
2528 | sector_sum->sum = sum; | ||
2529 | disk_bytenr += root->sectorsize; | ||
2530 | sector_sum++; | ||
2531 | } | ||
2532 | btrfs_free_path(path); | ||
2533 | return 0; | ||
2534 | } | ||
2535 | |||
2536 | static noinline int copy_items(struct btrfs_trans_handle *trans, | 2424 | static noinline int copy_items(struct btrfs_trans_handle *trans, |
2537 | struct btrfs_root *log, | 2425 | struct btrfs_root *log, |
2538 | struct btrfs_path *dst_path, | 2426 | struct btrfs_path *dst_path, |
@@ -2622,10 +2510,10 @@ static noinline int copy_items(struct btrfs_trans_handle *trans, | |||
2622 | trans->transid, | 2510 | trans->transid, |
2623 | ins_keys[i].objectid); | 2511 | ins_keys[i].objectid); |
2624 | BUG_ON(ret); | 2512 | BUG_ON(ret); |
2625 | ret = copy_extent_csums(trans, | 2513 | ret = btrfs_lookup_csums_range( |
2626 | &ordered_sums, | 2514 | log->fs_info->csum_root, |
2627 | log->fs_info->csum_root, | 2515 | ds + cs, ds + cs + cl - 1, |
2628 | ds + cs, cl); | 2516 | &ordered_sums); |
2629 | BUG_ON(ret); | 2517 | BUG_ON(ret); |
2630 | } | 2518 | } |
2631 | } | 2519 | } |
@@ -2942,9 +2830,9 @@ again: | |||
2942 | tmp_key.offset = (u64)-1; | 2830 | tmp_key.offset = (u64)-1; |
2943 | 2831 | ||
2944 | wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key); | 2832 | wc.replay_dest = btrfs_read_fs_root_no_name(fs_info, &tmp_key); |
2945 | |||
2946 | BUG_ON(!wc.replay_dest); | 2833 | BUG_ON(!wc.replay_dest); |
2947 | 2834 | ||
2835 | wc.replay_dest->log_root = log; | ||
2948 | btrfs_record_root_in_trans(wc.replay_dest); | 2836 | btrfs_record_root_in_trans(wc.replay_dest); |
2949 | ret = walk_log_tree(trans, log, &wc); | 2837 | ret = walk_log_tree(trans, log, &wc); |
2950 | BUG_ON(ret); | 2838 | BUG_ON(ret); |
@@ -2961,6 +2849,7 @@ again: | |||
2961 | } | 2849 | } |
2962 | 2850 | ||
2963 | key.offset = found_key.offset - 1; | 2851 | key.offset = found_key.offset - 1; |
2852 | wc.replay_dest->log_root = NULL; | ||
2964 | free_extent_buffer(log->node); | 2853 | free_extent_buffer(log->node); |
2965 | kfree(log); | 2854 | kfree(log); |
2966 | 2855 | ||