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