]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
dm vdo: add formatting parameters to table line
authorBruce Johnston <bjohnsto@redhat.com>
Tue, 24 Mar 2026 18:06:46 +0000 (14:06 -0400)
committerMikulas Patocka <mpatocka@redhat.com>
Thu, 26 Mar 2026 17:18:08 +0000 (18:18 +0100)
Extend the dm table line with three new optional parameters:
indexMemory (UDS index memory size), indexSparse (dense vs sparse
index), and slabSize (blocks per allocation slab). These values are
parsed, validated, and stored in the device configuration for use
during formatting.

Rework the slab size constants from the single MAX_VDO_SLAB_BITS into
explicit MIN_VDO_SLAB_BLOCKS, MAX_VDO_SLAB_BLOCKS, and
DEFAULT_VDO_SLAB_BLOCKS values.

Bump the target version from 9.1.0 to 9.2.0 to reflect this table
line change.

Signed-off-by: Bruce Johnston <bjohnsto@redhat.com>
Reviewed-by: Matthew Sakai <msakai@redhat.com>
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
drivers/md/dm-vdo/constants.h
drivers/md/dm-vdo/dm-vdo-target.c
drivers/md/dm-vdo/encodings.c
drivers/md/dm-vdo/encodings.h
drivers/md/dm-vdo/types.h

index cc7bc3571ba126502919affdf43bacd6e026f48c..b84e7edeb22ea6d2f0c389d17999279a17f697b2 100644 (file)
@@ -60,8 +60,14 @@ enum {
        /* The maximum number of physical zones */
        MAX_VDO_PHYSICAL_ZONES = 16,
 
-       /* The base-2 logarithm of the maximum blocks in one slab */
-       MAX_VDO_SLAB_BITS = 23,
+       /* The default blocks in one slab */
+       DEFAULT_VDO_SLAB_BLOCKS = 1U << 19,
+
+       /* The minimum blocks in one slab */
+       MIN_VDO_SLAB_BLOCKS = 1U << 13,
+
+       /* The maximum blocks in one slab */
+       MAX_VDO_SLAB_BLOCKS = 1U << 23,
 
        /* The maximum number of slabs the slab depot supports */
        MAX_VDO_SLABS = 8192,
index 7eb676e58ed530ca922e6f258f580d0d8992ee60..1065c88a761cb4e037b796b331db29472aa93859 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/delay.h>
 #include <linux/device-mapper.h>
 #include <linux/err.h>
+#include <linux/log2.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
@@ -377,6 +378,75 @@ static inline int __must_check parse_bool(const char *bool_str, const char *true
        return VDO_SUCCESS;
 }
 
+/**
+ * parse_memory() - Parse a string into an index memory value.
+ * @memory_str: The string value to convert to a memory value.
+ * @memory_ptr: A pointer to return the memory value in.
+ *
+ * Return: VDO_SUCCESS or an error
+ */
+static int __must_check parse_memory(const char *memory_str,
+                                    uds_memory_config_size_t *memory_ptr)
+{
+       uds_memory_config_size_t memory;
+
+       if (strcmp(memory_str, "0.25") == 0) {
+               memory = UDS_MEMORY_CONFIG_256MB;
+       } else if ((strcmp(memory_str, "0.5") == 0) || (strcmp(memory_str, "0.50") == 0)) {
+               memory = UDS_MEMORY_CONFIG_512MB;
+       } else if (strcmp(memory_str, "0.75") == 0) {
+               memory = UDS_MEMORY_CONFIG_768MB;
+       } else {
+               unsigned int value;
+               int result;
+
+               result = kstrtouint(memory_str, 10, &value);
+               if (result) {
+                       vdo_log_error("optional parameter error: invalid memory size, must be a postive integer");
+                       return -EINVAL;
+               }
+
+               if (value > UDS_MEMORY_CONFIG_MAX) {
+                       vdo_log_error("optional parameter error: invalid memory size, must not be greater than %d",
+                                     UDS_MEMORY_CONFIG_MAX);
+                       return -EINVAL;
+               }
+
+               memory = value;
+       }
+
+       *memory_ptr = memory;
+       return VDO_SUCCESS;
+}
+
+/**
+ * parse_slab_size() - Parse a string option into a slab size value.
+ * @slab_str: The string value representing slab size.
+ * @slab_size_ptr: A pointer to return the slab size in.
+ *
+ * Return: VDO_SUCCESS or an error
+ */
+static int __must_check parse_slab_size(const char *slab_str, block_count_t *slab_size_ptr)
+{
+       block_count_t value;
+       int result;
+
+       result = kstrtoull(slab_str, 10, &value);
+       if (result) {
+               vdo_log_error("optional parameter error: invalid slab size, must be a postive integer");
+               return -EINVAL;
+       }
+
+       if (value < MIN_VDO_SLAB_BLOCKS || value > MAX_VDO_SLAB_BLOCKS || (!is_power_of_2(value))) {
+               vdo_log_error("optional parameter error: invalid slab size, must be a power of two between %u and %u",
+                             MIN_VDO_SLAB_BLOCKS, MAX_VDO_SLAB_BLOCKS);
+               return -EINVAL;
+       }
+
+       *slab_size_ptr = value;
+       return VDO_SUCCESS;
+}
+
 /**
  * process_one_thread_config_spec() - Process one component of a thread parameter configuration
  *                                   string and update the configuration data structure.
@@ -566,7 +636,7 @@ static int process_one_key_value_pair(const char *key, unsigned int value,
                }
                /* Max discard sectors in blkdev_issue_discard is UINT_MAX >> 9 */
                if (value > (UINT_MAX / VDO_BLOCK_SIZE)) {
-                       vdo_log_error("optional parameter error: at most %d max discard  blocks are allowed",
+                       vdo_log_error("optional parameter error: at most %d max discard blocks are allowed",
                                      UINT_MAX / VDO_BLOCK_SIZE);
                        return -EINVAL;
                }
@@ -598,7 +668,16 @@ static int parse_one_key_value_pair(const char *key, const char *value,
        if (strcmp(key, "compression") == 0)
                return parse_bool(value, "on", "off", &config->compression);
 
-       /* The remaining arguments must have integral values. */
+       if (strcmp(key, "indexSparse") == 0)
+               return parse_bool(value, "on", "off", &config->index_sparse);
+
+       if (strcmp(key, "indexMemory") == 0)
+               return parse_memory(value, &config->index_memory);
+
+       if (strcmp(key, "slabSize") == 0)
+               return parse_slab_size(value, &config->slab_blocks);
+
+       /* The remaining arguments must have non-negative integral values. */
        result = kstrtouint(value, 10, &count);
        if (result) {
                vdo_log_error("optional config string error: integer value needed, found \"%s\"",
@@ -756,6 +835,9 @@ static int parse_device_config(int argc, char **argv, struct dm_target *ti,
        config->max_discard_blocks = 1;
        config->deduplication = true;
        config->compression = false;
+       config->index_memory = UDS_MEMORY_CONFIG_256MB;
+       config->index_sparse = false;
+       config->slab_blocks = DEFAULT_VDO_SLAB_BLOCKS;
 
        arg_set.argc = argc;
        arg_set.argv = argv;
@@ -781,7 +863,7 @@ static int parse_device_config(int argc, char **argv, struct dm_target *ti,
        /* Get the physical blocks, if known. */
        if (config->version >= 1) {
                result = kstrtoull(dm_shift_arg(&arg_set), 10, &config->physical_blocks);
-               if (result != VDO_SUCCESS) {
+               if (result) {
                        handle_parse_error(config, error_ptr,
                                           "Invalid physical block count");
                        return VDO_BAD_CONFIGURATION;
@@ -802,7 +884,7 @@ static int parse_device_config(int argc, char **argv, struct dm_target *ti,
 
        /* Get the page cache size. */
        result = kstrtouint(dm_shift_arg(&arg_set), 10, &config->cache_size);
-       if (result != VDO_SUCCESS) {
+       if (result) {
                handle_parse_error(config, error_ptr,
                                   "Invalid block map page cache size");
                return VDO_BAD_CONFIGURATION;
@@ -810,7 +892,7 @@ static int parse_device_config(int argc, char **argv, struct dm_target *ti,
 
        /* Get the block map era length. */
        result = kstrtouint(dm_shift_arg(&arg_set), 10, &config->block_map_maximum_age);
-       if (result != VDO_SUCCESS) {
+       if (result) {
                handle_parse_error(config, error_ptr, "Invalid block map maximum age");
                return VDO_BAD_CONFIGURATION;
        }
@@ -1457,10 +1539,13 @@ static int vdo_initialize(struct dm_target *ti, unsigned int instance,
        vdo_log_debug("Logical blocks         = %llu", logical_blocks);
        vdo_log_debug("Physical block size    = %llu", (u64) block_size);
        vdo_log_debug("Physical blocks        = %llu", config->physical_blocks);
+       vdo_log_debug("Slab size              = %llu", config->slab_blocks);
        vdo_log_debug("Block map cache blocks = %u", config->cache_size);
        vdo_log_debug("Block map maximum age  = %u", config->block_map_maximum_age);
        vdo_log_debug("Deduplication          = %s", (config->deduplication ? "on" : "off"));
        vdo_log_debug("Compression            = %s", (config->compression ? "on" : "off"));
+       vdo_log_debug("Index memory           = %u", config->index_memory);
+       vdo_log_debug("Index sparse           = %s", (config->index_sparse ? "on" : "off"));
 
        vdo = vdo_find_matching(vdo_uses_device, config);
        if (vdo != NULL) {
@@ -2856,7 +2941,7 @@ static void vdo_resume(struct dm_target *ti)
 static struct target_type vdo_target_bio = {
        .features = DM_TARGET_SINGLETON,
        .name = "vdo",
-       .version = { 9, 1, 0 },
+       .version = { 9, 2, 0 },
        .module = THIS_MODULE,
        .ctr = vdo_ctr,
        .dtr = vdo_dtr,
index 441c9aee1749085c5e21dee9b1c5e602b4064d64..3ceba010f4e6d0015c703b61f6203301e271b7e7 100644 (file)
 #include "status-codes.h"
 #include "types.h"
 
-/** The maximum logical space is 4 petabytes, which is 1 terablock. */
-static const block_count_t MAXIMUM_VDO_LOGICAL_BLOCKS = 1024ULL * 1024 * 1024 * 1024;
-
-/** The maximum physical space is 256 terabytes, which is 64 gigablocks. */
-static const block_count_t MAXIMUM_VDO_PHYSICAL_BLOCKS = 1024ULL * 1024 * 1024 * 64;
-
 struct geometry_block {
        char magic_number[VDO_GEOMETRY_MAGIC_NUMBER_SIZE];
        struct packed_header header;
@@ -1220,9 +1214,9 @@ int vdo_validate_config(const struct vdo_config *config,
        if (result != VDO_SUCCESS)
                return result;
 
-       result = VDO_ASSERT(config->slab_size <= (1 << MAX_VDO_SLAB_BITS),
-                           "slab size must be less than or equal to 2^%d",
-                           MAX_VDO_SLAB_BITS);
+       result = VDO_ASSERT(config->slab_size <= MAX_VDO_SLAB_BLOCKS,
+                           "slab size must be a power of two less than or equal to %d",
+                           MAX_VDO_SLAB_BLOCKS);
        if (result != VDO_SUCCESS)
                return result;
 
index 3cfbe4771a1cd82a7c7772b10378db5ad2d28277..0393936c8aeb7b8588520d936501eddfb3ffb323 100644 (file)
@@ -608,6 +608,12 @@ struct vdo_config {
        block_count_t slab_journal_blocks; /* number of slab journal blocks */
 };
 
+/** The maximum logical space is 4 petabytes, which is 1 terablock. */
+#define MAXIMUM_VDO_LOGICAL_BLOCKS ((block_count_t)(1024ULL * 1024 * 1024 * 1024))
+
+/** The maximum physical space is 256 terabytes, which is 64 gigablocks. */
+#define MAXIMUM_VDO_PHYSICAL_BLOCKS ((block_count_t)(1024ULL * 1024 * 1024 * 64))
+
 /* This is the structure that captures the vdo fields saved as a super block component. */
 struct vdo_component {
        enum vdo_state state;
index cdf36e7d770214f6e565f54c68e2158439c2a739..0d60a88aa0861627ac2321266862d2972fd4fcdd 100644 (file)
@@ -227,6 +227,9 @@ struct device_config {
        bool compression;
        struct thread_count_config thread_counts;
        block_count_t max_discard_blocks;
+       block_count_t slab_blocks;
+       int index_memory;
+       bool index_sparse;
 };
 
 enum vdo_completion_type {