diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-05-11 11:33:21 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-05-11 11:33:21 -0400 |
commit | 098f59c2512426926722a96f82af127bd91fb5e4 (patch) | |
tree | d4f281ac0c6d61a8ee443b9fe8b49434e82618a2 | |
parent | 509659cde578d891445afd67d87121dd13e71596 (diff) |
Btrfs: patch queue: fix corruption when splitting large items
Signed-off-by: Chris Mason <chris.mason@oracle.com>
-rw-r--r-- | fs/btrfs/ctree.c | 10 | ||||
-rw-r--r-- | fs/btrfs/super.c | 8 |
2 files changed, 12 insertions, 6 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 990d297a7a13..20e01f95ce6e 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -871,6 +871,7 @@ static int insert_ptr(struct btrfs_trans_handle *trans, struct btrfs_root | |||
871 | btrfs_set_node_blockptr(lower, slot, blocknr); | 871 | btrfs_set_node_blockptr(lower, slot, blocknr); |
872 | btrfs_set_header_nritems(&lower->header, nritems + 1); | 872 | btrfs_set_header_nritems(&lower->header, nritems + 1); |
873 | btrfs_mark_buffer_dirty(path->nodes[level]); | 873 | btrfs_mark_buffer_dirty(path->nodes[level]); |
874 | check_node(root, path, level); | ||
874 | return 0; | 875 | return 0; |
875 | } | 876 | } |
876 | 877 | ||
@@ -1101,6 +1102,8 @@ static int push_leaf_right(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1101 | } else { | 1102 | } else { |
1102 | btrfs_block_release(root, right_buf); | 1103 | btrfs_block_release(root, right_buf); |
1103 | } | 1104 | } |
1105 | if (path->nodes[1]) | ||
1106 | check_node(root, path, 1); | ||
1104 | return 0; | 1107 | return 0; |
1105 | } | 1108 | } |
1106 | /* | 1109 | /* |
@@ -1216,6 +1219,7 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1216 | 1219 | ||
1217 | btrfs_mark_buffer_dirty(t); | 1220 | btrfs_mark_buffer_dirty(t); |
1218 | btrfs_mark_buffer_dirty(right_buf); | 1221 | btrfs_mark_buffer_dirty(right_buf); |
1222 | |||
1219 | wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); | 1223 | wret = fixup_low_keys(trans, root, path, &right->items[0].key, 1); |
1220 | if (wret) | 1224 | if (wret) |
1221 | ret = wret; | 1225 | ret = wret; |
@@ -1231,6 +1235,8 @@ static int push_leaf_left(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1231 | path->slots[0] -= push_items; | 1235 | path->slots[0] -= push_items; |
1232 | } | 1236 | } |
1233 | BUG_ON(path->slots[0] < 0); | 1237 | BUG_ON(path->slots[0] < 0); |
1238 | if (path->nodes[1]) | ||
1239 | check_node(root, path, 1); | ||
1234 | return ret; | 1240 | return ret; |
1235 | } | 1241 | } |
1236 | 1242 | ||
@@ -1326,13 +1332,12 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1326 | wret = insert_ptr(trans, root, path, | 1332 | wret = insert_ptr(trans, root, path, |
1327 | &disk_key, | 1333 | &disk_key, |
1328 | bh_blocknr(right_buffer), | 1334 | bh_blocknr(right_buffer), |
1329 | path->slots[1] - 1, 1); | 1335 | path->slots[1], 1); |
1330 | if (wret) | 1336 | if (wret) |
1331 | ret = wret; | 1337 | ret = wret; |
1332 | btrfs_block_release(root, path->nodes[0]); | 1338 | btrfs_block_release(root, path->nodes[0]); |
1333 | path->nodes[0] = right_buffer; | 1339 | path->nodes[0] = right_buffer; |
1334 | path->slots[0] = 0; | 1340 | path->slots[0] = 0; |
1335 | path->slots[1] -= 1; | ||
1336 | if (path->slots[1] == 0) { | 1341 | if (path->slots[1] == 0) { |
1337 | wret = fixup_low_keys(trans, root, | 1342 | wret = fixup_low_keys(trans, root, |
1338 | path, &disk_key, 1); | 1343 | path, &disk_key, 1); |
@@ -1379,6 +1384,7 @@ static int split_leaf(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1379 | } else | 1384 | } else |
1380 | btrfs_block_release(root, right_buffer); | 1385 | btrfs_block_release(root, right_buffer); |
1381 | BUG_ON(path->slots[0] < 0); | 1386 | BUG_ON(path->slots[0] < 0); |
1387 | check_node(root, path, 1); | ||
1382 | 1388 | ||
1383 | if (!double_split) | 1389 | if (!double_split) |
1384 | return ret; | 1390 | return ret; |
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index 4c2870e2d12f..eaa48f09d1c4 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c | |||
@@ -1529,7 +1529,8 @@ static int dirty_and_release_pages(struct btrfs_trans_handle *trans, | |||
1529 | btrfs_set_file_extent_type(ei, | 1529 | btrfs_set_file_extent_type(ei, |
1530 | BTRFS_FILE_EXTENT_INLINE); | 1530 | BTRFS_FILE_EXTENT_INLINE); |
1531 | ptr = btrfs_file_extent_inline_start(ei); | 1531 | ptr = btrfs_file_extent_inline_start(ei); |
1532 | memcpy(ptr, bh->b_data, offset + write_bytes); | 1532 | btrfs_memcpy(root, path->nodes[0]->b_data, |
1533 | ptr, bh->b_data, offset + write_bytes); | ||
1533 | mark_buffer_dirty(path->nodes[0]); | 1534 | mark_buffer_dirty(path->nodes[0]); |
1534 | btrfs_free_path(path); | 1535 | btrfs_free_path(path); |
1535 | } else { | 1536 | } else { |
@@ -1686,9 +1687,9 @@ static int drop_extents(struct btrfs_trans_handle *trans, | |||
1686 | ret = btrfs_del_item(trans, root, path); | 1687 | ret = btrfs_del_item(trans, root, path); |
1687 | BUG_ON(ret); | 1688 | BUG_ON(ret); |
1688 | btrfs_release_path(root, path); | 1689 | btrfs_release_path(root, path); |
1690 | extent = NULL; | ||
1689 | if (found_extent) { | 1691 | if (found_extent) { |
1690 | inode->i_blocks -= | 1692 | inode->i_blocks -= extent_num_blocks << 3; |
1691 | btrfs_file_extent_num_blocks(extent) << 3; | ||
1692 | ret = btrfs_free_extent(trans, root, | 1693 | ret = btrfs_free_extent(trans, root, |
1693 | disk_blocknr, | 1694 | disk_blocknr, |
1694 | disk_num_blocks, 0); | 1695 | disk_num_blocks, 0); |
@@ -1832,7 +1833,6 @@ static ssize_t btrfs_file_write(struct file *file, const char __user *buf, | |||
1832 | u64 alloc_extent_start; | 1833 | u64 alloc_extent_start; |
1833 | struct btrfs_trans_handle *trans; | 1834 | struct btrfs_trans_handle *trans; |
1834 | struct btrfs_key ins; | 1835 | struct btrfs_key ins; |
1835 | |||
1836 | pinned[0] = NULL; | 1836 | pinned[0] = NULL; |
1837 | pinned[1] = NULL; | 1837 | pinned[1] = NULL; |
1838 | if (file->f_flags & O_DIRECT) | 1838 | if (file->f_flags & O_DIRECT) |