Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4bb31e92 authored by Arne Jansen's avatar Arne Jansen
Browse files

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: default avatarArne Jansen <sensille@gmx.net>
parent 7414a03f
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -609,11 +609,47 @@ static int btree_readpage_end_io_hook(struct page *page, u64 start, u64 end,
	end = min_t(u64, eb->len, PAGE_CACHE_SIZE);
	end = eb->start + end - 1;
err:
	if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) {
		clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags);
		btree_readahead_hook(root, eb, eb->start, ret);
	}

	free_extent_buffer(eb);
out:
	return ret;
}

static int btree_io_failed_hook(struct bio *failed_bio,
			 struct page *page, u64 start, u64 end,
			 struct extent_state *state)
{
	struct extent_io_tree *tree;
	unsigned long len;
	struct extent_buffer *eb;
	struct btrfs_root *root = BTRFS_I(page->mapping->host)->root;

	tree = &BTRFS_I(page->mapping->host)->io_tree;
	if (page->private == EXTENT_PAGE_PRIVATE)
		goto out;
	if (!page->private)
		goto out;

	len = page->private >> 2;
	WARN_ON(len == 0);

	eb = alloc_extent_buffer(tree, start, len, page);
	if (eb == NULL)
		goto out;

	if (test_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags)) {
		clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags);
		btree_readahead_hook(root, eb, eb->start, -EIO);
	}

out:
	return -EIO;	/* we fixed nothing */
}

static void end_workqueue_bio(struct bio *bio, int err)
{
	struct end_io_wq *end_io_wq = bio->bi_private;
@@ -3166,6 +3202,7 @@ static int btrfs_cleanup_transaction(struct btrfs_root *root)
static struct extent_io_ops btree_extent_io_ops = {
	.write_cache_pages_lock_hook = btree_lock_page_hook,
	.readpage_end_io_hook = btree_readpage_end_io_hook,
	.readpage_io_failed_hook = btree_io_failed_hook,
	.submit_bio_hook = btree_submit_bio_hook,
	/* note we're sharing with inode.c for the merge bio hook */
	.merge_bio_hook = btrfs_merge_bio_hook,
+1 −1
Original line number Diff line number Diff line
@@ -1731,7 +1731,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
		if (!uptodate && tree->ops &&
		    tree->ops->readpage_io_failed_hook) {
			ret = tree->ops->readpage_io_failed_hook(bio, page,
							 start, end, NULL);
							 start, end, state);
			if (ret == 0) {
				uptodate =
					test_bit(BIO_UPTODATE, &bio->bi_flags);