]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
btrfs: hooks for readahead
authorArne Jansen <sensille@gmx.net>
Fri, 10 Jun 2011 11:55:54 +0000 (13:55 +0200)
committerChris Mason <chris.mason@oracle.com>
Wed, 16 Nov 2011 01:56:03 +0000 (20:56 -0500)
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>
(cherry picked from commit 4bb31e928d1a47f5bd046ecb176b8eff7c589fc0 with conflicts)

fs/btrfs/disk-io.c
fs/btrfs/extent_io.c

index 3ff1a1039192076e11de6c809dc1493ed3eff350..827a5e49372e2f675c4a51a7b6bffac56445bfad 100644 (file)
@@ -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,
+                        u64 mirror_num, 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,
index 9a83b2093619ddfa8f2eaed1eef6b7c498261887..acd6e9996d60df089011b52470881bfe060384e6 100644 (file)
@@ -2102,7 +2102,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                        if (tree->ops && tree->ops->readpage_io_failed_hook)
                                ret = tree->ops->readpage_io_failed_hook(
                                                bio, page, start, end,
-                                               failed_mirror, NULL);
+                                               failed_mirror, state);
                        else
                                ret = bio_readpage_error(bio, page, start, end,
                                                         failed_mirror, NULL);