]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/lib/bdev/nvme/bdev_ftl.c
bump version to 15.2.11-pve1
[ceph.git] / ceph / src / spdk / lib / bdev / nvme / bdev_ftl.c
1 /*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
16 * distribution.
17 * * Neither the name of Intel Corporation nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "spdk/stdinc.h"
35 #include "spdk/bdev.h"
36 #include "spdk/conf.h"
37 #include "spdk/env.h"
38 #include "spdk/io_channel.h"
39 #include "spdk/json.h"
40 #include "spdk/string.h"
41 #include "spdk/likely.h"
42 #include "spdk/util.h"
43 #include "spdk/string.h"
44 #include "spdk/ftl.h"
45 #include "spdk_internal/log.h"
46
47 #include "bdev_ftl.h"
48 #include "common.h"
49
50 #define FTL_COMPLETION_RING_SIZE 4096
51
52 struct ftl_bdev {
53 struct spdk_bdev bdev;
54
55 struct nvme_bdev_ctrlr *ctrlr;
56
57 struct spdk_ftl_dev *dev;
58
59 struct spdk_bdev_desc *cache_bdev_desc;
60
61 ftl_bdev_init_fn init_cb;
62
63 void *init_arg;
64
65 LIST_ENTRY(ftl_bdev) list_entry;
66 };
67
68 struct ftl_io_channel {
69 struct spdk_ftl_dev *dev;
70
71 struct spdk_poller *poller;
72
73 #define FTL_MAX_COMPLETIONS 64
74 struct ftl_bdev_io *io[FTL_MAX_COMPLETIONS];
75
76 /* Completion ring */
77 struct spdk_ring *ring;
78
79 struct spdk_io_channel *ioch;
80 };
81
82 struct ftl_bdev_io {
83 struct ftl_bdev *bdev;
84
85 struct spdk_ring *ring;
86
87 int status;
88
89 struct spdk_thread *orig_thread;
90 };
91
92 struct ftl_deferred_init {
93 struct ftl_bdev_init_opts opts;
94
95 LIST_ENTRY(ftl_deferred_init) entry;
96 };
97
98 typedef void (*bdev_ftl_finish_fn)(void);
99
100 static LIST_HEAD(, ftl_bdev) g_ftl_bdevs = LIST_HEAD_INITIALIZER(g_ftl_bdevs);
101 static bdev_ftl_finish_fn g_finish_cb;
102 static size_t g_num_conf_bdevs;
103 static size_t g_num_init_bdevs;
104 static pthread_mutex_t g_ftl_bdev_lock;
105 static LIST_HEAD(, ftl_deferred_init) g_deferred_init;
106
107 static int bdev_ftl_initialize(void);
108 static void bdev_ftl_finish(void);
109 static void bdev_ftl_examine(struct spdk_bdev *);
110
111 static int
112 bdev_ftl_get_ctx_size(void)
113 {
114 return sizeof(struct ftl_bdev_io);
115 }
116
117 static struct spdk_bdev_module g_ftl_if = {
118 .name = "ftl",
119 .async_init = true,
120 .async_fini = true,
121 .module_init = bdev_ftl_initialize,
122 .module_fini = bdev_ftl_finish,
123 .examine_disk = bdev_ftl_examine,
124 .get_ctx_size = bdev_ftl_get_ctx_size,
125 };
126
127 SPDK_BDEV_MODULE_REGISTER(ftl, &g_ftl_if)
128
129 static struct nvme_bdev_ctrlr *
130 bdev_ftl_add_ctrlr(struct spdk_nvme_ctrlr *ctrlr, const struct spdk_nvme_transport_id *trid)
131 {
132 struct nvme_bdev_ctrlr *ftl_ctrlr = NULL;
133
134 pthread_mutex_lock(&g_bdev_nvme_mutex);
135
136 ftl_ctrlr = nvme_bdev_ctrlr_get(trid);
137 if (ftl_ctrlr) {
138 ftl_ctrlr->ref++;
139 } else {
140 ftl_ctrlr = calloc(1, sizeof(*ftl_ctrlr));
141 if (!ftl_ctrlr) {
142 goto out;
143 }
144
145 ftl_ctrlr->ctrlr = ctrlr;
146 ftl_ctrlr->trid = *trid;
147 ftl_ctrlr->ref = 1;
148
149 ftl_ctrlr->name = spdk_sprintf_alloc("NVMe_%s", trid->traddr);
150 if (!ftl_ctrlr->name) {
151 SPDK_ERRLOG("Unable to allocate memory for bdev controller name.\n");
152 free(ftl_ctrlr);
153 ftl_ctrlr = NULL;
154 goto out;
155 }
156
157 TAILQ_INSERT_HEAD(&g_nvme_bdev_ctrlrs, ftl_ctrlr, tailq);
158 }
159 out:
160 pthread_mutex_unlock(&g_bdev_nvme_mutex);
161 return ftl_ctrlr;
162 }
163
164 static void
165 bdev_ftl_remove_ctrlr(struct nvme_bdev_ctrlr *ctrlr)
166 {
167 pthread_mutex_lock(&g_bdev_nvme_mutex);
168
169 if (--ctrlr->ref == 0) {
170 if (spdk_nvme_detach(ctrlr->ctrlr)) {
171 SPDK_ERRLOG("Failed to detach the controller\n");
172 goto out;
173 }
174
175 TAILQ_REMOVE(&g_nvme_bdev_ctrlrs, ctrlr, tailq);
176 free(ctrlr->name);
177 free(ctrlr);
178 }
179 out:
180 pthread_mutex_unlock(&g_bdev_nvme_mutex);
181 }
182
183 static void
184 bdev_ftl_free_cb(void *ctx, int status)
185 {
186 struct ftl_bdev *ftl_bdev = ctx;
187 bool finish_done;
188
189 pthread_mutex_lock(&g_ftl_bdev_lock);
190 LIST_REMOVE(ftl_bdev, list_entry);
191 finish_done = LIST_EMPTY(&g_ftl_bdevs);
192 pthread_mutex_unlock(&g_ftl_bdev_lock);
193
194 spdk_io_device_unregister(ftl_bdev, NULL);
195
196 bdev_ftl_remove_ctrlr(ftl_bdev->ctrlr);
197
198 if (ftl_bdev->cache_bdev_desc) {
199 spdk_bdev_module_release_bdev(spdk_bdev_desc_get_bdev(ftl_bdev->cache_bdev_desc));
200 spdk_bdev_close(ftl_bdev->cache_bdev_desc);
201 }
202
203 spdk_bdev_destruct_done(&ftl_bdev->bdev, status);
204 free(ftl_bdev->bdev.name);
205 free(ftl_bdev);
206
207 if (finish_done && g_finish_cb) {
208 g_finish_cb();
209 }
210 }
211
212 static int
213 bdev_ftl_destruct(void *ctx)
214 {
215 struct ftl_bdev *ftl_bdev = ctx;
216 spdk_ftl_dev_free(ftl_bdev->dev, bdev_ftl_free_cb, ftl_bdev);
217
218 /* return 1 to indicate that the destruction is asynchronous */
219 return 1;
220 }
221
222 static void
223 bdev_ftl_complete_io(struct ftl_bdev_io *io, int rc)
224 {
225 enum spdk_bdev_io_status status;
226
227 switch (rc) {
228 case 0:
229 status = SPDK_BDEV_IO_STATUS_SUCCESS;
230 break;
231 case -ENOMEM:
232 status = SPDK_BDEV_IO_STATUS_NOMEM;
233 break;
234 default:
235 status = SPDK_BDEV_IO_STATUS_FAILED;
236 break;
237 }
238
239 spdk_bdev_io_complete(spdk_bdev_io_from_ctx(io), status);
240 }
241
242 static void
243 bdev_ftl_cb(void *arg, int status)
244 {
245 struct ftl_bdev_io *io = arg;
246 size_t cnt __attribute__((unused));
247
248 io->status = status;
249
250 cnt = spdk_ring_enqueue(io->ring, (void **)&io, 1, NULL);
251 assert(cnt == 1);
252 }
253
254 static int
255 bdev_ftl_fill_bio(struct ftl_bdev *ftl_bdev, struct spdk_io_channel *ch,
256 struct ftl_bdev_io *io)
257 {
258 struct ftl_io_channel *ioch = spdk_io_channel_get_ctx(ch);
259
260 memset(io, 0, sizeof(*io));
261
262 io->orig_thread = spdk_io_channel_get_thread(ch);
263 io->status = SPDK_BDEV_IO_STATUS_SUCCESS;
264 io->ring = ioch->ring;
265 io->bdev = ftl_bdev;
266 return 0;
267 }
268
269 static int
270 bdev_ftl_readv(struct ftl_bdev *ftl_bdev, struct spdk_io_channel *ch,
271 struct ftl_bdev_io *io)
272 {
273 struct spdk_bdev_io *bio;
274 struct ftl_io_channel *ioch = spdk_io_channel_get_ctx(ch);
275 int rc;
276
277 bio = spdk_bdev_io_from_ctx(io);
278
279 rc = bdev_ftl_fill_bio(ftl_bdev, ch, io);
280 if (rc) {
281 return rc;
282 }
283
284 return spdk_ftl_read(ftl_bdev->dev,
285 ioch->ioch,
286 bio->u.bdev.offset_blocks,
287 bio->u.bdev.num_blocks,
288 bio->u.bdev.iovs, bio->u.bdev.iovcnt, bdev_ftl_cb, io);
289 }
290
291 static int
292 bdev_ftl_writev(struct ftl_bdev *ftl_bdev, struct spdk_io_channel *ch,
293 struct ftl_bdev_io *io)
294 {
295 struct spdk_bdev_io *bio;
296 struct ftl_io_channel *ioch;
297 int rc;
298
299 bio = spdk_bdev_io_from_ctx(io);
300 ioch = spdk_io_channel_get_ctx(ch);
301
302 rc = bdev_ftl_fill_bio(ftl_bdev, ch, io);
303 if (rc) {
304 return rc;
305 }
306
307 return spdk_ftl_write(ftl_bdev->dev,
308 ioch->ioch,
309 bio->u.bdev.offset_blocks,
310 bio->u.bdev.num_blocks,
311 bio->u.bdev.iovs,
312 bio->u.bdev.iovcnt, bdev_ftl_cb, io);
313 }
314
315 static void
316 bdev_ftl_get_buf_cb(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io,
317 bool success)
318 {
319 if (!success) {
320 bdev_ftl_complete_io((struct ftl_bdev_io *)bdev_io->driver_ctx,
321 SPDK_BDEV_IO_STATUS_FAILED);
322 return;
323 }
324
325 int rc = bdev_ftl_readv((struct ftl_bdev *)bdev_io->bdev->ctxt,
326 ch, (struct ftl_bdev_io *)bdev_io->driver_ctx);
327
328 if (spdk_unlikely(rc != 0)) {
329 bdev_ftl_complete_io((struct ftl_bdev_io *)bdev_io->driver_ctx, rc);
330 }
331 }
332
333 static int
334 bdev_ftl_flush(struct ftl_bdev *ftl_bdev, struct spdk_io_channel *ch, struct ftl_bdev_io *io)
335 {
336 int rc;
337
338 rc = bdev_ftl_fill_bio(ftl_bdev, ch, io);
339 if (rc) {
340 return rc;
341 }
342
343 return spdk_ftl_flush(ftl_bdev->dev, bdev_ftl_cb, io);
344 }
345
346 static int
347 _bdev_ftl_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
348 {
349 struct ftl_bdev *ftl_bdev = (struct ftl_bdev *)bdev_io->bdev->ctxt;
350
351 switch (bdev_io->type) {
352 case SPDK_BDEV_IO_TYPE_READ:
353 spdk_bdev_io_get_buf(bdev_io, bdev_ftl_get_buf_cb,
354 bdev_io->u.bdev.num_blocks * bdev_io->bdev->blocklen);
355 return 0;
356
357 case SPDK_BDEV_IO_TYPE_WRITE:
358 return bdev_ftl_writev(ftl_bdev, ch, (struct ftl_bdev_io *)bdev_io->driver_ctx);
359
360 case SPDK_BDEV_IO_TYPE_FLUSH:
361 return bdev_ftl_flush(ftl_bdev, ch, (struct ftl_bdev_io *)bdev_io->driver_ctx);
362
363 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
364 case SPDK_BDEV_IO_TYPE_RESET:
365 case SPDK_BDEV_IO_TYPE_UNMAP:
366 default:
367 return -ENOTSUP;
368 break;
369 }
370 }
371
372 static void
373 bdev_ftl_submit_request(struct spdk_io_channel *ch, struct spdk_bdev_io *bdev_io)
374 {
375 int rc = _bdev_ftl_submit_request(ch, bdev_io);
376
377 if (spdk_unlikely(rc != 0)) {
378 bdev_ftl_complete_io((struct ftl_bdev_io *)bdev_io->driver_ctx, rc);
379 }
380 }
381
382 static bool
383 bdev_ftl_io_type_supported(void *ctx, enum spdk_bdev_io_type io_type)
384 {
385 switch (io_type) {
386 case SPDK_BDEV_IO_TYPE_READ:
387 case SPDK_BDEV_IO_TYPE_WRITE:
388 case SPDK_BDEV_IO_TYPE_FLUSH:
389 return true;
390 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
391 case SPDK_BDEV_IO_TYPE_RESET:
392 case SPDK_BDEV_IO_TYPE_UNMAP:
393 default:
394 return false;
395 }
396 }
397
398 static struct spdk_io_channel *
399 bdev_ftl_get_io_channel(void *ctx)
400 {
401 struct ftl_bdev *ftl_bdev = ctx;
402
403 return spdk_get_io_channel(ftl_bdev);
404 }
405
406 static void
407 _bdev_ftl_write_config_info(struct ftl_bdev *ftl_bdev, struct spdk_json_write_ctx *w)
408 {
409 struct spdk_ftl_attrs attrs;
410 const char *trtype_str, *cache_bdev;
411
412 spdk_ftl_dev_get_attrs(ftl_bdev->dev, &attrs);
413
414 trtype_str = spdk_nvme_transport_id_trtype_str(ftl_bdev->ctrlr->trid.trtype);
415 if (trtype_str) {
416 spdk_json_write_named_string(w, "trtype", trtype_str);
417 }
418
419 spdk_json_write_named_string(w, "traddr", ftl_bdev->ctrlr->trid.traddr);
420 spdk_json_write_named_string_fmt(w, "punits", "%d-%d", attrs.range.begin, attrs.range.end);
421
422 if (ftl_bdev->cache_bdev_desc) {
423 cache_bdev = spdk_bdev_get_name(spdk_bdev_desc_get_bdev(ftl_bdev->cache_bdev_desc));
424 spdk_json_write_named_string(w, "cache", cache_bdev);
425 }
426 }
427
428 static void
429 bdev_ftl_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w)
430 {
431 struct ftl_bdev *ftl_bdev = bdev->ctxt;
432 struct spdk_ftl_attrs attrs;
433 char uuid[SPDK_UUID_STRING_LEN];
434
435 spdk_ftl_dev_get_attrs(ftl_bdev->dev, &attrs);
436
437 spdk_json_write_object_begin(w);
438
439 spdk_json_write_named_string(w, "method", "construct_ftl_bdev");
440
441 spdk_json_write_named_object_begin(w, "params");
442 spdk_json_write_named_string(w, "name", ftl_bdev->bdev.name);
443
444 spdk_json_write_named_bool(w, "allow_open_bands", attrs.allow_open_bands);
445
446 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &attrs.uuid);
447 spdk_json_write_named_string(w, "uuid", uuid);
448
449 _bdev_ftl_write_config_info(ftl_bdev, w);
450
451 spdk_json_write_object_end(w);
452 spdk_json_write_object_end(w);
453 }
454
455 static int
456 bdev_ftl_dump_info_json(void *ctx, struct spdk_json_write_ctx *w)
457 {
458 struct ftl_bdev *ftl_bdev = ctx;
459 struct spdk_ftl_attrs attrs;
460
461 spdk_ftl_dev_get_attrs(ftl_bdev->dev, &attrs);
462
463 spdk_json_write_named_object_begin(w, "ftl");
464
465 _bdev_ftl_write_config_info(ftl_bdev, w);
466 spdk_json_write_named_string_fmt(w, "num_chunks", "%zu", attrs.num_chunks);
467 spdk_json_write_named_string_fmt(w, "chunk_size", "%zu", attrs.chunk_size);
468
469 /* ftl */
470 spdk_json_write_object_end(w);
471
472 return 0;
473 }
474
475 static const struct spdk_bdev_fn_table ftl_fn_table = {
476 .destruct = bdev_ftl_destruct,
477 .submit_request = bdev_ftl_submit_request,
478 .io_type_supported = bdev_ftl_io_type_supported,
479 .get_io_channel = bdev_ftl_get_io_channel,
480 .write_config_json = bdev_ftl_write_config_json,
481 .dump_info_json = bdev_ftl_dump_info_json,
482 };
483
484 int
485 bdev_ftl_parse_punits(struct spdk_ftl_punit_range *range, const char *range_string)
486 {
487 regex_t range_regex;
488 regmatch_t range_match;
489 unsigned long begin = 0, end = 0;
490 char *str_ptr;
491 int rc = -1;
492
493 if (regcomp(&range_regex, "\\b[[:digit:]]+-[[:digit:]]+\\b", REG_EXTENDED)) {
494 SPDK_ERRLOG("Regex init error\n");
495 return -1;
496 }
497
498 if (regexec(&range_regex, range_string, 1, &range_match, 0)) {
499 SPDK_WARNLOG("Invalid range\n");
500 goto out;
501 }
502
503 errno = 0;
504 begin = strtoul(range_string + range_match.rm_so, &str_ptr, 10);
505 if ((begin == ULONG_MAX && errno == ERANGE) || (begin == 0 && errno == EINVAL)) {
506 SPDK_WARNLOG("Invalid range '%s'\n", range_string);
507 goto out;
508 }
509
510 errno = 0;
511 /* +1 to skip the '-' delimiter */
512 end = strtoul(str_ptr + 1, NULL, 10);
513 if ((end == ULONG_MAX && errno == ERANGE) || (end == 0 && errno == EINVAL)) {
514 SPDK_WARNLOG("Invalid range '%s'\n", range_string);
515 goto out;
516 }
517
518 if (begin > UINT_MAX || end > UINT_MAX) {
519 SPDK_WARNLOG("Invalid range '%s'\n", range_string);
520 goto out;
521 }
522
523 if (begin > end) {
524 SPDK_WARNLOG("Invalid range '%s'\n", range_string);
525 goto out;
526 }
527
528 range->begin = (unsigned int)begin;
529 range->end = (unsigned int)end;
530
531 rc = 0;
532 out:
533 regfree(&range_regex);
534 return rc;
535 }
536
537 static int
538 bdev_ftl_defer_init(struct ftl_bdev_init_opts *opts)
539 {
540 struct ftl_deferred_init *init;
541
542 init = calloc(1, sizeof(*init));
543 if (!init) {
544 return -ENOMEM;
545 }
546
547 init->opts = *opts;
548 LIST_INSERT_HEAD(&g_deferred_init, init, entry);
549
550 return 0;
551 }
552
553 static int
554 bdev_ftl_read_bdev_config(struct spdk_conf_section *sp,
555 struct ftl_bdev_init_opts *opts,
556 size_t *num_bdevs)
557 {
558 const char *val, *trid;
559 int i, rc = 0, num_deferred = 0;
560
561 *num_bdevs = 0;
562
563 for (i = 0; i < FTL_MAX_BDEVS; i++, opts++) {
564 trid = val = spdk_conf_section_get_nmval(sp, "TransportID", i, 0);
565 if (!val) {
566 break;
567 }
568
569 rc = spdk_nvme_transport_id_parse(&opts->trid, val);
570 if (rc < 0) {
571 SPDK_ERRLOG("Unable to parse TransportID: %s\n", trid);
572 rc = -1;
573 break;
574 }
575
576 if (opts->trid.trtype != SPDK_NVME_TRANSPORT_PCIE) {
577 SPDK_ERRLOG("Unsupported transport type for TransportID: %s\n", trid);
578 continue;
579 }
580
581 val = spdk_conf_section_get_nmval(sp, "TransportID", i, 1);
582 if (!val) {
583 SPDK_ERRLOG("No name provided for TransportID: %s\n", trid);
584 rc = -1;
585 break;
586 }
587
588 opts->name = val;
589
590 val = spdk_conf_section_get_nmval(sp, "TransportID", i, 2);
591 if (!val) {
592 SPDK_ERRLOG("No punit range provided for TransportID: %s\n", trid);
593 rc = -1;
594 break;
595 }
596
597 if (bdev_ftl_parse_punits(&opts->range, val)) {
598 SPDK_ERRLOG("Invalid punit range for TransportID: %s\n", trid);
599 rc = -1;
600 break;
601 }
602
603 val = spdk_conf_section_get_nmval(sp, "TransportID", i, 3);
604 if (!val) {
605 SPDK_ERRLOG("No UUID provided for TransportID: %s\n", trid);
606 rc = -1;
607 break;
608 }
609
610 rc = spdk_uuid_parse(&opts->uuid, val);
611 if (rc < 0) {
612 SPDK_ERRLOG("Failed to parse uuid: %s for TransportID: %s\n", val, trid);
613 rc = -1;
614 break;
615 }
616
617 if (spdk_mem_all_zero(&opts->uuid, sizeof(opts->uuid))) {
618 opts->mode = SPDK_FTL_MODE_CREATE;
619 } else {
620 opts->mode = 0;
621 }
622
623 val = spdk_conf_section_get_nmval(sp, "TransportID", i, 4);
624 if (!val) {
625 continue;
626 }
627
628 opts->cache_bdev = val;
629 if (!spdk_bdev_get_by_name(val)) {
630 SPDK_INFOLOG(SPDK_LOG_BDEV_FTL, "Deferring bdev %s initialization\n", opts->name);
631
632 if (bdev_ftl_defer_init(opts)) {
633 SPDK_ERRLOG("Unable to initialize bdev %s\n", opts->name);
634 rc = -1;
635 break;
636 }
637
638 num_deferred++;
639 }
640 }
641
642 if (!rc) {
643 *num_bdevs = i - num_deferred;
644 }
645
646 return rc;
647 }
648
649 static int
650 bdev_ftl_poll(void *arg)
651 {
652 struct ftl_io_channel *ch = arg;
653 size_t cnt, i;
654
655 cnt = spdk_ring_dequeue(ch->ring, (void **)&ch->io, FTL_MAX_COMPLETIONS);
656
657 for (i = 0; i < cnt; ++i) {
658 bdev_ftl_complete_io(ch->io[i], ch->io[i]->status);
659 }
660
661 return cnt;
662 }
663
664 static int
665 bdev_ftl_io_channel_create_cb(void *io_device, void *ctx)
666 {
667 struct ftl_io_channel *ch = ctx;
668 struct ftl_bdev *ftl_bdev = (struct ftl_bdev *)io_device;
669
670 ch->dev = ftl_bdev->dev;
671 ch->ring = spdk_ring_create(SPDK_RING_TYPE_MP_SC, FTL_COMPLETION_RING_SIZE,
672 SPDK_ENV_SOCKET_ID_ANY);
673
674 if (!ch->ring) {
675 return -ENOMEM;
676 }
677
678 ch->poller = spdk_poller_register(bdev_ftl_poll, ch, 0);
679 if (!ch->poller) {
680 spdk_ring_free(ch->ring);
681 return -ENOMEM;
682 }
683
684 ch->ioch = spdk_get_io_channel(ftl_bdev->dev);
685
686 return 0;
687 }
688
689 static void
690 bdev_ftl_io_channel_destroy_cb(void *io_device, void *ctx_buf)
691 {
692 struct ftl_io_channel *ch = ctx_buf;
693
694 spdk_ring_free(ch->ring);
695 spdk_poller_unregister(&ch->poller);
696 spdk_put_io_channel(ch->ioch);
697 }
698
699 static void
700 bdev_ftl_cache_removed_cb(void *ctx)
701 {
702 assert(0 && "Removed cached bdev\n");
703 }
704
705 static void
706 bdev_ftl_create_cb(struct spdk_ftl_dev *dev, void *ctx, int status)
707 {
708 struct ftl_bdev *ftl_bdev = ctx;
709 struct ftl_bdev_info info = {};
710 struct spdk_ftl_attrs attrs;
711 ftl_bdev_init_fn init_cb = ftl_bdev->init_cb;
712 void *init_arg = ftl_bdev->init_arg;
713 int rc = -ENODEV;
714
715 if (status) {
716 SPDK_ERRLOG("Failed to create FTL device (%d)\n", status);
717 rc = status;
718 goto error_dev;
719 }
720
721 spdk_ftl_dev_get_attrs(dev, &attrs);
722
723 ftl_bdev->dev = dev;
724 ftl_bdev->bdev.product_name = "FTL disk";
725 ftl_bdev->bdev.write_cache = 0;
726 ftl_bdev->bdev.blocklen = attrs.lbk_size;
727 ftl_bdev->bdev.blockcnt = attrs.lbk_cnt;
728 /* TODO: Investigate why nbd test are failing without this alignment */
729 ftl_bdev->bdev.required_alignment = spdk_u32log2(attrs.lbk_size);
730 ftl_bdev->bdev.uuid = attrs.uuid;
731
732 SPDK_DEBUGLOG(SPDK_LOG_BDEV_FTL, "Creating bdev %s:\n", ftl_bdev->bdev.name);
733 SPDK_DEBUGLOG(SPDK_LOG_BDEV_FTL, "\tblock_len:\t%zu\n", attrs.lbk_size);
734 SPDK_DEBUGLOG(SPDK_LOG_BDEV_FTL, "\tblock_cnt:\t%"PRIu64"\n", attrs.lbk_cnt);
735 SPDK_DEBUGLOG(SPDK_LOG_BDEV_FTL, "\tpunits:\t\t%u-%u\n", attrs.range.begin,
736 attrs.range.end);
737
738 ftl_bdev->bdev.ctxt = ftl_bdev;
739 ftl_bdev->bdev.fn_table = &ftl_fn_table;
740 ftl_bdev->bdev.module = &g_ftl_if;
741
742 spdk_io_device_register(ftl_bdev, bdev_ftl_io_channel_create_cb,
743 bdev_ftl_io_channel_destroy_cb,
744 sizeof(struct ftl_io_channel),
745 ftl_bdev->bdev.name);
746
747 if (spdk_bdev_register(&ftl_bdev->bdev)) {
748 goto error_unregister;
749 }
750
751 info.name = ftl_bdev->bdev.name;
752 info.uuid = ftl_bdev->bdev.uuid;
753
754 pthread_mutex_lock(&g_ftl_bdev_lock);
755 LIST_INSERT_HEAD(&g_ftl_bdevs, ftl_bdev, list_entry);
756 pthread_mutex_unlock(&g_ftl_bdev_lock);
757
758 init_cb(&info, init_arg, 0);
759 return;
760
761 error_unregister:
762 spdk_io_device_unregister(ftl_bdev, NULL);
763 error_dev:
764 bdev_ftl_remove_ctrlr(ftl_bdev->ctrlr);
765
766 if (ftl_bdev->cache_bdev_desc) {
767 spdk_bdev_module_release_bdev(spdk_bdev_desc_get_bdev(ftl_bdev->cache_bdev_desc));
768 spdk_bdev_close(ftl_bdev->cache_bdev_desc);
769 }
770
771 free(ftl_bdev->bdev.name);
772 free(ftl_bdev);
773
774 init_cb(NULL, init_arg, rc);
775 }
776
777 static int
778 bdev_ftl_create(struct spdk_nvme_ctrlr *ctrlr, const struct ftl_bdev_init_opts *bdev_opts,
779 ftl_bdev_init_fn cb, void *cb_arg)
780 {
781 struct ftl_bdev *ftl_bdev = NULL;
782 struct spdk_bdev *cache_bdev = NULL;
783 struct nvme_bdev_ctrlr *ftl_ctrlr;
784 struct spdk_ftl_dev_init_opts opts = {};
785 struct spdk_ftl_conf conf = {};
786 int rc;
787
788 spdk_ftl_conf_init_defaults(&conf);
789
790 conf.allow_open_bands = bdev_opts->allow_open_bands;
791
792 ftl_ctrlr = bdev_ftl_add_ctrlr(ctrlr, &bdev_opts->trid);
793 if (!ftl_ctrlr) {
794 spdk_nvme_detach(ctrlr);
795 return -ENOMEM;
796 }
797
798 ftl_bdev = calloc(1, sizeof(*ftl_bdev));
799 if (!ftl_bdev) {
800 SPDK_ERRLOG("Could not allocate ftl_bdev\n");
801 rc = -ENOMEM;
802 goto error_ctrlr;
803 }
804
805 ftl_bdev->bdev.name = strdup(bdev_opts->name);
806 if (!ftl_bdev->bdev.name) {
807 rc = -ENOMEM;
808 goto error_ctrlr;
809 }
810
811 if (bdev_opts->cache_bdev) {
812 cache_bdev = spdk_bdev_get_by_name(bdev_opts->cache_bdev);
813 if (!cache_bdev) {
814 SPDK_ERRLOG("Unable to find bdev: %s\n", bdev_opts->cache_bdev);
815 rc = -ENOENT;
816 goto error_name;
817 }
818
819 if (spdk_bdev_open(cache_bdev, true, bdev_ftl_cache_removed_cb,
820 ftl_bdev, &ftl_bdev->cache_bdev_desc)) {
821 SPDK_ERRLOG("Unable to open cache bdev: %s\n", bdev_opts->cache_bdev);
822 rc = -EPERM;
823 goto error_name;
824 }
825
826 if (spdk_bdev_module_claim_bdev(cache_bdev, ftl_bdev->cache_bdev_desc, &g_ftl_if)) {
827 SPDK_ERRLOG("Unable to claim cache bdev %s\n", bdev_opts->cache_bdev);
828 spdk_bdev_close(ftl_bdev->cache_bdev_desc);
829 rc = -EPERM;
830 goto error_name;
831 }
832 }
833
834 ftl_bdev->ctrlr = ftl_ctrlr;
835 ftl_bdev->init_cb = cb;
836 ftl_bdev->init_arg = cb_arg;
837
838 opts.ctrlr = ctrlr;
839 opts.trid = bdev_opts->trid;
840 opts.range = bdev_opts->range;
841 opts.mode = bdev_opts->mode;
842 opts.uuid = bdev_opts->uuid;
843 opts.name = ftl_bdev->bdev.name;
844 opts.cache_bdev_desc = ftl_bdev->cache_bdev_desc;
845 opts.conf = &conf;
846
847 /* TODO: set threads based on config */
848 opts.core_thread = opts.read_thread = spdk_get_thread();
849
850 rc = spdk_ftl_dev_init(&opts, bdev_ftl_create_cb, ftl_bdev);
851 if (rc) {
852 SPDK_ERRLOG("Could not create FTL device\n");
853 goto error_cache;
854 }
855
856 return 0;
857
858 error_cache:
859 if (ftl_bdev->cache_bdev_desc) {
860 spdk_bdev_module_release_bdev(cache_bdev);
861 spdk_bdev_close(ftl_bdev->cache_bdev_desc);
862 }
863 error_name:
864 free(ftl_bdev->bdev.name);
865 error_ctrlr:
866 bdev_ftl_remove_ctrlr(ftl_ctrlr);
867 free(ftl_bdev);
868 return rc;
869 }
870
871 static void
872 bdev_ftl_bdev_init_done(void)
873 {
874 pthread_mutex_lock(&g_ftl_bdev_lock);
875
876 if (++g_num_init_bdevs != g_num_conf_bdevs) {
877 pthread_mutex_unlock(&g_ftl_bdev_lock);
878 return;
879 }
880
881 pthread_mutex_unlock(&g_ftl_bdev_lock);
882
883 spdk_bdev_module_init_done(&g_ftl_if);
884 }
885
886 static void
887 bdev_ftl_init_cb(const struct ftl_bdev_info *info, void *ctx, int status)
888 {
889 struct ftl_deferred_init *opts;
890
891 if (status) {
892 SPDK_ERRLOG("Failed to initialize FTL bdev\n");
893 }
894
895 LIST_FOREACH(opts, &g_deferred_init, entry) {
896 if (!strcmp(opts->opts.name, info->name)) {
897 spdk_bdev_module_examine_done(&g_ftl_if);
898 LIST_REMOVE(opts, entry);
899 free(opts);
900 break;
901 }
902 }
903
904 bdev_ftl_bdev_init_done();
905 }
906
907 static void
908 bdev_ftl_initialize_cb(void *ctx, int status)
909 {
910 struct spdk_conf_section *sp;
911 struct ftl_bdev_init_opts *opts = NULL;
912 struct ftl_deferred_init *defer_opts;
913 size_t i;
914
915 if (status) {
916 SPDK_ERRLOG("Failed to initialize FTL module\n");
917 goto out;
918 }
919
920 sp = spdk_conf_find_section(NULL, "Ftl");
921 if (!sp) {
922 goto out;
923 }
924
925 opts = calloc(FTL_MAX_BDEVS, sizeof(*opts));
926 if (!opts) {
927 SPDK_ERRLOG("Failed to allocate bdev init opts\n");
928 goto out;
929 }
930
931 if (bdev_ftl_read_bdev_config(sp, opts, &g_num_conf_bdevs)) {
932 goto out;
933 }
934
935 for (i = 0; i < g_num_conf_bdevs; ++i) {
936 bool defer_init = false;
937
938 LIST_FOREACH(defer_opts, &g_deferred_init, entry) {
939 if (!strcmp(defer_opts->opts.name, opts[i].name)) {
940 defer_init = true;
941 break;
942 }
943 }
944
945 if (!defer_init && bdev_ftl_init_bdev(&opts[i], bdev_ftl_init_cb, NULL)) {
946 SPDK_ERRLOG("Failed to create bdev '%s'\n", opts[i].name);
947 bdev_ftl_bdev_init_done();
948 }
949 }
950 out:
951 if (g_num_conf_bdevs == 0) {
952 spdk_bdev_module_init_done(&g_ftl_if);
953 }
954
955 free(opts);
956 }
957
958 static int
959 bdev_ftl_initialize(void)
960 {
961 struct ftl_module_init_opts ftl_opts = {};
962 pthread_mutexattr_t attr;
963 int rc = 0;
964
965 if (pthread_mutexattr_init(&attr)) {
966 SPDK_ERRLOG("Mutex initialization failed\n");
967 return -1;
968 }
969
970 if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)) {
971 SPDK_ERRLOG("Mutex initialization failed\n");
972 rc = -1;
973 goto error;
974 }
975
976 if (pthread_mutex_init(&g_ftl_bdev_lock, &attr)) {
977 SPDK_ERRLOG("Mutex initialization failed\n");
978 rc = -1;
979 goto error;
980 }
981
982 /* TODO: retrieve this from config */
983 ftl_opts.anm_thread = spdk_get_thread();
984 rc = spdk_ftl_module_init(&ftl_opts, bdev_ftl_initialize_cb, NULL);
985
986 if (rc) {
987 bdev_ftl_initialize_cb(NULL, rc);
988
989 }
990 error:
991 pthread_mutexattr_destroy(&attr);
992 return rc;
993 }
994
995 int
996 bdev_ftl_init_bdev(struct ftl_bdev_init_opts *opts, ftl_bdev_init_fn cb, void *cb_arg)
997 {
998 struct nvme_bdev_ctrlr *ftl_ctrlr;
999 struct spdk_nvme_ctrlr *ctrlr;
1000
1001 assert(opts != NULL);
1002 assert(cb != NULL);
1003
1004 pthread_mutex_lock(&g_bdev_nvme_mutex);
1005
1006 /* Check already attached controllers first */
1007 TAILQ_FOREACH(ftl_ctrlr, &g_nvme_bdev_ctrlrs, tailq) {
1008 if (!spdk_nvme_transport_id_compare(&ftl_ctrlr->trid, &opts->trid)) {
1009 pthread_mutex_unlock(&g_bdev_nvme_mutex);
1010 return bdev_ftl_create(ftl_ctrlr->ctrlr, opts, cb, cb_arg);
1011 }
1012 }
1013
1014 pthread_mutex_unlock(&g_bdev_nvme_mutex);
1015
1016 ctrlr = spdk_nvme_connect(&opts->trid, NULL, 0);
1017 if (!ctrlr) {
1018 return -ENODEV;
1019 }
1020
1021 if (!spdk_nvme_ctrlr_is_ocssd_supported(ctrlr)) {
1022 spdk_nvme_detach(ctrlr);
1023 return -EPERM;
1024 }
1025
1026 return bdev_ftl_create(ctrlr, opts, cb, cb_arg);
1027 }
1028
1029 static void
1030 bdev_ftl_examine(struct spdk_bdev *bdev)
1031 {
1032 struct ftl_deferred_init *opts;
1033
1034 LIST_FOREACH(opts, &g_deferred_init, entry) {
1035 if (spdk_bdev_get_by_name(opts->opts.cache_bdev) == bdev) {
1036 if (bdev_ftl_init_bdev(&opts->opts, bdev_ftl_init_cb, NULL)) {
1037 SPDK_ERRLOG("Unable to initialize bdev '%s'\n", opts->opts.name);
1038 LIST_REMOVE(opts, entry);
1039 free(opts);
1040 break;
1041 }
1042
1043 /* spdk_bdev_module_examine_done will be called by bdev_ftl_init_cb */
1044 return;
1045 }
1046 }
1047
1048 spdk_bdev_module_examine_done(&g_ftl_if);
1049 }
1050
1051 void
1052 bdev_ftl_delete_bdev(const char *name, spdk_bdev_unregister_cb cb_fn, void *cb_arg)
1053 {
1054 struct ftl_bdev *ftl_bdev, *tmp;
1055
1056 pthread_mutex_lock(&g_ftl_bdev_lock);
1057
1058 LIST_FOREACH_SAFE(ftl_bdev, &g_ftl_bdevs, list_entry, tmp) {
1059 if (strcmp(ftl_bdev->bdev.name, name) == 0) {
1060 pthread_mutex_unlock(&g_ftl_bdev_lock);
1061 spdk_bdev_unregister(&ftl_bdev->bdev, cb_fn, cb_arg);
1062 return;
1063 }
1064 }
1065
1066 pthread_mutex_unlock(&g_ftl_bdev_lock);
1067 cb_fn(cb_arg, -ENODEV);
1068 }
1069
1070 static void
1071 bdev_ftl_ftl_module_fini_cb(void *ctx, int status)
1072 {
1073 if (status) {
1074 SPDK_ERRLOG("Failed to deinitialize FTL module\n");
1075 assert(0);
1076 }
1077
1078 spdk_bdev_module_finish_done();
1079 }
1080
1081 static void
1082 bdev_ftl_finish_cb(void)
1083 {
1084 if (spdk_ftl_module_fini(bdev_ftl_ftl_module_fini_cb, NULL)) {
1085 SPDK_ERRLOG("Failed to deinitialize FTL module\n");
1086 assert(0);
1087 }
1088 }
1089
1090 static void
1091 bdev_ftl_finish(void)
1092 {
1093 pthread_mutex_lock(&g_ftl_bdev_lock);
1094
1095 if (LIST_EMPTY(&g_ftl_bdevs)) {
1096 pthread_mutex_unlock(&g_ftl_bdev_lock);
1097 bdev_ftl_finish_cb();
1098 return;
1099 }
1100
1101 g_finish_cb = bdev_ftl_finish_cb;
1102 pthread_mutex_unlock(&g_ftl_bdev_lock);
1103 }
1104
1105 SPDK_LOG_REGISTER_COMPONENT("bdev_ftl", SPDK_LOG_BDEV_FTL)