struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize, u64 parent_transid) { int ret; struct extent_buffer *eb; u64 best_transid = 0; int mirror_num = 0; int good_mirror = 0; int num_copies; int ignore = 0; eb = btrfs_find_create_tree_block(root, bytenr, blocksize); if (!eb) return NULL; if (btrfs_buffer_uptodate(eb, parent_transid)) return eb; while (1) { ret = read_whole_eb(root->fs_info, eb, mirror_num); if (ret == 0 && check_tree_block(root, eb) == 0 && csum_tree_block(root, eb, 1) == 0 && verify_parent_transid(eb->tree, eb, parent_transid, ignore) == 0) { btrfs_set_buffer_uptodate(eb); return eb; } if (ignore) { if (check_tree_block(root, eb)) printk("read block failed check_tree_block\n"); else printk("Csum didn't match\n"); break; } num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, eb->start, eb->len); if (num_copies == 1) { ignore = 1; continue; } if (btrfs_header_generation(eb) > best_transid) { best_transid = btrfs_header_generation(eb); good_mirror = mirror_num; } mirror_num++; if (mirror_num > num_copies) { mirror_num = good_mirror; ignore = 1; continue; } } free_extent_buffer(eb); return NULL; }
struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize, u64 parent_transid) { int ret; int dev_nr; struct extent_buffer *eb; u64 length; struct btrfs_multi_bio *multi = NULL; struct btrfs_device *device; int mirror_num = 0; int num_copies; eb = btrfs_find_create_tree_block(root, bytenr, blocksize); if (!eb) return NULL; if (btrfs_buffer_uptodate(eb, parent_transid)) return eb; dev_nr = 0; length = blocksize; while (1) { ret = btrfs_map_block(&root->fs_info->mapping_tree, READ, eb->start, &length, &multi, mirror_num); BUG_ON(ret); device = multi->stripes[0].dev; eb->fd = device->fd; device->total_ios++; eb->dev_bytenr = multi->stripes[0].physical; kfree(multi); ret = read_extent_from_disk(eb); if (ret == 0 && check_tree_block(root, eb) == 0 && csum_tree_block(root, eb, 1) == 0 && verify_parent_transid(eb->tree, eb, parent_transid) == 0) { btrfs_set_buffer_uptodate(eb); return eb; } num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, eb->start, eb->len); if (num_copies == 1) { break; } mirror_num++; if (mirror_num > num_copies) { break; } } free_extent_buffer(eb); return NULL; }
struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize, u64 parent_transid) { int ret; struct extent_buffer *eb; u64 length; u64 best_transid = 0; struct btrfs_multi_bio *multi = NULL; struct btrfs_device *device; int mirror_num = 0; int good_mirror = 0; int num_copies; int ignore = 0; eb = btrfs_find_create_tree_block(root, bytenr, blocksize); if (!eb) return NULL; if (btrfs_buffer_uptodate(eb, parent_transid)) return eb; length = blocksize; while (1) { ret = btrfs_map_block(&root->fs_info->mapping_tree, READ, eb->start, &length, &multi, mirror_num); if (ret) { printk("Couldn't map the block %Lu\n", bytenr); break; } device = multi->stripes[0].dev; eb->fd = device->fd; device->total_ios++; eb->dev_bytenr = multi->stripes[0].physical; kfree(multi); ret = read_extent_from_disk(eb); if (ret == 0 && check_tree_block(root, eb) == 0 && csum_tree_block(root, eb, 1) == 0 && verify_parent_transid(eb->tree, eb, parent_transid, ignore) == 0) { btrfs_set_buffer_uptodate(eb); return eb; } if (ignore) { if (check_tree_block(root, eb)) printk("read block failed check_tree_block\n"); else printk("Csum didn't match\n"); break; } num_copies = btrfs_num_copies(&root->fs_info->mapping_tree, eb->start, eb->len); if (num_copies == 1) { ignore = 1; continue; } if (btrfs_header_generation(eb) > best_transid) { best_transid = btrfs_header_generation(eb); good_mirror = mirror_num; } mirror_num++; if (mirror_num > num_copies) { mirror_num = good_mirror; ignore = 1; continue; } } free_extent_buffer(eb); return NULL; }