diff options
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r-- | fs/btrfs/disk-io.c | 59 |
1 files changed, 32 insertions, 27 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 4b02591b0301..4e47849d7427 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 |
@@ -1055,7 +1062,7 @@ static void btree_invalidatepage(struct page *page, unsigned int offset, | |||
1055 | (unsigned long long)page_offset(page)); | 1062 | (unsigned long long)page_offset(page)); |
1056 | ClearPagePrivate(page); | 1063 | ClearPagePrivate(page); |
1057 | set_page_private(page, 0); | 1064 | set_page_private(page, 0); |
1058 | page_cache_release(page); | 1065 | put_page(page); |
1059 | } | 1066 | } |
1060 | } | 1067 | } |
1061 | 1068 | ||
@@ -1757,7 +1764,7 @@ static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) | |||
1757 | if (err) | 1764 | if (err) |
1758 | return err; | 1765 | return err; |
1759 | 1766 | ||
1760 | bdi->ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_CACHE_SIZE; | 1767 | bdi->ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_SIZE; |
1761 | bdi->congested_fn = btrfs_congested_fn; | 1768 | bdi->congested_fn = btrfs_congested_fn; |
1762 | bdi->congested_data = info; | 1769 | bdi->congested_data = info; |
1763 | bdi->capabilities |= BDI_CAP_CGROUP_WRITEBACK; | 1770 | bdi->capabilities |= BDI_CAP_CGROUP_WRITEBACK; |
@@ -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 | } |
@@ -2537,7 +2542,7 @@ int open_ctree(struct super_block *sb, | |||
2537 | err = ret; | 2542 | err = ret; |
2538 | goto fail_bdi; | 2543 | goto fail_bdi; |
2539 | } | 2544 | } |
2540 | fs_info->dirty_metadata_batch = PAGE_CACHE_SIZE * | 2545 | fs_info->dirty_metadata_batch = PAGE_SIZE * |
2541 | (1 + ilog2(nr_cpu_ids)); | 2546 | (1 + ilog2(nr_cpu_ids)); |
2542 | 2547 | ||
2543 | ret = percpu_counter_init(&fs_info->delalloc_bytes, 0, GFP_KERNEL); | 2548 | ret = percpu_counter_init(&fs_info->delalloc_bytes, 0, GFP_KERNEL); |
@@ -2782,7 +2787,7 @@ int open_ctree(struct super_block *sb, | |||
2782 | * flag our filesystem as having big metadata blocks if | 2787 | * flag our filesystem as having big metadata blocks if |
2783 | * they are bigger than the page size | 2788 | * they are bigger than the page size |
2784 | */ | 2789 | */ |
2785 | if (btrfs_super_nodesize(disk_super) > PAGE_CACHE_SIZE) { | 2790 | if (btrfs_super_nodesize(disk_super) > PAGE_SIZE) { |
2786 | if (!(features & BTRFS_FEATURE_INCOMPAT_BIG_METADATA)) | 2791 | if (!(features & BTRFS_FEATURE_INCOMPAT_BIG_METADATA)) |
2787 | printk(KERN_INFO "BTRFS: flagging fs with big metadata feature\n"); | 2792 | printk(KERN_INFO "BTRFS: flagging fs with big metadata feature\n"); |
2788 | features |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA; | 2793 | features |= BTRFS_FEATURE_INCOMPAT_BIG_METADATA; |
@@ -2832,7 +2837,7 @@ int open_ctree(struct super_block *sb, | |||
2832 | 2837 | ||
2833 | fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); | 2838 | fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); |
2834 | fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, | 2839 | fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, |
2835 | SZ_4M / PAGE_CACHE_SIZE); | 2840 | SZ_4M / PAGE_SIZE); |
2836 | 2841 | ||
2837 | tree_root->nodesize = nodesize; | 2842 | tree_root->nodesize = nodesize; |
2838 | tree_root->sectorsize = sectorsize; | 2843 | tree_root->sectorsize = sectorsize; |
@@ -4071,9 +4076,9 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info, | |||
4071 | ret = -EINVAL; | 4076 | ret = -EINVAL; |
4072 | } | 4077 | } |
4073 | /* Only PAGE SIZE is supported yet */ | 4078 | /* Only PAGE SIZE is supported yet */ |
4074 | if (sectorsize != PAGE_CACHE_SIZE) { | 4079 | if (sectorsize != PAGE_SIZE) { |
4075 | printk(KERN_ERR "BTRFS: sectorsize %llu not supported yet, only support %lu\n", | 4080 | printk(KERN_ERR "BTRFS: sectorsize %llu not supported yet, only support %lu\n", |
4076 | sectorsize, PAGE_CACHE_SIZE); | 4081 | sectorsize, PAGE_SIZE); |
4077 | ret = -EINVAL; | 4082 | ret = -EINVAL; |
4078 | } | 4083 | } |
4079 | if (!is_power_of_2(nodesize) || nodesize < sectorsize || | 4084 | if (!is_power_of_2(nodesize) || nodesize < sectorsize || |