Commit 138082f3 authored by Naohiro Aota's avatar Naohiro Aota Committed by David Sterba

btrfs: extend btrfs_rmap_block for specifying a device

btrfs_rmap_block currently reverse-maps the physical addresses on all
devices to the corresponding logical addresses.

Extend the function to match to a specified device. The old functionality
of querying all devices is left intact by specifying NULL as target
device.

A block_device instead of a btrfs_device is passed into btrfs_rmap_block,
as this function is intended to reverse-map the result of a bio, which
only has a block_device.

Also export the function for later use.
Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Signed-off-by: default avatarNaohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent cacb2cea
...@@ -1588,6 +1588,7 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) ...@@ -1588,6 +1588,7 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
* *
* @fs_info: the filesystem * @fs_info: the filesystem
* @chunk_start: logical address of block group * @chunk_start: logical address of block group
* @bdev: physical device to resolve, can be NULL to indicate any device
* @physical: physical address to map to logical addresses * @physical: physical address to map to logical addresses
* @logical: return array of logical addresses which map to @physical * @logical: return array of logical addresses which map to @physical
* @naddrs: length of @logical * @naddrs: length of @logical
...@@ -1597,9 +1598,9 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags) ...@@ -1597,9 +1598,9 @@ static void set_avail_alloc_bits(struct btrfs_fs_info *fs_info, u64 flags)
* Used primarily to exclude those portions of a block group that contain super * Used primarily to exclude those portions of a block group that contain super
* block copies. * block copies.
*/ */
EXPORT_FOR_TESTS
int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start, int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start,
u64 physical, u64 **logical, int *naddrs, int *stripe_len) struct block_device *bdev, u64 physical, u64 **logical,
int *naddrs, int *stripe_len)
{ {
struct extent_map *em; struct extent_map *em;
struct map_lookup *map; struct map_lookup *map;
...@@ -1617,6 +1618,7 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start, ...@@ -1617,6 +1618,7 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start,
map = em->map_lookup; map = em->map_lookup;
data_stripe_length = em->orig_block_len; data_stripe_length = em->orig_block_len;
io_stripe_size = map->stripe_len; io_stripe_size = map->stripe_len;
chunk_start = em->start;
/* For RAID5/6 adjust to a full IO stripe length */ /* For RAID5/6 adjust to a full IO stripe length */
if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK)
...@@ -1631,14 +1633,18 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start, ...@@ -1631,14 +1633,18 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start,
for (i = 0; i < map->num_stripes; i++) { for (i = 0; i < map->num_stripes; i++) {
bool already_inserted = false; bool already_inserted = false;
u64 stripe_nr; u64 stripe_nr;
u64 offset;
int j; int j;
if (!in_range(physical, map->stripes[i].physical, if (!in_range(physical, map->stripes[i].physical,
data_stripe_length)) data_stripe_length))
continue; continue;
if (bdev && map->stripes[i].dev->bdev != bdev)
continue;
stripe_nr = physical - map->stripes[i].physical; stripe_nr = physical - map->stripes[i].physical;
stripe_nr = div64_u64(stripe_nr, map->stripe_len); stripe_nr = div64_u64_rem(stripe_nr, map->stripe_len, &offset);
if (map->type & BTRFS_BLOCK_GROUP_RAID10) { if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
stripe_nr = stripe_nr * map->num_stripes + i; stripe_nr = stripe_nr * map->num_stripes + i;
...@@ -1652,7 +1658,7 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start, ...@@ -1652,7 +1658,7 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start,
* instead of map->stripe_len * instead of map->stripe_len
*/ */
bytenr = chunk_start + stripe_nr * io_stripe_size; bytenr = chunk_start + stripe_nr * io_stripe_size + offset;
/* Ensure we don't add duplicate addresses */ /* Ensure we don't add duplicate addresses */
for (j = 0; j < nr; j++) { for (j = 0; j < nr; j++) {
...@@ -1694,7 +1700,7 @@ static int exclude_super_stripes(struct btrfs_block_group *cache) ...@@ -1694,7 +1700,7 @@ static int exclude_super_stripes(struct btrfs_block_group *cache)
for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) { for (i = 0; i < BTRFS_SUPER_MIRROR_MAX; i++) {
bytenr = btrfs_sb_offset(i); bytenr = btrfs_sb_offset(i);
ret = btrfs_rmap_block(fs_info, cache->start, ret = btrfs_rmap_block(fs_info, cache->start, NULL,
bytenr, &logical, &nr, &stripe_len); bytenr, &logical, &nr, &stripe_len);
if (ret) if (ret)
return ret; return ret;
......
...@@ -277,6 +277,9 @@ void btrfs_put_block_group_cache(struct btrfs_fs_info *info); ...@@ -277,6 +277,9 @@ void btrfs_put_block_group_cache(struct btrfs_fs_info *info);
int btrfs_free_block_groups(struct btrfs_fs_info *info); int btrfs_free_block_groups(struct btrfs_fs_info *info);
void btrfs_wait_space_cache_v1_finished(struct btrfs_block_group *cache, void btrfs_wait_space_cache_v1_finished(struct btrfs_block_group *cache,
struct btrfs_caching_control *caching_ctl); struct btrfs_caching_control *caching_ctl);
int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start,
struct block_device *bdev, u64 physical, u64 **logical,
int *naddrs, int *stripe_len);
static inline u64 btrfs_data_alloc_profile(struct btrfs_fs_info *fs_info) static inline u64 btrfs_data_alloc_profile(struct btrfs_fs_info *fs_info)
{ {
...@@ -303,9 +306,4 @@ static inline int btrfs_block_group_done(struct btrfs_block_group *cache) ...@@ -303,9 +306,4 @@ static inline int btrfs_block_group_done(struct btrfs_block_group *cache)
void btrfs_freeze_block_group(struct btrfs_block_group *cache); void btrfs_freeze_block_group(struct btrfs_block_group *cache);
void btrfs_unfreeze_block_group(struct btrfs_block_group *cache); void btrfs_unfreeze_block_group(struct btrfs_block_group *cache);
#ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
int btrfs_rmap_block(struct btrfs_fs_info *fs_info, u64 chunk_start,
u64 physical, u64 **logical, int *naddrs, int *stripe_len);
#endif
#endif /* BTRFS_BLOCK_GROUP_H */ #endif /* BTRFS_BLOCK_GROUP_H */
...@@ -507,7 +507,7 @@ static int test_rmap_block(struct btrfs_fs_info *fs_info, ...@@ -507,7 +507,7 @@ static int test_rmap_block(struct btrfs_fs_info *fs_info,
goto out_free; goto out_free;
} }
ret = btrfs_rmap_block(fs_info, em->start, btrfs_sb_offset(1), ret = btrfs_rmap_block(fs_info, em->start, NULL, btrfs_sb_offset(1),
&logical, &out_ndaddrs, &out_stripe_len); &logical, &out_ndaddrs, &out_stripe_len);
if (ret || (out_ndaddrs == 0 && test->expected_mapped_addr)) { if (ret || (out_ndaddrs == 0 && test->expected_mapped_addr)) {
test_err("didn't rmap anything but expected %d", test_err("didn't rmap anything but expected %d",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment