]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - fs/btrfs/extent_io.c
Btrfs: add branch prediction hints in the read page end IO function
[karo-tx-linux.git] / fs / btrfs / extent_io.c
index 583d98bd065ed83ca979a2786b59ae4342380c47..0297f6f4d4c3f34002eb4136f0955a730f5cd8e1 100644 (file)
@@ -2202,8 +2202,7 @@ out:
  */
 
 static int bio_readpage_error(struct bio *failed_bio, struct page *page,
-                               u64 start, u64 end, int failed_mirror,
-                               struct extent_state *state)
+                               u64 start, u64 end, int failed_mirror)
 {
        struct io_failure_record *failrec = NULL;
        u64 private;
@@ -2212,6 +2211,7 @@ static int bio_readpage_error(struct bio *failed_bio, struct page *page,
        struct extent_io_tree *failure_tree = &BTRFS_I(inode)->io_failure_tree;
        struct extent_io_tree *tree = &BTRFS_I(inode)->io_tree;
        struct extent_map_tree *em_tree = &BTRFS_I(inode)->extent_tree;
+       struct extent_state *state;
        struct bio *bio;
        int num_copies;
        int ret;
@@ -2296,22 +2296,18 @@ static int bio_readpage_error(struct bio *failed_bio, struct page *page,
                 * all the retry and error correction code that follows. no
                 * matter what the error is, it is very likely to persist.
                 */
-               pr_debug("bio_readpage_error: cannot repair, num_copies == 1. "
-                        "state=%p, num_copies=%d, next_mirror %d, "
-                        "failed_mirror %d\n", state, num_copies,
-                        failrec->this_mirror, failed_mirror);
+               pr_debug("bio_readpage_error: cannot repair, num_copies=%d, next_mirror %d, failed_mirror %d\n",
+                        num_copies, failrec->this_mirror, failed_mirror);
                free_io_failure(inode, failrec, 0);
                return -EIO;
        }
 
-       if (!state) {
-               spin_lock(&tree->lock);
-               state = find_first_extent_bit_state(tree, failrec->start,
-                                                   EXTENT_LOCKED);
-               if (state && state->start != failrec->start)
-                       state = NULL;
-               spin_unlock(&tree->lock);
-       }
+       spin_lock(&tree->lock);
+       state = find_first_extent_bit_state(tree, failrec->start,
+                                           EXTENT_LOCKED);
+       if (state && state->start != failrec->start)
+               state = NULL;
+       spin_unlock(&tree->lock);
 
        /*
         * there are two premises:
@@ -2506,7 +2502,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
 
                spin_lock(&tree->lock);
                state = find_first_extent_bit_state(tree, start, EXTENT_LOCKED);
-               if (state && state->start == start) {
+               if (likely(state && state->start == start)) {
                        /*
                         * take a reference on the state, unlock will drop
                         * the ref
@@ -2516,7 +2512,8 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                spin_unlock(&tree->lock);
 
                mirror = io_bio->mirror_num;
-               if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) {
+               if (likely(uptodate && tree->ops &&
+                          tree->ops->readpage_end_io_hook)) {
                        ret = tree->ops->readpage_end_io_hook(page, start, end,
                                                              state, mirror);
                        if (ret)
@@ -2525,12 +2522,15 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                                clean_io_failure(start, page);
                }
 
-               if (!uptodate && tree->ops && tree->ops->readpage_io_failed_hook) {
+               if (likely(uptodate))
+                       goto readpage_ok;
+
+               if (tree->ops && tree->ops->readpage_io_failed_hook) {
                        ret = tree->ops->readpage_io_failed_hook(page, mirror);
                        if (!ret && !err &&
                            test_bit(BIO_UPTODATE, &bio->bi_flags))
                                uptodate = 1;
-               } else if (!uptodate) {
+               } else {
                        /*
                         * The generic bio_readpage_error handles errors the
                         * following way: If possible, new read requests are
@@ -2541,7 +2541,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                         * can't handle the error it will return -EIO and we
                         * remain responsible for that page.
                         */
-                       ret = bio_readpage_error(bio, page, start, end, mirror, NULL);
+                       ret = bio_readpage_error(bio, page, start, end, mirror);
                        if (ret == 0) {
                                uptodate =
                                        test_bit(BIO_UPTODATE, &bio->bi_flags);
@@ -2551,7 +2551,7 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                                continue;
                        }
                }
-
+readpage_ok:
                if (uptodate && tree->track_uptodate) {
                        set_extent_uptodate(tree, start, end, &cached,
                                            GFP_ATOMIC);
@@ -4048,7 +4048,7 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
        }
 
        while (!end) {
-               u64 offset_in_extent;
+               u64 offset_in_extent = 0;
 
                /* break if the extent we found is outside the range */
                if (em->start >= max || extent_map_end(em) < off)
@@ -4064,9 +4064,12 @@ int extent_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
 
                /*
                 * record the offset from the start of the extent
-                * for adjusting the disk offset below
+                * for adjusting the disk offset below.  Only do this if the
+                * extent isn't compressed since our in ram offset may be past
+                * what we have actually allocated on disk.
                 */
-               offset_in_extent = em_start - em->start;
+               if (!test_bit(EXTENT_FLAG_COMPRESSED, &em->flags))
+                       offset_in_extent = em_start - em->start;
                em_end = extent_map_end(em);
                em_len = em_end - em_start;
                emflags = em->flags;