diff options
author | Chris Mason <chris.mason@oracle.com> | 2007-04-02 10:50:19 -0400 |
---|---|---|
committer | David Woodhouse <dwmw2@hera.kernel.org> | 2007-04-02 10:50:19 -0400 |
commit | 2c90e5d658424bc71b111eb5a972240d5d06fe86 (patch) | |
tree | f46b830654af0f67ef1691353fe4d79943a05465 /fs/btrfs/ctree.c | |
parent | d6025579531b7ea170ba283b171ff7a6bf7d0e12 (diff) |
Btrfs: still corruption hunting
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/ctree.c')
-rw-r--r-- | fs/btrfs/ctree.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index a0dfa2d6cb9b..453ce835209a 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c | |||
@@ -16,6 +16,16 @@ static int balance_node_right(struct btrfs_trans_handle *trans, struct | |||
16 | static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 16 | static int del_ptr(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
17 | struct btrfs_path *path, int level, int slot); | 17 | struct btrfs_path *path, int level, int slot); |
18 | 18 | ||
19 | struct btrfs_path *btrfs_alloc_path(void) | ||
20 | { | ||
21 | return kmem_cache_alloc(btrfs_path_cachep, GFP_NOFS); | ||
22 | } | ||
23 | |||
24 | void btrfs_free_path(struct btrfs_path *p) | ||
25 | { | ||
26 | kmem_cache_free(btrfs_path_cachep, p); | ||
27 | } | ||
28 | |||
19 | inline void btrfs_init_path(struct btrfs_path *p) | 29 | inline void btrfs_init_path(struct btrfs_path *p) |
20 | { | 30 | { |
21 | memset(p, 0, sizeof(*p)); | 31 | memset(p, 0, sizeof(*p)); |
@@ -47,17 +57,18 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
47 | } | 57 | } |
48 | cow = btrfs_alloc_free_block(trans, root); | 58 | cow = btrfs_alloc_free_block(trans, root); |
49 | cow_node = btrfs_buffer_node(cow); | 59 | cow_node = btrfs_buffer_node(cow); |
60 | if (buf->b_size != root->blocksize || cow->b_size != root->blocksize) | ||
61 | WARN_ON(1); | ||
50 | memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize); | 62 | memcpy(cow_node, btrfs_buffer_node(buf), root->blocksize); |
51 | btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr); | 63 | btrfs_set_header_blocknr(&cow_node->header, cow->b_blocknr); |
52 | btrfs_set_header_generation(&cow_node->header, trans->transid); | 64 | btrfs_set_header_generation(&cow_node->header, trans->transid); |
53 | *cow_ret = cow; | ||
54 | btrfs_mark_buffer_dirty(cow); | ||
55 | btrfs_inc_ref(trans, root, buf); | 65 | btrfs_inc_ref(trans, root, buf); |
56 | if (buf == root->node) { | 66 | if (buf == root->node) { |
57 | root->node = cow; | 67 | root->node = cow; |
58 | get_bh(cow); | 68 | get_bh(cow); |
59 | if (buf != root->commit_root) | 69 | if (buf != root->commit_root) { |
60 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); | 70 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); |
71 | } | ||
61 | btrfs_block_release(root, buf); | 72 | btrfs_block_release(root, buf); |
62 | } else { | 73 | } else { |
63 | btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot, | 74 | btrfs_set_node_blockptr(btrfs_buffer_node(parent), parent_slot, |
@@ -66,6 +77,7 @@ static int btrfs_cow_block(struct btrfs_trans_handle *trans, struct btrfs_root | |||
66 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); | 77 | btrfs_free_extent(trans, root, buf->b_blocknr, 1, 1); |
67 | } | 78 | } |
68 | btrfs_block_release(root, buf); | 79 | btrfs_block_release(root, buf); |
80 | *cow_ret = cow; | ||
69 | return 0; | 81 | return 0; |
70 | } | 82 | } |
71 | 83 | ||
@@ -477,9 +489,12 @@ again: | |||
477 | p->slots[level + 1], | 489 | p->slots[level + 1], |
478 | &cow_buf); | 490 | &cow_buf); |
479 | b = cow_buf; | 491 | b = cow_buf; |
492 | c = btrfs_buffer_node(b); | ||
480 | } | 493 | } |
481 | BUG_ON(!cow && ins_len); | 494 | BUG_ON(!cow && ins_len); |
482 | c = btrfs_buffer_node(b); | 495 | if (level != btrfs_header_level(&c->header)) |
496 | WARN_ON(1); | ||
497 | level = btrfs_header_level(&c->header); | ||
483 | p->nodes[level] = b; | 498 | p->nodes[level] = b; |
484 | ret = check_block(root, p, level); | 499 | ret = check_block(root, p, level); |
485 | if (ret) | 500 | if (ret) |
@@ -1257,19 +1272,22 @@ int btrfs_insert_item(struct btrfs_trans_handle *trans, struct btrfs_root | |||
1257 | data_size) | 1272 | data_size) |
1258 | { | 1273 | { |
1259 | int ret = 0; | 1274 | int ret = 0; |
1260 | struct btrfs_path path; | 1275 | struct btrfs_path *path; |
1261 | u8 *ptr; | 1276 | u8 *ptr; |
1262 | 1277 | ||
1263 | btrfs_init_path(&path); | 1278 | path = btrfs_alloc_path(); |
1264 | ret = btrfs_insert_empty_item(trans, root, &path, cpu_key, data_size); | 1279 | BUG_ON(!path); |
1280 | btrfs_init_path(path); | ||
1281 | ret = btrfs_insert_empty_item(trans, root, path, cpu_key, data_size); | ||
1265 | if (!ret) { | 1282 | if (!ret) { |
1266 | ptr = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), | 1283 | ptr = btrfs_item_ptr(btrfs_buffer_leaf(path->nodes[0]), |
1267 | path.slots[0], u8); | 1284 | path->slots[0], u8); |
1268 | btrfs_memcpy(root, path.nodes[0]->b_data, | 1285 | btrfs_memcpy(root, path->nodes[0]->b_data, |
1269 | ptr, data, data_size); | 1286 | ptr, data, data_size); |
1270 | btrfs_mark_buffer_dirty(path.nodes[0]); | 1287 | btrfs_mark_buffer_dirty(path->nodes[0]); |
1271 | } | 1288 | } |
1272 | btrfs_release_path(root, &path); | 1289 | btrfs_release_path(root, path); |
1290 | btrfs_free_path(path); | ||
1273 | return ret; | 1291 | return ret; |
1274 | } | 1292 | } |
1275 | 1293 | ||