#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>
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.
}
/* 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;
}
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\"",
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;
/* 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;
/* 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;
/* 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;
}
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) {
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,