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/disk-io.c | |
parent | d6025579531b7ea170ba283b171ff7a6bf7d0e12 (diff) |
Btrfs: still corruption hunting
Signed-off-by: Chris Mason <chris.mason@oracle.com>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 84 |
1 files changed, 41 insertions, 43 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index bb133104e2e9..2dbd55084a4e 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -8,18 +8,6 @@ | |||
8 | #include "disk-io.h" | 8 | #include "disk-io.h" |
9 | #include "transaction.h" | 9 | #include "transaction.h" |
10 | 10 | ||
11 | #define PATTERN 0xDEADBEEFUL | ||
12 | static inline void check_pattern(struct buffer_head *buf) | ||
13 | { | ||
14 | if (buf->b_private != (void *)PATTERN) | ||
15 | WARN_ON(1); | ||
16 | } | ||
17 | |||
18 | static inline void set_pattern(struct buffer_head *buf) | ||
19 | { | ||
20 | buf->b_private = (void *)PATTERN; | ||
21 | } | ||
22 | |||
23 | static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) | 11 | static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) |
24 | { | 12 | { |
25 | struct btrfs_node *node = btrfs_buffer_node(buf); | 13 | struct btrfs_node *node = btrfs_buffer_node(buf); |
@@ -35,6 +23,8 @@ static int check_tree_block(struct btrfs_root *root, struct buffer_head *buf) | |||
35 | 23 | ||
36 | struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr) | 24 | struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr) |
37 | { | 25 | { |
26 | return sb_find_get_block(root->fs_info->sb, blocknr); | ||
27 | #if 0 | ||
38 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; | 28 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; |
39 | int blockbits = root->fs_info->sb->s_blocksize_bits; | 29 | int blockbits = root->fs_info->sb->s_blocksize_bits; |
40 | unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); | 30 | unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); |
@@ -43,6 +33,7 @@ struct buffer_head *btrfs_find_tree_block(struct btrfs_root *root, u64 blocknr) | |||
43 | struct buffer_head *head; | 33 | struct buffer_head *head; |
44 | struct buffer_head *ret = NULL; | 34 | struct buffer_head *ret = NULL; |
45 | 35 | ||
36 | |||
46 | page = find_lock_page(mapping, index); | 37 | page = find_lock_page(mapping, index); |
47 | if (!page) | 38 | if (!page) |
48 | return NULL; | 39 | return NULL; |
@@ -64,15 +55,17 @@ out_unlock: | |||
64 | unlock_page(page); | 55 | unlock_page(page); |
65 | if (ret) { | 56 | if (ret) { |
66 | touch_buffer(ret); | 57 | touch_buffer(ret); |
67 | check_pattern(ret); | ||
68 | } | 58 | } |
69 | page_cache_release(page); | 59 | page_cache_release(page); |
70 | return ret; | 60 | return ret; |
61 | #endif | ||
71 | } | 62 | } |
72 | 63 | ||
73 | struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, | 64 | struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, |
74 | u64 blocknr) | 65 | u64 blocknr) |
75 | { | 66 | { |
67 | return sb_getblk(root->fs_info->sb, blocknr); | ||
68 | #if 0 | ||
76 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; | 69 | struct address_space *mapping = root->fs_info->btree_inode->i_mapping; |
77 | int blockbits = root->fs_info->sb->s_blocksize_bits; | 70 | int blockbits = root->fs_info->sb->s_blocksize_bits; |
78 | unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); | 71 | unsigned long index = blocknr >> (PAGE_CACHE_SHIFT - blockbits); |
@@ -95,7 +88,6 @@ struct buffer_head *btrfs_find_create_tree_block(struct btrfs_root *root, | |||
95 | bh->b_bdev = root->fs_info->sb->s_bdev; | 88 | bh->b_bdev = root->fs_info->sb->s_bdev; |
96 | bh->b_blocknr = first_block; | 89 | bh->b_blocknr = first_block; |
97 | set_buffer_mapped(bh); | 90 | set_buffer_mapped(bh); |
98 | set_pattern(bh); | ||
99 | } | 91 | } |
100 | if (bh->b_blocknr == blocknr) { | 92 | if (bh->b_blocknr == blocknr) { |
101 | ret = bh; | 93 | ret = bh; |
@@ -111,6 +103,7 @@ out_unlock: | |||
111 | touch_buffer(ret); | 103 | touch_buffer(ret); |
112 | page_cache_release(page); | 104 | page_cache_release(page); |
113 | return ret; | 105 | return ret; |
106 | #endif | ||
114 | } | 107 | } |
115 | 108 | ||
116 | static sector_t max_block(struct block_device *bdev) | 109 | static sector_t max_block(struct block_device *bdev) |
@@ -225,6 +218,8 @@ static struct address_space_operations btree_aops = { | |||
225 | 218 | ||
226 | struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) | 219 | struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) |
227 | { | 220 | { |
221 | return sb_bread(root->fs_info->sb, blocknr); | ||
222 | #if 0 | ||
228 | struct buffer_head *bh = NULL; | 223 | struct buffer_head *bh = NULL; |
229 | 224 | ||
230 | bh = btrfs_find_create_tree_block(root, blocknr); | 225 | bh = btrfs_find_create_tree_block(root, blocknr); |
@@ -239,7 +234,6 @@ struct buffer_head *read_tree_block(struct btrfs_root *root, u64 blocknr) | |||
239 | if (!buffer_uptodate(bh)) | 234 | if (!buffer_uptodate(bh)) |
240 | goto fail; | 235 | goto fail; |
241 | csum_tree_block(root, bh, 1); | 236 | csum_tree_block(root, bh, 1); |
242 | set_pattern(bh); | ||
243 | } else { | 237 | } else { |
244 | unlock_buffer(bh); | 238 | unlock_buffer(bh); |
245 | } | 239 | } |
@@ -250,6 +244,7 @@ fail: | |||
250 | brelse(bh); | 244 | brelse(bh); |
251 | return NULL; | 245 | return NULL; |
252 | 246 | ||
247 | #endif | ||
253 | } | 248 | } |
254 | 249 | ||
255 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | 250 | int dirty_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, |
@@ -268,14 +263,14 @@ int clean_tree_block(struct btrfs_trans_handle *trans, struct btrfs_root *root, | |||
268 | return 0; | 263 | return 0; |
269 | } | 264 | } |
270 | 265 | ||
271 | static int __setup_root(struct btrfs_super_block *super, | 266 | static int __setup_root(int blocksize, |
272 | struct btrfs_root *root, | 267 | struct btrfs_root *root, |
273 | struct btrfs_fs_info *fs_info, | 268 | struct btrfs_fs_info *fs_info, |
274 | u64 objectid) | 269 | u64 objectid) |
275 | { | 270 | { |
276 | root->node = NULL; | 271 | root->node = NULL; |
277 | root->commit_root = NULL; | 272 | root->commit_root = NULL; |
278 | root->blocksize = btrfs_super_blocksize(super); | 273 | root->blocksize = blocksize; |
279 | root->ref_cows = 0; | 274 | root->ref_cows = 0; |
280 | root->fs_info = fs_info; | 275 | root->fs_info = fs_info; |
281 | memset(&root->root_key, 0, sizeof(root->root_key)); | 276 | memset(&root->root_key, 0, sizeof(root->root_key)); |
@@ -283,7 +278,7 @@ static int __setup_root(struct btrfs_super_block *super, | |||
283 | return 0; | 278 | return 0; |
284 | } | 279 | } |
285 | 280 | ||
286 | static int find_and_setup_root(struct btrfs_super_block *super, | 281 | static int find_and_setup_root(int blocksize, |
287 | struct btrfs_root *tree_root, | 282 | struct btrfs_root *tree_root, |
288 | struct btrfs_fs_info *fs_info, | 283 | struct btrfs_fs_info *fs_info, |
289 | u64 objectid, | 284 | u64 objectid, |
@@ -291,7 +286,7 @@ static int find_and_setup_root(struct btrfs_super_block *super, | |||
291 | { | 286 | { |
292 | int ret; | 287 | int ret; |
293 | 288 | ||
294 | __setup_root(super, root, fs_info, objectid); | 289 | __setup_root(blocksize, root, fs_info, objectid); |
295 | ret = btrfs_find_last_root(tree_root, objectid, | 290 | ret = btrfs_find_last_root(tree_root, objectid, |
296 | &root->root_item, &root->root_key); | 291 | &root->root_item, &root->root_key); |
297 | BUG_ON(ret); | 292 | BUG_ON(ret); |
@@ -302,9 +297,7 @@ static int find_and_setup_root(struct btrfs_super_block *super, | |||
302 | return 0; | 297 | return 0; |
303 | } | 298 | } |
304 | 299 | ||
305 | struct btrfs_root *open_ctree(struct super_block *sb, | 300 | struct btrfs_root *open_ctree(struct super_block *sb) |
306 | struct buffer_head *sb_buffer, | ||
307 | struct btrfs_super_block *disk_super) | ||
308 | { | 301 | { |
309 | struct btrfs_root *root = kmalloc(sizeof(struct btrfs_root), | 302 | struct btrfs_root *root = kmalloc(sizeof(struct btrfs_root), |
310 | GFP_NOFS); | 303 | GFP_NOFS); |
@@ -317,13 +310,11 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
317 | struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), | 310 | struct btrfs_fs_info *fs_info = kmalloc(sizeof(*fs_info), |
318 | GFP_NOFS); | 311 | GFP_NOFS); |
319 | int ret; | 312 | int ret; |
313 | struct btrfs_super_block *disk_super; | ||
320 | 314 | ||
321 | if (!btrfs_super_root(disk_super)) { | ||
322 | return NULL; | ||
323 | } | ||
324 | init_bit_radix(&fs_info->pinned_radix); | 315 | init_bit_radix(&fs_info->pinned_radix); |
325 | init_bit_radix(&fs_info->pending_del_radix); | 316 | init_bit_radix(&fs_info->pending_del_radix); |
326 | sb_set_blocksize(sb, sb_buffer->b_size); | 317 | sb_set_blocksize(sb, 4096); |
327 | fs_info->running_transaction = NULL; | 318 | fs_info->running_transaction = NULL; |
328 | fs_info->fs_root = root; | 319 | fs_info->fs_root = root; |
329 | fs_info->tree_root = tree_root; | 320 | fs_info->tree_root = tree_root; |
@@ -331,55 +322,59 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
331 | fs_info->inode_root = inode_root; | 322 | fs_info->inode_root = inode_root; |
332 | fs_info->last_inode_alloc = 0; | 323 | fs_info->last_inode_alloc = 0; |
333 | fs_info->last_inode_alloc_dirid = 0; | 324 | fs_info->last_inode_alloc_dirid = 0; |
334 | fs_info->disk_super = disk_super; | ||
335 | fs_info->sb = sb; | 325 | fs_info->sb = sb; |
326 | fs_info->btree_inode = NULL; | ||
327 | #if 0 | ||
336 | fs_info->btree_inode = new_inode(sb); | 328 | fs_info->btree_inode = new_inode(sb); |
337 | fs_info->btree_inode->i_ino = 1; | 329 | fs_info->btree_inode->i_ino = 1; |
330 | fs_info->btree_inode->i_nlink = 1; | ||
338 | fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; | 331 | fs_info->btree_inode->i_size = sb->s_bdev->bd_inode->i_size; |
339 | fs_info->btree_inode->i_mapping->a_ops = &btree_aops; | 332 | fs_info->btree_inode->i_mapping->a_ops = &btree_aops; |
340 | insert_inode_hash(fs_info->btree_inode); | 333 | insert_inode_hash(fs_info->btree_inode); |
341 | |||
342 | mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); | 334 | mapping_set_gfp_mask(fs_info->btree_inode->i_mapping, GFP_NOFS); |
335 | #endif | ||
343 | fs_info->hash_tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); | 336 | fs_info->hash_tfm = crypto_alloc_hash("sha256", 0, CRYPTO_ALG_ASYNC); |
344 | spin_lock_init(&fs_info->hash_lock); | 337 | spin_lock_init(&fs_info->hash_lock); |
345 | |||
346 | if (!fs_info->hash_tfm || IS_ERR(fs_info->hash_tfm)) { | 338 | if (!fs_info->hash_tfm || IS_ERR(fs_info->hash_tfm)) { |
347 | printk("failed to allocate sha256 hash\n"); | 339 | printk("failed to allocate sha256 hash\n"); |
348 | return NULL; | 340 | return NULL; |
349 | } | 341 | } |
350 | |||
351 | mutex_init(&fs_info->trans_mutex); | 342 | mutex_init(&fs_info->trans_mutex); |
352 | mutex_init(&fs_info->fs_mutex); | 343 | mutex_init(&fs_info->fs_mutex); |
353 | memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert)); | 344 | memset(&fs_info->current_insert, 0, sizeof(fs_info->current_insert)); |
354 | memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); | 345 | memset(&fs_info->last_insert, 0, sizeof(fs_info->last_insert)); |
355 | 346 | ||
356 | __setup_root(disk_super, tree_root, fs_info, BTRFS_ROOT_TREE_OBJECTID); | 347 | __setup_root(sb->s_blocksize, tree_root, |
357 | 348 | fs_info, BTRFS_ROOT_TREE_OBJECTID); | |
358 | fs_info->sb_buffer = read_tree_block(tree_root, sb_buffer->b_blocknr); | 349 | fs_info->sb_buffer = read_tree_block(tree_root, |
350 | BTRFS_SUPER_INFO_OFFSET / | ||
351 | sb->s_blocksize); | ||
359 | 352 | ||
360 | if (!fs_info->sb_buffer) { | 353 | if (!fs_info->sb_buffer) { |
361 | printk("failed2\n"); | 354 | printk("failed2\n"); |
362 | return NULL; | 355 | return NULL; |
363 | } | 356 | } |
364 | brelse(sb_buffer); | ||
365 | sb_buffer = NULL; | ||
366 | disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data; | 357 | disk_super = (struct btrfs_super_block *)fs_info->sb_buffer->b_data; |
358 | if (!btrfs_super_root(disk_super)) { | ||
359 | return NULL; | ||
360 | } | ||
367 | fs_info->disk_super = disk_super; | 361 | fs_info->disk_super = disk_super; |
368 | |||
369 | tree_root->node = read_tree_block(tree_root, | 362 | tree_root->node = read_tree_block(tree_root, |
370 | btrfs_super_root(disk_super)); | 363 | btrfs_super_root(disk_super)); |
371 | BUG_ON(!tree_root->node); | 364 | BUG_ON(!tree_root->node); |
372 | 365 | ||
373 | ret = find_and_setup_root(disk_super, tree_root, fs_info, | 366 | mutex_lock(&fs_info->fs_mutex); |
367 | ret = find_and_setup_root(sb->s_blocksize, tree_root, fs_info, | ||
374 | BTRFS_EXTENT_TREE_OBJECTID, extent_root); | 368 | BTRFS_EXTENT_TREE_OBJECTID, extent_root); |
375 | BUG_ON(ret); | 369 | BUG_ON(ret); |
376 | 370 | ||
377 | ret = find_and_setup_root(disk_super, tree_root, fs_info, | 371 | ret = find_and_setup_root(sb->s_blocksize, tree_root, fs_info, |
378 | BTRFS_INODE_MAP_OBJECTID, inode_root); | 372 | BTRFS_INODE_MAP_OBJECTID, inode_root); |
379 | BUG_ON(ret); | 373 | BUG_ON(ret); |
380 | 374 | ||
381 | ret = find_and_setup_root(disk_super, tree_root, fs_info, | 375 | ret = find_and_setup_root(sb->s_blocksize, tree_root, fs_info, |
382 | BTRFS_FS_TREE_OBJECTID, root); | 376 | BTRFS_FS_TREE_OBJECTID, root); |
377 | mutex_unlock(&fs_info->fs_mutex); | ||
383 | BUG_ON(ret); | 378 | BUG_ON(ret); |
384 | root->commit_root = root->node; | 379 | root->commit_root = root->node; |
385 | get_bh(root->node); | 380 | get_bh(root->node); |
@@ -392,9 +387,11 @@ int write_ctree_super(struct btrfs_trans_handle *trans, struct btrfs_root | |||
392 | *root) | 387 | *root) |
393 | { | 388 | { |
394 | struct buffer_head *bh = root->fs_info->sb_buffer; | 389 | struct buffer_head *bh = root->fs_info->sb_buffer; |
390 | |||
395 | btrfs_set_super_root(root->fs_info->disk_super, | 391 | btrfs_set_super_root(root->fs_info->disk_super, |
396 | root->fs_info->tree_root->node->b_blocknr); | 392 | root->fs_info->tree_root->node->b_blocknr); |
397 | lock_buffer(bh); | 393 | lock_buffer(bh); |
394 | WARN_ON(atomic_read(&bh->b_count) < 1); | ||
398 | clear_buffer_dirty(bh); | 395 | clear_buffer_dirty(bh); |
399 | csum_tree_block(root, bh, 0); | 396 | csum_tree_block(root, bh, 0); |
400 | bh->b_end_io = end_buffer_write_sync; | 397 | bh->b_end_io = end_buffer_write_sync; |
@@ -413,6 +410,7 @@ int close_ctree(struct btrfs_root *root) | |||
413 | int ret; | 410 | int ret; |
414 | struct btrfs_trans_handle *trans; | 411 | struct btrfs_trans_handle *trans; |
415 | 412 | ||
413 | mutex_lock(&root->fs_info->fs_mutex); | ||
416 | trans = btrfs_start_transaction(root, 1); | 414 | trans = btrfs_start_transaction(root, 1); |
417 | btrfs_commit_transaction(trans, root); | 415 | btrfs_commit_transaction(trans, root); |
418 | /* run commit again to drop the original snapshot */ | 416 | /* run commit again to drop the original snapshot */ |
@@ -421,6 +419,7 @@ int close_ctree(struct btrfs_root *root) | |||
421 | ret = btrfs_write_and_wait_transaction(NULL, root); | 419 | ret = btrfs_write_and_wait_transaction(NULL, root); |
422 | BUG_ON(ret); | 420 | BUG_ON(ret); |
423 | write_ctree_super(NULL, root); | 421 | write_ctree_super(NULL, root); |
422 | mutex_unlock(&root->fs_info->fs_mutex); | ||
424 | 423 | ||
425 | if (root->node) | 424 | if (root->node) |
426 | btrfs_block_release(root, root->node); | 425 | btrfs_block_release(root, root->node); |
@@ -436,8 +435,8 @@ int close_ctree(struct btrfs_root *root) | |||
436 | btrfs_block_release(root, root->commit_root); | 435 | btrfs_block_release(root, root->commit_root); |
437 | btrfs_block_release(root, root->fs_info->sb_buffer); | 436 | btrfs_block_release(root, root->fs_info->sb_buffer); |
438 | crypto_free_hash(root->fs_info->hash_tfm); | 437 | crypto_free_hash(root->fs_info->hash_tfm); |
439 | truncate_inode_pages(root->fs_info->btree_inode->i_mapping, 0); | 438 | // truncate_inode_pages(root->fs_info->btree_inode->i_mapping, 0); |
440 | iput(root->fs_info->btree_inode); | 439 | // iput(root->fs_info->btree_inode); |
441 | kfree(root->fs_info->extent_root); | 440 | kfree(root->fs_info->extent_root); |
442 | kfree(root->fs_info->inode_root); | 441 | kfree(root->fs_info->inode_root); |
443 | kfree(root->fs_info->tree_root); | 442 | kfree(root->fs_info->tree_root); |
@@ -448,7 +447,6 @@ int close_ctree(struct btrfs_root *root) | |||
448 | 447 | ||
449 | void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf) | 448 | void btrfs_block_release(struct btrfs_root *root, struct buffer_head *buf) |
450 | { | 449 | { |
451 | check_pattern(buf); | 450 | // brelse(buf); |
452 | brelse(buf); | ||
453 | } | 451 | } |
454 | 452 | ||