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