Commit dbfcc18f authored by Johannes Thumshirn's avatar Johannes Thumshirn Committed by David Sterba

btrfs: zoned: prepare for allowing DUP on zoned

Allow for a block-group to be placed on more than one physical zone.

This is a preparation for allowing DUP profiles for meta-data on a zoned
file-system.
Signed-off-by: default avatarJohannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 4dcbb8ab
...@@ -1215,12 +1215,12 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new) ...@@ -1215,12 +1215,12 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
struct btrfs_device *device; struct btrfs_device *device;
u64 logical = cache->start; u64 logical = cache->start;
u64 length = cache->length; u64 length = cache->length;
u64 physical = 0;
int ret; int ret;
int i; int i;
unsigned int nofs_flag; unsigned int nofs_flag;
u64 *alloc_offsets = NULL; u64 *alloc_offsets = NULL;
u64 *caps = NULL; u64 *caps = NULL;
u64 *physical = NULL;
unsigned long *active = NULL; unsigned long *active = NULL;
u64 last_alloc = 0; u64 last_alloc = 0;
u32 num_sequential = 0, num_conventional = 0; u32 num_sequential = 0, num_conventional = 0;
...@@ -1264,6 +1264,12 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new) ...@@ -1264,6 +1264,12 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
goto out; goto out;
} }
physical = kcalloc(map->num_stripes, sizeof(*physical), GFP_NOFS);
if (!physical) {
ret = -ENOMEM;
goto out;
}
active = bitmap_zalloc(map->num_stripes, GFP_NOFS); active = bitmap_zalloc(map->num_stripes, GFP_NOFS);
if (!active) { if (!active) {
ret = -ENOMEM; ret = -ENOMEM;
...@@ -1277,14 +1283,14 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new) ...@@ -1277,14 +1283,14 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
int dev_replace_is_ongoing = 0; int dev_replace_is_ongoing = 0;
device = map->stripes[i].dev; device = map->stripes[i].dev;
physical = map->stripes[i].physical; physical[i] = map->stripes[i].physical;
if (device->bdev == NULL) { if (device->bdev == NULL) {
alloc_offsets[i] = WP_MISSING_DEV; alloc_offsets[i] = WP_MISSING_DEV;
continue; continue;
} }
is_sequential = btrfs_dev_is_sequential(device, physical); is_sequential = btrfs_dev_is_sequential(device, physical[i]);
if (is_sequential) if (is_sequential)
num_sequential++; num_sequential++;
else else
...@@ -1299,21 +1305,21 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new) ...@@ -1299,21 +1305,21 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
* This zone will be used for allocation, so mark this zone * This zone will be used for allocation, so mark this zone
* non-empty. * non-empty.
*/ */
btrfs_dev_clear_zone_empty(device, physical); btrfs_dev_clear_zone_empty(device, physical[i]);
down_read(&dev_replace->rwsem); down_read(&dev_replace->rwsem);
dev_replace_is_ongoing = btrfs_dev_replace_is_ongoing(dev_replace); dev_replace_is_ongoing = btrfs_dev_replace_is_ongoing(dev_replace);
if (dev_replace_is_ongoing && dev_replace->tgtdev != NULL) if (dev_replace_is_ongoing && dev_replace->tgtdev != NULL)
btrfs_dev_clear_zone_empty(dev_replace->tgtdev, physical); btrfs_dev_clear_zone_empty(dev_replace->tgtdev, physical[i]);
up_read(&dev_replace->rwsem); up_read(&dev_replace->rwsem);
/* /*
* The group is mapped to a sequential zone. Get the zone write * The group is mapped to a sequential zone. Get the zone write
* pointer to determine the allocation offset within the zone. * pointer to determine the allocation offset within the zone.
*/ */
WARN_ON(!IS_ALIGNED(physical, fs_info->zone_size)); WARN_ON(!IS_ALIGNED(physical[i], fs_info->zone_size));
nofs_flag = memalloc_nofs_save(); nofs_flag = memalloc_nofs_save();
ret = btrfs_get_dev_zone(device, physical, &zone); ret = btrfs_get_dev_zone(device, physical[i], &zone);
memalloc_nofs_restore(nofs_flag); memalloc_nofs_restore(nofs_flag);
if (ret == -EIO || ret == -EOPNOTSUPP) { if (ret == -EIO || ret == -EOPNOTSUPP) {
ret = 0; ret = 0;
...@@ -1339,7 +1345,7 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new) ...@@ -1339,7 +1345,7 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
case BLK_ZONE_COND_READONLY: case BLK_ZONE_COND_READONLY:
btrfs_err(fs_info, btrfs_err(fs_info,
"zoned: offline/readonly zone %llu on device %s (devid %llu)", "zoned: offline/readonly zone %llu on device %s (devid %llu)",
physical >> device->zone_info->zone_size_shift, physical[i] >> device->zone_info->zone_size_shift,
rcu_str_deref(device->name), device->devid); rcu_str_deref(device->name), device->devid);
alloc_offsets[i] = WP_MISSING_DEV; alloc_offsets[i] = WP_MISSING_DEV;
break; break;
...@@ -1404,7 +1410,7 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new) ...@@ -1404,7 +1410,7 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
if (alloc_offsets[0] == WP_MISSING_DEV) { if (alloc_offsets[0] == WP_MISSING_DEV) {
btrfs_err(fs_info, btrfs_err(fs_info,
"zoned: cannot recover write pointer for zone %llu", "zoned: cannot recover write pointer for zone %llu",
physical); physical[0]);
ret = -EIO; ret = -EIO;
goto out; goto out;
} }
...@@ -1465,6 +1471,7 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new) ...@@ -1465,6 +1471,7 @@ int btrfs_load_block_group_zone_info(struct btrfs_block_group *cache, bool new)
cache->physical_map = NULL; cache->physical_map = NULL;
} }
bitmap_free(active); bitmap_free(active);
kfree(physical);
kfree(caps); kfree(caps);
kfree(alloc_offsets); kfree(alloc_offsets);
free_extent_map(em); free_extent_map(em);
......
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