From cef13315d0932a7f63c53fd4aa1941b0ab37cc5f Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Wed, 11 Oct 2023 12:42:18 +0200 Subject: [PATCH] Compare properties of a new cache device during cache attach New cache device must have all the same properties then the previously attached one. Keeping cache properties in cache priv also allows to add new cores to detached cache instance. Signed-off-by: Michal Mielewczyk Signed-off-by: Rafal Stefanowski --- modules/cas_cache/cas_cache.h | 6 ++ modules/cas_cache/layer_cache_management.c | 69 +++++++++++++++++++++- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/modules/cas_cache/cas_cache.h b/modules/cas_cache/cas_cache.h index ac27681..efc78b2 100644 --- a/modules/cas_cache/cas_cache.h +++ b/modules/cas_cache/cas_cache.h @@ -1,5 +1,6 @@ /* * Copyright(c) 2012-2022 Intel Corporation + * Copyright(c) 2024 Huawei Technologies * SPDX-License-Identifier: BSD-3-Clause */ @@ -70,6 +71,11 @@ struct cache_priv { ocf_queue_t mngt_queue; void *attach_context; bool cache_exp_obj_initialized; + struct { + struct queue_limits queue_limits; + bool fua; + bool flush; + } device_properties; ocf_queue_t io_queues[]; }; diff --git a/modules/cas_cache/layer_cache_management.c b/modules/cas_cache/layer_cache_management.c index 1e6ab44..89c779d 100644 --- a/modules/cas_cache/layer_cache_management.c +++ b/modules/cas_cache/layer_cache_management.c @@ -2220,6 +2220,24 @@ static void volume_set_no_merges_flag_helper(ocf_cache_t cache) cas_cache_set_no_merges_flag(cache_q); } +static void _cache_save_device_properties(ocf_cache_t cache) +{ + struct block_device *bd; + struct bd_object *bvol; + struct request_queue *cache_q; + struct cache_priv *cache_priv = ocf_cache_get_priv(cache); + + bvol = bd_object(ocf_cache_get_volume(cache)); + bd = cas_disk_get_blkdev(bvol->dsk); + cache_q = bd->bd_disk->queue; + + cache_priv->device_properties.queue_limits = cache_q->limits; + cache_priv->device_properties.flush = + CAS_CHECK_QUEUE_FLUSH(cache_q); + cache_priv->device_properties.fua = + CAS_CHECK_QUEUE_FUA(cache_q); +} + static int _cache_start_finalize(ocf_cache_t cache, int init_mode, bool activate) { @@ -2239,6 +2257,8 @@ static int _cache_start_finalize(ocf_cache_t cache, int init_mode, ctx->cls_inited = true; volume_set_no_merges_flag_helper(cache); + + _cache_save_device_properties(cache); } if (activate) @@ -2278,14 +2298,21 @@ static int _cache_start_finalize(ocf_cache_t cache, int init_mode, } static int cache_mngt_check_bdev(struct ocf_mngt_cache_device_config *cfg, - bool force) + bool force, bool reattach, ocf_cache_t cache) { char holder[] = "CAS START\n"; cas_bdev_handle_t bdev_handle; struct block_device *bdev; int part_count; bool is_part; + bool reattach_properties_diff = false; + struct cache_priv *cache_priv; const struct ocf_volume_uuid *uuid = ocf_volume_get_uuid(cfg->volume); + /* The only reason to use blk_stack_limits() is checking compatibility of + * the new device with the original cache. But since the functions modifies + * content of queue_limits, we use copy of the original struct. + */ + struct queue_limits tmp_limits; bdev_handle = cas_bdev_open_by_path(uuid->data, (CAS_BLK_MODE_EXCL | CAS_BLK_MODE_READ), holder); @@ -2298,12 +2325,48 @@ static int cache_mngt_check_bdev(struct ocf_mngt_cache_device_config *cfg, is_part = (cas_bdev_whole(bdev) != bdev); part_count = cas_blk_get_part_count(bdev); + + if (reattach) { + ENV_BUG_ON(!cache); + + cache_priv = ocf_cache_get_priv(cache); + tmp_limits = cache_priv->device_properties.queue_limits; + + if (blk_stack_limits(&tmp_limits, &bdev->bd_disk->queue->limits, 0)) { + reattach_properties_diff = true; + printk(KERN_WARNING "New cache device block properties " + "differ from the previous one.\n"); + } + if (tmp_limits.misaligned) { + reattach_properties_diff = true; + printk(KERN_WARNING "New cache device block interval " + "doesn't line up with the previous one.\n"); + } + if (CAS_CHECK_QUEUE_FLUSH(bdev->bd_disk->queue) != + cache_priv->device_properties.flush) { + reattach_properties_diff = true; + printk(KERN_WARNING "New cache device %s support flush " + "in contrary to the previous cache device.\n", + cache_priv->device_properties.flush ? "doesn't" : "does"); + } + if (CAS_CHECK_QUEUE_FUA(bdev->bd_disk->queue) != + cache_priv->device_properties.fua) { + reattach_properties_diff = true; + printk(KERN_WARNING "New cache device %s support fua " + "in contrary to the previous cache device.\n", + cache_priv->device_properties.fua ? "doesn't" : "does"); + } + } + cas_bdev_release(bdev_handle, (CAS_BLK_MODE_EXCL | CAS_BLK_MODE_READ), holder); if (!is_part && part_count > 1 && !force) return -KCAS_ERR_CONTAINS_PART; + if (reattach_properties_diff) + return -KCAS_ERR_DEVICE_PROPERTIES_MISMATCH; + return 0; } @@ -2416,7 +2479,7 @@ int cache_mngt_activate(struct ocf_mngt_cache_standby_activate_config *cfg, * to compare data on drive and in DRAM to provide more specific * error code. */ - result = cache_mngt_check_bdev(&cfg->device, true); + result = cache_mngt_check_bdev(&cfg->device, true, false, NULL); if (result) goto out_cache_unlock; @@ -2513,7 +2576,7 @@ int cache_mngt_init_instance(struct ocf_mngt_cache_config *cfg, if (!try_module_get(THIS_MODULE)) return -KCAS_ERR_SYSTEM; - result = cache_mngt_check_bdev(&attach_cfg->device, attach_cfg->force); + result = cache_mngt_check_bdev(&attach_cfg->device, attach_cfg->force, false, NULL); if (result) { module_put(THIS_MODULE); return result;