diff options
| -rw-r--r-- | fs/btrfs/disk-io.c | 45 |
1 files changed, 25 insertions, 20 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index c95e3ce9f22e..f6705252b5b2 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <linux/buffer_head.h> | 25 | #include <linux/buffer_head.h> |
| 26 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
| 27 | #include <linux/kthread.h> | 27 | #include <linux/kthread.h> |
| 28 | #include <linux/freezer.h> | ||
| 29 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 30 | #include <linux/migrate.h> | 29 | #include <linux/migrate.h> |
| 31 | #include <linux/ratelimit.h> | 30 | #include <linux/ratelimit.h> |
| @@ -303,7 +302,7 @@ static int csum_tree_block(struct btrfs_fs_info *fs_info, | |||
| 303 | err = map_private_extent_buffer(buf, offset, 32, | 302 | err = map_private_extent_buffer(buf, offset, 32, |
| 304 | &kaddr, &map_start, &map_len); | 303 | &kaddr, &map_start, &map_len); |
| 305 | if (err) | 304 | if (err) |
| 306 | return 1; | 305 | return err; |
| 307 | cur_len = min(len, map_len - (offset - map_start)); | 306 | cur_len = min(len, map_len - (offset - map_start)); |
| 308 | crc = btrfs_csum_data(kaddr + offset - map_start, | 307 | crc = btrfs_csum_data(kaddr + offset - map_start, |
| 309 | crc, cur_len); | 308 | crc, cur_len); |
| @@ -313,7 +312,7 @@ static int csum_tree_block(struct btrfs_fs_info *fs_info, | |||
| 313 | if (csum_size > sizeof(inline_result)) { | 312 | if (csum_size > sizeof(inline_result)) { |
| 314 | result = kzalloc(csum_size, GFP_NOFS); | 313 | result = kzalloc(csum_size, GFP_NOFS); |
| 315 | if (!result) | 314 | if (!result) |
| 316 | return 1; | 315 | return -ENOMEM; |
| 317 | } else { | 316 | } else { |
| 318 | result = (char *)&inline_result; | 317 | result = (char *)&inline_result; |
| 319 | } | 318 | } |
| @@ -334,7 +333,7 @@ static int csum_tree_block(struct btrfs_fs_info *fs_info, | |||
| 334 | val, found, btrfs_header_level(buf)); | 333 | val, found, btrfs_header_level(buf)); |
| 335 | if (result != (char *)&inline_result) | 334 | if (result != (char *)&inline_result) |
| 336 | kfree(result); | 335 | kfree(result); |
| 337 | return 1; | 336 | return -EUCLEAN; |
| 338 | } | 337 | } |
| 339 | } else { | 338 | } else { |
| 340 | write_extent_buffer(buf, result, 0, csum_size); | 339 | write_extent_buffer(buf, result, 0, csum_size); |
| @@ -513,11 +512,21 @@ static int csum_dirty_buffer(struct btrfs_fs_info *fs_info, struct page *page) | |||
| 513 | eb = (struct extent_buffer *)page->private; | 512 | eb = (struct extent_buffer *)page->private; |
| 514 | if (page != eb->pages[0]) | 513 | if (page != eb->pages[0]) |
| 515 | return 0; | 514 | return 0; |
| 515 | |||
| 516 | found_start = btrfs_header_bytenr(eb); | 516 | found_start = btrfs_header_bytenr(eb); |
| 517 | if (WARN_ON(found_start != start || !PageUptodate(page))) | 517 | /* |
| 518 | return 0; | 518 | * Please do not consolidate these warnings into a single if. |
| 519 | csum_tree_block(fs_info, eb, 0); | 519 | * It is useful to know what went wrong. |
| 520 | return 0; | 520 | */ |
| 521 | if (WARN_ON(found_start != start)) | ||
| 522 | return -EUCLEAN; | ||
| 523 | if (WARN_ON(!PageUptodate(page))) | ||
| 524 | return -EUCLEAN; | ||
| 525 | |||
| 526 | ASSERT(memcmp_extent_buffer(eb, fs_info->fsid, | ||
| 527 | btrfs_header_fsid(), BTRFS_FSID_SIZE) == 0); | ||
| 528 | |||
| 529 | return csum_tree_block(fs_info, eb, 0); | ||
| 521 | } | 530 | } |
| 522 | 531 | ||
| 523 | static int check_tree_block_fsid(struct btrfs_fs_info *fs_info, | 532 | static int check_tree_block_fsid(struct btrfs_fs_info *fs_info, |
| @@ -661,10 +670,8 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio, | |||
| 661 | eb, found_level); | 670 | eb, found_level); |
| 662 | 671 | ||
| 663 | ret = csum_tree_block(fs_info, eb, 1); | 672 | ret = csum_tree_block(fs_info, eb, 1); |
| 664 | if (ret) { | 673 | if (ret) |
| 665 | ret = -EIO; | ||
| 666 | goto err; | 674 | goto err; |
| 667 | } | ||
| 668 | 675 | ||
| 669 | /* | 676 | /* |
| 670 | * If this is a leaf block and it is corrupt, set the corrupt bit so | 677 | * If this is a leaf block and it is corrupt, set the corrupt bit so |
| @@ -1831,7 +1838,7 @@ static int cleaner_kthread(void *arg) | |||
| 1831 | */ | 1838 | */ |
| 1832 | btrfs_delete_unused_bgs(root->fs_info); | 1839 | btrfs_delete_unused_bgs(root->fs_info); |
| 1833 | sleep: | 1840 | sleep: |
| 1834 | if (!try_to_freeze() && !again) { | 1841 | if (!again) { |
| 1835 | set_current_state(TASK_INTERRUPTIBLE); | 1842 | set_current_state(TASK_INTERRUPTIBLE); |
| 1836 | if (!kthread_should_stop()) | 1843 | if (!kthread_should_stop()) |
| 1837 | schedule(); | 1844 | schedule(); |
| @@ -1921,14 +1928,12 @@ sleep: | |||
| 1921 | if (unlikely(test_bit(BTRFS_FS_STATE_ERROR, | 1928 | if (unlikely(test_bit(BTRFS_FS_STATE_ERROR, |
| 1922 | &root->fs_info->fs_state))) | 1929 | &root->fs_info->fs_state))) |
| 1923 | btrfs_cleanup_transaction(root); | 1930 | btrfs_cleanup_transaction(root); |
| 1924 | if (!try_to_freeze()) { | 1931 | set_current_state(TASK_INTERRUPTIBLE); |
| 1925 | set_current_state(TASK_INTERRUPTIBLE); | 1932 | if (!kthread_should_stop() && |
| 1926 | if (!kthread_should_stop() && | 1933 | (!btrfs_transaction_blocked(root->fs_info) || |
| 1927 | (!btrfs_transaction_blocked(root->fs_info) || | 1934 | cannot_commit)) |
| 1928 | cannot_commit)) | 1935 | schedule_timeout(delay); |
| 1929 | schedule_timeout(delay); | 1936 | __set_current_state(TASK_RUNNING); |
| 1930 | __set_current_state(TASK_RUNNING); | ||
| 1931 | } | ||
| 1932 | } while (!kthread_should_stop()); | 1937 | } while (!kthread_should_stop()); |
| 1933 | return 0; | 1938 | return 0; |
| 1934 | } | 1939 | } |
