1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2022 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/ftl.h" 7 8 #include "ftl_conf.h" 9 #include "ftl_core.h" 10 #include "ftl_utils.h" 11 12 static const struct spdk_ftl_conf g_default_conf = { 13 /* 2 free bands - compaction is blocked, gc only */ 14 .limits[SPDK_FTL_LIMIT_CRIT] = 2, 15 /* 3 free bands */ 16 .limits[SPDK_FTL_LIMIT_HIGH] = 3, 17 /* 4 free bands */ 18 .limits[SPDK_FTL_LIMIT_LOW] = 4, 19 /* 5 free bands - gc starts running */ 20 .limits[SPDK_FTL_LIMIT_START] = 5, 21 /* 20% spare blocks */ 22 .overprovisioning = 20, 23 /* 2GiB of DRAM for l2p cache */ 24 .l2p_dram_limit = 2048, 25 /* IO pool size per user thread (this should be adjusted to thread IO qdepth) */ 26 .user_io_pool_size = 2048, 27 .nv_cache = { 28 .chunk_compaction_threshold = 80, 29 .chunk_free_target = 5, 30 }, 31 .fast_shutdown = true, 32 }; 33 34 void 35 spdk_ftl_get_default_conf(struct spdk_ftl_conf *conf, size_t conf_size) 36 { 37 assert(conf_size > 0); 38 assert(conf_size <= sizeof(struct spdk_ftl_conf)); 39 40 memcpy(conf, &g_default_conf, conf_size); 41 conf->conf_size = conf_size; 42 } 43 44 void 45 spdk_ftl_dev_get_conf(const struct spdk_ftl_dev *dev, struct spdk_ftl_conf *conf, size_t conf_size) 46 { 47 assert(conf_size > 0); 48 assert(conf_size <= sizeof(struct spdk_ftl_conf)); 49 50 memcpy(conf, &dev->conf, conf_size); 51 conf->conf_size = conf_size; 52 } 53 54 int 55 spdk_ftl_conf_copy(struct spdk_ftl_conf *dst, const struct spdk_ftl_conf *src) 56 { 57 char *name = NULL; 58 char *core_mask = NULL; 59 char *base_bdev = NULL; 60 char *cache_bdev = NULL; 61 62 if (!src->conf_size || src->conf_size > sizeof(struct spdk_ftl_conf)) { 63 return -EINVAL; 64 } 65 66 if (src->name) { 67 name = strdup(src->name); 68 if (!name) { 69 goto error; 70 } 71 } 72 if (src->core_mask) { 73 core_mask = strdup(src->core_mask); 74 if (!core_mask) { 75 goto error; 76 } 77 } 78 if (src->base_bdev) { 79 base_bdev = strdup(src->base_bdev); 80 if (!base_bdev) { 81 goto error; 82 } 83 } 84 if (src->cache_bdev) { 85 cache_bdev = strdup(src->cache_bdev); 86 if (!cache_bdev) { 87 goto error; 88 } 89 } 90 91 memcpy(dst, src, src->conf_size); 92 93 dst->name = name; 94 dst->core_mask = core_mask; 95 dst->base_bdev = base_bdev; 96 dst->cache_bdev = cache_bdev; 97 return 0; 98 error: 99 free(name); 100 free(core_mask); 101 free(base_bdev); 102 free(cache_bdev); 103 return -ENOMEM; 104 } 105 106 void 107 spdk_ftl_conf_deinit(struct spdk_ftl_conf *conf) 108 { 109 free(conf->name); 110 free(conf->core_mask); 111 free(conf->base_bdev); 112 free(conf->cache_bdev); 113 } 114 115 int 116 ftl_conf_init_dev(struct spdk_ftl_dev *dev, const struct spdk_ftl_conf *conf) 117 { 118 int rc; 119 120 if (!conf->conf_size) { 121 FTL_ERRLOG(dev, "FTL configuration is uninitialized\n"); 122 return -EINVAL; 123 } 124 125 if (!conf->name) { 126 FTL_ERRLOG(dev, "No FTL name in configuration\n"); 127 return -EINVAL; 128 } 129 if (!conf->base_bdev) { 130 FTL_ERRLOG(dev, "No base device in configuration\n"); 131 return -EINVAL; 132 } 133 if (!conf->cache_bdev) { 134 FTL_ERRLOG(dev, "No NV cache device in configuration\n"); 135 return -EINVAL; 136 } 137 138 rc = spdk_ftl_conf_copy(&dev->conf, conf); 139 if (rc) { 140 return rc; 141 } 142 143 dev->limit = SPDK_FTL_LIMIT_MAX; 144 145 ftl_property_register_bool_rw(dev, "prep_upgrade_on_shutdown", &dev->conf.prep_upgrade_on_shutdown, 146 "", "During shutdown, FTL executes all actions which " 147 "are needed for upgrade to a new version", false); 148 149 ftl_property_register_bool_rw(dev, "verbose_mode", &dev->conf.verbose_mode, 150 "", "In verbose mode, user is able to get access to additional " 151 "advanced FTL properties", false); 152 153 return 0; 154 } 155 156 bool 157 ftl_conf_is_valid(const struct spdk_ftl_conf *conf) 158 { 159 if (conf->overprovisioning >= 100) { 160 return false; 161 } 162 if (conf->overprovisioning == 0) { 163 return false; 164 } 165 166 if (conf->nv_cache.chunk_compaction_threshold == 0 || 167 conf->nv_cache.chunk_compaction_threshold > 100) { 168 return false; 169 } 170 171 if (conf->nv_cache.chunk_free_target == 0 || conf->nv_cache.chunk_free_target > 100) { 172 return false; 173 } 174 175 if (conf->l2p_dram_limit == 0) { 176 return false; 177 } 178 179 return true; 180 } 181