aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/disk-io.c
diff options
context:
space:
mode:
authorArne Jansen <sensille@gmx.net>2011-06-10 07:55:54 -0400
committerArne Jansen <sensille@gmx.net>2011-10-02 02:48:44 -0400
commit4bb31e928d1a47f5bd046ecb176b8eff7c589fc0 (patch)
tree61693e91f7a179b75cc43f5bcb504d50a342ecb7 /fs/btrfs/disk-io.c
parent7414a03fbf9e75fbbf2a3c16828cd862e572aa44 (diff)
btrfs: hooks for readahead
This adds the hooks needed for readahead. In the readpage_end_io_hook, the extent state is checked for the EXTENT_READAHEAD flag. Only in this case the readahead hook is called, to keep the impact on non-ra as low as possible. Additionally, a hook for a failed IO is added, otherwise readahead would wait indefinitely for the extent to finish. Changes for v2: - eliminate race condition Signed-off-by: Arne Jansen <sensille@gmx.net>
Diffstat (limited to 'fs/btrfs/disk-io.c')
-rw-r--r--fs/btrfs/disk-io.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index fd28c40e9ec3..2151828aa142 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -609,11 +609,47 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
609 end = min_t(u64, eb->len, PAGE_CACHE_SIZE); 609 end = min_t(u64, eb->len, PAGE_CACHE_SIZE);
610 end = eb->start + end - 1; 610 end = eb->start + end - 1;
611err: 611err:
612 if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) {
613 clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags);
614 btree_readahead_hook(root, eb, eb->start, ret);
615 }
616
612 free_extent_buffer(eb); 617 free_extent_buffer(eb);
613out: 618out:
614 return ret; 619 return ret;
615} 620}
616 621
622static int btree_io_failed_hook(struct bio *failed_bio,
623 struct page *page, u64 start, u64 end,
624 struct extent_state *state)
625{
626 struct extent_io_tree *tree;
627 unsigned long len;
628 struct extent_buffer *eb;
629 struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;
630
631 tree = &BTRFS_I(page->mapping->host)->io_tree;
632 if (page->private == EXTENT_PAGE_PRIVATE)
633 goto out;
634 if (!page->private)
635 goto out;
636
637 len = page->private >> 2;
638 WARN_ON(len == 0);
639
640 eb = alloc_extent_buffer(tree, start, len, page);
641 if (eb == NULL)
642 goto out;
643
644 if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) {
645 clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags);
646 btree_readahead_hook(root, eb, eb->start, -EIO);
647 }
648
649out:
650 return -EIO; /* we fixed nothing */
651}
652
617static void end_workqueue_bio(struct bio *bio, int err) 653static void end_workqueue_bio(struct bio *bio, int err)
618{ 654{
619 struct end_io_wq *end_io_wq = bio->bi_private; 655 struct end_io_wq *end_io_wq = bio->bi_private;
@@ -3166,6 +3202,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
3166static struct extent_io_ops btree_extent_io_ops = { 3202static struct extent_io_ops btree_extent_io_ops = {
3167 .write_cache_pages_lock_hook = btree_lock_page_hook, 3203 .write_cache_pages_lock_hook = btree_lock_page_hook,
3168 .readpage_end_io_hook = btree_readpage_end_io_hook, 3204 .readpage_end_io_hook = btree_readpage_end_io_hook,
3205 .readpage_io_failed_hook = btree_io_failed_hook,
3169 .submit_bio_hook = btree_submit_bio_hook, 3206 .submit_bio_hook = btree_submit_bio_hook,
3170 /* note we're sharing with inode.c for the merge bio hook */ 3207 /* note we're sharing with inode.c for the merge bio hook */
3171 .merge_bio_hook = btrfs_merge_bio_hook, 3208 .merge_bio_hook = btrfs_merge_bio_hook,