Skip to content

Commit 4bb31e9

Browse files
author
Arne Jansen
committed
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 <[email protected]>
1 parent 7414a03 commit 4bb31e9

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

fs/btrfs/disk-io.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,11 +609,47 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
609609
end = min_t(u64, eb->len, PAGE_CACHE_SIZE);
610610
end = eb->start + end - 1;
611611
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+
612617
free_extent_buffer(eb);
613618
out:
614619
return ret;
615620
}
616621

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+
617653
static void end_workqueue_bio(struct bio *bio, int err)
618654
{
619655
struct end_io_wq *end_io_wq = bio->bi_private;
@@ -3166,6 +3202,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
31663202
static struct extent_io_ops btree_extent_io_ops = {
31673203
.write_cache_pages_lock_hook = btree_lock_page_hook,
31683204
.readpage_end_io_hook = btree_readpage_end_io_hook,
3205+
.readpage_io_failed_hook = btree_io_failed_hook,
31693206
.submit_bio_hook = btree_submit_bio_hook,
31703207
/* note we're sharing with inode.c for the merge bio hook */
31713208
.merge_bio_hook = btrfs_merge_bio_hook,

fs/btrfs/extent_io.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1731,7 +1731,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
17311731
if (!uptodate && tree->ops &&
17321732
tree->ops->readpage_io_failed_hook) {
17331733
ret = tree->ops->readpage_io_failed_hook(bio, page,
1734-
start, end, NULL);
1734+
start, end, state);
17351735
if (ret == 0) {
17361736
uptodate =
17371737
test_bit(BIO_UPTODATE, &bio->bi_flags);

0 commit comments

Comments
 (0)