[dm-devel] [PATCH] dm-zoned: support zone sizes smaller than 128MiB
Damien Le Moal
Damien.LeMoal at wdc.com
Wed Dec 25 04:33:47 UTC 2019
On 2019/12/24 10:05, Dmitry Fomichev wrote:
> dm-zoned is observed to log failed kernel assertions and not to work
> correctly when operating against a device with a zone size smaller
> than 128MiB (4K block size times 32768 bits per 4K block). The reason
> is that the bitmap size per zone is calculated as zero with such a
> small zone size. This patch fixes this problem and also makes the code
> related to zone bitmap management be able to handle per zone bitmaps
> smaller than a single block.
>
> A dm-zoned-tools patch is required to properly format dm-zoned devices
> with zone sizes smaller than 128MiB and this patch is being posted
> separately.
>
> Fixes: 3b1a94c88b79 ("dm zoned: drive-managed zoned block device target")
> Cc: stable at vger.kernel.org
> Signed-off-by: Dmitry Fomichev <dmitry.fomichev at wdc.com>
Looks good to me.
Reviewed-by: Damien Le Moal <damien.lemoal at wdc.com>
> ---
> drivers/md/dm-zoned-metadata.c | 23 ++++++++++++++---------
> 1 file changed, 14 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/md/dm-zoned-metadata.c b/drivers/md/dm-zoned-metadata.c
> index 069e4675da6b..91512eb40458 100644
> --- a/drivers/md/dm-zoned-metadata.c
> +++ b/drivers/md/dm-zoned-metadata.c
> @@ -134,6 +134,7 @@ struct dmz_metadata {
>
> sector_t zone_bitmap_size;
> unsigned int zone_nr_bitmap_blocks;
> + unsigned int zone_bits_per_mblk;
>
> unsigned int nr_bitmap_blocks;
> unsigned int nr_map_blocks;
> @@ -1153,7 +1154,10 @@ static int dmz_init_zones(struct dmz_metadata *zmd)
>
> /* Init */
> zmd->zone_bitmap_size = dev->zone_nr_blocks >> 3;
> - zmd->zone_nr_bitmap_blocks = zmd->zone_bitmap_size >> DMZ_BLOCK_SHIFT;
> + zmd->zone_nr_bitmap_blocks =
> + max_t(sector_t, 1, zmd->zone_bitmap_size >> DMZ_BLOCK_SHIFT);
> + zmd->zone_bits_per_mblk = min_t(sector_t, dev->zone_nr_blocks,
> + DMZ_BLOCK_SIZE_BITS);
>
> /* Allocate zone array */
> zmd->zones = kcalloc(dev->nr_zones, sizeof(struct dm_zone), GFP_KERNEL);
> @@ -1947,7 +1951,7 @@ int dmz_copy_valid_blocks(struct dmz_metadata *zmd, struct dm_zone *from_zone,
> dmz_release_mblock(zmd, to_mblk);
> dmz_release_mblock(zmd, from_mblk);
>
> - chunk_block += DMZ_BLOCK_SIZE_BITS;
> + chunk_block += zmd->zone_bits_per_mblk;
> }
>
> to_zone->weight = from_zone->weight;
> @@ -2008,7 +2012,7 @@ int dmz_validate_blocks(struct dmz_metadata *zmd, struct dm_zone *zone,
>
> /* Set bits */
> bit = chunk_block & DMZ_BLOCK_MASK_BITS;
> - nr_bits = min(nr_blocks, DMZ_BLOCK_SIZE_BITS - bit);
> + nr_bits = min(nr_blocks, zmd->zone_bits_per_mblk - bit);
>
> count = dmz_set_bits((unsigned long *)mblk->data, bit, nr_bits);
> if (count) {
> @@ -2087,7 +2091,7 @@ int dmz_invalidate_blocks(struct dmz_metadata *zmd, struct dm_zone *zone,
>
> /* Clear bits */
> bit = chunk_block & DMZ_BLOCK_MASK_BITS;
> - nr_bits = min(nr_blocks, DMZ_BLOCK_SIZE_BITS - bit);
> + nr_bits = min(nr_blocks, zmd->zone_bits_per_mblk - bit);
>
> count = dmz_clear_bits((unsigned long *)mblk->data,
> bit, nr_bits);
> @@ -2147,6 +2151,7 @@ static int dmz_to_next_set_block(struct dmz_metadata *zmd, struct dm_zone *zone,
> {
> struct dmz_mblock *mblk;
> unsigned int bit, set_bit, nr_bits;
> + unsigned int zone_bits = zmd->zone_bits_per_mblk;
> unsigned long *bitmap;
> int n = 0;
>
> @@ -2161,15 +2166,15 @@ static int dmz_to_next_set_block(struct dmz_metadata *zmd, struct dm_zone *zone,
> /* Get offset */
> bitmap = (unsigned long *) mblk->data;
> bit = chunk_block & DMZ_BLOCK_MASK_BITS;
> - nr_bits = min(nr_blocks, DMZ_BLOCK_SIZE_BITS - bit);
> + nr_bits = min(nr_blocks, zone_bits - bit);
> if (set)
> - set_bit = find_next_bit(bitmap, DMZ_BLOCK_SIZE_BITS, bit);
> + set_bit = find_next_bit(bitmap, zone_bits, bit);
> else
> - set_bit = find_next_zero_bit(bitmap, DMZ_BLOCK_SIZE_BITS, bit);
> + set_bit = find_next_zero_bit(bitmap, zone_bits, bit);
> dmz_release_mblock(zmd, mblk);
>
> n += set_bit - bit;
> - if (set_bit < DMZ_BLOCK_SIZE_BITS)
> + if (set_bit < zone_bits)
> break;
>
> nr_blocks -= nr_bits;
> @@ -2272,7 +2277,7 @@ static void dmz_get_zone_weight(struct dmz_metadata *zmd, struct dm_zone *zone)
> /* Count bits in this block */
> bitmap = mblk->data;
> bit = chunk_block & DMZ_BLOCK_MASK_BITS;
> - nr_bits = min(nr_blocks, DMZ_BLOCK_SIZE_BITS - bit);
> + nr_bits = min(nr_blocks, zmd->zone_bits_per_mblk - bit);
> n += dmz_count_bits(bitmap, bit, nr_bits);
>
> dmz_release_mblock(zmd, mblk);
>
--
Damien Le Moal
Western Digital Research
More information about the dm-devel
mailing list