From 1cd1db2b45d08d56f946d01665b39c4b28b6a7a9 Mon Sep 17 00:00:00 2001 From: Michal Rakowski Date: Fri, 19 Jun 2020 11:38:32 +0200 Subject: [PATCH] Fully remove format nvme command Since there is no kernel-kernel api available to communicate with nvme driver it is more convenient to use some nvme-dedicated software (e.g. nvme-cli) to manage nvme devices. It is even not possible to format nvme device with CAS using current implementation on newest kernels. Signed-off-by: Michal Rakowski Signed-off-by: Michal Mielewczyk --- casadm/cas_lib.c | 86 ----- casadm/cas_lib.h | 5 - casadm/cas_main.c | 139 ------- casadm/extended_err_msg.c | 17 - modules/cas_cache/service_ui_ioctl.c | 30 +- modules/cas_cache/utils/cas_err.h | 3 - modules/cas_cache/utils/utils_nvme.c | 519 --------------------------- modules/cas_cache/utils/utils_nvme.h | 10 - modules/include/cas_ioctl_codes.h | 16 +- 9 files changed, 3 insertions(+), 822 deletions(-) diff --git a/casadm/cas_lib.c b/casadm/cas_lib.c index c131c59..d72601f 100644 --- a/casadm/cas_lib.c +++ b/casadm/cas_lib.c @@ -2785,92 +2785,6 @@ int list_caches(unsigned int list_format) return result; } -int _get_cas_capabilites(struct kcas_capabilites *caps, int quiet) -{ - static bool retrieved = false; - static struct kcas_capabilites caps_buf; - int status = SUCCESS; - int ctrl_fd; - if (!retrieved) { - if (quiet) { - ctrl_fd = open_ctrl_device_quiet(); - } else { - ctrl_fd = open_ctrl_device(); - } - - if (ctrl_fd < 0) { - if (!quiet) - print_err(KCAS_ERR_SYSTEM); - - return FAILURE; - } - - status = ioctl(ctrl_fd, KCAS_IOCTL_GET_CAPABILITIES, &caps_buf); - close(ctrl_fd); - - if (status) { - return FAILURE; - } - retrieved = true; - } - - memcpy_s(caps, sizeof(*caps), &caps_buf, sizeof(caps_buf)); - return status; -} - -int get_cas_capabilites_quiet(struct kcas_capabilites *caps) -{ - return _get_cas_capabilites(caps, true); -} - -int get_cas_capabilites(struct kcas_capabilites *caps) -{ - return _get_cas_capabilites(caps, false); -} - -int nvme_format(const char *device_path, int metadata_mode, int force) -{ - struct kcas_nvme_format cmd_info; - int fd; - int result = 0; - - strncpy_s(cmd_info.device_path_name, - sizeof(cmd_info.device_path_name), device_path, - strnlen_s(device_path, sizeof(cmd_info.device_path_name))); - - switch (metadata_mode) { - case METADATA_MODE_NORMAL: - cmd_info.metadata_mode = CAS_METADATA_MODE_NORMAL; - break; - case METADATA_MODE_ATOMIC: - cmd_info.metadata_mode = CAS_METADATA_MODE_ATOMIC; - break; - default: - return FAILURE; - } - cmd_info.force = force; - - fd = open_ctrl_device(); - if (fd == -1) - return FAILURE; - - /* Format NVMe */ - result = run_ioctl(fd, KCAS_IOCTL_NVME_FORMAT, &cmd_info); - close(fd); - - if (result) { - result = cmd_info.ext_err_code ? : KCAS_ERR_SYSTEM; - cas_printf(LOG_INFO, "Changing NVMe format failed!\n"); - print_err(result); - return FAILURE; - } - - cas_printf(LOG_INFO, "Changing NVMe format succeeded.\n" - "IMPORTANT: Reboot is required!\n"); - - return SUCCESS; -} - int _check_cache_device(const char *device_path, struct kcas_cache_check_device *cmd_info) { diff --git a/casadm/cas_lib.h b/casadm/cas_lib.h index 776b0f0..04aa1ee 100644 --- a/casadm/cas_lib.h +++ b/casadm/cas_lib.h @@ -226,11 +226,6 @@ int purge_core(unsigned int cache_id, unsigned int core_id); int flush_cache(unsigned int cache_id); int flush_core(unsigned int cache_id, unsigned int core_id); -int get_cas_capabilites_quiet(struct kcas_capabilites *caps); -int get_cas_capabilites(struct kcas_capabilites *caps); - -int nvme_format(const char *device_path, int metadata_mode, int force); - int check_cache_device(const char *device_path); int partition_list(unsigned int cache_id, unsigned int output_format); diff --git a/casadm/cas_main.c b/casadm/cas_main.c index 5e3172c..781955c 100644 --- a/casadm/cas_main.c +++ b/casadm/cas_main.c @@ -1697,128 +1697,6 @@ int script_handle() { return FAILURE; } -/******************************************************************************* - * NVMe Commands - ******************************************************************************/ - -enum { - nvme_opt_subcmd_format = 0, - - nvme_opt_device, - nvme_opt_force, - - nvme_opt_flag_required, - nvme_opt_flag_set, - - nvme_opt_subcmd_unknown, -}; - -/* NVMe command options */ -static cli_option nvme_options[] = { - [nvme_opt_subcmd_format] = { - .short_name = 'F', - .long_name = "format", - .desc = "Change NVMe metadata mode {normal|atomic} WARNING: Reboot required!", - .args_count = 1, - .arg = "MODE", - .flags = CLI_OPTION_REQUIRED, - }, - [nvme_opt_device] = { - .short_name = 'd', - .long_name = "device", - .desc = "NVMe device to be formatted", - .args_count = 1, - .arg = "DEVICE", - .flags = CLI_OPTION_REQUIRED, - }, - [nvme_opt_force] = { - .short_name = 'f', - .long_name = "force", - .desc = "Force NVMe format", - .args_count = 0, - .arg = NULL, - .flags = CLI_OPTION_OPTIONAL_ARG, - }, - {0} -}; - - -struct { - const char *device; - int metadata_mode; - int force; -} static nvme_params = { - .device = "", - .metadata_mode = 0, - .force = 0, -}; - - -/* Parser of option for IO class command */ -int nvme_handle_option(char *opt, const char **arg) -{ - if (!strcmp(opt, "device")) { - nvme_params.device = arg[0]; - } else if (!strcmp(opt, "format")) { - nvme_params.metadata_mode = validate_str_metadata_mode(arg[0]); - - if (METADATA_MODE_INVALID == nvme_params.metadata_mode) - return FAILURE; - } else if (!strcmp(opt, "force")) { - nvme_params.force = 1; - } else { - return FAILURE; - } - - return 0; -} - -static int handle_nvme_format() -{ - struct kcas_capabilites cas_capabilites; - static const char fsck_cmd[] = "/sbin/fsck -n %s > /dev/null 2>&1"; - static const uint32_t size = MAX_STR_LEN + sizeof(fsck_cmd) + 1; - char nvme_dev_path[MAX_STR_LEN]; - char buff[size]; - - if (get_cas_capabilites(&cas_capabilites)) { - cas_printf(LOG_ERR, "Can't obtain CAS capabilities\n"); - return FAILURE; - } - - if (!cas_capabilites.nvme_format) { - cas_printf(LOG_ERR, "Command is not supported by current kernel\n"); - return FAILURE; - } - - if (get_dev_path(nvme_params.device, nvme_dev_path, - sizeof(nvme_dev_path))) { - cas_printf(LOG_ERR, "Device does not exist\n"); - return FAILURE; - } - - snprintf(buff, sizeof(buff), fsck_cmd, nvme_dev_path); - - if (!system(buff)) { - if (nvme_params.force) { - cas_printf(LOG_INFO, "A filesystem existed on %s. " - "Data may have been lost\n", - nvme_params.device); - } else { - /* file system on cache device */ - cas_printf(LOG_ERR, "A filesystem exists on %s. " - "Specify the --force option if you " - "wish to format the device anyway.\n" - "Note: this may result in loss of data\n", - nvme_params.device); - return FAILURE; - } - } - - return nvme_format(nvme_dev_path, nvme_params.metadata_mode, - nvme_params.force); -} - static cli_option version_options[] = { { .short_name = 'o', @@ -1891,12 +1769,6 @@ void io_class_help(app *app_values, cli_command *cmd) char option_name[MAX_STR_LEN]; cli_option* iter = &(cmd->options[0]); - struct kcas_capabilites caps; - if (get_cas_capabilites(&caps)) { - memset(&caps, 0, sizeof(caps)); - } - - /* Print usage */ cas_printf(LOG_INFO, "Usage: %s --%s {", app_values->name, cmd->name); print_options_usage(cmd->options, "|", io_class_print_subcmd, 0); @@ -2149,17 +2021,6 @@ static cli_command cas_commands[] = { .flags = CLI_SU_REQUIRED, .help = io_class_help, }, - { - .name = "nvme", - .short_name = 'N', - .desc = "Manage NVMe namespace", - .long_desc = NULL, - .options = nvme_options, - .command_handle_opts = nvme_handle_option, - .handle = handle_nvme_format, - .flags = CLI_SU_REQUIRED, - .help = NULL, - }, { .name = "version", .short_name = 'V', diff --git a/casadm/extended_err_msg.c b/casadm/extended_err_msg.c index 8f386c3..3a88a6d 100644 --- a/casadm/extended_err_msg.c +++ b/casadm/extended_err_msg.c @@ -184,11 +184,6 @@ struct { KCAS_ERR_DEV_PENDING, "Device opens or mount are pending to this cache" }, - { - KCAS_ERR_DIRTY_EXISTS_NVME, - "Cache device contains dirty data.\nIf you want to format it, " - "please use --force option.\nWarning: all data will be lost!" - }, { KCAS_ERR_FILE_EXISTS, "Could not create exported object because file in /dev " @@ -212,22 +207,10 @@ struct { KCAS_ERR_ROLLBACK, "Cannot restore previous configuration" }, - { - KCAS_ERR_NOT_NVME, - "Given block device is not NVMe" - }, - { - KCAS_ERR_FORMAT_FAILED, - "Failed to format NVMe device" - }, { KCAS_ERR_NVME_BAD_FORMAT, "NVMe is formatted to unsupported format" }, - { - KCAS_ERR_UNSUPPORTED_LBA_FORMAT, - "Specified LBA format is not supported by the NVMe device" - }, { KCAS_ERR_CONTAINS_PART, "Device contains partitions.\nIf you want to continue, " diff --git a/modules/cas_cache/service_ui_ioctl.c b/modules/cas_cache/service_ui_ioctl.c index 55d23ec..c13a0b1 100644 --- a/modules/cas_cache/service_ui_ioctl.c +++ b/modules/cas_cache/service_ui_ioctl.c @@ -51,8 +51,7 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd, cmd != KCAS_IOCTL_LIST_CACHE && cmd != KCAS_IOCTL_GET_CACHE_COUNT && cmd != KCAS_IOCTL_CORE_INFO && - cmd != KCAS_IOCTL_PARTITION_INFO && - cmd != KCAS_IOCTL_GET_CAPABILITIES) { + cmd != KCAS_IOCTL_PARTITION_INFO) { return -EFAULT; } @@ -306,18 +305,6 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd, RETURN_CMD_RESULT(cmd_info, arg, retval > 0 ? 0 : retval); } - case KCAS_IOCTL_GET_CAPABILITIES: { - struct kcas_capabilites *cmd_info; - - GET_CMD_INFO(cmd_info, arg); - - memset(cmd_info, 0, sizeof(*cmd_info)); -#ifdef CAS_NVME_FULL - cmd_info->nvme_format = 1; -#endif - RETURN_CMD_RESULT(cmd_info, arg, 0); - } - case KCAS_IOCTL_UPGRADE: { struct kcas_upgrade *cmd_info; @@ -328,21 +315,6 @@ long cas_service_ioctl_ctrl(struct file *filp, unsigned int cmd, RETURN_CMD_RESULT(cmd_info, arg, retval); } -#if defined(CAS_NVME_FULL) - case KCAS_IOCTL_NVME_FORMAT: { - struct kcas_nvme_format *cmd_info; - - GET_CMD_INFO(cmd_info, arg); - - retval = cas_nvme_format_optimal( - cmd_info->device_path_name, - cmd_info->metadata_mode, - cmd_info->force); - - RETURN_CMD_RESULT(cmd_info, arg, retval); - } -#endif - case KCAS_IOCTL_GET_CORE_POOL_COUNT: { struct kcas_core_pool_count *cmd_info; diff --git a/modules/cas_cache/utils/cas_err.h b/modules/cas_cache/utils/cas_err.h index d35e2f0..45d93a3 100644 --- a/modules/cas_cache/utils/cas_err.h +++ b/modules/cas_cache/utils/cas_err.h @@ -55,14 +55,11 @@ struct { { KCAS_ERR_DEV_SPACE, ENOSPC }, { KCAS_ERR_INV_IOCTL, EINVAL }, { KCAS_ERR_DEV_PENDING, EBUSY }, - { KCAS_ERR_DIRTY_EXISTS_NVME, EFAULT }, { KCAS_ERR_FILE_EXISTS, EEXIST }, { KCAS_ERR_IN_UPGRADE, EFAULT }, { KCAS_ERR_UNALIGNED, EINVAL }, { KCAS_ERR_NO_STORED_CONF, EINTR }, { KCAS_ERR_ROLLBACK, EFAULT }, - { KCAS_ERR_NOT_NVME, ENODEV }, - { KCAS_ERR_FORMAT_FAILED, EFAULT }, { KCAS_ERR_NVME_BAD_FORMAT, EINVAL }, { KCAS_ERR_CONTAINS_PART, EINVAL }, { KCAS_ERR_A_PART, EINVAL }, diff --git a/modules/cas_cache/utils/utils_nvme.c b/modules/cas_cache/utils/utils_nvme.c index bf1140c..b21c432 100644 --- a/modules/cas_cache/utils/utils_nvme.c +++ b/modules/cas_cache/utils/utils_nvme.c @@ -3,8 +3,6 @@ * SPDX-License-Identifier: BSD-3-Clause-Clear */ -#if defined(CAS_NVME_PARTIAL) - #include "cas_cache.h" #include "utils_nvme.h" #include "utils_blk.h" @@ -64,520 +62,3 @@ out: cas_vm_munmap(buffer, sizeof(*ns)); return ret; } - -int cas_nvme_identify_ns_contorller(struct file *file, struct nvme_id_ns *ns) -{ - struct nvme_admin_cmd cmd = { }; - unsigned long __user buffer; - mm_segment_t old_fs; - 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 = 1; - cmd.addr = (__u64)buffer; - cmd.data_len = sizeof(*ns); - cmd.cdw10 = NVME_ID_CNS_NS; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = file->f_op->unlocked_ioctl(file, - NVME_IOCTL_ADMIN_CMD, (unsigned long)&cmd); - set_fs(old_fs); - 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; -} - -#if defined(CAS_NVME_FULL) - -#define FORMAT_WORKAROUND_NOT_NEED 0 -#define FORMAT_WORKAROUND_NEED 1 - -static int __cas_nvme_check_fw(struct nvme_id_ctrl *id_ctrl) -{ - /* - * If firmware is older then 8DV101H0 we need do - * workaround - make format twice. We need to compare - * only 5 last characters. - */ - - return (strncmp(&id_ctrl->fr[3], "101H0", 5) < 0) ? - FORMAT_WORKAROUND_NEED : - FORMAT_WORKAROUND_NOT_NEED; -} - -int cas_nvme_identify_ctrl(struct block_device *bdev, - struct nvme_id_ctrl *id_ctrl) -{ - struct nvme_admin_cmd cmd = { }; - unsigned long __user buffer; - int ret = 0; - - buffer = cas_vm_mmap(NULL, 0, sizeof(*id_ctrl)); - if (IS_ERR((void *)buffer)) - return PTR_ERR((void *)buffer); - - cmd.opcode = nvme_admin_identify; - cmd.addr = (__u64)buffer; - cmd.data_len = sizeof(*id_ctrl); - cmd.cdw10 = NVME_ID_CNS_CTRL; - - ret = ioctl_by_bdev(bdev, NVME_IOCTL_ADMIN_CMD, (unsigned long)&cmd); - if (ret < 0) - goto out; - - ret = copy_from_user(id_ctrl, (void *)buffer, sizeof(*id_ctrl)); - if (ret > 0) - ret = -EINVAL; - -out: - cas_vm_munmap(buffer, sizeof(*id_ctrl)); - return ret; -} - -static int _cas_nvme_format_bdev(struct block_device *bdev, unsigned int nsid, - int lbaf, int ms) -{ - struct nvme_admin_cmd cmd = { }; - - cmd.opcode = nvme_admin_format_nvm; - cmd.nsid = nsid; - cmd.cdw10 = lbaf | ms<<4; - cmd.timeout_ms = 1200000; - return ioctl_by_bdev(bdev, NVME_IOCTL_ADMIN_CMD, (unsigned long)&cmd); -} - -static int _cas_nvme_controller_identify(struct file *character_device_file, - unsigned long __user buffer) -{ - struct nvme_admin_cmd cmd = { }; - mm_segment_t old_fs; - int ret; - - old_fs = get_fs(); - - cmd.opcode = nvme_admin_identify; - cmd.nsid = 0; - cmd.addr = (__u64)buffer; - /* 1 - identify contorller, 0 - identify namespace */ - cmd.cdw10 = 1; - cmd.data_len = 0x1000; - - set_fs(KERNEL_DS); - ret = character_device_file->f_op->unlocked_ioctl(character_device_file, - NVME_IOCTL_ADMIN_CMD, (unsigned long)&cmd); - set_fs(old_fs); - return ret; -} - -static int _cas_nvme_format_controller(struct file *character_device_file, - int lbaf, bool sbnsupp) -{ - struct nvme_admin_cmd cmd = { }; - mm_segment_t old_fs; - int ret; - - old_fs = get_fs(); - - /* Send format command to device */ - cmd.opcode = nvme_admin_format_nvm; - cmd.nsid = 0xFFFFFFFF; - cmd.cdw10 = lbaf | sbnsupp << 4; - cmd.timeout_ms = 120000; - cmd.addr = 0; - - set_fs(KERNEL_DS); - ret = character_device_file->f_op->unlocked_ioctl(character_device_file, - NVME_IOCTL_ADMIN_CMD, (unsigned long)&cmd); - set_fs(old_fs); - return ret; -} - -static inline int find_lbaf(struct nvme_lbaf *lbaf, int cnt, int atomic) -{ - int ms = atomic ? 8 : 0; - int i; - - for (i = 0; i <= cnt; ++i) - if (lbaf[i].ms == ms && lbaf[i].ds == 9) - return i; - - return -EINVAL; -} - -/* context for async probe */ -struct _probe_context -{ - struct completion cmpl; - struct ocf_metadata_probe_status status; - int error; -}; - -static void _cas_nvme_probe_cmpl(void *priv, int error, - struct ocf_metadata_probe_status *status) -{ - struct _probe_context *ctx = (struct _probe_context*)priv; - - ctx->error = error; - if (!error) { - ctx->status = *status; - } - - complete(&ctx->cmpl); -} - -static int _cas_nvme_preformat_check(struct block_device *bdev, int force) -{ - ocf_volume_t volume; - struct _probe_context probe_ctx; - int ret = 0; - - if (bdev != bdev->bd_contains) - return -KCAS_ERR_A_PART; - - if (cas_blk_get_part_count(bdev) > 1 && !force) - return -KCAS_ERR_CONTAINS_PART; - - ret = cas_blk_open_volume_by_bdev(&volume, bdev); - if (ret == -KCAS_ERR_NVME_BAD_FORMAT) { - /* Current format is not supported by CAS, so we can be sure - * that there is no dirty data. Do format - */ - return 0; - } else if (ret) { - /* An error occurred, stop processing */ - return ret; - } - - init_completion(&probe_ctx.cmpl); - ocf_metadata_probe(cas_ctx, volume, _cas_nvme_probe_cmpl, &probe_ctx); - if (wait_for_completion_interruptible(&probe_ctx.cmpl)) { - ocf_volume_close(volume); - return -OCF_ERR_FLUSHING_INTERRUPTED; - } - - if (probe_ctx.error == -ENODATA) { - /* Cache was not detected on this device - * NVMe can be formated - */ - ret = 0; - } else if (probe_ctx.error == -EBUSY) { - ret = -OCF_ERR_NOT_OPEN_EXC; - } else if (probe_ctx.error) { - /* Some error occurred, we are not sure whether cache is clean or not */ - ret = -KCAS_ERR_FORMAT_FAILED; - } else { - /* Check if cache was closed in proper way */ - if (!probe_ctx.status.clean_shutdown || - probe_ctx.status.cache_dirty) { - /* Dirty shutdown */ - ret = -KCAS_ERR_DIRTY_EXISTS_NVME; - } - - if (force) { - /* Force overwrites dirty shutdown */ - ret = 0; - } - } - - ocf_volume_close(volume); - return ret; -} - -static int _cas_nvme_format_namespace_by_path(const char *device_path, - int metadata_mode, int force) -{ - struct nvme_id_ns *ns; - struct nvme_id_ctrl *id; - - unsigned int nsid, sbnsupp = 0; - int best_lbaf = 0; - int ret = 0; - struct block_device *bdev; - char holder[] = "CAS FORMAT\n"; - - ns = kmalloc(sizeof(*ns), GFP_KERNEL); - if (!ns) - return -OCF_ERR_NO_MEM; - - id = kmalloc(sizeof(*id), GFP_KERNEL); - if (!id) { - ret = -OCF_ERR_NO_MEM; - goto out1; - } - - bdev = blkdev_get_by_path(device_path, - FMODE_READ | FMODE_WRITE | FMODE_EXCL, holder); - if (IS_ERR(bdev)) { - if (PTR_ERR(bdev) == -EBUSY) - ret = -OCF_ERR_NOT_OPEN_EXC; - else - ret = -OCF_ERR_INVAL_VOLUME_TYPE; - - goto out1; - } - - ret = cas_nvme_get_nsid(bdev, &nsid); - if (ret < 0) { - ret = -KCAS_ERR_NOT_NVME; - goto out2; - } - - ret = _cas_nvme_preformat_check(bdev, force); - if (ret) - goto out2; - - ret = cas_nvme_identify_ns(bdev, nsid, ns); - if (ret < 0) { - ret = -KCAS_ERR_FORMAT_FAILED; - goto out2; - } - - if (metadata_mode == CAS_METADATA_MODE_NORMAL) { - best_lbaf = find_lbaf(ns->lbaf, ns->nlbaf, 0); - sbnsupp = 0; - } else if (metadata_mode == CAS_METADATA_MODE_ATOMIC) { - best_lbaf = find_lbaf(ns->lbaf, ns->nlbaf, 1); - sbnsupp = !(ns->mc & (1<<1)); - } - - if (best_lbaf < 0) { - ret = -KCAS_ERR_UNSUPPORTED_LBA_FORMAT; - goto out2; - } - - ret = cas_nvme_identify_ctrl(bdev, id); - if (ret < 0) { - ret = -KCAS_ERR_FORMAT_FAILED; - goto out2; - } - - if (__cas_nvme_check_fw(id) == FORMAT_WORKAROUND_NEED) { - /* - * If firmware is older then 8DV101H0 we need do - * workaround - make format twice. - */ - ret = _cas_nvme_format_bdev(bdev, nsid, best_lbaf, sbnsupp); - if (ret) - goto out2; - } - - ret = _cas_nvme_format_bdev(bdev, nsid, best_lbaf, sbnsupp); - if (ret) - goto out2; - - ret = ioctl_by_bdev(bdev, BLKRRPART, (unsigned long)NULL); -out2: - blkdev_put(bdev, FMODE_READ | FMODE_WRITE | FMODE_EXCL); -out1: - kfree(id); - kfree(ns); - return ret; -} - -static int _cas_nvme_get_bdev_from_controller(struct block_device **bdev, - int major, int minor, int namespace_number) -{ - mm_segment_t old_fs; - char *sys_path; - struct file *file; - char readbuffer[12] = {0}; - char holder[] = "CAS FORMAT\n"; - int ret = 0; - - sys_path = kzalloc(sizeof(char)*MAX_STR_LEN, GFP_KERNEL); - if (!sys_path) - return -OCF_ERR_NO_MEM; - - sprintf(sys_path, "/sys/dev/char/%d:%d/nvme%dn%d/dev", - major, minor, minor, namespace_number); - - file = filp_open(sys_path, O_RDONLY, 0); - kfree(sys_path); - if (IS_ERR(file)) - return -KCAS_ERR_FORMAT_FAILED; - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = file->f_op->read(file, readbuffer, sizeof(readbuffer), - &file->f_pos); - set_fs(old_fs); - filp_close(file, 0); - if (ret < 0) - return -KCAS_ERR_FORMAT_FAILED; - - ret = sscanf(readbuffer, "%d:%d", &major, &minor); - if (ret < 0) - return -KCAS_ERR_FORMAT_FAILED; - - *bdev = blkdev_get_by_dev(MKDEV(major, minor), - FMODE_READ | FMODE_WRITE | FMODE_EXCL, holder); - if (IS_ERR(*bdev)) - return -OCF_ERR_INVAL_VOLUME_TYPE; - - return 0; -} - -static int _cas_nvme_format_character_device(const char *device_path, - int metadata_mode, int force) -{ - mm_segment_t old_fs; - int ret; - struct file *character_device_file = NULL; - struct nvme_id_ctrl *ctrl; - unsigned long __user buffer; - struct kstat *stat; - struct block_device **ndev = NULL; - int i; - struct nvme_id_ns *ns; - int best_lbaf = 0; - int sbnsupp = 0; - - ctrl = kzalloc(sizeof(struct nvme_id_ctrl), GFP_KERNEL); - buffer = cas_vm_mmap(NULL, 0, sizeof(*ctrl)); - stat = kmalloc(sizeof(struct kstat), GFP_KERNEL); - ns = kmalloc(sizeof(*ns), GFP_KERNEL); - - old_fs = get_fs(); - - if (!ctrl || !buffer || !stat || !ns) { - ret = -OCF_ERR_NO_MEM; - goto out1; - } - - character_device_file = filp_open(device_path, O_RDWR | O_EXCL, 0); - if (IS_ERR(character_device_file)) { - ret = -OCF_ERR_INVAL_VOLUME_TYPE; - goto out1; - } - - ret = _cas_nvme_controller_identify(character_device_file, buffer); - if (ret < 0) { - ret = KCAS_ERR_FORMAT_FAILED; - goto out1; - } - - ret = copy_from_user(ctrl, (void *)buffer, sizeof(*ctrl)); - if (ret) - goto out1; - - ndev = kmalloc_array(ctrl->nn, sizeof(struct block_device), GFP_KERNEL); - if (!ndev) { - ret = -OCF_ERR_NO_MEM; - goto out1; - } - - set_fs(KERNEL_DS); - ret = vfs_stat(device_path, stat); - set_fs(old_fs); - if (ret) - goto out1; - - for (i = 1; i <= ctrl->nn; i++) { - ret = _cas_nvme_get_bdev_from_controller(&ndev[i-1], - MAJOR(stat->rdev), MINOR(stat->rdev), i); - if (ret) { - i--; - goto cleanup; - } - - ret = _cas_nvme_preformat_check(ndev[i-1], force); - if (ret) - goto cleanup; - } - - ret = cas_nvme_identify_ns_contorller(character_device_file, ns); - if (ret) - goto cleanup; - - if (metadata_mode == CAS_METADATA_MODE_NORMAL) { - best_lbaf = find_lbaf(ns->lbaf, ns->nlbaf, 0); - sbnsupp = 0; - } else if (metadata_mode == CAS_METADATA_MODE_ATOMIC) { - best_lbaf = find_lbaf(ns->lbaf, ns->nlbaf, 1); - sbnsupp = !(ns->mc & (1<<1)); - } - - if (best_lbaf < 0) { - ret = -KCAS_ERR_UNSUPPORTED_LBA_FORMAT; - goto cleanup; - } - - if (__cas_nvme_check_fw(ctrl) == FORMAT_WORKAROUND_NEED) { - /* - * If firmware is older then 8DV101H0 we need do - * workaround - make format twice. - */ - ret = _cas_nvme_format_controller(character_device_file, - best_lbaf, sbnsupp); - if (ret < 0) { - ret = -KCAS_ERR_FORMAT_FAILED; - goto cleanup; - } - } - - ret = _cas_nvme_format_controller(character_device_file, - best_lbaf, sbnsupp); - if (ret < 0) - ret = -KCAS_ERR_FORMAT_FAILED; - -cleanup: - for (i = i-1; i >= 1; i--) { - ret |= ioctl_by_bdev(ndev[i-1], BLKRRPART, (unsigned long)NULL); - blkdev_put(ndev[i-1], FMODE_READ | FMODE_WRITE | FMODE_EXCL); - } - -out1: - kfree(ndev); - kfree(ctrl); - kfree(stat); - - kfree(ns); - cas_vm_munmap(buffer, sizeof(buffer)); - filp_close(character_device_file, 0); - - return ret; -} - -int cas_nvme_format_optimal(const char *device_path, int metadata_mode, - int force) -{ - int ret; - uint8_t type; - - ret = cas_blk_identify_type(device_path, &type); - if (ret == -OCF_ERR_INVAL_VOLUME_TYPE) { - /* An error occurred, stop processing */ - return ret; - } - - if (type == BLOCK_DEVICE_VOLUME || type == ATOMIC_DEVICE_VOLUME) { - ret = _cas_nvme_format_namespace_by_path(device_path, - metadata_mode, force); - } else if (type == NVME_CONTROLLER && false) { - /* - * TODO(rbaldyga): Make it safe with NVMe drives that do not - * handle format change properly. - */ - ret = _cas_nvme_format_character_device(device_path, - metadata_mode, force); - } else { - ret = -OCF_ERR_INVAL_VOLUME_TYPE; - } - - return ret; -} - -#endif - -#endif diff --git a/modules/cas_cache/utils/utils_nvme.h b/modules/cas_cache/utils/utils_nvme.h index d052754..560a28c 100644 --- a/modules/cas_cache/utils/utils_nvme.h +++ b/modules/cas_cache/utils/utils_nvme.h @@ -18,21 +18,11 @@ #include #endif -#if defined(CAS_NVME_PARTIAL) - #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); -#if defined(CAS_NVME_FULL) - -int cas_nvme_format_optimal(const char *device_path, int metadata_mode, - int force); - -#endif /* CAS_NVME_FULL */ - -#endif /* CAS_NVME_PARTIAL */ #endif /* UTILS_NVME_H_ */ diff --git a/modules/include/cas_ioctl_codes.h b/modules/include/cas_ioctl_codes.h index 403805a..e5d3e2b 100644 --- a/modules/include/cas_ioctl_codes.h +++ b/modules/include/cas_ioctl_codes.h @@ -393,9 +393,9 @@ struct kcas_get_cache_param { * 15 * KCAS_IOCTL_PARTITION_SET * OK * * 16 * KCAS_IOCTL_GET_CACHE_COUNT * OK * * 17 * KCAS_IOCTL_LIST_CACHE * OK * - * 18 * KCAS_IOCTL_GET_CAPABILITIES * OK * + * 18 * KCAS_IOCTL_GET_CAPABILITIES * DEPRECATED * * 19 * KCAS_IOCTL_UPGRADE * OK * - * 20 * KCAS_IOCTL_NVME_FORMAT * OK * + * 20 * KCAS_IOCTL_NVME_FORMAT * DEPRECATED * * 21 * KCAS_IOCTL_START_CACHE * OK * * 22 * KCAS_IOCTL_INSERT_CORE * OK * * 23 * KCAS_IOCTL_REMOVE_CORE * OK * @@ -532,9 +532,6 @@ enum kcas_error { /** Device opens or mount are pending to this cache */ KCAS_ERR_DEV_PENDING, - /** NVMe Cache device contains dirty data. */ - KCAS_ERR_DIRTY_EXISTS_NVME, - /** Could not create exported object because file in /dev directory * exists */ @@ -553,18 +550,9 @@ enum kcas_error { /** Cannot roll-back previous configuration */ KCAS_ERR_ROLLBACK, - /** Device is not NVMe */ - KCAS_ERR_NOT_NVME, - - /** Failed to format NVMe device */ - KCAS_ERR_FORMAT_FAILED, - /** NVMe is formatted to unsupported format */ KCAS_ERR_NVME_BAD_FORMAT, - /** Specified LBA format is not supported by the NVMe device */ - KCAS_ERR_UNSUPPORTED_LBA_FORMAT, - /** Device contains partitions */ KCAS_ERR_CONTAINS_PART,