dm zoned: use array for superblock zones
authorHannes Reinecke <hare@suse.de>
Mon, 11 May 2020 08:24:19 +0000 (10:24 +0200)
committerMike Snitzer <snitzer@redhat.com>
Fri, 15 May 2020 14:29:37 +0000 (10:29 -0400)
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>
drivers/md/dm-zoned-metadata.c

index 1993eeb26bc1170f6a1afbf8a29c6a504c90fb9d..900b1c1224f5ff9831a9892e55fb4b2e09e28298 100644 (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);