Btrfs: patch queue: fix corruption when splitting large items
Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
509659cde5
commit
098f59c251
|
@ -871,6 +871,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
btrfs_set_node_blockptr(lower, slot, blocknr);
|
btrfs_set_node_blockptr(lower, slot, blocknr);
|
||||||
btrfs_set_header_nritems(&lower->header, nritems + 1);
|
btrfs_set_header_nritems(&lower->header, nritems + 1);
|
||||||
btrfs_mark_buffer_dirty(path->nodes[level]);
|
btrfs_mark_buffer_dirty(path->nodes[level]);
|
||||||
|
check_node(root, path, level);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1101,6 +1102,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
} else {
|
} else {
|
||||||
btrfs_block_release(root, right_buf);
|
btrfs_block_release(root, right_buf);
|
||||||
}
|
}
|
||||||
|
if (path->nodes[1])
|
||||||
|
check_node(root, path, 1);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -1216,6 +1219,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
|
|
||||||
btrfs_mark_buffer_dirty(t);
|
btrfs_mark_buffer_dirty(t);
|
||||||
btrfs_mark_buffer_dirty(right_buf);
|
btrfs_mark_buffer_dirty(right_buf);
|
||||||
|
|
||||||
wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
|
wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
|
@ -1231,6 +1235,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
path->slots[0] -= push_items;
|
path->slots[0] -= push_items;
|
||||||
}
|
}
|
||||||
BUG_ON(path->slots[0] < 0);
|
BUG_ON(path->slots[0] < 0);
|
||||||
|
if (path->nodes[1])
|
||||||
|
check_node(root, path, 1);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1326,13 +1332,12 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
wret = insert_ptr(trans, root, path,
|
wret = insert_ptr(trans, root, path,
|
||||||
&disk_key,
|
&disk_key,
|
||||||
bh_blocknr(right_buffer),
|
bh_blocknr(right_buffer),
|
||||||
path->slots[1] - 1, 1);
|
path->slots[1], 1);
|
||||||
if (wret)
|
if (wret)
|
||||||
ret = wret;
|
ret = wret;
|
||||||
btrfs_block_release(root, path->nodes[0]);
|
btrfs_block_release(root, path->nodes[0]);
|
||||||
path->nodes[0] = right_buffer;
|
path->nodes[0] = right_buffer;
|
||||||
path->slots[0] = 0;
|
path->slots[0] = 0;
|
||||||
path->slots[1] -= 1;
|
|
||||||
if (path->slots[1] == 0) {
|
if (path->slots[1] == 0) {
|
||||||
wret = fixup_low_keys(trans, root,
|
wret = fixup_low_keys(trans, root,
|
||||||
path, &disk_key, 1);
|
path, &disk_key, 1);
|
||||||
|
@ -1379,6 +1384,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root
|
||||||
} else
|
} else
|
||||||
btrfs_block_release(root, right_buffer);
|
btrfs_block_release(root, right_buffer);
|
||||||
BUG_ON(path->slots[0] < 0);
|
BUG_ON(path->slots[0] < 0);
|
||||||
|
check_node(root, path, 1);
|
||||||
|
|
||||||
if (!double_split)
|
if (!double_split)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
|
@ -1529,7 +1529,8 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans,
|
||||||
btrfs_set_file_extent_type(ei,
|
btrfs_set_file_extent_type(ei,
|
||||||
BTRFS_FILE_EXTENT_INLINE);
|
BTRFS_FILE_EXTENT_INLINE);
|
||||||
ptr = btrfs_file_extent_inline_start(ei);
|
ptr = btrfs_file_extent_inline_start(ei);
|
||||||
memcpy(ptr, bh->b_data, offset + write_bytes);
|
btrfs_memcpy(root, path->nodes[0]->b_data,
|
||||||
|
ptr, bh->b_data, offset + write_bytes);
|
||||||
mark_buffer_dirty(path->nodes[0]);
|
mark_buffer_dirty(path->nodes[0]);
|
||||||
btrfs_free_path(path);
|
btrfs_free_path(path);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1686,9 +1687,9 @@ static int drop_extents(struct btrfs_trans_handle *trans,
|
||||||
ret = btrfs_del_item(trans, root, path);
|
ret = btrfs_del_item(trans, root, path);
|
||||||
BUG_ON(ret);
|
BUG_ON(ret);
|
||||||
btrfs_release_path(root, path);
|
btrfs_release_path(root, path);
|
||||||
|
extent = NULL;
|
||||||
if (found_extent) {
|
if (found_extent) {
|
||||||
inode->i_blocks -=
|
inode->i_blocks -= extent_num_blocks << 3;
|
||||||
btrfs_file_extent_num_blocks(extent) << 3;
|
|
||||||
ret = btrfs_free_extent(trans, root,
|
ret = btrfs_free_extent(trans, root,
|
||||||
disk_blocknr,
|
disk_blocknr,
|
||||||
disk_num_blocks, 0);
|
disk_num_blocks, 0);
|
||||||
|
@ -1832,7 +1833,6 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf,
|
||||||
u64 alloc_extent_start;
|
u64 alloc_extent_start;
|
||||||
struct btrfs_trans_handle *trans;
|
struct btrfs_trans_handle *trans;
|
||||||
struct btrfs_key ins;
|
struct btrfs_key ins;
|
||||||
|
|
||||||
pinned[0] = NULL;
|
pinned[0] = NULL;
|
||||||
pinned[1] = NULL;
|
pinned[1] = NULL;
|
||||||
if (file->f_flags & O_DIRECT)
|
if (file->f_flags & O_DIRECT)
|
||||||
|
|
Loading…
Reference in New Issue