aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorChris Mason <chris.mason@oracle.com>2007-05-11 11:33:21 -0400
committerDavid Woodhouse <dwmw2@hera.kernel.org>2007-05-11 11:33:21 -0400
commit098f59c2512426926722a96f82af127bd91fb5e4 (patch)
treed4f281ac0c6d61a8ee443b9fe8b49434e82618a2 /fs
parent509659cde578d891445afd67d87121dd13e71596 (diff)
Btrfs: patch queue: fix corruption when splitting large items
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.c10
-rw-r--r--fs/btrfs/super.c8
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)