From c68de777990f2e964b91d26c4efeb320fe42ad53 Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Thu, 12 Aug 2021 16:30:27 +0200 Subject: [PATCH 1/2] Remove remains of atomic writes support Signed-off-by: Michal Mielewczyk --- casadm/cas_lib.c | 49 - casadm/cas_lib.h | 11 - casadm/extended_err_msg.c | 4 - casadm/statistics_model.c | 3 - modules/cas_cache/cas_cache.h | 4 - modules/cas_cache/context.c | 6 - modules/cas_cache/layer_cache_management.c | 35 +- modules/cas_cache/layer_cache_management.h | 3 - modules/cas_cache/service_ui_ioctl.c | 4 +- modules/cas_cache/utils/cas_cache_utils.h | 12 - modules/cas_cache/utils/utils_nvme.c | 68 - modules/cas_cache/utils/utils_nvme.h | 28 - modules/cas_cache/volume/obj_blk.h | 3 - .../cas_cache/volume/vol_atomic_dev_bottom.c | 1148 ----------------- .../cas_cache/volume/vol_atomic_dev_bottom.h | 29 - modules/cas_cache/volume/vol_blk_utils.c | 197 +-- modules/cas_cache/volume/vol_blk_utils.h | 6 - .../cas_cache/volume/vol_block_dev_bottom.c | 16 - .../cas_cache/volume/vol_block_dev_bottom.h | 3 - modules/config.mk | 48 - modules/include/cas_ioctl_codes.h | 36 - 21 files changed, 9 insertions(+), 1704 deletions(-) delete mode 100644 modules/cas_cache/utils/cas_cache_utils.h delete mode 100644 modules/cas_cache/utils/utils_nvme.c delete mode 100644 modules/cas_cache/utils/utils_nvme.h delete mode 100644 modules/cas_cache/volume/vol_atomic_dev_bottom.c delete mode 100644 modules/cas_cache/volume/vol_atomic_dev_bottom.h diff --git a/casadm/cas_lib.c b/casadm/cas_lib.c index f6a9f9e..95a0cea 100644 --- a/casadm/cas_lib.c +++ b/casadm/cas_lib.c @@ -281,12 +281,6 @@ static struct name_to_val_mapping promotion_policy_names[] = { { NULL} }; -static struct name_to_val_mapping metadata_mode_names[] = { - { .short_name = "normal", .value = CAS_METADATA_MODE_NORMAL }, - { .short_name = "atomic", .value = CAS_METADATA_MODE_ATOMIC }, - { NULL } -}; - static struct name_to_val_mapping seq_cutoff_policy_names[] = { { .short_name = "always", .value = ocf_seq_cutoff_policy_always }, { .short_name = "full", .value = ocf_seq_cutoff_policy_full }, @@ -310,12 +304,6 @@ static struct name_to_val_mapping output_formats_names[] = { { NULL } }; -static struct name_to_val_mapping metadata_modes_names[] = { - { .short_name = "normal", .value = METADATA_MODE_NORMAL }, - { .short_name = "atomic", .value = METADATA_MODE_ATOMIC }, - { NULL } -}; - static int validate_str_val_mapping(const char* s, const struct name_to_val_mapping* mappings, int invalid_value) @@ -447,11 +435,6 @@ inline const char *promotion_policy_to_name(uint8_t policy) return val_to_short_name(policy, promotion_policy_names, "Unknown"); } -const char *metadata_mode_to_name(uint8_t metadata_mode) -{ - return val_to_short_name(metadata_mode, metadata_mode_names, "Invalid"); -} - const char *seq_cutoff_policy_to_name(uint8_t seq_cutoff_policy) { return val_to_short_name(seq_cutoff_policy, @@ -495,15 +478,6 @@ int validate_str_output_format(const char* s) OUTPUT_FORMAT_INVALID); } -/* Returns one of METADATA_MODE values - * or METADATA_MODE_INVALID in case of error. - */ -int validate_str_metadata_mode(const char* s) -{ - return validate_str_val_mapping(s, metadata_modes_names, - METADATA_MODE_INVALID); -} - void print_err(int error_code) { const char *msg = cas_strerr(error_code); @@ -534,21 +508,6 @@ const char *get_core_state_name(int core_state) } -/* check if device is atomic and print information about potential slow start */ -void print_slow_atomic_cache_start_info(const char *device_path) -{ - struct kcas_cache_check_device cmd_info; - int ret; - - ret = _check_cache_device(device_path, &cmd_info); - - if (!ret && cmd_info.format_atomic) { - cas_printf(LOG_INFO, - "Starting new cache instance on a device with atomic metadata format may take \n" - "several minutes depending on device model and size.\n"); - } -} - /** * Save to dest an absolute device file path of src. * Return number of characters copied to dest if succeed, negative value if failed. @@ -1015,9 +974,6 @@ int start_cache(uint16_t cache_id, unsigned int cache_init, } close(fd); - if (cache_init == CACHE_INIT_NEW) - print_slow_atomic_cache_start_info(cache_device); - fd = open_ctrl_device(); if (fd == -1) return FAILURE; @@ -1080,11 +1036,6 @@ int start_cache(uint16_t cache_id, unsigned int cache_init, } } - if (!cmd.metadata_mode_optimal) - cas_printf(LOG_NOTICE, "Selected metadata mode is not optimal for device %s.\n" - "You can improve cache performance by formatting your device\n", - cache_device); - check_cache_scheduler(cache_device, cmd.cache_elevator); diff --git a/casadm/cas_lib.h b/casadm/cas_lib.h index 05290cd..ee736bb 100644 --- a/casadm/cas_lib.h +++ b/casadm/cas_lib.h @@ -68,13 +68,6 @@ enum output_format_t { OUTPUT_FORMAT_DEFAULT = OUTPUT_FORMAT_TABLE }; -enum metadata_mode_t { - METADATA_MODE_INVALID = 0, - METADATA_MODE_NORMAL, - METADATA_MODE_ATOMIC, - METADATA_MODE_DEFAULT = METADATA_MODE_NORMAL, -}; - #define STATS_FILTER_INVALID 0 #define STATS_FILTER_CONF (1 << 0) #define STATS_FILTER_USAGE (1 << 1) @@ -96,8 +89,6 @@ const char *promotion_policy_to_name(uint8_t policy); const char *cache_mode_to_name(uint8_t cache_mode); const char *get_cache_state_name(int cache_state); const char *get_core_state_name(int core_state); -const char *metadata_variant_to_name(uint8_t variant); -const char *metadata_mode_to_name(uint8_t metadata_mode); const char *seq_cutoff_policy_to_name(uint8_t seq_cutoff_policy); __attribute__((format(printf, 2, 3))) @@ -264,10 +255,8 @@ int validate_path(const char *path, int exist); int validate_str_cache_mode(const char *s); int validate_str_cln_policy(const char *s); int validate_str_promotion_policy(const char *s); -int validate_str_meta_variant(const char *s); int validate_str_stats_filters(const char* s); int validate_str_output_format(const char* s); -int validate_str_metadata_mode(const char* s); /** * @brief clear metadata diff --git a/casadm/extended_err_msg.c b/casadm/extended_err_msg.c index 8881403..f56723e 100644 --- a/casadm/extended_err_msg.c +++ b/casadm/extended_err_msg.c @@ -208,10 +208,6 @@ struct { KCAS_ERR_ROLLBACK, "Cannot restore previous configuration" }, - { - KCAS_ERR_NVME_BAD_FORMAT, - "NVMe is formatted to unsupported format" - }, { KCAS_ERR_CONTAINS_PART, "Device contains partitions.\nIf you want to continue, " diff --git a/casadm/statistics_model.c b/casadm/statistics_model.c index c0a6de1..52b1d7c 100644 --- a/casadm/statistics_model.c +++ b/casadm/statistics_model.c @@ -581,9 +581,6 @@ int cache_stats_conf(int ctrl_fd, const struct kcas_cache_info *cache_info, print_kv_pair_time(outfile, "Dirty for", cache_info->info.dirty_for); - print_kv_pair(outfile, "Metadata Mode", "%s", - metadata_mode_to_name(cache_info->metadata_mode)); - if (flush_progress) { print_kv_pair(outfile, "Status", "%s (%3.1f %%)", "Flushing", flush_progress); diff --git a/modules/cas_cache/cas_cache.h b/modules/cas_cache/cas_cache.h index e05a320..1be5508 100644 --- a/modules/cas_cache/cas_cache.h +++ b/modules/cas_cache/cas_cache.h @@ -15,7 +15,6 @@ #include "control.h" #include "layer_cache_management.h" #include "service_ui_ioctl.h" -#include "utils/cas_cache_utils.h" #include "volume/vol_blk_utils.h" #include "classifier.h" #include "context.h" @@ -45,11 +44,8 @@ * cache/core object types */ enum { BLOCK_DEVICE_VOLUME = 1, /**< block device volume */ - ATOMIC_DEVICE_VOLUME, /**< block device volume with atomic - metadata support */ /** \cond SKIP_IN_DOC */ OBJECT_TYPE_MAX, - NVME_CONTROLLER /** \endcond */ }; diff --git a/modules/cas_cache/context.c b/modules/cas_cache/context.c index 5215bab..b34b13e 100644 --- a/modules/cas_cache/context.c +++ b/modules/cas_cache/context.c @@ -440,12 +440,6 @@ int cas_initialize_context(void) } - ret = atomic_dev_init(); - if (ret) { - printk(KERN_ERR "Cannot initialize atomic device layer\n"); - goto err_rpool; - } - return 0; err_rpool: diff --git a/modules/cas_cache/layer_cache_management.c b/modules/cas_cache/layer_cache_management.c index dc1b976..142d961 100644 --- a/modules/cas_cache/layer_cache_management.c +++ b/modules/cas_cache/layer_cache_management.c @@ -1136,9 +1136,6 @@ int cache_mngt_cache_check_device(struct kcas_cache_check_device *cmd_info) if (result) goto out_bdev; - cmd_info->format_atomic = (ocf_ctx_get_volume_type_id(cas_ctx, - ocf_volume_get_type(volume)) == ATOMIC_DEVICE_VOLUME); - init_completion(&context.cmpl); context.cmd_info = cmd_info; context.result = &result; @@ -1198,8 +1195,6 @@ int cache_mngt_prepare_core_cfg(struct ocf_mngt_core_config *cfg, return 0; result = cas_blk_identify_type(cfg->uuid.data, &cfg->volume_type); - if (!result && cfg->volume_type == ATOMIC_DEVICE_VOLUME) - result = -KCAS_ERR_NVME_BAD_FORMAT; if (OCF_ERR_NOT_OPEN_EXC == abs(result)) { printk(KERN_WARNING OCF_PREFIX_SHORT "Cannot open device %s exclusively. " @@ -1761,7 +1756,6 @@ static int cache_mngt_initialize_core_objects(ocf_cache_t cache) int cache_mngt_prepare_cache_cfg(struct ocf_mngt_cache_config *cfg, struct ocf_mngt_cache_device_config *device_cfg, - struct atomic_dev_params *atomic_params, struct kcas_start_cache *cmd) { int init_cache, result; @@ -1790,7 +1784,6 @@ int cache_mngt_prepare_cache_cfg(struct ocf_mngt_cache_config *cfg, memset(cfg, 0, sizeof(*cfg)); memset(device_cfg, 0, sizeof(*device_cfg)); - memset(atomic_params, 0, sizeof(*atomic_params)); strncpy(cfg->name, cache_name, OCF_CACHE_NAME_SIZE - 1); cfg->cache_mode = cmd->caching_mode; @@ -1811,6 +1804,7 @@ int cache_mngt_prepare_cache_cfg(struct ocf_mngt_cache_config *cfg, device_cfg->cache_line_size = cmd->line_size; device_cfg->force = cmd->force; device_cfg->discard_on_start = true; + device_cfg->perform_test = false; init_cache = cmd->init_cache; @@ -1838,22 +1832,11 @@ int cache_mngt_prepare_cache_cfg(struct ocf_mngt_cache_config *cfg, if (!is_part && part_count > 1 && !device_cfg->force) return -KCAS_ERR_CONTAINS_PART; - result = cas_blk_identify_type_atomic(device_cfg->uuid.data, - &device_cfg->volume_type, atomic_params); + result = cas_blk_identify_type(device_cfg->uuid.data, + &device_cfg->volume_type); if (result) return result; - if (device_cfg->volume_type == ATOMIC_DEVICE_VOLUME) { - device_cfg->volume_params = atomic_params; - device_cfg->perform_test = true; - } else { - device_cfg->perform_test = false; - } - - cmd->metadata_mode_optimal = - block_dev_is_metadata_mode_optimal(atomic_params, - device_cfg->volume_type); - return 0; } @@ -2684,18 +2667,6 @@ int cache_mngt_get_info(struct kcas_cache_info *info) BUG_ON(!uuid); strlcpy(info->cache_path_name, uuid->data, min(sizeof(info->cache_path_name), uuid->size)); - - switch (info->info.volume_type) { - case BLOCK_DEVICE_VOLUME: - info->metadata_mode = CAS_METADATA_MODE_NORMAL; - break; - case ATOMIC_DEVICE_VOLUME: - info->metadata_mode = CAS_METADATA_MODE_ATOMIC; - break; - default: - info->metadata_mode = CAS_METADATA_MODE_INVALID; - break; - } } /* Collect cores IDs */ diff --git a/modules/cas_cache/layer_cache_management.h b/modules/cas_cache/layer_cache_management.h index 398aad5..23da710 100644 --- a/modules/cas_cache/layer_cache_management.h +++ b/modules/cas_cache/layer_cache_management.h @@ -8,8 +8,6 @@ #define CAS_BLK_DEV_REQ_TYPE_BIO 1 #define CAS_BLK_DEV_REQ_TYPE_REQ 3 -struct atomic_dev_params; - int cache_mngt_set_cleaning_policy(ocf_cache_t cache, uint32_t type); int cache_mngt_get_cleaning_policy(ocf_cache_t cache, uint32_t *type); @@ -49,7 +47,6 @@ int cache_mngt_exit_instance(const char *cache_name, size_t name_len, int cache_mngt_prepare_cache_cfg(struct ocf_mngt_cache_config *cfg, struct ocf_mngt_cache_device_config *device_cfg, - struct atomic_dev_params *atomic_params, struct kcas_start_cache *cmd); int cache_mngt_core_pool_get_paths(struct kcas_core_pool_path *cmd_info); diff --git a/modules/cas_cache/service_ui_ioctl.c b/modules/cas_cache/service_ui_ioctl.c index 13c196a..14fe4d2 100644 --- a/modules/cas_cache/service_ui_ioctl.c +++ b/modules/cas_cache/service_ui_ioctl.c @@ -51,12 +51,10 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd, struct kcas_start_cache *cmd_info; struct ocf_mngt_cache_config cfg; struct ocf_mngt_cache_device_config device_cfg; - struct atomic_dev_params atomic_params; GET_CMD_INFO(cmd_info, arg); - retval = cache_mngt_prepare_cache_cfg(&cfg, &device_cfg, - &atomic_params, cmd_info); + retval = cache_mngt_prepare_cache_cfg(&cfg, &device_cfg, cmd_info); if (retval) RETURN_CMD_RESULT(cmd_info, arg, retval); diff --git a/modules/cas_cache/utils/cas_cache_utils.h b/modules/cas_cache/utils/cas_cache_utils.h deleted file mode 100644 index 99870e1..0000000 --- a/modules/cas_cache/utils/cas_cache_utils.h +++ /dev/null @@ -1,12 +0,0 @@ -/* -* Copyright(c) 2012-2021 Intel Corporation -* SPDX-License-Identifier: BSD-3-Clause-Clear -*/ - - -#ifndef __CAS_UTILS_H__ -#define __CAS_UTILS_H__ - -#include "utils_nvme.h" - -#endif /* __CAS_UTILS_H__ */ diff --git a/modules/cas_cache/utils/utils_nvme.c b/modules/cas_cache/utils/utils_nvme.c deleted file mode 100644 index 8a7963b..0000000 --- a/modules/cas_cache/utils/utils_nvme.c +++ /dev/null @@ -1,68 +0,0 @@ -/* -* Copyright(c) 2012-2021 Intel Corporation -* SPDX-License-Identifier: BSD-3-Clause-Clear -*/ - -#if defined(CAS_NVME_PARTIAL) - -#include "cas_cache.h" -#include "utils_nvme.h" -#include "utils_blk.h" - -#include -#include - - -int cas_nvme_get_nsid(struct block_device *bdev, unsigned int *nsid) -{ - int ret = 0; - - /* - * Maximum NSID is 0xFFFFFFFF, so theoretically there is no free - * room for error code. However it's unlikely that there will ever - * be device with such number of namespaces, so we treat this value - * as it was signed. Then in case of negative value we interpret it - * as an error code. Moreover in case of error we can be sure, that - * we deal with non-NVMe device, because this ioctl should never - * fail with NVMe driver. - */ - ret = ioctl_by_bdev(bdev, NVME_IOCTL_ID, (unsigned long)NULL); - if (ret < 0) - return ret; - - *nsid = (unsigned int)ret; - return 0; -} - -#define NVME_ID_CNS_NS 0x00 -#define NVME_ID_CNS_CTRL 0x01 - -int cas_nvme_identify_ns(struct block_device *bdev, unsigned int nsid, - struct nvme_id_ns *ns) -{ - struct nvme_admin_cmd cmd = { }; - unsigned long __user buffer; - int ret = 0; - - buffer = cas_vm_mmap(NULL, 0, sizeof(*ns)); - if (IS_ERR((void *)buffer)) - return PTR_ERR((void *)buffer); - - cmd.opcode = nvme_admin_identify; - cmd.nsid = cpu_to_le32(nsid); - cmd.addr = (__u64)buffer; - cmd.data_len = sizeof(*ns); - cmd.cdw10 = NVME_ID_CNS_NS; - ret = ioctl_by_bdev(bdev, NVME_IOCTL_ADMIN_CMD, (unsigned long)&cmd); - if (ret < 0) - goto out; - - ret = copy_from_user(ns, (void *)buffer, sizeof(*ns)); - if (ret > 0) - ret = -EINVAL; -out: - cas_vm_munmap(buffer, sizeof(*ns)); - return ret; -} - -#endif diff --git a/modules/cas_cache/utils/utils_nvme.h b/modules/cas_cache/utils/utils_nvme.h deleted file mode 100644 index aeb59ab..0000000 --- a/modules/cas_cache/utils/utils_nvme.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -* Copyright(c) 2012-2021 Intel Corporation -* SPDX-License-Identifier: BSD-3-Clause-Clear -*/ - -#ifndef UTILS_NVME_H_ -#define UTILS_NVME_H_ - -#if defined(CAS_UAPI_NVME) -#include -#endif - -#if defined(CAS_UAPI_LINUX_NVME) -#include -#endif - -#if defined(CAS_UAPI_LINUX_NVME_IOCTL) -#include -#endif - -#include - -int cas_nvme_get_nsid(struct block_device *bdev, unsigned int *nsid); -int cas_nvme_identify_ns(struct block_device *bdev, unsigned int nsid, - struct nvme_id_ns *ns); - - -#endif /* UTILS_NVME_H_ */ diff --git a/modules/cas_cache/volume/obj_blk.h b/modules/cas_cache/volume/obj_blk.h index 00d3a38..24e37d0 100644 --- a/modules/cas_cache/volume/obj_blk.h +++ b/modules/cas_cache/volume/obj_blk.h @@ -6,7 +6,6 @@ #ifndef __OBJ_BLK_H__ #define __OBJ_BLK_H__ -#include "vol_atomic_dev_bottom.h" #include "vol_block_dev_bottom.h" #include "vol_block_dev_top.h" @@ -26,8 +25,6 @@ struct bd_object { uint32_t opened_by_bdev : 1; /*!< Opened by supplying bdev manually */ - struct atomic_dev_params atomic_params; - atomic64_t pending_rqs; /*!< This fields describes in flight IO requests */ diff --git a/modules/cas_cache/volume/vol_atomic_dev_bottom.c b/modules/cas_cache/volume/vol_atomic_dev_bottom.c deleted file mode 100644 index 83e83d7..0000000 --- a/modules/cas_cache/volume/vol_atomic_dev_bottom.c +++ /dev/null @@ -1,1148 +0,0 @@ -/* -* Copyright(c) 2012-2021 Intel Corporation -* SPDX-License-Identifier: BSD-3-Clause-Clear -*/ - -#include "cas_cache.h" -#include "utils/utils_mpool.h" -#if defined(CAS_NVME_FULL) - -#include -#include - -#define CAS_DEBUG_IO_ATOMIC 0 - -#if 1 == CAS_DEBUG_IO_ATOMIC -#define CAS_DEBUG_TRACE() printk(KERN_DEBUG \ - "[IO][ATOMIC] %s:%d\n", __func__, __LINE__) - -#define CAS_DEBUG_MSG(msg) printk(KERN_DEBUG \ - "[IO][ATOMIC] %s:%d - %s\n", __func__, __LINE__, msg) - -#define CAS_DEBUG_PARAM(format, ...) printk(KERN_DEBUG \ - "[IO][ATOMIC] %s:%d - "format"\n", __func__, \ - __LINE__, ##__VA_ARGS__) -#else -#define CAS_DEBUG_TRACE() -#define CAS_DEBUG_MSG(msg) -#define CAS_DEBUG_PARAM(format, ...) -#endif - -#define ADMIN_TIMEOUT (60 * HZ) - -struct cas_atomic_io { - ocf_volume_t volume; - - struct cas_atomic_io *master; - atomic_t req_remaining; - uint32_t count; - - uint64_t addr; - uint32_t bytes; - uint32_t start; - uint32_t end; - - int error; - unsigned dir:1; - unsigned metadata:1; - unsigned discard:1; - unsigned long flags; - - ocf_end_io_t cmpl_fn; - void *cmpl_context; - - struct blk_data *data; - uint32_t bvec_size; - - struct nvme_command cmd; - struct bio *bio; - struct request *request; - - struct bio_vec_iter iter; -}; - -static struct env_mpool *atomic_io_allocator; - -static inline uint32_t cas_atomic_max_io_sectors(void) -{ - /* TODO Take into account max IO size of bottom device */ - return 128 * KiB / (SECTOR_SIZE + OCF_ATOMIC_METADATA_SIZE); -} - -static inline uint32_t cas_atomic_size_of(uint32_t size) -{ - BUG_ON(size % SECTOR_SIZE); - return size + (size / SECTOR_SIZE * OCF_ATOMIC_METADATA_SIZE); -} - -static void cas_atomic_dealloc(struct cas_atomic_io *atomics) -{ - uint32_t i; - - for (i = 0; i < atomics->count; i++) { - struct cas_atomic_io *this = &atomics[i]; - - if (this->request && !IS_ERR(this->request)) { - blk_mq_free_request(this->request); - this->request = NULL; - } - - if (this->bio) - bio_put(this->bio); - - if (this->data) { - cas_ctx_data_secure_erase(this->data); - cas_ctx_data_free(this->data); - } - } - - env_mpool_del(atomic_io_allocator, atomics, atomics->count); -} - -static struct cas_atomic_io *cas_atomic_alloc(int dir, struct ocf_io *io, bool write_zero) -{ - /* Get max size of IO */ - const uint32_t max_io_size = cas_atomic_max_io_sectors() - * SECTOR_SIZE; - - /* Get number of IOs to be issued */ - uint32_t ios_count; - ocf_cache_t cache = ocf_volume_get_cache(ocf_io_get_volume(io)); - - uint64_t addr = io->addr; - uint32_t i, bytes = io->bytes; - uint32_t increase_sectors_start = 0, increase_sectors_end = 0; - struct cas_atomic_io *atoms; - - if (dir == OCF_WRITE && !write_zero) { - /* TODO: this logic is probably no longer required */ - BUG_ON(!cache); - increase_sectors_start = - ocf_metadata_check_invalid_before(cache, addr); - - increase_sectors_end = - ocf_metadata_check_invalid_after(cache, addr, - io->bytes); - increase_sectors_start *= 512; - increase_sectors_end *= 512; - - if (increase_sectors_start) { - bytes += increase_sectors_start; - addr -= increase_sectors_start; - } - - if (increase_sectors_end) - bytes += increase_sectors_end; - } - - /* Get number of IOs to be issued */ - ios_count = DIV_ROUND_UP(bytes, max_io_size); - - atoms = env_mpool_new(atomic_io_allocator, - ios_count); - if (!atoms) - return NULL; - - CAS_DEBUG_PARAM("Addr = %llu, bytes = %u", io->addr, io->bytes); - - /* setup master IO */ - atomic_set(&atoms->req_remaining, ios_count); - - atoms->count = ios_count; - atoms->cmpl_fn = io->end; - atoms->cmpl_context = io; - - for (i = 0; i < ios_count; i++) { - struct cas_atomic_io *this = &atoms[i]; - - this->master = atoms; - this->addr = addr; - this->bytes = min(bytes, max_io_size); - this->dir = dir; - this->flags = io->flags; - this->volume = ocf_io_get_volume(io); - - CAS_DEBUG_PARAM("Sub-atomic IO (%u), Addr = %llu, bytes = %u", - i, this->addr, this->bytes); - - addr += this->bytes; - bytes -= this->bytes; - - /* Allocate BIO data vector with pages */ - this->bvec_size = cas_atomic_size_of(this->bytes); - this->bvec_size = DIV_ROUND_UP(this->bvec_size, PAGE_SIZE); - - if (write_zero || increase_sectors_start || - increase_sectors_end) - this->data = cas_ctx_data_zalloc(this->bvec_size); - else - this->data = cas_ctx_data_alloc(this->bvec_size); - - if (!this->data) - goto cas_atomic_alloc_ERROR; - - /* Set length of last page */ - this->data->vec[this->bvec_size - 1].bv_len = - cas_atomic_size_of(this->bytes) % PAGE_SIZE; - - CAS_DEBUG_PARAM("Sub-atomic IO (%u), BIO vector size = %u, " - "alignment %u", i, this->bvec_size, - this->data->vec[this->bvec_size - 1].bv_len); - - this->start = min(this->bytes, increase_sectors_start); - increase_sectors_start -= this->start; - } - BUG_ON(bytes); - - for (i = ios_count; i && increase_sectors_end; i--) { - struct cas_atomic_io *this = &atoms[i - 1]; - - this->end = min(this->bytes, increase_sectors_end); - increase_sectors_end -= this->end; - } - - return atoms; - -cas_atomic_alloc_ERROR: - - if (atoms) - cas_atomic_dealloc(atoms); - - return NULL; -} - -static int cas_atomic_rd_complete(struct cas_atomic_io *atom) -{ - struct bio_vec_iter *dst, src; - uint32_t copied; - const uint32_t size = OCF_ATOMIC_METADATA_SIZE; - - uint32_t bytes = atom->bytes; - - CAS_DEBUG_TRACE(); - - /* Initialize iterators */ - cas_io_iter_init(&src, atom->data->vec, atom->bvec_size); - dst = &atom->iter; - - BUG_ON(bytes % SECTOR_SIZE); - BUG_ON(size != OCF_ATOMIC_METADATA_SIZE); - - copied = 0; - while (bytes) { - /* Copy data */ - copied += cas_io_iter_cpy(dst, &src, SECTOR_SIZE); - - /* Omit metadata */ - copied += cas_io_iter_move(&src, size); - - bytes -= SECTOR_SIZE; - } - - /* Validate if copied proper numbers of bytes */ - if (copied != cas_atomic_size_of(atom->bytes)) { - CAS_DEBUG_PARAM("ERROR, copied %u, expected = %u", - copied, cas_atomic_size_of(atom->bytes)); - /* Metadata and data coping problem */ - return -EIO; - } - - return 0; -} - -static int cas_atomic_rd_metadata_complete(struct cas_atomic_io *atom) -{ - struct bio_vec_iter *dst, src; - uint32_t copied; - const uint32_t size = OCF_ATOMIC_METADATA_SIZE; - - uint32_t bytes = atom->bytes; - - CAS_DEBUG_TRACE(); - - /* Initialize iterators */ - cas_io_iter_init(&src, atom->data->vec, atom->bvec_size); - dst = &atom->iter; - - BUG_ON(bytes % SECTOR_SIZE); - BUG_ON(size != OCF_ATOMIC_METADATA_SIZE); - - copied = 0; - while (bytes) { - /* Copy data */ - copied += cas_io_iter_move(&src, SECTOR_SIZE); - - /* Omit metadata */ - copied += cas_io_iter_cpy(dst, &src, size); - - bytes -= SECTOR_SIZE; - } - - /* Validate if copied proper numbers of bytes */ - if (copied != cas_atomic_size_of(atom->bytes)) { - CAS_DEBUG_PARAM("ERROR, copied %u, expected = %u", - copied, cas_atomic_size_of(atom->bytes)); - /* Metadata and data coping problem */ - return -EIO; - } - - return 0; -} - -static int cas_atomic_rd_prepare(struct ocf_io *io, - struct cas_atomic_io *atom) -{ - struct blkio *blkio = cas_io_to_blkio(io); - uint32_t moved; - - /* Store BIO vector iterator, when read completed then it will be - * known were place data - */ - cas_io_iter_copy_set(&atom->iter, &blkio->iter); - - /* Move iterator for next IO */ - moved = cas_io_iter_move(&blkio->iter, atom->bytes); - - /* Validate if there is enough space in BIO data vector to do read */ - if (moved != atom->bytes) { - CAS_DEBUG_PARAM("ERROR, moved %u, expected = %u", - moved, cas_atomic_size_of(atom->bytes)); - return -EINVAL; - } - - return 0; -} - -static int cas_atomic_wr_prepare(struct ocf_io *io, - struct cas_atomic_io *atom) -{ - struct blkio *blkio = cas_io_to_blkio(io); - ocf_cache_t cache; - struct ocf_atomic_metadata metadata; - struct bio_vec_iter dst, src; - uint32_t copied, added; - - uint64_t addr = atom->addr; - uint32_t bytes = atom->bytes; - - cache = ocf_volume_get_cache(ocf_io_get_volume(io)); - - /* Initialize iterators */ - cas_io_iter_init(&dst, atom->data->vec, atom->bvec_size); - cas_io_iter_copy_set(&src, &blkio->iter); - - BUG_ON(!cache); - BUG_ON(bytes % SECTOR_SIZE); - - copied = 0; - if (atom->start) { - added = cas_atomic_size_of(atom->start); - cas_io_iter_move(&dst, added); - - bytes -= atom->start; - copied = added; - - addr += atom->start; - } - - if (atom->end) { - added = cas_atomic_size_of(atom->end); - bytes -= atom->end; - copied += added; - } - - BUG_ON(sizeof(metadata) != OCF_ATOMIC_METADATA_SIZE); - - while (bytes) { - /* Get metadata */ - if (ocf_metadata_get_atomic_entry(cache, addr, &metadata)) - break; - - /* Copy data */ - copied += cas_io_iter_cpy(&dst, &src, SECTOR_SIZE); - - /* Copy metadata */ - copied += cas_io_iter_cpy_from_data(&dst, &metadata, - sizeof(metadata)); - - bytes -= SECTOR_SIZE; - addr += SECTOR_SIZE; - } - - cas_io_iter_move(&blkio->iter, atom->bytes - (atom->start + atom->end)); - - /* Validate if copied proper numbers of bytes */ - if (copied != cas_atomic_size_of(atom->bytes)) { - CAS_DEBUG_PARAM("ERROR, copied %u, expected = %u", - copied, cas_atomic_size_of(atom->bytes)); - /* Metadata and data coping problem */ - return -EINVAL; - } - - return 0; -} - -static int cas_atomic_rd_metadata_prepare(struct ocf_io *io, - struct cas_atomic_io *atom) -{ - struct blkio *blkio = cas_io_to_blkio(io); - uint32_t moved; - - BUG_ON(io->dir != OCF_READ); - - atom->metadata = true; - - /* Store BIO vector iterator, when read completed then it will be - * known were place data - */ - cas_io_iter_copy_set(&atom->iter, &blkio->iter); - - /* Move iterator for next IO */ - moved = cas_io_iter_move(&blkio->iter, (atom->bytes / SECTOR_SIZE) * - OCF_ATOMIC_METADATA_SIZE); - - /* Validate if copied proper numbers of bytes */ - if (moved != (atom->bytes / SECTOR_SIZE) * - OCF_ATOMIC_METADATA_SIZE) { - CAS_DEBUG_PARAM("ERROR, copied %u, expected = %u", - moved, cas_atomic_size_of(atom->bytes)); - /* Metadata and data coping problem */ - return -EIO; - } - - return 0; -} - -static void cas_atomic_end_atom(struct cas_atomic_io *atom, int error) -{ - struct cas_atomic_io *master = atom->master; - struct ocf_io *io = master->cmpl_context; - - if (error) - master->error |= error; - - if (atomic_dec_return(&master->req_remaining)) - return; - - CAS_DEBUG_MSG("Completion"); - - /* Send completion to caller */ - master->cmpl_fn(io, master->error); - - /* Free allocated structures */ - cas_atomic_dealloc(master); - ocf_io_put(io); -} - -static CAS_DECLARE_BLOCK_CALLBACK(cas_atomic_fire_atom, struct bio *bio, - unsigned int bytes, int error) -{ - int err; - struct cas_atomic_io *atom; - struct bd_object *bdobj; - - BUG_ON(!bio); - BUG_ON(!bio->bi_private); - err = CAS_BLOCK_CALLBACK_ERROR(bio, error); - atom = bio->bi_private; - BUG_ON(!atom->master); - bdobj = bd_object(atom->volume); - - CAS_DEBUG_PARAM("BIO result = %d", CAS_BLOCK_CALLBACK_ERROR(bio, error)); - - if (err != 0) - goto out; - - if (atom->discard) - goto out; - - if (atom->metadata) { - if (cas_atomic_rd_metadata_complete(atom)) - atom->master->error = -EIO; - goto out; - } - - if (atom->dir == OCF_READ && cas_atomic_rd_complete(atom)) - atom->master->error = -EIO; - -out: - /* Free BIO, no needed any more */ - BUG_ON(bio != atom->bio); - bio_put(bio); - atom->bio = NULL; - - cas_atomic_end_atom(atom, err); -} - -static void _cas_atomic_setup_cmd( - ocf_volume_t volume, - struct request *req, - struct bio* bio, - uint64_t bytes, - int dir, - void *end_io_data, - struct nvme_command *cmd) -{ - struct bd_object *bdobj = bd_object(volume); - unsigned int ns_id = bdobj->atomic_params.nsid; - unsigned long *cmd_addr = blk_mq_rq_to_pdu(req); - - cmd->rw.opcode = (dir == OCF_WRITE) ? nvme_cmd_write : nvme_cmd_read; - cmd->rw.nsid = cpu_to_le32(ns_id); - cmd->rw.slba = cpu_to_le64(CAS_BIO_BISECTOR(bio)); - cmd->rw.length = cpu_to_le16((bytes / SECTOR_SIZE) - 1); - cmd->rw.control = cpu_to_le16(NVME_RW_LR); - - req->cmd_type = REQ_TYPE_DRV_PRIV; - req->cmd_flags |= REQ_FAILFAST_DRIVER; - - *cmd_addr = (unsigned long)cmd; - - req->timeout = ADMIN_TIMEOUT; /* TODO Use timeout for regular IO */ - - req->cmd = (unsigned char *) cmd; - req->cmd_len = sizeof(*cmd); - req->special = NULL; - req->end_io_data = end_io_data; -} - -static void cas_atomic_setup_cmd(int dir, struct cas_atomic_io *atom) -{ - _cas_atomic_setup_cmd(atom->volume, atom->request, atom->bio, - atom->bytes, dir, atom, &atom->cmd); -} - -static void cas_atomic_end_request(struct request *request, int error) -{ - struct cas_atomic_io *atom; - - BUG_ON(!request); - atom = request->end_io_data; - - /* Free request not needed any more */ - BUG_ON(atom->request != request); - blk_mq_free_request(request); - atom->request = NULL; - - CAS_DEBUG_PARAM("RQ result = %d", error); - - cas_atomic_end_atom(atom, error); -} - -static void cas_atomic_fire_atom(int dir, struct ocf_io *io, - struct cas_atomic_io *atom) -{ - struct bd_object *bdobj = bd_object(atom->volume); - struct block_device *bdev = bdobj->btm_bd; - struct request_queue *queue = bdev_get_queue(bdev); - - struct bio *bio; - struct bio_vec *bvec; - uint32_t i; - - /* Allocate BIO */ - bio = atom->bio = bio_alloc(GFP_NOIO, atom->bvec_size); - if (!bio) - goto _fire_atom_ERROR; - - /* Setup BIO */ - bio->bi_bdev = bdev; - CAS_BIO_BISECTOR(bio) = atom->addr / SECTOR_SIZE; - bio->bi_next = NULL; - bio->bi_private = atom; - CAS_BIO_OP_FLAGS(bio) |= io->flags; - bio->bi_end_io = CAS_REFER_BLOCK_CALLBACK(cas_atomic_fire_atom); - - /* Add pages to the BIO */ - bvec = atom->data->vec; - for (i = 0; i < atom->bvec_size; i++, bvec++) { - int added = bio_add_pc_page(queue, bio, - bvec->bv_page, bvec->bv_len, bvec->bv_offset); - - if (added != bvec->bv_len) { - /* Oops, a problem, cannot add page to the BIO */ - goto _fire_atom_ERROR; - } - } - - /* Allocate request */ - atom->request = cas_blk_make_request(queue, atom->bio, GFP_NOIO); - if (IS_ERR(atom->request)) { - atom->request = NULL; - goto _fire_atom_ERROR; - } - - /* Setup command */ - cas_atomic_setup_cmd(dir, atom); - - /* Additional completion for request */ - atomic_inc(&atom->master->req_remaining); - - /* Send requests (NVME atomic command) */ - blk_execute_rq_nowait(queue, NULL, atom->request, 0, - cas_atomic_end_request); - - return; - -_fire_atom_ERROR: - CAS_DEBUG_MSG("ERROR"); - cas_atomic_end_atom(atom, -EIO); -} - -static void cas_atomic_fire_atoms(int dir, struct ocf_io *io, - struct cas_atomic_io *atoms) -{ - uint32_t i; - - ocf_io_get(io); - - for (i = 0; i < atoms->count; i++) { - struct cas_atomic_io *this = &atoms[i]; - - CAS_DEBUG_PARAM("Fire(%u), Addr = %llu, bytes = %u", - i, this->addr, this->bytes); - cas_atomic_fire_atom(dir, io, this); - } -} - -typedef int (*cas_prepare_atom_pfn_t)(struct ocf_io *io, - struct cas_atomic_io *atoms); - -static int cas_atomic_prepare_atoms(struct ocf_io *io, - cas_prepare_atom_pfn_t prepare, - struct cas_atomic_io *atoms) -{ - int i; - int result = 0; - - if (!prepare) - return 0; - - for (i = 0; i < atoms->count; i++) { - struct cas_atomic_io *this = &atoms[i]; - - CAS_DEBUG_PARAM("Sub-atomic IO preparation(%u), Addr = %llu, " - "bytes = %u, dir = %d", i, this->addr, - this->bytes, dir); - - result |= prepare(io, this); - } - - return result; -} - -static void cas_atomic_fire_io(struct ocf_io *io, - cas_prepare_atom_pfn_t prepare, - bool write_zero) -{ - int dir = io->dir; - - /* Create atomic IOs context, mainly allocations */ - struct cas_atomic_io *atoms = cas_atomic_alloc(dir, io, write_zero); - - if (!atoms) { - CAS_DEBUG_MSG("Memory allocation ERROR"); - goto _submit_io_ERROR; - } - - /* Prepare IOs, mainly coping data */ - if (cas_atomic_prepare_atoms(io, prepare, atoms)) { - CAS_DEBUG_MSG("Preparation ERROR"); - goto _submit_io_ERROR; - } - - /* Send IO */ - atomic_inc(&atoms->req_remaining); - cas_atomic_fire_atoms(dir, io, atoms); - cas_atomic_end_atom(atoms, 0); - - return; - -_submit_io_ERROR: - if (atoms) - cas_atomic_dealloc(atoms); - - io->end(io, -EIO); -} - -static void cas_atomic_submit_flush_bio(struct cas_atomic_io *atom) -{ - struct request *req = atom->request; - struct bd_object *bdobj = bd_object(atom->volume); - unsigned int ns_id = bdobj->atomic_params.nsid; - struct nvme_command *cmd = &atom->cmd; - unsigned long *cmd_addr = blk_mq_rq_to_pdu(req); - - cmd->rw.opcode = nvme_cmd_flush; - cmd->rw.nsid = cpu_to_le32(ns_id); - - *cmd_addr = (unsigned long)cmd; - - req->cmd_type = REQ_TYPE_DRV_PRIV; - - req->timeout = ADMIN_TIMEOUT; - - req->cmd = (unsigned char *) cmd; - req->cmd_len = sizeof(*cmd); - req->special = NULL; - req->end_io_data = atom; - - /* Additional completion for request */ - atomic_inc(&atom->master->req_remaining); - - /* Send NVMe flush command */ - blk_execute_rq_nowait(req->q, NULL, req, 0, cas_atomic_end_request); -} - -static int cas_atomic_submit_discard_bio(struct cas_atomic_io *atom) -{ - struct request *req = atom->request; - struct nvme_command *cmd = &atom->cmd; - struct bd_object *bdobj = bd_object(atom->volume); - unsigned int ns_id = bdobj->atomic_params.nsid; - struct nvme_dsm_range *nvm_discard; - struct page *page; - int offset; - unsigned long *cmd_addr = blk_mq_rq_to_pdu(req); - - nvm_discard = kmalloc(sizeof(*nvm_discard), GFP_NOIO); - if (!nvm_discard) { - return -ENOMEM; - } - - nvm_discard->cattr = cpu_to_le32(0); - nvm_discard->nlb = cpu_to_le32(CAS_BIO_BISIZE(atom->bio) >> SECTOR_SHIFT); - nvm_discard->slba = cpu_to_le64(CAS_BIO_BISECTOR(atom->bio)); - - cmd->dsm.opcode = nvme_cmd_dsm; - cmd->dsm.nsid = cpu_to_le32(ns_id); - cmd->dsm.nr = 0; - cmd->dsm.attributes = cpu_to_le32(NVME_DSMGMT_AD); - - req->completion_data = nvm_discard; - page = virt_to_page(nvm_discard); - offset = offset_in_page(nvm_discard); - blk_add_request_payload(req, page, offset, sizeof(*nvm_discard)); - - req->__sector = CAS_BIO_BISECTOR(atom->bio); - req->__data_len = CAS_BIO_BISIZE(atom->bio); - req->ioprio = bio_prio(atom->bio); - - req->timeout = ADMIN_TIMEOUT; - req->end_io_data = atom; - req->cmd_type = REQ_TYPE_DRV_PRIV; - req->cmd_flags = CAS_BIO_DISCARD; - - req->errors = 0; - - *cmd_addr = (unsigned long)cmd; - - /* Additional completion for request */ - atomic_inc(&atom->master->req_remaining); - - /* Send NVMe flush command */ - blk_execute_rq_nowait(req->q, NULL, req, 0, cas_atomic_end_request); - - return 0; -} - -static int cas_atomic_special_req_prepare(struct cas_atomic_io *atom, - struct ocf_io *io) -{ - struct bd_object *bdobj = bd_object(ocf_io_get_volume(io)); - struct block_device *bdev = bdobj->btm_bd; - - CAS_DEBUG_TRACE(); - atom->master = atom; - atom->count = 1; - atom->cmpl_fn = io->end; - atom->cmpl_context = io; - atom->volume = ocf_io_get_volume(io); - atom->flags = io->flags; - atomic_set(&atom->req_remaining, 1); - - atom->bio = bio_alloc(GFP_NOIO, 1); - if (!atom->bio) { - CAS_PRINT_RL(KERN_ERR "Couldn't allocate memory for bio\n"); - return -ENOMEM; - } - - atom->bio->bi_end_io = CAS_REFER_BLOCK_CALLBACK(cas_atomic_fire_atom); - atom->bio->bi_bdev = bdev; - atom->bio->bi_private = atom; - - return 0; -} - -void cas_atomic_submit_discard(struct ocf_io *io) -{ - struct bd_object *bdobj = bd_object(ocf_io_get_volume(io)); - struct block_device *bdev = bdobj->btm_bd; - struct request_queue *q = bdev_get_queue(bdev); - int result = 0; - - struct cas_atomic_io *atom = NULL; - struct blkio *blkio = cas_io_to_blkio(io); - - CAS_DEBUG_TRACE(); - - if (!q) { - /* No queue, error */ - io->end(io, -EINVAL); - return; - } - - /* Allocate and setup control structure. */ - atom = env_mpool_new(atomic_io_allocator, 1); - if (!atom) { - CAS_PRINT_RL(KERN_ERR "Couldn't allocate memory for IO ctrl\n"); - io->end(io, -ENOMEM); - return; - } - - result = cas_atomic_special_req_prepare(atom, io); - if (result) { - blkio->error = result; - goto out; - } - - /* Increase IO reference counter for FLUSH IO */ - ocf_io_get(io); - - /* Set up specific field */ - atom->discard = true; - CAS_BIO_OP_FLAGS(atom->bio) = CAS_BIO_DISCARD; - CAS_BIO_BISECTOR(atom->bio) = io->addr / SECTOR_SIZE; - CAS_BIO_BISIZE(atom->bio) = io->bytes; - - atom->request = cas_blk_make_request(q, atom->bio, GFP_NOIO); - if (IS_ERR(atom->request)) { - blkio->error = PTR_ERR(atom->request); - goto out; - } - - atomic_inc(&atom->req_remaining); - result = cas_atomic_submit_discard_bio(atom); - if (result) - blkio->error = result; - -out: - cas_atomic_end_atom(atom, blkio->error); -} - -void cas_atomic_submit_flush(struct ocf_io *io) -{ - struct bd_object *bdobj = bd_object(ocf_io_get_volume(io)); - struct block_device *bdev = bdobj->btm_bd; - struct request_queue *q = bdev_get_queue(bdev); - int result = 0; - struct cas_atomic_io *atom = NULL; - struct blkio *blkio = cas_io_to_blkio(io); - - CAS_DEBUG_TRACE(); - - if (!q) { - io->end(io, -EINVAL); - return; - } - - if (!CAS_CHECK_QUEUE_FLUSH(q)) { - /* This block device does not support flush */ - io->end(io, 0); - return; - } - - /* Allocate and setup control structure. */ - atom = env_mpool_new(atomic_io_allocator, 1); - if (!atom) { - CAS_PRINT_RL(KERN_ERR "Couldn't allocate memory for IO ctrl\n"); - io->end(io, -ENOMEM); - return; - } - - /* Increase IO reference counter for FLUSH IO */ - ocf_io_get(io); - - result = cas_atomic_special_req_prepare(atom, io); - if (result) { - CAS_PRINT_RL(CAS_KERN_ERR "Couldn't allocate memory for BIO\n"); - blkio->error = -ENOMEM; - goto out; - } - - /* Set up specific field */ - atom->dir = OCF_WRITE; - - atom->request = cas_blk_make_request(q, atom->bio, GFP_NOIO); - if (IS_ERR(atom->request)) { - blkio->error = PTR_ERR(atom->request); - goto out; - } - - atomic_inc(&atom->req_remaining); - cas_atomic_submit_flush_bio(atom); - -out: - cas_atomic_end_atom(atom, blkio->error); -} - -void cas_atomic_submit_io(struct ocf_io *io) -{ - CAS_DEBUG_TRACE(); - - if (CAS_IS_SET_FLUSH(io->flags)) { - /* FLUSH */ - cas_atomic_submit_flush(io); - return; - } - - if (unlikely(!io->bytes)) { - CAS_PRINT_RL(KERN_ERR "Zero length request\n"); - io->end(io, -EINVAL); - return; - } - - cas_atomic_fire_io(io, io->dir == OCF_READ ? cas_atomic_rd_prepare : - cas_atomic_wr_prepare, false); -} - -void cas_atomic_submit_metadata(struct ocf_io *io) -{ - BUG_ON(io->dir != OCF_READ); - - CAS_DEBUG_TRACE(); - - if (unlikely(!io->bytes)) { - CAS_PRINT_RL(CAS_KERN_ERR "Zero length request\n"); - io->end(io, -EINVAL); - return; - } - - cas_atomic_fire_io(io, cas_atomic_rd_metadata_prepare, false); -} - -unsigned int cas_atomic_get_max_io_size(ocf_volume_t volume) -{ - struct block_device *bd; - - if (!volume) - return 0; - - bd = bd_object(volume)->btm_bd; - if (!bd->bd_disk) - return 0; - - return queue_max_sectors(bd->bd_disk->queue) << SECTOR_SHIFT; -} - -void cas_atomic_close_object(ocf_volume_t volume) -{ - struct bd_object *bdobj = bd_object(volume); - - if(bdobj->btm_wq) - destroy_workqueue(bdobj->btm_wq); - - block_dev_close_object(volume); -} - -int cas_atomic_open_object(ocf_volume_t volume, void *volume_params) -{ - int result; - struct bd_object *bdobj = NULL; - - if (!volume_params) - return -EINVAL; - - result = block_dev_open_object(volume, volume_params); - if (result) - return result; - - bdobj = bd_object(volume); - - memcpy(&bdobj->atomic_params, volume_params, - sizeof(bdobj->atomic_params)); - - bdobj->btm_wq = create_workqueue("CAS_AT_ZER"); - if (!bdobj->btm_wq) { - cas_atomic_close_object(volume); - result = -ENOMEM; - goto end; - } - -end: - return result; -} - -uint64_t cas_atomic_get_length(ocf_volume_t volume) -{ - struct bd_object *bdobj = bd_object(volume); - - return bdobj->atomic_params.size; -} - -/* context to keep track of write_zero progress across child IOs */ -struct cas_atomic_write_zero_ctx -{ - struct ocf_io *sub_io; - struct ocf_io *original_io; - struct work_struct cmpl_work; - unsigned step_size; -}; - -static void _cas_atomic_write_zeroes_end(struct cas_atomic_write_zero_ctx *ctx, - int error) -{ - struct ocf_io *io = ctx->original_io; - - /* end master io */ - io->end(io, error); - ocf_io_put(io); - - /* cleanup context */ - ocf_io_put(ctx->sub_io); - kfree(ctx); -} - -/* atomic write zerores I/O completion */ -static void _cas_atomic_write_zeroes_step_cmpl(struct ocf_io *io, int error) -{ - struct cas_atomic_write_zero_ctx *ctx = io->priv1; - struct bd_object *bdobj = bd_object(ocf_io_get_volume(io)); - const unsigned bytes_processed = (io->addr - ctx->original_io->addr) - + io->bytes; - const unsigned bytes_left = ctx->original_io->bytes - bytes_processed; - - BUG_ON(io->bytes > ctx->step_size); - - /* update I/O address and size */ - io->addr += io->bytes; - io->bytes = min(bytes_left, ctx->step_size); - - if (!bytes_left || error) { - _cas_atomic_write_zeroes_end(ctx, error); - } else { - /* submit next IO from work context */ - queue_work(bdobj->btm_wq, &ctx->cmpl_work); - } -} - -/* work routine to schedule next portion of write zero I/O */ -void _cas_atomic_write_zeroes_work(struct work_struct *work) -{ - struct cas_atomic_write_zero_ctx *ctx = container_of(work, - struct cas_atomic_write_zero_ctx, cmpl_work); - - cas_atomic_fire_io(ctx->sub_io, NULL, true); -} - -void cas_atomic_submit_write_zeroes(struct ocf_io *io) -{ - /* send 8 atoms in each I/O */ - const unsigned step_size = min(cas_atomic_max_io_sectors() - * SECTOR_SIZE * 8, io->bytes); - struct cas_atomic_write_zero_ctx *ctx = NULL; - int result = 0; - - if (unlikely(!io->bytes)) { - CAS_PRINT_RL(CAS_KERN_ERR "Zero length request\n"); - result = -EINVAL; - goto error; - } - - ctx = kmalloc(sizeof(*ctx), GFP_NOIO); - if (!ctx) { - result = -ENOMEM; - goto error; - } - - ctx->sub_io = ocf_volume_new_io(ocf_io_get_volume(io), io->io_queue, - io->addr, min(io->bytes, step_size), - OCF_WRITE, 0, 0); - if (!ctx->sub_io) { - result = -ENOMEM; - goto error_after_ctx; - } - - /* set up context */ - ctx->step_size = step_size; - ctx->original_io = io; - INIT_WORK(&ctx->cmpl_work, _cas_atomic_write_zeroes_work); - - /* get reference to original io */ - ocf_io_get(io); - - /* set up sub-io */ - ocf_io_set_cmpl(ctx->sub_io, ctx, NULL, _cas_atomic_write_zeroes_step_cmpl); - - cas_atomic_fire_io(ctx->sub_io, NULL, true); - - return; - -error_after_ctx: - kfree(ctx); -error: - io->end(io, result); -} - -static void atomic_dev_deinit(void) -{ - if (atomic_io_allocator) { - env_mpool_destroy(atomic_io_allocator); - atomic_io_allocator = NULL; - } -} - -const struct ocf_volume_properties cas_object_atomic_properties = { - .name = "Atomic_Writes_NVMe", - .io_priv_size = sizeof(struct blkio), - .volume_priv_size = sizeof(struct bd_object), - .caps = { - .atomic_writes = 1, - }, - .ops = { - .submit_io = cas_atomic_submit_io, - .submit_flush = cas_atomic_submit_flush, - .submit_discard = cas_atomic_submit_discard, - .submit_metadata = cas_atomic_submit_metadata, - .submit_write_zeroes = cas_atomic_submit_write_zeroes, - .open = cas_atomic_open_object, - .close = block_dev_close_object, - .get_max_io_size = cas_atomic_get_max_io_size, - .get_length = cas_atomic_get_length, - }, - .io_ops = { - .set_data = cas_blk_io_set_data, - .get_data = cas_blk_io_get_data, - }, - .deinit = atomic_dev_deinit -}; - -int atomic_dev_init(void) -{ - int ret; - - ret = ocf_ctx_register_volume_type(cas_ctx, ATOMIC_DEVICE_VOLUME, - &cas_object_atomic_properties); - - if (ret < 0) - return -EINVAL; - - atomic_io_allocator = env_mpool_create(0, sizeof(struct cas_atomic_io), - GFP_NOIO, 1, true, NULL, "cas_atomic_io", true); - - if (!atomic_io_allocator) { - ocf_ctx_unregister_volume_type(cas_ctx, ATOMIC_DEVICE_VOLUME); - return -ENOMEM; - } - - return 0; -} - -#else - -int atomic_dev_init(void) -{ - return 0; -} - -#endif diff --git a/modules/cas_cache/volume/vol_atomic_dev_bottom.h b/modules/cas_cache/volume/vol_atomic_dev_bottom.h deleted file mode 100644 index ff2bc79..0000000 --- a/modules/cas_cache/volume/vol_atomic_dev_bottom.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -* Copyright(c) 2012-2021 Intel Corporation -* SPDX-License-Identifier: BSD-3-Clause-Clear -*/ - -#ifndef __VOL_ATOMIC_DEV_BOTTOM_H__ -#define __VOL_ATOMIC_DEV_BOTTOM_H__ - -#include "../cas_cache.h" - -enum atomic_metadata_mode { - ATOMIC_METADATA_MODE_ELBA, - ATOMIC_METADATA_MODE_SEPBUF, - ATOMIC_METADATA_MODE_NONE, -}; - -struct atomic_dev_params { - unsigned int nsid; - uint64_t size; - enum atomic_metadata_mode metadata_mode; - unsigned is_mode_optimal : 1; - - /* IMPORTANT: If this field is 0, the other fields are invalid! */ - unsigned is_atomic_capable : 1; -}; - -int atomic_dev_init(void); - -#endif /* __VOL_ATOMIC_DEV_BOTTOM_H__ */ diff --git a/modules/cas_cache/volume/vol_blk_utils.c b/modules/cas_cache/volume/vol_blk_utils.c index 74cae21..743d967 100644 --- a/modules/cas_cache/volume/vol_blk_utils.c +++ b/modules/cas_cache/volume/vol_blk_utils.c @@ -227,183 +227,12 @@ ctx_data_t *cas_blk_io_get_data(struct ocf_io *io) return blkio->data; } -#if defined(CAS_NVME_PARTIAL) - -#include "utils/utils_nvme.h" - -int cas_blk_identify_type_by_bdev(struct block_device *bdev, - uint8_t *type, struct atomic_dev_params *atomic_params) +int cas_blk_open_volume_by_bdev(ocf_volume_t *vol, struct block_device *bdev) { - struct nvme_id_ns *ns; - unsigned int nsid, selected, ms, ds, pi, elba, sbsupp; - long long int ret = 0; - struct atomic_dev_params atomic_params_int = {0}; - - ns = kmalloc(sizeof(*ns), GFP_KERNEL); - if (!ns) - return -OCF_ERR_NO_MEM; - - ret = cas_nvme_get_nsid(bdev, &nsid); - if (ret < 0) { - /* - * We cannot obtain NSID which means we are not dealing with - * NVMe device - */ - goto out1; - } - - ret = cas_nvme_identify_ns(bdev, nsid, ns); - if (ret < 0) { - /* - * We cannot obtain ns structure which means we ARE dealing with - * NVMe device but can not recognize format so let's treat that - * device as block device - */ - goto out1; - } - - selected = ns->flbas & 0xf; - ms = ns->lbaf[selected].ms; - ds = ns->lbaf[selected].ds; - pi = ns->dps & 0x7; - elba = !!(ns->flbas & (1<<4)); - sbsupp = !!(ns->mc & (1<<1)); - - atomic_params_int.is_atomic_capable = 1; - atomic_params_int.nsid = nsid; - atomic_params_int.size = (ns->nsze << (ds - 9)) * SECTOR_SIZE; - - if (pi != 0) { - /* We don't support formats which have - * enable Protection Information feature. - */ - ret = -KCAS_ERR_NVME_BAD_FORMAT; - goto out2; - } - - switch (ms) { - case 0: - /* NVMe metadata features disabled, so we handle it as - * regular block device - */ - - if (ds != 9 && ds != 12) { - ret = -KCAS_ERR_NVME_BAD_FORMAT; - goto out2; - } - - *type = BLOCK_DEVICE_VOLUME; - atomic_params_int.metadata_mode = ATOMIC_METADATA_MODE_NONE; - -#if !defined(CAS_NVME_FULL) - /* - * Only partial support user can't using - * device in atomic mode, so mode is optimal - */ - atomic_params_int.is_mode_optimal = 1; - break; -#else - if (bdev == cas_bdev_whole(bdev)) { - /* - * Entire device - format isn't optimal - */ - atomic_params_int.is_mode_optimal = 0; - } else { - /* - * Partition - format is optimal, user can't using - * partitions in atomic mode - */ - atomic_params_int.is_mode_optimal = 1; - } - break; - - case 8: - /* For atomic writes we support only metadata size 8B and - * data size 512B - */ - - if (ds != 9) { - ret = -KCAS_ERR_NVME_BAD_FORMAT; - goto out2; - } - - *type = ATOMIC_DEVICE_VOLUME; - atomic_params_int.metadata_mode = elba ? - ATOMIC_METADATA_MODE_ELBA : - ATOMIC_METADATA_MODE_SEPBUF; - atomic_params_int.is_mode_optimal = sbsupp ? !elba : 1; - break; -#endif - - default: - ret = -KCAS_ERR_NVME_BAD_FORMAT; - } - - if (atomic_params) - *atomic_params = atomic_params_int; - - goto out2; -out1: - *type = BLOCK_DEVICE_VOLUME; - ret = 0; -out2: - kfree(ns); - return ret; -} - -static inline int _cas_detect_blk_type(const char *path, uint8_t *type, - struct atomic_dev_params *atomic_params) -{ - int ret; - struct block_device *bdev; - char holder[] = "CAS DETECT\n"; - - bdev = blkdev_get_by_path(path, (FMODE_EXCL|FMODE_READ), holder); - if (IS_ERR(bdev)) - return -OCF_ERR_NOT_OPEN_EXC; - - ret = cas_blk_identify_type_by_bdev(bdev, type, atomic_params); - blkdev_put(bdev, (FMODE_EXCL|FMODE_READ)); - return ret; -} - -#else - -static inline int _cas_detect_blk_type(const char *path, uint8_t *type, - struct atomic_dev_params *atomic_params) -{ - /* - * NVMe is not supported with given kernel version, so we - * have no way to figure out what the current NVMe format - * is. In this situation we make a naive assumption that - * it's formatted to LBA size 512B, and try to treat it - * as regular block device. - */ - *type = BLOCK_DEVICE_VOLUME; - return 0; -} - -int cas_blk_identify_type_by_bdev(struct block_device *bdev, - uint8_t *type, struct atomic_dev_params *atomic_params) -{ - *type = BLOCK_DEVICE_VOLUME; - return 0; -} -#endif - -int cas_blk_open_volume_by_bdev(ocf_volume_t *vol, - struct block_device *bdev) -{ - struct atomic_dev_params atomic_params = {0}; struct bd_object *bdobj; - uint8_t type; int ret; - ret = cas_blk_identify_type_by_bdev(bdev, &type, &atomic_params); - if (ret) - goto err; - - ret = ocf_ctx_volume_create(cas_ctx, vol, NULL, type); + ret = ocf_ctx_volume_create(cas_ctx, vol, NULL, BLOCK_DEVICE_VOLUME); if (ret) goto err; @@ -412,7 +241,7 @@ int cas_blk_open_volume_by_bdev(ocf_volume_t *vol, bdobj->btm_bd = bdev; bdobj->opened_by_bdev = true; - return ocf_volume_open(*vol, &atomic_params); + return ocf_volume_open(*vol, NULL); err: return ret; @@ -425,8 +254,7 @@ void cas_blk_close_volume(ocf_volume_t vol) env_free(vol); } -int _cas_blk_identify_type(const char *path, uint8_t *type, - struct atomic_dev_params *atomic_params) +int _cas_blk_identify_type(const char *path, uint8_t *type) { struct file *file; int result = 0; @@ -437,8 +265,6 @@ int _cas_blk_identify_type(const char *path, uint8_t *type, if (S_ISBLK(CAS_FILE_INODE(file)->i_mode)) *type = BLOCK_DEVICE_VOLUME; - else if (S_ISCHR(CAS_FILE_INODE(file)->i_mode)) - *type = NVME_CONTROLLER; else result = -OCF_ERR_INVAL_VOLUME_TYPE; @@ -446,23 +272,10 @@ int _cas_blk_identify_type(const char *path, uint8_t *type, if (result) return result; - if (*type == BLOCK_DEVICE_VOLUME) { - result = _cas_detect_blk_type(path, type, atomic_params); - if (result < 0) - return result; - } - return 0; } int cas_blk_identify_type(const char *path, uint8_t *type) { - return _cas_blk_identify_type(path, type, NULL); + return _cas_blk_identify_type(path, type); } - -int cas_blk_identify_type_atomic(const char *path, uint8_t *type, - struct atomic_dev_params *atomic_params) -{ - return _cas_blk_identify_type(path, type, atomic_params); -} - diff --git a/modules/cas_cache/volume/vol_blk_utils.h b/modules/cas_cache/volume/vol_blk_utils.h index 0d069a5..332a4b5 100644 --- a/modules/cas_cache/volume/vol_blk_utils.h +++ b/modules/cas_cache/volume/vol_blk_utils.h @@ -30,18 +30,12 @@ int cas_blk_io_set_data(struct ocf_io *io, ctx_data_t *data, uint32_t offset); ctx_data_t *cas_blk_io_get_data(struct ocf_io *io); -int cas_blk_identify_type_by_bdev(struct block_device *bdev, - uint8_t *type, struct atomic_dev_params *atomic_params); - int cas_blk_open_volume_by_bdev(ocf_volume_t *vol, struct block_device *bdev); void cas_blk_close_volume(ocf_volume_t vol); int cas_blk_identify_type(const char *path, uint8_t *type); -int cas_blk_identify_type_atomic(const char *path, uint8_t *type, - struct atomic_dev_params *atomic_params); - static inline void cas_io_iter_init(struct bio_vec_iter *iter, struct bio_vec *vec, uint32_t vec_size) { diff --git a/modules/cas_cache/volume/vol_block_dev_bottom.c b/modules/cas_cache/volume/vol_block_dev_bottom.c index 49846d4..201899e 100644 --- a/modules/cas_cache/volume/vol_block_dev_bottom.c +++ b/modules/cas_cache/volume/vol_block_dev_bottom.c @@ -124,22 +124,6 @@ const char *block_dev_get_elevator_name(struct request_queue *q) return __block_dev_get_elevator_name(q); } -/* - * - */ -int block_dev_is_metadata_mode_optimal(struct atomic_dev_params *atomic_params, - uint8_t type) -{ - if (type == BLOCK_DEVICE_VOLUME) { - if (atomic_params->is_atomic_capable) - return atomic_params->is_mode_optimal; - } else if (type == ATOMIC_DEVICE_VOLUME) { - return atomic_params->is_mode_optimal; - } - - return 1; -} - /* * */ diff --git a/modules/cas_cache/volume/vol_block_dev_bottom.h b/modules/cas_cache/volume/vol_block_dev_bottom.h index 945a4a5..0486686 100644 --- a/modules/cas_cache/volume/vol_block_dev_bottom.h +++ b/modules/cas_cache/volume/vol_block_dev_bottom.h @@ -14,9 +14,6 @@ void block_dev_close_object(ocf_volume_t vol); const char *block_dev_get_elevator_name(struct request_queue *q); -int block_dev_is_metadata_mode_optimal(struct atomic_dev_params *atomic_params, - uint8_t type); - int block_dev_try_get_io_class(struct bio *bio, int *io_class); int block_dev_init(void); diff --git a/modules/config.mk b/modules/config.mk index 30889ea..13994a8 100644 --- a/modules/config.mk +++ b/modules/config.mk @@ -27,57 +27,9 @@ check_header=$(shell echo "\#include <${1}>" | \ INCDIR = $(PWD)/include -NVME_FULL = 0 - -SLES ?= $(shell cat /etc/SuSE-release 2>/dev/null) -ifneq ($(SLES),) -EXTRA_CFLAGS += -DCAS_UAPI_LINUX_NVME_IOCTL -EXTRA_CFLAGS += -DCAS_SLES -SLES_VERSION := $(shell cat /etc/os-release |\ - sed -n 's/VERSION="\([0-9]\+\)-\(.\+\)"/\1\2/p') -EXTRA_CFLAGS += -DCAS_SLES$(SLES_VERSION) -INCDIR = "" -NVME_PARTIAL = 1 -endif - -ifeq ($(call check_header,$(INCDIR)/uapi/nvme.h), 1) -EXTRA_CFLAGS += -DCAS_UAPI_NVME_IOCTL -EXTRA_CFLAGS += -DCAS_UAPI_NVME -NVME_PARTIAL = 1 -endif - -ifeq ($(call check_header,$(INCDIR)/uapi/linux/nvme.h), 1) -EXTRA_CFLAGS += -DCAS_UAPI_LINUX_NVME -NVME_PARTIAL = 1 -endif - -ifeq ($(call check_header,$(INCDIR)/uapi/linux/nvme_ioctl.h), 1) -EXTRA_CFLAGS += -DCAS_UAPI_LINUX_NVME_IOCTL -NVME_PARTIAL = 1 -ifeq ($(shell cat /etc/redhat-release 2>/dev/null | grep "\(Red Hat\|CentOS\) [a-zA-Z ]* 7\.[45]" | wc -l), 1) -NVME_FULL = 1 -endif -endif - KERNEL_VERSION = $(shell echo $(KERNELRELEASE) | cut -d'.' -f1) KERNEL_MAJOR = $(shell echo $(KERNELRELEASE) | cut -d'.' -f2) -ifeq ($(shell expr $(KERNEL_VERSION) \> 4 \| $(KERNEL_VERSION) \== 4 \& $(KERNEL_MAJOR) \> 11),1) -NVME_FULL = 0 -endif - -ifeq ($(shell expr $(KERNEL_VERSION) \> 5 \| $(KERNEL_VERSION) \== 5 \& $(KERNEL_MAJOR) \> 7),1) -NVME_PARTIAL = 0 -endif - -ifeq ($(NVME_PARTIAL),1) -EXTRA_CFLAGS += -DCAS_NVME_PARTIAL -endif - -ifeq ($(NVME_FULL),1) -EXTRA_CFLAGS += -DCAS_NVME_FULL -endif - EXTRA_CFLAGS += -Werror EXTRA_LDFLAGS += -z noexecstack -z relro -z now diff --git a/modules/include/cas_ioctl_codes.h b/modules/include/cas_ioctl_codes.h index 0f3bce7..ec30a75 100644 --- a/modules/include/cas_ioctl_codes.h +++ b/modules/include/cas_ioctl_codes.h @@ -74,8 +74,6 @@ struct kcas_start_cache { uint64_t min_free_ram; /**< Minimum free RAM memory for cache metadata */ - uint8_t metadata_mode_optimal; /**< Current metadata mode is optimal */ - char cache_elevator[MAX_ELEVATOR_NAME]; int ext_err_code; @@ -188,8 +186,6 @@ struct kcas_cache_info { struct ocf_cache_info info; - uint8_t metadata_mode; /**< metadata mode (normal/atomic) */ - int ext_err_code; }; @@ -280,31 +276,6 @@ struct kcas_cache_list { int ext_err_code; }; -/** - * CAS capabilities. - */ -struct kcas_capabilites { - uint8_t nvme_format : 1; - /**< NVMe format support */ - - int ext_err_code; -}; - -/** - * Format NVMe namespace. - */ -#define CAS_METADATA_MODE_NORMAL 0 -#define CAS_METADATA_MODE_ATOMIC 1 -#define CAS_METADATA_MODE_INVALID 255 - -struct kcas_nvme_format { - char device_path_name[MAX_STR_LEN]; /**< path to NVMe device*/ - int metadata_mode; /**< selected metadata mode */ - int force; - - int ext_err_code; -}; - struct kcas_core_pool_remove { char core_path_name[MAX_STR_LEN]; /**< path to a core object */ @@ -321,7 +292,6 @@ struct kcas_cache_check_device { /* following bool flags are defined iff is_metadata_compatible == 1 */ bool clean_shutdown; bool cache_dirty; - bool format_atomic; int ext_err_code; }; @@ -458,12 +428,6 @@ struct kcas_get_cache_param { /** List valid cache ids within Open CAS module */ #define KCAS_IOCTL_LIST_CACHE _IOWR(KCAS_IOCTL_MAGIC, 17, struct kcas_cache_list) -/** Provides capabilites of installed open cas module */ -#define KCAS_IOCTL_GET_CAPABILITIES _IOWR(KCAS_IOCTL_MAGIC, 18, struct kcas_capabilites) - -/** Format NVMe namespace to support selected metadata mode */ -#define KCAS_IOCTL_NVME_FORMAT _IOWR(KCAS_IOCTL_MAGIC, 20, struct kcas_nvme_format) - /** Start new cache instance, load cache or recover cache */ #define KCAS_IOCTL_START_CACHE _IOWR(KCAS_IOCTL_MAGIC, 21, struct kcas_start_cache) From 07ba79c57c5ac80b09d998015788e7a58d711692 Mon Sep 17 00:00:00 2001 From: Michal Mielewczyk Date: Mon, 16 Aug 2021 16:02:09 +0200 Subject: [PATCH 2/2] Remove remains of upgrade-in-flight support Signed-off-by: Michal Mielewczyk --- casadm/extended_err_msg.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/casadm/extended_err_msg.c b/casadm/extended_err_msg.c index f56723e..1681381 100644 --- a/casadm/extended_err_msg.c +++ b/casadm/extended_err_msg.c @@ -204,10 +204,6 @@ struct { "on current cache device \nor try other device with the same " "logical sector size as core device." }, - { - KCAS_ERR_ROLLBACK, - "Cannot restore previous configuration" - }, { KCAS_ERR_CONTAINS_PART, "Device contains partitions.\nIf you want to continue, "