1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2018 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 #include "spdk/nvme.h" 8 #include "spdk/thread.h" 9 #include "spdk/string.h" 10 #include "spdk/likely.h" 11 #include "spdk/ftl.h" 12 #include "spdk/likely.h" 13 #include "spdk/string.h" 14 #include "spdk/bdev_module.h" 15 #include "spdk/config.h" 16 17 #include "ftl_core.h" 18 #include "ftl_io.h" 19 #include "ftl_band.h" 20 #include "ftl_debug.h" 21 #include "ftl_nv_cache.h" 22 #include "ftl_writer.h" 23 #include "ftl_utils.h" 24 #include "mngt/ftl_mngt.h" 25 26 struct ftl_dev_init_ctx { 27 spdk_ftl_init_fn cb_fn; 28 /* Callback's argument */ 29 void *cb_arg; 30 }; 31 32 struct ftl_dev_free_ctx { 33 spdk_ftl_fn cb_fn; 34 /* Callback's argument */ 35 void *cb_arg; 36 }; 37 38 static int 39 init_core_thread(struct spdk_ftl_dev *dev) 40 { 41 struct spdk_cpuset cpumask = {}; 42 43 /* 44 * If core mask is provided create core thread on first cpu that match with the mask, 45 * otherwise use current user thread 46 */ 47 if (dev->conf.core_mask) { 48 if (spdk_cpuset_parse(&cpumask, dev->conf.core_mask)) { 49 return -EINVAL; 50 } 51 dev->core_thread = spdk_thread_create("ftl_core_thread", &cpumask); 52 } else { 53 dev->core_thread = spdk_get_thread(); 54 } 55 56 if (dev->core_thread == NULL) { 57 FTL_ERRLOG(dev, "Cannot create thread for mask %s\n", dev->conf.core_mask); 58 return -ENOMEM; 59 } 60 61 return 0; 62 } 63 64 static void 65 exit_thread(void *ctx) 66 { 67 struct spdk_thread *thread = ctx; 68 69 spdk_thread_exit(thread); 70 } 71 72 static void 73 deinit_core_thread(struct spdk_ftl_dev *dev) 74 { 75 if (dev->core_thread && dev->conf.core_mask) { 76 spdk_thread_send_msg(dev->core_thread, exit_thread, 77 dev->core_thread); 78 dev->core_thread = NULL; 79 } 80 } 81 82 static void 83 free_dev(struct spdk_ftl_dev *dev) 84 { 85 if (!dev) { 86 return; 87 } 88 89 deinit_core_thread(dev); 90 spdk_ftl_conf_deinit(&dev->conf); 91 ftl_properties_deinit(dev); 92 free(dev); 93 } 94 95 static struct spdk_ftl_dev * 96 allocate_dev(const struct spdk_ftl_conf *conf, int *error) 97 { 98 int rc; 99 struct spdk_ftl_dev *dev = calloc(1, sizeof(*dev)); 100 101 if (!dev) { 102 FTL_ERRLOG(dev, "Cannot allocate FTL device\n"); 103 *error = -ENOMEM; 104 return NULL; 105 } 106 107 rc = ftl_properties_init(dev); 108 if (rc) { 109 *error = rc; 110 goto error; 111 } 112 113 rc = ftl_conf_init_dev(dev, conf); 114 if (rc) { 115 *error = rc; 116 goto error; 117 } 118 119 rc = init_core_thread(dev); 120 if (rc) { 121 *error = rc; 122 goto error; 123 } 124 125 TAILQ_INIT(&dev->rd_sq); 126 TAILQ_INIT(&dev->wr_sq); 127 TAILQ_INIT(&dev->unmap_sq); 128 TAILQ_INIT(&dev->ioch_queue); 129 130 ftl_writer_init(dev, &dev->writer_user, SPDK_FTL_LIMIT_HIGH, FTL_BAND_TYPE_COMPACTION); 131 ftl_writer_init(dev, &dev->writer_gc, SPDK_FTL_LIMIT_CRIT, FTL_BAND_TYPE_GC); 132 133 return dev; 134 error: 135 free_dev(dev); 136 return NULL; 137 } 138 139 static void 140 dev_init_cb(struct spdk_ftl_dev *dev, void *_ctx, int status) 141 { 142 struct ftl_dev_init_ctx *ctx = _ctx; 143 int rc; 144 145 if (status) { 146 if (dev->init_retry) { 147 FTL_NOTICELOG(dev, "Startup retry\n"); 148 rc = spdk_ftl_dev_init(&dev->conf, ctx->cb_fn, ctx->cb_arg); 149 if (!rc) { 150 free_dev(dev); 151 free(ctx); 152 return; 153 } 154 FTL_NOTICELOG(dev, "Startup retry failed: %d\n", rc); 155 } 156 157 free_dev(dev); 158 dev = NULL; 159 } 160 ctx->cb_fn(dev, ctx->cb_arg, status); 161 free(ctx); 162 } 163 164 int 165 spdk_ftl_dev_init(const struct spdk_ftl_conf *conf, spdk_ftl_init_fn cb_fn, void *cb_arg) 166 { 167 int rc = -1; 168 struct ftl_dev_init_ctx *ctx; 169 struct spdk_ftl_dev *dev = NULL; 170 171 ctx = calloc(1, sizeof(*ctx)); 172 if (!ctx) { 173 rc = -ENOMEM; 174 goto error; 175 } 176 ctx->cb_fn = cb_fn; 177 ctx->cb_arg = cb_arg; 178 179 dev = allocate_dev(conf, &rc); 180 if (!dev) { 181 goto error; 182 } 183 184 rc = ftl_mngt_call_dev_startup(dev, dev_init_cb, ctx); 185 if (rc) { 186 goto error; 187 } 188 189 return 0; 190 191 error: 192 free(ctx); 193 free_dev(dev); 194 return rc; 195 } 196 197 static void 198 dev_free_cb(struct spdk_ftl_dev *dev, void *_ctx, int status) 199 { 200 struct ftl_dev_free_ctx *ctx = _ctx; 201 202 if (!status) { 203 free_dev(dev); 204 } 205 ctx->cb_fn(ctx->cb_arg, status); 206 free(ctx); 207 } 208 209 int 210 spdk_ftl_dev_free(struct spdk_ftl_dev *dev, spdk_ftl_fn cb_fn, void *cb_arg) 211 { 212 int rc = -1; 213 struct ftl_dev_free_ctx *ctx; 214 215 ctx = calloc(1, sizeof(*ctx)); 216 if (!ctx) { 217 rc = -ENOMEM; 218 goto error; 219 } 220 ctx->cb_fn = cb_fn; 221 ctx->cb_arg = cb_arg; 222 223 rc = ftl_mngt_call_dev_shutdown(dev, dev_free_cb, ctx); 224 if (rc) { 225 goto error; 226 } 227 228 return 0; 229 230 error: 231 free(ctx); 232 return rc; 233 } 234 235 SPDK_LOG_REGISTER_COMPONENT(ftl_init) 236