Loading fs/btrfs/disk-io.c +15 −11 Original line number Original line Diff line number Diff line Loading @@ -913,18 +913,22 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits) void btrfs_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) void btrfs_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) { { struct list_head *cur; struct inode *inode = page->mapping->host; struct btrfs_device *device; struct extent_map_tree *em_tree; struct btrfs_fs_info *info; struct extent_map *em; u64 offset = page_offset(page); info = (struct btrfs_fs_info *)bdi->unplug_io_data; em_tree = &BTRFS_I(inode)->extent_tree; list_for_each(cur, &info->fs_devices->devices) { spin_lock(&em_tree->lock); device = list_entry(cur, struct btrfs_device, dev_list); em = lookup_extent_mapping(em_tree, offset, PAGE_CACHE_SIZE); bdi = blk_get_backing_dev_info(device->bdev); spin_unlock(&em_tree->lock); if (bdi->unplug_io_fn) { if (!em) bdi->unplug_io_fn(bdi, page); return; } } offset = offset - em->start; btrfs_unplug_page(&BTRFS_I(inode)->root->fs_info->mapping_tree, em->block_start + offset, page); free_extent_map(em); } } static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) Loading fs/btrfs/inode.c +1 −5 Original line number Original line Diff line number Diff line Loading @@ -313,13 +313,9 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset, u64 logical = bio->bi_sector << 9; u64 logical = bio->bi_sector << 9; u64 length = 0; u64 length = 0; u64 map_length; u64 map_length; struct bio_vec *bvec; int i; int ret; int ret; bio_for_each_segment(bvec, bio, i) { length = bio->bi_size; length += bvec->bv_len; } map_tree = &root->fs_info->mapping_tree; map_tree = &root->fs_info->mapping_tree; map_length = length; map_length = length; ret = btrfs_map_block(map_tree, READ, logical, ret = btrfs_map_block(map_tree, READ, logical, Loading fs/btrfs/volumes.c +57 −22 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <linux/sched.h> #include <linux/sched.h> #include <linux/bio.h> #include <linux/bio.h> #include <linux/buffer_head.h> #include <linux/buffer_head.h> #include <linux/blkdev.h> #include <asm/div64.h> #include <asm/div64.h> #include "ctree.h" #include "ctree.h" #include "extent_map.h" #include "extent_map.h" Loading Loading @@ -930,9 +931,10 @@ int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len) return ret; return ret; } } int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, u64 logical, u64 *length, u64 logical, u64 *length, struct btrfs_multi_bio **multi_ret, int mirror_num) struct btrfs_multi_bio **multi_ret, int mirror_num, struct page *unplug_page) { { struct extent_map *em; struct extent_map *em; struct map_lookup *map; struct map_lookup *map; Loading @@ -944,6 +946,7 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, int stripes_required = 1; int stripes_required = 1; int stripe_index; int stripe_index; int i; int i; int num_stripes; struct btrfs_multi_bio *multi = NULL; struct btrfs_multi_bio *multi = NULL; if (multi_ret && !(rw & (1 << BIO_RW))) { if (multi_ret && !(rw & (1 << BIO_RW))) { Loading @@ -960,10 +963,14 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, spin_lock(&em_tree->lock); spin_lock(&em_tree->lock); em = lookup_extent_mapping(em_tree, logical, *length); em = lookup_extent_mapping(em_tree, logical, *length); spin_unlock(&em_tree->lock); spin_unlock(&em_tree->lock); if (!em && unplug_page) return 0; if (!em) { if (!em) { printk("unable to find logical %Lu\n", logical); printk("unable to find logical %Lu\n", logical); BUG(); } } BUG_ON(!em); BUG_ON(em->start > logical || em->start + em->len < logical); BUG_ON(em->start > logical || em->start + em->len < logical); map = (struct map_lookup *)em->bdev; map = (struct map_lookup *)em->bdev; Loading Loading @@ -1010,14 +1017,15 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, } else { } else { *length = em->len - offset; *length = em->len - offset; } } if (!multi_ret) if (!multi_ret && !unplug_page) goto out; goto out; multi->num_stripes = 1; num_stripes = 1; stripe_index = 0; stripe_index = 0; if (map->type & BTRFS_BLOCK_GROUP_RAID1) { if (map->type & BTRFS_BLOCK_GROUP_RAID1) { if (rw & (1 << BIO_RW)) if (unplug_page || (rw & (1 << BIO_RW))) multi->num_stripes = map->num_stripes; num_stripes = map->num_stripes; else if (mirror_num) { else if (mirror_num) { stripe_index = mirror_num - 1; stripe_index = mirror_num - 1; } else { } else { Loading @@ -1037,7 +1045,7 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, } } } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { if (rw & (1 << BIO_RW)) if (rw & (1 << BIO_RW)) multi->num_stripes = map->num_stripes; num_stripes = map->num_stripes; else if (mirror_num) else if (mirror_num) stripe_index = mirror_num - 1; stripe_index = mirror_num - 1; } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { Loading @@ -1047,8 +1055,8 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, stripe_index = do_div(stripe_nr, factor); stripe_index = do_div(stripe_nr, factor); stripe_index *= map->sub_stripes; stripe_index *= map->sub_stripes; if (rw & (1 << BIO_RW)) if (unplug_page || (rw & (1 << BIO_RW))) multi->num_stripes = map->sub_stripes; num_stripes = map->sub_stripes; else if (mirror_num) else if (mirror_num) stripe_index += mirror_num - 1; stripe_index += mirror_num - 1; else else Loading @@ -1063,19 +1071,50 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, } } BUG_ON(stripe_index >= map->num_stripes); BUG_ON(stripe_index >= map->num_stripes); for (i = 0; i < multi->num_stripes; i++) { for (i = 0; i < num_stripes; i++) { if (unplug_page) { struct btrfs_device *device; struct backing_dev_info *bdi; device = map->stripes[stripe_index].dev; bdi = blk_get_backing_dev_info(device->bdev); if (bdi->unplug_io_fn) { bdi->unplug_io_fn(bdi, unplug_page); } } else { multi->stripes[i].physical = multi->stripes[i].physical = map->stripes[stripe_index].physical + stripe_offset + map->stripes[stripe_index].physical + stripe_nr * map->stripe_len; stripe_offset + stripe_nr * map->stripe_len; multi->stripes[i].dev = map->stripes[stripe_index].dev; multi->stripes[i].dev = map->stripes[stripe_index].dev; } stripe_index++; stripe_index++; } } if (multi_ret) { *multi_ret = multi; *multi_ret = multi; multi->num_stripes = num_stripes; } out: out: free_extent_map(em); free_extent_map(em); return 0; return 0; } } int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, u64 logical, u64 *length, struct btrfs_multi_bio **multi_ret, int mirror_num) { return __btrfs_map_block(map_tree, rw, logical, length, multi_ret, mirror_num, NULL); } int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, u64 logical, struct page *page) { u64 length = PAGE_CACHE_SIZE; return __btrfs_map_block(map_tree, READ, logical, &length, NULL, 0, page); } #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) static void end_bio_multi_stripe(struct bio *bio, int err) static void end_bio_multi_stripe(struct bio *bio, int err) #else #else Loading Loading @@ -1122,16 +1161,12 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, u64 logical = bio->bi_sector << 9; u64 logical = bio->bi_sector << 9; u64 length = 0; u64 length = 0; u64 map_length; u64 map_length; struct bio_vec *bvec; struct btrfs_multi_bio *multi = NULL; struct btrfs_multi_bio *multi = NULL; int i; int ret; int ret; int dev_nr = 0; int dev_nr = 0; int total_devs = 1; int total_devs = 1; bio_for_each_segment(bvec, bio, i) { length = bio->bi_size; length += bvec->bv_len; } map_tree = &root->fs_info->mapping_tree; map_tree = &root->fs_info->mapping_tree; map_length = length; map_length = length; Loading fs/btrfs/volumes.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -119,4 +119,6 @@ int btrfs_add_device(struct btrfs_trans_handle *trans, struct btrfs_device *device); struct btrfs_device *device); int btrfs_cleanup_fs_uuids(void); int btrfs_cleanup_fs_uuids(void); int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len); int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len); int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, u64 logical, struct page *page); #endif #endif Loading
fs/btrfs/disk-io.c +15 −11 Original line number Original line Diff line number Diff line Loading @@ -913,18 +913,22 @@ static int btrfs_congested_fn(void *congested_data, int bdi_bits) void btrfs_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) void btrfs_unplug_io_fn(struct backing_dev_info *bdi, struct page *page) { { struct list_head *cur; struct inode *inode = page->mapping->host; struct btrfs_device *device; struct extent_map_tree *em_tree; struct btrfs_fs_info *info; struct extent_map *em; u64 offset = page_offset(page); info = (struct btrfs_fs_info *)bdi->unplug_io_data; em_tree = &BTRFS_I(inode)->extent_tree; list_for_each(cur, &info->fs_devices->devices) { spin_lock(&em_tree->lock); device = list_entry(cur, struct btrfs_device, dev_list); em = lookup_extent_mapping(em_tree, offset, PAGE_CACHE_SIZE); bdi = blk_get_backing_dev_info(device->bdev); spin_unlock(&em_tree->lock); if (bdi->unplug_io_fn) { if (!em) bdi->unplug_io_fn(bdi, page); return; } } offset = offset - em->start; btrfs_unplug_page(&BTRFS_I(inode)->root->fs_info->mapping_tree, em->block_start + offset, page); free_extent_map(em); } } static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) Loading
fs/btrfs/inode.c +1 −5 Original line number Original line Diff line number Diff line Loading @@ -313,13 +313,9 @@ int btrfs_merge_bio_hook(struct page *page, unsigned long offset, u64 logical = bio->bi_sector << 9; u64 logical = bio->bi_sector << 9; u64 length = 0; u64 length = 0; u64 map_length; u64 map_length; struct bio_vec *bvec; int i; int ret; int ret; bio_for_each_segment(bvec, bio, i) { length = bio->bi_size; length += bvec->bv_len; } map_tree = &root->fs_info->mapping_tree; map_tree = &root->fs_info->mapping_tree; map_length = length; map_length = length; ret = btrfs_map_block(map_tree, READ, logical, ret = btrfs_map_block(map_tree, READ, logical, Loading
fs/btrfs/volumes.c +57 −22 Original line number Original line Diff line number Diff line Loading @@ -18,6 +18,7 @@ #include <linux/sched.h> #include <linux/sched.h> #include <linux/bio.h> #include <linux/bio.h> #include <linux/buffer_head.h> #include <linux/buffer_head.h> #include <linux/blkdev.h> #include <asm/div64.h> #include <asm/div64.h> #include "ctree.h" #include "ctree.h" #include "extent_map.h" #include "extent_map.h" Loading Loading @@ -930,9 +931,10 @@ int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len) return ret; return ret; } } int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, static int __btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, u64 logical, u64 *length, u64 logical, u64 *length, struct btrfs_multi_bio **multi_ret, int mirror_num) struct btrfs_multi_bio **multi_ret, int mirror_num, struct page *unplug_page) { { struct extent_map *em; struct extent_map *em; struct map_lookup *map; struct map_lookup *map; Loading @@ -944,6 +946,7 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, int stripes_required = 1; int stripes_required = 1; int stripe_index; int stripe_index; int i; int i; int num_stripes; struct btrfs_multi_bio *multi = NULL; struct btrfs_multi_bio *multi = NULL; if (multi_ret && !(rw & (1 << BIO_RW))) { if (multi_ret && !(rw & (1 << BIO_RW))) { Loading @@ -960,10 +963,14 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, spin_lock(&em_tree->lock); spin_lock(&em_tree->lock); em = lookup_extent_mapping(em_tree, logical, *length); em = lookup_extent_mapping(em_tree, logical, *length); spin_unlock(&em_tree->lock); spin_unlock(&em_tree->lock); if (!em && unplug_page) return 0; if (!em) { if (!em) { printk("unable to find logical %Lu\n", logical); printk("unable to find logical %Lu\n", logical); BUG(); } } BUG_ON(!em); BUG_ON(em->start > logical || em->start + em->len < logical); BUG_ON(em->start > logical || em->start + em->len < logical); map = (struct map_lookup *)em->bdev; map = (struct map_lookup *)em->bdev; Loading Loading @@ -1010,14 +1017,15 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, } else { } else { *length = em->len - offset; *length = em->len - offset; } } if (!multi_ret) if (!multi_ret && !unplug_page) goto out; goto out; multi->num_stripes = 1; num_stripes = 1; stripe_index = 0; stripe_index = 0; if (map->type & BTRFS_BLOCK_GROUP_RAID1) { if (map->type & BTRFS_BLOCK_GROUP_RAID1) { if (rw & (1 << BIO_RW)) if (unplug_page || (rw & (1 << BIO_RW))) multi->num_stripes = map->num_stripes; num_stripes = map->num_stripes; else if (mirror_num) { else if (mirror_num) { stripe_index = mirror_num - 1; stripe_index = mirror_num - 1; } else { } else { Loading @@ -1037,7 +1045,7 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, } } } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { } else if (map->type & BTRFS_BLOCK_GROUP_DUP) { if (rw & (1 << BIO_RW)) if (rw & (1 << BIO_RW)) multi->num_stripes = map->num_stripes; num_stripes = map->num_stripes; else if (mirror_num) else if (mirror_num) stripe_index = mirror_num - 1; stripe_index = mirror_num - 1; } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { } else if (map->type & BTRFS_BLOCK_GROUP_RAID10) { Loading @@ -1047,8 +1055,8 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, stripe_index = do_div(stripe_nr, factor); stripe_index = do_div(stripe_nr, factor); stripe_index *= map->sub_stripes; stripe_index *= map->sub_stripes; if (rw & (1 << BIO_RW)) if (unplug_page || (rw & (1 << BIO_RW))) multi->num_stripes = map->sub_stripes; num_stripes = map->sub_stripes; else if (mirror_num) else if (mirror_num) stripe_index += mirror_num - 1; stripe_index += mirror_num - 1; else else Loading @@ -1063,19 +1071,50 @@ int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, } } BUG_ON(stripe_index >= map->num_stripes); BUG_ON(stripe_index >= map->num_stripes); for (i = 0; i < multi->num_stripes; i++) { for (i = 0; i < num_stripes; i++) { if (unplug_page) { struct btrfs_device *device; struct backing_dev_info *bdi; device = map->stripes[stripe_index].dev; bdi = blk_get_backing_dev_info(device->bdev); if (bdi->unplug_io_fn) { bdi->unplug_io_fn(bdi, unplug_page); } } else { multi->stripes[i].physical = multi->stripes[i].physical = map->stripes[stripe_index].physical + stripe_offset + map->stripes[stripe_index].physical + stripe_nr * map->stripe_len; stripe_offset + stripe_nr * map->stripe_len; multi->stripes[i].dev = map->stripes[stripe_index].dev; multi->stripes[i].dev = map->stripes[stripe_index].dev; } stripe_index++; stripe_index++; } } if (multi_ret) { *multi_ret = multi; *multi_ret = multi; multi->num_stripes = num_stripes; } out: out: free_extent_map(em); free_extent_map(em); return 0; return 0; } } int btrfs_map_block(struct btrfs_mapping_tree *map_tree, int rw, u64 logical, u64 *length, struct btrfs_multi_bio **multi_ret, int mirror_num) { return __btrfs_map_block(map_tree, rw, logical, length, multi_ret, mirror_num, NULL); } int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, u64 logical, struct page *page) { u64 length = PAGE_CACHE_SIZE; return __btrfs_map_block(map_tree, READ, logical, &length, NULL, 0, page); } #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,23) static void end_bio_multi_stripe(struct bio *bio, int err) static void end_bio_multi_stripe(struct bio *bio, int err) #else #else Loading Loading @@ -1122,16 +1161,12 @@ int btrfs_map_bio(struct btrfs_root *root, int rw, struct bio *bio, u64 logical = bio->bi_sector << 9; u64 logical = bio->bi_sector << 9; u64 length = 0; u64 length = 0; u64 map_length; u64 map_length; struct bio_vec *bvec; struct btrfs_multi_bio *multi = NULL; struct btrfs_multi_bio *multi = NULL; int i; int ret; int ret; int dev_nr = 0; int dev_nr = 0; int total_devs = 1; int total_devs = 1; bio_for_each_segment(bvec, bio, i) { length = bio->bi_size; length += bvec->bv_len; } map_tree = &root->fs_info->mapping_tree; map_tree = &root->fs_info->mapping_tree; map_length = length; map_length = length; Loading
fs/btrfs/volumes.h +2 −0 Original line number Original line Diff line number Diff line Loading @@ -119,4 +119,6 @@ int btrfs_add_device(struct btrfs_trans_handle *trans, struct btrfs_device *device); struct btrfs_device *device); int btrfs_cleanup_fs_uuids(void); int btrfs_cleanup_fs_uuids(void); int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len); int btrfs_num_copies(struct btrfs_mapping_tree *map_tree, u64 logical, u64 len); int btrfs_unplug_page(struct btrfs_mapping_tree *map_tree, u64 logical, struct page *page); #endif #endif