diff options
author | Chris Mason <chris.mason@oracle.com> | 2011-11-06 03:05:08 -0500 |
---|---|---|
committer | Chris Mason <chris.mason@oracle.com> | 2011-11-06 03:05:08 -0500 |
commit | 531f4b1ae5e0fc8c9b3f03838218e5ea178f80d3 (patch) | |
tree | 63efdfe9b192243fefb76be3921b9a2aaa26291e /fs/btrfs/disk-io.c | |
parent | c06a0e120a4e381a1c291c1fce3c6155c5791cae (diff) | |
parent | 7a26285eea8eb92e0088db011571d887d4551b0f (diff) |
Merge branch 'for-chris' of git://github.com/sensille/linux into integration
Conflicts:
fs/btrfs/ctree.h
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, 82 insertions, 2 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 23b6776477b7..cedfbfb278eb 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c | |||
@@ -366,7 +366,8 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root, | |||
366 | clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); | 366 | clear_bit(EXTENT_BUFFER_CORRUPT, &eb->bflags); |
367 | io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; | 367 | io_tree = &BTRFS_I(root->fs_info->btree_inode)->io_tree; |
368 | while (1) { | 368 | while (1) { |
369 | ret = read_extent_buffer_pages(io_tree, eb, start, 1, | 369 | ret = read_extent_buffer_pages(io_tree, eb, start, |
370 | WAIT_COMPLETE, | ||
370 | btree_get_extent, mirror_num); | 371 | btree_get_extent, mirror_num); |
371 | if (!ret && | 372 | if (!ret && |
372 | !verify_parent_transid(io_tree, eb, parent_transid)) | 373 | !verify_parent_transid(io_tree, eb, parent_transid)) |
@@ -607,11 +608,47 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end, | |||
607 | end = min_t(u64, eb->len, PAGE_CACHE_SIZE); | 608 | end = min_t(u64, eb->len, PAGE_CACHE_SIZE); |
608 | end = eb->start + end - 1; | 609 | end = eb->start + end - 1; |
609 | err: | 610 | err: |
611 | if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) { | ||
612 | clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags); | ||
613 | btree_readahead_hook(root, eb, eb->start, ret); | ||
614 | } | ||
615 | |||
610 | free_extent_buffer(eb); | 616 | free_extent_buffer(eb); |
611 | out: | 617 | out: |
612 | return ret; | 618 | return ret; |
613 | } | 619 | } |
614 | 620 | ||
621 | static int btree_io_failed_hook(struct bio *failed_bio, | ||
622 | struct page *page, u64 start, u64 end, | ||
623 | struct extent_state *state) | ||
624 | { | ||
625 | struct extent_io_tree *tree; | ||
626 | unsigned long len; | ||
627 | struct extent_buffer *eb; | ||
628 | struct btrfs_root *root = BTRFS_I(page->mapping->host)->root; | ||
629 | |||
630 | tree = &BTRFS_I(page->mapping->host)->io_tree; | ||
631 | if (page->private == EXTENT_PAGE_PRIVATE) | ||
632 | goto out; | ||
633 | if (!page->private) | ||
634 | goto out; | ||
635 | |||
636 | len = page->private >> 2; | ||
637 | WARN_ON(len == 0); | ||
638 | |||
639 | eb = alloc_extent_buffer(tree, start, len, page); | ||
640 | if (eb == NULL) | ||
641 | goto out; | ||
642 | |||
643 | if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) { | ||
644 | clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags); | ||
645 | btree_readahead_hook(root, eb, eb->start, -EIO); | ||
646 | } | ||
647 | |||
648 | out: | ||
649 | return -EIO; /* we fixed nothing */ | ||
650 | } | ||
651 | |||
615 | static void end_workqueue_bio(struct bio *bio, int err) | 652 | static void end_workqueue_bio(struct bio *bio, int err) |
616 | { | 653 | { |
617 | struct end_io_wq *end_io_wq = bio->bi_private; | 654 | struct end_io_wq *end_io_wq = bio->bi_private; |
@@ -973,11 +1010,43 @@ int readahead_tree_block(struct btrfs_root *root, u64 bytenr, u32 blocksize, | |||
973 | if (!buf) | 1010 | if (!buf) |
974 | return 0; | 1011 | return 0; |
975 | read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, | 1012 | read_extent_buffer_pages(&BTRFS_I(btree_inode)->io_tree, |
976 | buf, 0, 0, btree_get_extent, 0); | 1013 | buf, 0, WAIT_NONE, btree_get_extent, 0); |
977 | free_extent_buffer(buf); | 1014 | free_extent_buffer(buf); |
978 | return ret; | 1015 | return ret; |
979 | } | 1016 | } |
980 | 1017 | ||
1018 | int reada_tree_block_flagged(struct btrfs_root *root, u64 bytenr, u32 blocksize, | ||
1019 | int mirror_num, struct extent_buffer **eb) | ||
1020 | { | ||
1021 | struct extent_buffer *buf = NULL; | ||
1022 | struct inode *btree_inode = root->fs_info->btree_inode; | ||
1023 | struct extent_io_tree *io_tree = &BTRFS_I(btree_inode)->io_tree; | ||
1024 | int ret; | ||
1025 | |||
1026 | buf = btrfs_find_create_tree_block(root, bytenr, blocksize); | ||
1027 | if (!buf) | ||
1028 | return 0; | ||
1029 | |||
1030 | set_bit(EXTENT_BUFFER_READAHEAD, &buf->bflags); | ||
1031 | |||
1032 | ret = read_extent_buffer_pages(io_tree, buf, 0, WAIT_PAGE_LOCK, | ||
1033 | btree_get_extent, mirror_num); | ||
1034 | if (ret) { | ||
1035 | free_extent_buffer(buf); | ||
1036 | return ret; | ||
1037 | } | ||
1038 | |||
1039 | if (test_bit(EXTENT_BUFFER_CORRUPT, &buf->bflags)) { | ||
1040 | free_extent_buffer(buf); | ||
1041 | return -EIO; | ||
1042 | } else if (extent_buffer_uptodate(io_tree, buf, NULL)) { | ||
1043 | *eb = buf; | ||
1044 | } else { | ||
1045 | free_extent_buffer(buf); | ||
1046 | } | ||
1047 | return 0; | ||
1048 | } | ||
1049 | |||
981 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, | 1050 | struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root, |
982 | u64 bytenr, u32 blocksize) | 1051 | u64 bytenr, u32 blocksize) |
983 | { | 1052 | { |
@@ -1904,6 +1973,10 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
1904 | fs_info->trans_no_join = 0; | 1973 | fs_info->trans_no_join = 0; |
1905 | fs_info->free_chunk_space = 0; | 1974 | fs_info->free_chunk_space = 0; |
1906 | 1975 | ||
1976 | /* readahead state */ | ||
1977 | INIT_RADIX_TREE(&fs_info->reada_tree, GFP_NOFS & ~__GFP_WAIT); | ||
1978 | spin_lock_init(&fs_info->reada_lock); | ||
1979 | |||
1907 | fs_info->thread_pool_size = min_t(unsigned long, | 1980 | fs_info->thread_pool_size = min_t(unsigned long, |
1908 | num_online_cpus() + 2, 8); | 1981 | num_online_cpus() + 2, 8); |
1909 | 1982 | ||
@@ -2103,6 +2176,9 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
2103 | btrfs_init_workers(&fs_info->delayed_workers, "delayed-meta", | 2176 | btrfs_init_workers(&fs_info->delayed_workers, "delayed-meta", |
2104 | fs_info->thread_pool_size, | 2177 | fs_info->thread_pool_size, |
2105 | &fs_info->generic_worker); | 2178 | &fs_info->generic_worker); |
2179 | btrfs_init_workers(&fs_info->readahead_workers, "readahead", | ||
2180 | fs_info->thread_pool_size, | ||
2181 | &fs_info->generic_worker); | ||
2106 | 2182 | ||
2107 | /* | 2183 | /* |
2108 | * endios are largely parallel and should have a very | 2184 | * endios are largely parallel and should have a very |
@@ -2113,6 +2189,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
2113 | 2189 | ||
2114 | fs_info->endio_write_workers.idle_thresh = 2; | 2190 | fs_info->endio_write_workers.idle_thresh = 2; |
2115 | fs_info->endio_meta_write_workers.idle_thresh = 2; | 2191 | fs_info->endio_meta_write_workers.idle_thresh = 2; |
2192 | fs_info->readahead_workers.idle_thresh = 2; | ||
2116 | 2193 | ||
2117 | btrfs_start_workers(&fs_info->workers, 1); | 2194 | btrfs_start_workers(&fs_info->workers, 1); |
2118 | btrfs_start_workers(&fs_info->generic_worker, 1); | 2195 | btrfs_start_workers(&fs_info->generic_worker, 1); |
@@ -2126,6 +2203,7 @@ struct btrfs_root *open_ctree(struct super_block *sb, | |||
2126 | btrfs_start_workers(&fs_info->endio_freespace_worker, 1); | 2203 | btrfs_start_workers(&fs_info->endio_freespace_worker, 1); |
2127 | btrfs_start_workers(&fs_info->delayed_workers, 1); | 2204 | btrfs_start_workers(&fs_info->delayed_workers, 1); |
2128 | btrfs_start_workers(&fs_info->caching_workers, 1); | 2205 | btrfs_start_workers(&fs_info->caching_workers, 1); |
2206 | btrfs_start_workers(&fs_info->readahead_workers, 1); | ||
2129 | 2207 | ||
2130 | fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); | 2208 | fs_info->bdi.ra_pages *= btrfs_super_num_devices(disk_super); |
2131 | fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, | 2209 | fs_info->bdi.ra_pages = max(fs_info->bdi.ra_pages, |
@@ -2855,6 +2933,7 @@ int close_ctree(struct btrfs_root *root) | |||
2855 | btrfs_stop_workers(&fs_info->submit_workers); | 2933 | btrfs_stop_workers(&fs_info->submit_workers); |
2856 | btrfs_stop_workers(&fs_info->delayed_workers); | 2934 | btrfs_stop_workers(&fs_info->delayed_workers); |
2857 | btrfs_stop_workers(&fs_info->caching_workers); | 2935 | btrfs_stop_workers(&fs_info->caching_workers); |
2936 | btrfs_stop_workers(&fs_info->readahead_workers); | ||
2858 | 2937 | ||
2859 | btrfs_close_devices(fs_info->fs_devices); | 2938 | btrfs_close_devices(fs_info->fs_devices); |
2860 | btrfs_mapping_tree_free(&fs_info->mapping_tree); | 2939 | btrfs_mapping_tree_free(&fs_info->mapping_tree); |
@@ -3363,6 +3442,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root) | |||
3363 | static struct extent_io_ops btree_extent_io_ops = { | 3442 | static struct extent_io_ops btree_extent_io_ops = { |
3364 | .write_cache_pages_lock_hook = btree_lock_page_hook, | 3443 | .write_cache_pages_lock_hook = btree_lock_page_hook, |
3365 | .readpage_end_io_hook = btree_readpage_end_io_hook, | 3444 | .readpage_end_io_hook = btree_readpage_end_io_hook, |
3445 | .readpage_io_failed_hook = btree_io_failed_hook, | ||
3366 | .submit_bio_hook = btree_submit_bio_hook, | 3446 | .submit_bio_hook = btree_submit_bio_hook, |
3367 | /* note we're sharing with inode.c for the merge bio hook */ | 3447 | /* note we're sharing with inode.c for the merge bio hook */ |
3368 | .merge_bio_hook = btrfs_merge_bio_hook, | 3448 | .merge_bio_hook = btrfs_merge_bio_hook, |