diff options
author | Arne Jansen <sensille@gmx.net> | 2011-06-10 07:55:54 -0400 |
---|---|---|
committer | Arne Jansen <sensille@gmx.net> | 2011-10-02 02:48:44 -0400 |
commit | 4bb31e928d1a47f5bd046ecb176b8eff7c589fc0 (patch) | |
tree | 61693e91f7a179b75cc43f5bcb504d50a342ecb7 /fs/btrfs/disk-io.c | |
parent | 7414a03fbf9e75fbbf2a3c16828cd862e572aa44 (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.c | 37 |
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; |
611 | err: | 611 | err: |
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); |
613 | out: | 618 | out: |
614 | return ret; | 619 | return ret; |
615 | } | 620 | } |
616 | 621 | ||
622 | static 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 | |||
649 | out: | ||
650 | return -EIO; /* we fixed nothing */ | ||
651 | } | ||
652 | |||
617 | static void end_workqueue_bio(struct bio *bio, int err) | 653 | static 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) | |||
3166 | static struct extent_io_ops btree_extent_io_ops = { | 3202 | static 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, |