• Damien Le Moal's avatar
    dm zoned: fix various dmz_get_mblock() issues · 3d4e7383
    Damien Le Moal authored
    dmz_fetch_mblock() called from dmz_get_mblock() has a race since the
    allocation of the new metadata block descriptor and its insertion in
    the cache rbtree with the READING state is not atomic. Two different
    contexts requesting the same block may end up each adding two different
    descriptors of the same block to the cache.
    Another problem for this function is that the BIO for processing the
    block read is allocated after the metadata block descriptor is inserted
    in the cache rbtree. If the BIO allocation fails, the metadata block
    descriptor is freed without first being removed from the rbtree.
    Fix the first problem by checking again if the requested block is not in
    the cache right before inserting the newly allocated descriptor,
    atomically under the mblk_lock spinlock. The second problem is fixed by
    simply allocating the BIO before inserting the new block in the cache.
    Finally, since dmz_fetch_mblock() also increments a block reference
    counter, rename the function to dmz_get_mblock_slow(). To be symmetric
    and clear, also rename dmz_lookup_mblock() to dmz_get_mblock_fast() and
    increment the block reference counter directly in that function rather
    than in dmz_get_mblock().
    Fixes: 3b1a94c8 ("dm zoned: drive-managed zoned block device target")
    Cc: stable@vger.kernel.org
    Signed-off-by: default avatarDamien Le Moal <damien.lemoal@wdc.com>
    Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
dm-zoned-metadata.c 58.9 KB