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