dm zoned: use array for superblock zones

Instead of storing just the first superblock zone and calculate
the secondary relative to that we should be using an array for
holding the superblock zones.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Damien Le Moal <damien.lemoal@wdc.com>
Reviewed-by: Bob Liu <bob.liu@oracle.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
This commit is contained in:
Hannes Reinecke 2020-05-11 10:24:19 +02:00 committed by Mike Snitzer
parent b712287398
commit 735bd7e4cd

View file

@ -124,6 +124,7 @@ struct dmz_sb {
sector_t block;
struct dmz_mblock *mblk;
struct dmz_super *sb;
struct dm_zone *zone;
};
/*
@ -150,7 +151,6 @@ struct dmz_metadata {
/* Zone information array */
struct dm_zone *zones;
struct dm_zone *sb_zone;
struct dmz_sb sb[2];
unsigned int mblk_primary;
u64 sb_gen;
@ -839,8 +839,9 @@ err:
/*
* Check super block.
*/
static int dmz_check_sb(struct dmz_metadata *zmd, struct dmz_super *sb)
static int dmz_check_sb(struct dmz_metadata *zmd, unsigned int set)
{
struct dmz_super *sb = zmd->sb[set].sb;
unsigned int nr_meta_zones, nr_data_zones;
struct dmz_dev *dev = zmd->dev;
u32 crc, stored_crc;
@ -932,16 +933,20 @@ static int dmz_lookup_secondary_sb(struct dmz_metadata *zmd)
/* Bad first super block: search for the second one */
zmd->sb[1].block = zmd->sb[0].block + zone_nr_blocks;
zmd->sb[1].zone = zmd->sb[0].zone + 1;
for (i = 0; i < zmd->nr_rnd_zones - 1; i++) {
if (dmz_read_sb(zmd, 1) != 0)
break;
if (le32_to_cpu(zmd->sb[1].sb->magic) == DMZ_MAGIC)
if (le32_to_cpu(zmd->sb[1].sb->magic) == DMZ_MAGIC) {
zmd->sb[1].zone += i;
return 0;
}
zmd->sb[1].block += zone_nr_blocks;
}
dmz_free_mblock(zmd, mblk);
zmd->sb[1].mblk = NULL;
zmd->sb[1].zone = NULL;
return -EIO;
}
@ -985,11 +990,9 @@ static int dmz_recover_mblocks(struct dmz_metadata *zmd, unsigned int dst_set)
dmz_dev_warn(zmd->dev, "Metadata set %u invalid: recovering", dst_set);
if (dst_set == 0)
zmd->sb[0].block = dmz_start_block(zmd, zmd->sb_zone);
else {
zmd->sb[1].block = zmd->sb[0].block +
(zmd->nr_meta_zones << zmd->dev->zone_nr_blocks_shift);
}
zmd->sb[0].block = dmz_start_block(zmd, zmd->sb[0].zone);
else
zmd->sb[1].block = dmz_start_block(zmd, zmd->sb[1].zone);
page = alloc_page(GFP_NOIO);
if (!page)
@ -1033,21 +1036,27 @@ static int dmz_load_sb(struct dmz_metadata *zmd)
u64 sb_gen[2] = {0, 0};
int ret;
if (!zmd->sb[0].zone) {
dmz_dev_err(zmd->dev, "Primary super block zone not set");
return -ENXIO;
}
/* Read and check the primary super block */
zmd->sb[0].block = dmz_start_block(zmd, zmd->sb_zone);
zmd->sb[0].block = dmz_start_block(zmd, zmd->sb[0].zone);
ret = dmz_get_sb(zmd, 0);
if (ret) {
dmz_dev_err(zmd->dev, "Read primary super block failed");
return ret;
}
ret = dmz_check_sb(zmd, zmd->sb[0].sb);
ret = dmz_check_sb(zmd, 0);
/* Read and check secondary super block */
if (ret == 0) {
sb_good[0] = true;
zmd->sb[1].block = zmd->sb[0].block +
(zmd->nr_meta_zones << zmd->dev->zone_nr_blocks_shift);
if (!zmd->sb[1].zone)
zmd->sb[1].zone = zmd->sb[0].zone + zmd->nr_meta_zones;
zmd->sb[1].block = dmz_start_block(zmd, zmd->sb[1].zone);
ret = dmz_get_sb(zmd, 1);
} else
ret = dmz_lookup_secondary_sb(zmd);
@ -1057,7 +1066,7 @@ static int dmz_load_sb(struct dmz_metadata *zmd)
return ret;
}
ret = dmz_check_sb(zmd, zmd->sb[1].sb);
ret = dmz_check_sb(zmd, 1);
if (ret == 0)
sb_good[1] = true;
@ -1142,9 +1151,9 @@ static int dmz_init_zone(struct blk_zone *blkz, unsigned int idx, void *data)
zmd->nr_useable_zones++;
if (dmz_is_rnd(zone)) {
zmd->nr_rnd_zones++;
if (!zmd->sb_zone) {
if (!zmd->sb[0].zone) {
/* Super block zone */
zmd->sb_zone = zone;
zmd->sb[0].zone = zone;
}
}
}
@ -2415,7 +2424,7 @@ int dmz_ctr_metadata(struct dmz_dev *dev, struct dmz_metadata **metadata)
/* Set metadata zones starting from sb_zone */
for (i = 0; i < zmd->nr_meta_zones << 1; i++) {
zone = dmz_get(zmd, zmd->sb_zone->id + i);
zone = dmz_get(zmd, zmd->sb[0].zone->id + i);
if (!dmz_is_rnd(zone))
goto err;
set_bit(DMZ_META, &zone->flags);