aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/volumes.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/btrfs/volumes.c')
-rw-r--r--fs/btrfs/volumes.c94
1 files changed, 92 insertions, 2 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 48a06d1fc067..2915521f44ee 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -23,6 +23,7 @@
23#include <linux/random.h> 23#include <linux/random.h>
24#include <linux/iocontext.h> 24#include <linux/iocontext.h>
25#include <linux/capability.h> 25#include <linux/capability.h>
26#include <linux/ratelimit.h>
26#include <linux/kthread.h> 27#include <linux/kthread.h>
27#include <asm/div64.h> 28#include <asm/div64.h>
28#include "compat.h" 29#include "compat.h"
@@ -4001,13 +4002,58 @@ int btrfs_rmap_block(struct btrfs_mapping_tree *map_tree,
4001 return 0; 4002 return 0;
4002} 4003}
4003 4004
4005static void *merge_stripe_index_into_bio_private(void *bi_private,
4006 unsigned int stripe_index)
4007{
4008 /*
4009 * with single, dup, RAID0, RAID1 and RAID10, stripe_index is
4010 * at most 1.
4011 * The alternative solution (instead of stealing bits from the
4012 * pointer) would be to allocate an intermediate structure
4013 * that contains the old private pointer plus the stripe_index.
4014 */
4015 BUG_ON((((uintptr_t)bi_private) & 3) != 0);
4016 BUG_ON(stripe_index > 3);
4017 return (void *)(((uintptr_t)bi_private) | stripe_index);
4018}
4019
4020static struct btrfs_bio *extract_bbio_from_bio_private(void *bi_private)
4021{
4022 return (struct btrfs_bio *)(((uintptr_t)bi_private) & ~((uintptr_t)3));
4023}
4024
4025static unsigned int extract_stripe_index_from_bio_private(void *bi_private)
4026{
4027 return (unsigned int)((uintptr_t)bi_private) & 3;
4028}
4029
4004static void btrfs_end_bio(struct bio *bio, int err) 4030static void btrfs_end_bio(struct bio *bio, int err)
4005{ 4031{
4006 struct btrfs_bio *bbio = bio->bi_private; 4032 struct btrfs_bio *bbio = extract_bbio_from_bio_private(bio->bi_private);
4007 int is_orig_bio = 0; 4033 int is_orig_bio = 0;
4008 4034
4009 if (err) 4035 if (err) {
4010 atomic_inc(&bbio->error); 4036 atomic_inc(&bbio->error);
4037 if (err == -EIO || err == -EREMOTEIO) {
4038 unsigned int stripe_index =
4039 extract_stripe_index_from_bio_private(
4040 bio->bi_private);
4041 struct btrfs_device *dev;
4042
4043 BUG_ON(stripe_index >= bbio->num_stripes);
4044 dev = bbio->stripes[stripe_index].dev;
4045 if (bio->bi_rw & WRITE)
4046 btrfs_dev_stat_inc(dev,
4047 BTRFS_DEV_STAT_WRITE_ERRS);
4048 else
4049 btrfs_dev_stat_inc(dev,
4050 BTRFS_DEV_STAT_READ_ERRS);
4051 if ((bio->bi_rw & WRITE_FLUSH) == WRITE_FLUSH)
4052 btrfs_dev_stat_inc(dev,
4053 BTRFS_DEV_STAT_FLUSH_ERRS);
4054 btrfs_dev_stat_print_on_error(dev);
4055 }
4056 }
4011 4057
4012 if (bio == bbio->orig_bio) 4058 if (bio == bbio->orig_bio)
4013 is_orig_bio = 1; 4059 is_orig_bio = 1;
@@ -4149,6 +4195,8 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio,
4149 bio = first_bio; 4195 bio = first_bio;
4150 } 4196 }
4151 bio->bi_private = bbio; 4197 bio->bi_private = bbio;
4198 bio->bi_private = merge_stripe_index_into_bio_private(
4199 bio->bi_private, (unsigned int)dev_nr);
4152 bio->bi_end_io = btrfs_end_bio; 4200 bio->bi_end_io = btrfs_end_bio;
4153 bio->bi_sector = bbio->stripes[dev_nr].physical >> 9; 4201 bio->bi_sector = bbio->stripes[dev_nr].physical >> 9;
4154 dev = bbio->stripes[dev_nr].dev; 4202 dev = bbio->stripes[dev_nr].dev;
@@ -4509,6 +4557,28 @@ int btrfs_read_sys_array(struct btrfs_root *root)
4509 return ret; 4557 return ret;
4510} 4558}
4511 4559
4560struct btrfs_device *btrfs_find_device_for_logical(struct btrfs_root *root,
4561 u64 logical, int mirror_num)
4562{
4563 struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
4564 int ret;
4565 u64 map_length = 0;
4566 struct btrfs_bio *bbio = NULL;
4567 struct btrfs_device *device;
4568
4569 BUG_ON(mirror_num == 0);
4570 ret = btrfs_map_block(map_tree, WRITE, logical, &map_length, &bbio,
4571 mirror_num);
4572 if (ret) {
4573 BUG_ON(bbio != NULL);
4574 return NULL;
4575 }
4576 BUG_ON(mirror_num != bbio->mirror_num);
4577 device = bbio->stripes[mirror_num - 1].dev;
4578 kfree(bbio);
4579 return device;
4580}
4581
4512int btrfs_read_chunk_tree(struct btrfs_root *root) 4582int btrfs_read_chunk_tree(struct btrfs_root *root)
4513{ 4583{
4514 struct btrfs_path *path; 4584 struct btrfs_path *path;
@@ -4583,3 +4653,23 @@ error:
4583 btrfs_free_path(path); 4653 btrfs_free_path(path);
4584 return ret; 4654 return ret;
4585} 4655}
4656
4657void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index)
4658{
4659 btrfs_dev_stat_inc(dev, index);
4660 btrfs_dev_stat_print_on_error(dev);
4661}
4662
4663void btrfs_dev_stat_print_on_error(struct btrfs_device *dev)
4664{
4665 printk_ratelimited(KERN_ERR
4666 "btrfs: bdev %s errs: wr %u, rd %u, flush %u, corrupt %u, gen %u\n",
4667 dev->name,
4668 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_WRITE_ERRS),
4669 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_READ_ERRS),
4670 btrfs_dev_stat_read(dev, BTRFS_DEV_STAT_FLUSH_ERRS),
4671 btrfs_dev_stat_read(dev,
4672 BTRFS_DEV_STAT_CORRUPTION_ERRS),
4673 btrfs_dev_stat_read(dev,
4674 BTRFS_DEV_STAT_GENERATION_ERRS));
4675}