Hi

I nack this series of patches, because sharing mempools (or dm_io_client) 
is prone to deadlocks.

If you have two dm-verity devices stacked on each other, the upper device 
may deplete the mempool and the lower device has no way to do forward 
progress, resulting in a deadlock.

For example, suppose that you have dm-snapshot on the top of dm-verity on 
the top of another dm-verity device. If the kernel needs to write back 
dirty memory, it calls the dm-snapshot target, the dm-snapshot reads data 
from the upper dm-verity device, the upper dm-verity device depletes the 
shared mempool and the lower dm-verity device has no way to make forward 
progress - deadlock.

If you want to reduce memory consumption, set reserved_bio_based_ios to 1, 
that should be safe. (setting it to 0 is prone to deadlock).

I remember that the one of the first things that I did at Red Hat 17 years 
ago was removing shared resources from device mapper and making them 
per-device :-)

Mikulas


On Wed, 23 Apr 2025, LongPing Wei wrote:

> The size of biovec's memory of one dm_io_client will be
> reserved_bio_based_ios(default value is 16) * 4KiB memory.
> When the number of dm-verity devices is dozens,
> the total memory size will be several MiBs.
> 
> The number of dm-verity devices is 59 on my test device,
> and the size of biovec's memory here will be 3.87MiB.
> 
> This commit will reduce the memory usage of dm-verity
> by making all verity devices share the same dm_io_client and recheck_pool.
> 
> Fixes: 9177f3c0dea61 ("dm-verity: recheck the hash after a failure")
> 
> Signed-off-by: LongPing Wei <weilongp...@oppo.com>
> ---
>  drivers/md/dm-verity-target.c | 71 ++++++++++++++++++++++++-----------
>  drivers/md/dm-verity.h        |  3 --
>  2 files changed, 49 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
> index 3c427f18a04b..986c3386aa59 100644
> --- a/drivers/md/dm-verity-target.c
> +++ b/drivers/md/dm-verity-target.c
> @@ -72,6 +72,9 @@ struct dm_verity_prefetch_work {
>       unsigned int n_blocks;
>  };
>  
> +static struct dm_io_client *verity_io_client;
> +static mempool_t verity_recheck_pool;
> +
>  /*
>   * Auxiliary structure appended to each dm-bufio buffer. If the value
>   * hash_verified is nonzero, hash of the block has been verified.
> @@ -449,14 +452,14 @@ static noinline int verity_recheck(struct dm_verity *v, 
> struct dm_verity_io *io,
>       struct dm_io_request io_req;
>       struct dm_io_region io_loc;
>  
> -     page = mempool_alloc(&v->recheck_pool, GFP_NOIO);
> +     page = mempool_alloc(&verity_recheck_pool, GFP_NOIO);
>       buffer = page_to_virt(page);
>  
>       io_req.bi_opf = REQ_OP_READ;
>       io_req.mem.type = DM_IO_KMEM;
>       io_req.mem.ptr.addr = buffer;
>       io_req.notify.fn = NULL;
> -     io_req.client = v->io;
> +     io_req.client = verity_io_client;
>       io_loc.bdev = v->data_dev->bdev;
>       io_loc.sector = cur_block << (v->data_dev_block_bits - SECTOR_SHIFT);
>       io_loc.count = 1 << (v->data_dev_block_bits - SECTOR_SHIFT);
> @@ -478,7 +481,7 @@ static noinline int verity_recheck(struct dm_verity *v, 
> struct dm_verity_io *io,
>       memcpy(dest, buffer, 1 << v->data_dev_block_bits);
>       r = 0;
>  free_ret:
> -     mempool_free(page, &v->recheck_pool);
> +     mempool_free(page, &verity_recheck_pool);
>  
>       return r;
>  }
> @@ -1075,10 +1078,6 @@ static void verity_dtr(struct dm_target *ti)
>       if (v->verify_wq)
>               destroy_workqueue(v->verify_wq);
>  
> -     mempool_exit(&v->recheck_pool);
> -     if (v->io)
> -             dm_io_client_destroy(v->io);
> -
>       if (v->bufio)
>               dm_bufio_client_destroy(v->bufio);
>  
> @@ -1625,20 +1624,6 @@ static int verity_ctr(struct dm_target *ti, unsigned 
> int argc, char **argv)
>       }
>       v->hash_blocks = hash_position;
>  
> -     r = mempool_init_page_pool(&v->recheck_pool, 1, 0);
> -     if (unlikely(r)) {
> -             ti->error = "Cannot allocate mempool";
> -             goto bad;
> -     }
> -
> -     v->io = dm_io_client_create();
> -     if (IS_ERR(v->io)) {
> -             r = PTR_ERR(v->io);
> -             v->io = NULL;
> -             ti->error = "Cannot allocate dm io";
> -             goto bad;
> -     }
> -
>       v->bufio = dm_bufio_client_create(v->hash_dev->bdev,
>               1 << v->hash_dev_block_bits, 1, sizeof(struct buffer_aux),
>               dm_bufio_alloc_callback, NULL,
> @@ -1822,7 +1807,49 @@ static struct target_type verity_target = {
>       .preresume      = verity_preresume,
>  #endif /* CONFIG_SECURITY */
>  };
> -module_dm(verity);
> +
> +static int __init dm_verity_init(void)
> +{
> +     int r;
> +
> +     r = mempool_init_page_pool(&verity_recheck_pool, 1, 0);
> +     if (unlikely(r)) {
> +             DMERR("Cannot allocate mempool");
> +             goto mempool_init_page_pool_failed;
> +     }
> +
> +     verity_io_client = dm_io_client_create();
> +     if (IS_ERR(verity_io_client)) {
> +             r = PTR_ERR(verity_io_client);
> +             verity_io_client = NULL;
> +             DMERR("Cannot allocate dm io");
> +             goto dm_io_client_create_failed;
> +     }
> +
> +     r = dm_register_target(&(verity_target));
> +     if (unlikely(r))
> +             goto dm_register_target_failed;
> +     return r;
> +
> +dm_register_target_failed:
> +     dm_io_client_destroy(verity_io_client);
> +     verity_io_client = NULL;
> +dm_io_client_create_failed:
> +     mempool_exit(&verity_recheck_pool);
> +mempool_init_page_pool_failed:
> +     return r;
> +}
> +module_init(dm_verity_init);
> +
> +static void __exit dm_verity_exit(void)
> +{
> +     dm_unregister_target(&(verity_target));
> +     mempool_exit(&verity_recheck_pool);
> +     if (verity_io_client)
> +             dm_io_client_destroy(verity_io_client);
> +     verity_io_client = NULL;
> +}
> +module_exit(dm_verity_exit)
>  
>  /*
>   * Check whether a DM target is a verity target.
> diff --git a/drivers/md/dm-verity.h b/drivers/md/dm-verity.h
> index 8cbb57862ae1..f28454f81249 100644
> --- a/drivers/md/dm-verity.h
> +++ b/drivers/md/dm-verity.h
> @@ -75,9 +75,6 @@ struct dm_verity {
>       unsigned long *validated_blocks; /* bitset blocks validated */
>  
>       char *signature_key_desc; /* signature keyring reference */
> -
> -     struct dm_io_client *io;
> -     mempool_t recheck_pool;
>  };
>  
>  struct dm_verity_io {
> -- 
> 2.34.1
> 


Reply via email to