mirror of
https://github.com/kdave/btrfs-progs
synced 2025-04-11 03:31:17 +00:00
Verify parent generation number on btree reads
This commit is contained in:
parent
9a9bdd6047
commit
351d17fca2
@ -105,7 +105,10 @@ int main(int ac, char **av)
|
||||
print_usage();
|
||||
mnt = av[optind];
|
||||
|
||||
if (device) {
|
||||
if (device && strcmp(device, "missing") == 0 &&
|
||||
cmd == BTRFS_IOC_RM_DEV) {
|
||||
fprintf(stderr, "removing missing devices from %s\n", mnt);
|
||||
} else if (device) {
|
||||
devfd = open(device, O_RDWR);
|
||||
if (!devfd) {
|
||||
fprintf(stderr, "Unable to open device %s\n", device);
|
||||
|
@ -1094,7 +1094,7 @@ static int create_image_file_range(struct btrfs_trans_handle *trans,
|
||||
u32 blocksize = ext2_fs->blocksize;
|
||||
u32 block = start_byte / blocksize;
|
||||
u32 last_block = (end_byte + blocksize - 1) / blocksize;
|
||||
int ret;
|
||||
int ret = 0;
|
||||
struct blk_iterate_data data = {
|
||||
.trans = trans,
|
||||
.root = root,
|
||||
|
2
ctree.c
2
ctree.c
@ -378,7 +378,7 @@ int btrfs_realloc_node(struct btrfs_trans_handle *trans,
|
||||
|
||||
cur = btrfs_find_tree_block(root, blocknr, blocksize);
|
||||
if (cur)
|
||||
uptodate = btrfs_buffer_uptodate(cur);
|
||||
uptodate = btrfs_buffer_uptodate(cur, gen);
|
||||
else
|
||||
uptodate = 0;
|
||||
if (!cur || !uptodate) {
|
||||
|
47
disk-io.c
47
disk-io.c
@ -106,7 +106,7 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
|
||||
struct btrfs_device *device;
|
||||
|
||||
eb = btrfs_find_tree_block(root, bytenr, blocksize);
|
||||
if (eb && btrfs_buffer_uptodate(eb)) {
|
||||
if (eb && btrfs_buffer_uptodate(eb, parent_transid)) {
|
||||
free_extent_buffer(eb);
|
||||
return 0;
|
||||
}
|
||||
@ -124,6 +124,31 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int verify_parent_transid(struct extent_io_tree *io_tree,
|
||||
struct extent_buffer *eb, u64 parent_transid)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!parent_transid || btrfs_header_generation(eb) == parent_transid)
|
||||
return 0;
|
||||
|
||||
if (extent_buffer_uptodate(eb) &&
|
||||
btrfs_header_generation(eb) == parent_transid) {
|
||||
ret = 0;
|
||||
goto out;
|
||||
}
|
||||
printk("parent transid verify failed on %llu wanted %llu found %llu\n",
|
||||
(unsigned long long)eb->start,
|
||||
(unsigned long long)parent_transid,
|
||||
(unsigned long long)btrfs_header_generation(eb));
|
||||
ret = 1;
|
||||
out:
|
||||
clear_extent_buffer_uptodate(io_tree, eb);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
|
||||
u32 blocksize, u64 parent_transid)
|
||||
{
|
||||
@ -140,7 +165,7 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
|
||||
if (!eb)
|
||||
return NULL;
|
||||
|
||||
if (btrfs_buffer_uptodate(eb))
|
||||
if (btrfs_buffer_uptodate(eb, parent_transid))
|
||||
return eb;
|
||||
|
||||
dev_nr = 0;
|
||||
@ -156,19 +181,18 @@ struct extent_buffer *read_tree_block(struct btrfs_root *root, u64 bytenr,
|
||||
kfree(multi);
|
||||
ret = read_extent_from_disk(eb);
|
||||
if (ret == 0 && check_tree_block(root, eb) == 0 &&
|
||||
csum_tree_block(root, eb, 1) == 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) {
|
||||
printk("reading %Lu failed only one copy\n", eb->start);
|
||||
break;
|
||||
}
|
||||
mirror_num++;
|
||||
if (mirror_num > num_copies) {
|
||||
printk("bailing at mirror %d of %d\n", mirror_num, num_copies);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -186,7 +210,7 @@ int write_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root,
|
||||
|
||||
if (check_tree_block(root, eb))
|
||||
BUG();
|
||||
if (!btrfs_buffer_uptodate(eb))
|
||||
if (!btrfs_buffer_uptodate(eb, trans->transid))
|
||||
BUG();
|
||||
|
||||
btrfs_set_header_flag(eb, BTRFS_HEADER_FLAG_WRITTEN);
|
||||
@ -773,9 +797,16 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *eb)
|
||||
set_extent_buffer_dirty(eb);
|
||||
}
|
||||
|
||||
int btrfs_buffer_uptodate(struct extent_buffer *eb)
|
||||
int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid)
|
||||
{
|
||||
return extent_buffer_uptodate(eb);
|
||||
int ret;
|
||||
|
||||
ret = extent_buffer_uptodate(buf);
|
||||
if (!ret)
|
||||
return ret;
|
||||
|
||||
ret = verify_parent_transid(buf->tree, buf, parent_transid);
|
||||
return !ret;
|
||||
}
|
||||
|
||||
int btrfs_set_buffer_uptodate(struct extent_buffer *eb)
|
||||
|
@ -46,7 +46,7 @@ struct btrfs_root *btrfs_read_fs_root(struct btrfs_fs_info *fs_info,
|
||||
struct btrfs_key *location);
|
||||
int btrfs_free_fs_root(struct btrfs_fs_info *fs_info, struct btrfs_root *root);
|
||||
void btrfs_mark_buffer_dirty(struct extent_buffer *buf);
|
||||
int btrfs_buffer_uptodate(struct extent_buffer *buf);
|
||||
int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid);
|
||||
int btrfs_set_buffer_uptodate(struct extent_buffer *buf);
|
||||
int wait_on_tree_block_writeback(struct btrfs_root *root,
|
||||
struct extent_buffer *buf);
|
||||
|
@ -1253,7 +1253,7 @@ static int pin_down_bytes(struct btrfs_root *root, u64 bytenr, u32 num_bytes,
|
||||
if (!pending) {
|
||||
buf = btrfs_find_tree_block(root, bytenr, num_bytes);
|
||||
if (buf) {
|
||||
if (btrfs_buffer_uptodate(buf)) {
|
||||
if (btrfs_buffer_uptodate(buf, 0)) {
|
||||
u64 transid =
|
||||
root->fs_info->running_transaction->transid;
|
||||
if (btrfs_header_generation(buf) ==
|
||||
@ -1967,7 +1967,7 @@ static int noinline walk_down_tree(struct btrfs_trans_handle *trans,
|
||||
continue;
|
||||
}
|
||||
next = btrfs_find_tree_block(root, bytenr, blocksize);
|
||||
if (!next || !btrfs_buffer_uptodate(next)) {
|
||||
if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) {
|
||||
free_extent_buffer(next);
|
||||
reada_walk_down(root, cur, path->slots[*level]);
|
||||
mutex_unlock(&root->fs_info->fs_mutex);
|
||||
|
@ -1,3 +1,4 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2007 Oracle. All rights reserved.
|
||||
*
|
||||
@ -688,6 +689,13 @@ int set_extent_buffer_uptodate(struct extent_buffer *eb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
|
||||
struct extent_buffer *eb)
|
||||
{
|
||||
eb->flags &= ~EXTENT_UPTODATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int extent_buffer_uptodate(struct extent_buffer *eb)
|
||||
{
|
||||
if (eb->flags & EXTENT_UPTODATE)
|
||||
|
@ -84,6 +84,8 @@ int clear_extent_dirty(struct extent_io_tree *tree, u64 start,
|
||||
u64 end, gfp_t mask);
|
||||
int extent_buffer_uptodate(struct extent_buffer *eb);
|
||||
int set_extent_buffer_uptodate(struct extent_buffer *eb);
|
||||
int clear_extent_buffer_uptodate(struct extent_io_tree *tree,
|
||||
struct extent_buffer *eb);
|
||||
int set_state_private(struct extent_io_tree *tree, u64 start, u64 private);
|
||||
int get_state_private(struct extent_io_tree *tree, u64 start, u64 *private);
|
||||
struct extent_buffer *find_extent_buffer(struct extent_io_tree *tree,
|
||||
|
Loading…
Reference in New Issue
Block a user