4 * Copyright (c) Intel Corporation.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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
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.
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.
34 #include "spdk/stdinc.h"
35 #include "spdk/bdev.h"
36 #include "spdk/conf.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"
45 #include "spdk_internal/log.h"
50 #define FTL_COMPLETION_RING_SIZE 4096
53 struct spdk_bdev bdev
;
55 struct nvme_bdev_ctrlr
*ctrlr
;
57 struct spdk_ftl_dev
*dev
;
59 struct spdk_bdev_desc
*cache_bdev_desc
;
61 ftl_bdev_init_fn init_cb
;
65 LIST_ENTRY(ftl_bdev
) list_entry
;
68 struct ftl_io_channel
{
69 struct spdk_ftl_dev
*dev
;
71 struct spdk_poller
*poller
;
73 #define FTL_MAX_COMPLETIONS 64
74 struct ftl_bdev_io
*io
[FTL_MAX_COMPLETIONS
];
77 struct spdk_ring
*ring
;
79 struct spdk_io_channel
*ioch
;
83 struct ftl_bdev
*bdev
;
85 struct spdk_ring
*ring
;
89 struct spdk_thread
*orig_thread
;
92 struct ftl_deferred_init
{
93 struct ftl_bdev_init_opts opts
;
95 LIST_ENTRY(ftl_deferred_init
) entry
;
98 typedef void (*bdev_ftl_finish_fn
)(void);
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
;
107 static int bdev_ftl_initialize(void);
108 static void bdev_ftl_finish(void);
109 static void bdev_ftl_examine(struct spdk_bdev
*);
112 bdev_ftl_get_ctx_size(void)
114 return sizeof(struct ftl_bdev_io
);
117 static struct spdk_bdev_module g_ftl_if
= {
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
,
127 SPDK_BDEV_MODULE_REGISTER(ftl
, &g_ftl_if
)
129 static struct nvme_bdev_ctrlr
*
130 bdev_ftl_add_ctrlr(struct spdk_nvme_ctrlr
*ctrlr
, const struct spdk_nvme_transport_id
*trid
)
132 struct nvme_bdev_ctrlr
*ftl_ctrlr
= NULL
;
134 pthread_mutex_lock(&g_bdev_nvme_mutex
);
136 ftl_ctrlr
= nvme_bdev_ctrlr_get(trid
);
140 ftl_ctrlr
= calloc(1, sizeof(*ftl_ctrlr
));
145 ftl_ctrlr
->ctrlr
= ctrlr
;
146 ftl_ctrlr
->trid
= *trid
;
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");
157 TAILQ_INSERT_HEAD(&g_nvme_bdev_ctrlrs
, ftl_ctrlr
, tailq
);
160 pthread_mutex_unlock(&g_bdev_nvme_mutex
);
165 bdev_ftl_remove_ctrlr(struct nvme_bdev_ctrlr
*ctrlr
)
167 pthread_mutex_lock(&g_bdev_nvme_mutex
);
169 if (--ctrlr
->ref
== 0) {
170 if (spdk_nvme_detach(ctrlr
->ctrlr
)) {
171 SPDK_ERRLOG("Failed to detach the controller\n");
175 TAILQ_REMOVE(&g_nvme_bdev_ctrlrs
, ctrlr
, tailq
);
180 pthread_mutex_unlock(&g_bdev_nvme_mutex
);
184 bdev_ftl_free_cb(void *ctx
, int status
)
186 struct ftl_bdev
*ftl_bdev
= ctx
;
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
);
194 spdk_io_device_unregister(ftl_bdev
, NULL
);
196 bdev_ftl_remove_ctrlr(ftl_bdev
->ctrlr
);
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
);
203 spdk_bdev_destruct_done(&ftl_bdev
->bdev
, status
);
204 free(ftl_bdev
->bdev
.name
);
207 if (finish_done
&& g_finish_cb
) {
213 bdev_ftl_destruct(void *ctx
)
215 struct ftl_bdev
*ftl_bdev
= ctx
;
216 spdk_ftl_dev_free(ftl_bdev
->dev
, bdev_ftl_free_cb
, ftl_bdev
);
218 /* return 1 to indicate that the destruction is asynchronous */
223 bdev_ftl_complete_io(struct ftl_bdev_io
*io
, int rc
)
225 enum spdk_bdev_io_status status
;
229 status
= SPDK_BDEV_IO_STATUS_SUCCESS
;
232 status
= SPDK_BDEV_IO_STATUS_NOMEM
;
235 status
= SPDK_BDEV_IO_STATUS_FAILED
;
239 spdk_bdev_io_complete(spdk_bdev_io_from_ctx(io
), status
);
243 bdev_ftl_cb(void *arg
, int status
)
245 struct ftl_bdev_io
*io
= arg
;
246 size_t cnt
__attribute__((unused
));
250 cnt
= spdk_ring_enqueue(io
->ring
, (void **)&io
, 1, NULL
);
255 bdev_ftl_fill_bio(struct ftl_bdev
*ftl_bdev
, struct spdk_io_channel
*ch
,
256 struct ftl_bdev_io
*io
)
258 struct ftl_io_channel
*ioch
= spdk_io_channel_get_ctx(ch
);
260 memset(io
, 0, sizeof(*io
));
262 io
->orig_thread
= spdk_io_channel_get_thread(ch
);
263 io
->status
= SPDK_BDEV_IO_STATUS_SUCCESS
;
264 io
->ring
= ioch
->ring
;
270 bdev_ftl_readv(struct ftl_bdev
*ftl_bdev
, struct spdk_io_channel
*ch
,
271 struct ftl_bdev_io
*io
)
273 struct spdk_bdev_io
*bio
;
274 struct ftl_io_channel
*ioch
= spdk_io_channel_get_ctx(ch
);
277 bio
= spdk_bdev_io_from_ctx(io
);
279 rc
= bdev_ftl_fill_bio(ftl_bdev
, ch
, io
);
284 return spdk_ftl_read(ftl_bdev
->dev
,
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
);
292 bdev_ftl_writev(struct ftl_bdev
*ftl_bdev
, struct spdk_io_channel
*ch
,
293 struct ftl_bdev_io
*io
)
295 struct spdk_bdev_io
*bio
;
296 struct ftl_io_channel
*ioch
;
299 bio
= spdk_bdev_io_from_ctx(io
);
300 ioch
= spdk_io_channel_get_ctx(ch
);
302 rc
= bdev_ftl_fill_bio(ftl_bdev
, ch
, io
);
307 return spdk_ftl_write(ftl_bdev
->dev
,
309 bio
->u
.bdev
.offset_blocks
,
310 bio
->u
.bdev
.num_blocks
,
312 bio
->u
.bdev
.iovcnt
, bdev_ftl_cb
, io
);
316 bdev_ftl_get_buf_cb(struct spdk_io_channel
*ch
, struct spdk_bdev_io
*bdev_io
,
320 bdev_ftl_complete_io((struct ftl_bdev_io
*)bdev_io
->driver_ctx
,
321 SPDK_BDEV_IO_STATUS_FAILED
);
325 int rc
= bdev_ftl_readv((struct ftl_bdev
*)bdev_io
->bdev
->ctxt
,
326 ch
, (struct ftl_bdev_io
*)bdev_io
->driver_ctx
);
328 if (spdk_unlikely(rc
!= 0)) {
329 bdev_ftl_complete_io((struct ftl_bdev_io
*)bdev_io
->driver_ctx
, rc
);
334 bdev_ftl_flush(struct ftl_bdev
*ftl_bdev
, struct spdk_io_channel
*ch
, struct ftl_bdev_io
*io
)
338 rc
= bdev_ftl_fill_bio(ftl_bdev
, ch
, io
);
343 return spdk_ftl_flush(ftl_bdev
->dev
, bdev_ftl_cb
, io
);
347 _bdev_ftl_submit_request(struct spdk_io_channel
*ch
, struct spdk_bdev_io
*bdev_io
)
349 struct ftl_bdev
*ftl_bdev
= (struct ftl_bdev
*)bdev_io
->bdev
->ctxt
;
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
);
357 case SPDK_BDEV_IO_TYPE_WRITE
:
358 return bdev_ftl_writev(ftl_bdev
, ch
, (struct ftl_bdev_io
*)bdev_io
->driver_ctx
);
360 case SPDK_BDEV_IO_TYPE_FLUSH
:
361 return bdev_ftl_flush(ftl_bdev
, ch
, (struct ftl_bdev_io
*)bdev_io
->driver_ctx
);
363 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES
:
364 case SPDK_BDEV_IO_TYPE_RESET
:
365 case SPDK_BDEV_IO_TYPE_UNMAP
:
373 bdev_ftl_submit_request(struct spdk_io_channel
*ch
, struct spdk_bdev_io
*bdev_io
)
375 int rc
= _bdev_ftl_submit_request(ch
, bdev_io
);
377 if (spdk_unlikely(rc
!= 0)) {
378 bdev_ftl_complete_io((struct ftl_bdev_io
*)bdev_io
->driver_ctx
, rc
);
383 bdev_ftl_io_type_supported(void *ctx
, enum spdk_bdev_io_type io_type
)
386 case SPDK_BDEV_IO_TYPE_READ
:
387 case SPDK_BDEV_IO_TYPE_WRITE
:
388 case SPDK_BDEV_IO_TYPE_FLUSH
:
390 case SPDK_BDEV_IO_TYPE_WRITE_ZEROES
:
391 case SPDK_BDEV_IO_TYPE_RESET
:
392 case SPDK_BDEV_IO_TYPE_UNMAP
:
398 static struct spdk_io_channel
*
399 bdev_ftl_get_io_channel(void *ctx
)
401 struct ftl_bdev
*ftl_bdev
= ctx
;
403 return spdk_get_io_channel(ftl_bdev
);
407 _bdev_ftl_write_config_info(struct ftl_bdev
*ftl_bdev
, struct spdk_json_write_ctx
*w
)
409 struct spdk_ftl_attrs attrs
;
410 const char *trtype_str
, *cache_bdev
;
412 spdk_ftl_dev_get_attrs(ftl_bdev
->dev
, &attrs
);
414 trtype_str
= spdk_nvme_transport_id_trtype_str(ftl_bdev
->ctrlr
->trid
.trtype
);
416 spdk_json_write_named_string(w
, "trtype", trtype_str
);
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
);
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
);
429 bdev_ftl_write_config_json(struct spdk_bdev
*bdev
, struct spdk_json_write_ctx
*w
)
431 struct ftl_bdev
*ftl_bdev
= bdev
->ctxt
;
432 struct spdk_ftl_attrs attrs
;
433 char uuid
[SPDK_UUID_STRING_LEN
];
435 spdk_ftl_dev_get_attrs(ftl_bdev
->dev
, &attrs
);
437 spdk_json_write_object_begin(w
);
439 spdk_json_write_named_string(w
, "method", "construct_ftl_bdev");
441 spdk_json_write_named_object_begin(w
, "params");
442 spdk_json_write_named_string(w
, "name", ftl_bdev
->bdev
.name
);
444 spdk_json_write_named_bool(w
, "allow_open_bands", attrs
.allow_open_bands
);
446 spdk_uuid_fmt_lower(uuid
, sizeof(uuid
), &attrs
.uuid
);
447 spdk_json_write_named_string(w
, "uuid", uuid
);
449 _bdev_ftl_write_config_info(ftl_bdev
, w
);
451 spdk_json_write_object_end(w
);
452 spdk_json_write_object_end(w
);
456 bdev_ftl_dump_info_json(void *ctx
, struct spdk_json_write_ctx
*w
)
458 struct ftl_bdev
*ftl_bdev
= ctx
;
459 struct spdk_ftl_attrs attrs
;
461 spdk_ftl_dev_get_attrs(ftl_bdev
->dev
, &attrs
);
463 spdk_json_write_named_object_begin(w
, "ftl");
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
);
470 spdk_json_write_object_end(w
);
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
,
485 bdev_ftl_parse_punits(struct spdk_ftl_punit_range
*range
, const char *range_string
)
488 regmatch_t range_match
;
489 unsigned long begin
= 0, end
= 0;
493 if (regcomp(&range_regex
, "\\b[[:digit:]]+-[[:digit:]]+\\b", REG_EXTENDED
)) {
494 SPDK_ERRLOG("Regex init error\n");
498 if (regexec(&range_regex
, range_string
, 1, &range_match
, 0)) {
499 SPDK_WARNLOG("Invalid range\n");
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
);
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
);
518 if (begin
> UINT_MAX
|| end
> UINT_MAX
) {
519 SPDK_WARNLOG("Invalid range '%s'\n", range_string
);
524 SPDK_WARNLOG("Invalid range '%s'\n", range_string
);
528 range
->begin
= (unsigned int)begin
;
529 range
->end
= (unsigned int)end
;
533 regfree(&range_regex
);
538 bdev_ftl_defer_init(struct ftl_bdev_init_opts
*opts
)
540 struct ftl_deferred_init
*init
;
542 init
= calloc(1, sizeof(*init
));
548 LIST_INSERT_HEAD(&g_deferred_init
, init
, entry
);
554 bdev_ftl_read_bdev_config(struct spdk_conf_section
*sp
,
555 struct ftl_bdev_init_opts
*opts
,
558 const char *val
, *trid
;
559 int i
, rc
= 0, num_deferred
= 0;
563 for (i
= 0; i
< FTL_MAX_BDEVS
; i
++, opts
++) {
564 trid
= val
= spdk_conf_section_get_nmval(sp
, "TransportID", i
, 0);
569 rc
= spdk_nvme_transport_id_parse(&opts
->trid
, val
);
571 SPDK_ERRLOG("Unable to parse TransportID: %s\n", trid
);
576 if (opts
->trid
.trtype
!= SPDK_NVME_TRANSPORT_PCIE
) {
577 SPDK_ERRLOG("Unsupported transport type for TransportID: %s\n", trid
);
581 val
= spdk_conf_section_get_nmval(sp
, "TransportID", i
, 1);
583 SPDK_ERRLOG("No name provided for TransportID: %s\n", trid
);
590 val
= spdk_conf_section_get_nmval(sp
, "TransportID", i
, 2);
592 SPDK_ERRLOG("No punit range provided for TransportID: %s\n", trid
);
597 if (bdev_ftl_parse_punits(&opts
->range
, val
)) {
598 SPDK_ERRLOG("Invalid punit range for TransportID: %s\n", trid
);
603 val
= spdk_conf_section_get_nmval(sp
, "TransportID", i
, 3);
605 SPDK_ERRLOG("No UUID provided for TransportID: %s\n", trid
);
610 rc
= spdk_uuid_parse(&opts
->uuid
, val
);
612 SPDK_ERRLOG("Failed to parse uuid: %s for TransportID: %s\n", val
, trid
);
617 if (spdk_mem_all_zero(&opts
->uuid
, sizeof(opts
->uuid
))) {
618 opts
->mode
= SPDK_FTL_MODE_CREATE
;
623 val
= spdk_conf_section_get_nmval(sp
, "TransportID", i
, 4);
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
);
632 if (bdev_ftl_defer_init(opts
)) {
633 SPDK_ERRLOG("Unable to initialize bdev %s\n", opts
->name
);
643 *num_bdevs
= i
- num_deferred
;
650 bdev_ftl_poll(void *arg
)
652 struct ftl_io_channel
*ch
= arg
;
655 cnt
= spdk_ring_dequeue(ch
->ring
, (void **)&ch
->io
, FTL_MAX_COMPLETIONS
);
657 for (i
= 0; i
< cnt
; ++i
) {
658 bdev_ftl_complete_io(ch
->io
[i
], ch
->io
[i
]->status
);
665 bdev_ftl_io_channel_create_cb(void *io_device
, void *ctx
)
667 struct ftl_io_channel
*ch
= ctx
;
668 struct ftl_bdev
*ftl_bdev
= (struct ftl_bdev
*)io_device
;
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
);
678 ch
->poller
= spdk_poller_register(bdev_ftl_poll
, ch
, 0);
680 spdk_ring_free(ch
->ring
);
684 ch
->ioch
= spdk_get_io_channel(ftl_bdev
->dev
);
690 bdev_ftl_io_channel_destroy_cb(void *io_device
, void *ctx_buf
)
692 struct ftl_io_channel
*ch
= ctx_buf
;
694 spdk_ring_free(ch
->ring
);
695 spdk_poller_unregister(&ch
->poller
);
696 spdk_put_io_channel(ch
->ioch
);
700 bdev_ftl_cache_removed_cb(void *ctx
)
702 assert(0 && "Removed cached bdev\n");
706 bdev_ftl_create_cb(struct spdk_ftl_dev
*dev
, void *ctx
, int status
)
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
;
716 SPDK_ERRLOG("Failed to create FTL device (%d)\n", status
);
721 spdk_ftl_dev_get_attrs(dev
, &attrs
);
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
;
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
,
738 ftl_bdev
->bdev
.ctxt
= ftl_bdev
;
739 ftl_bdev
->bdev
.fn_table
= &ftl_fn_table
;
740 ftl_bdev
->bdev
.module
= &g_ftl_if
;
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
);
747 if (spdk_bdev_register(&ftl_bdev
->bdev
)) {
748 goto error_unregister
;
751 info
.name
= ftl_bdev
->bdev
.name
;
752 info
.uuid
= ftl_bdev
->bdev
.uuid
;
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
);
758 init_cb(&info
, init_arg
, 0);
762 spdk_io_device_unregister(ftl_bdev
, NULL
);
764 bdev_ftl_remove_ctrlr(ftl_bdev
->ctrlr
);
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
);
771 free(ftl_bdev
->bdev
.name
);
774 init_cb(NULL
, init_arg
, rc
);
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
)
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
= {};
788 spdk_ftl_conf_init_defaults(&conf
);
790 conf
.allow_open_bands
= bdev_opts
->allow_open_bands
;
792 ftl_ctrlr
= bdev_ftl_add_ctrlr(ctrlr
, &bdev_opts
->trid
);
794 spdk_nvme_detach(ctrlr
);
798 ftl_bdev
= calloc(1, sizeof(*ftl_bdev
));
800 SPDK_ERRLOG("Could not allocate ftl_bdev\n");
805 ftl_bdev
->bdev
.name
= strdup(bdev_opts
->name
);
806 if (!ftl_bdev
->bdev
.name
) {
811 if (bdev_opts
->cache_bdev
) {
812 cache_bdev
= spdk_bdev_get_by_name(bdev_opts
->cache_bdev
);
814 SPDK_ERRLOG("Unable to find bdev: %s\n", bdev_opts
->cache_bdev
);
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
);
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
);
834 ftl_bdev
->ctrlr
= ftl_ctrlr
;
835 ftl_bdev
->init_cb
= cb
;
836 ftl_bdev
->init_arg
= cb_arg
;
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
;
847 /* TODO: set threads based on config */
848 opts
.core_thread
= opts
.read_thread
= spdk_get_thread();
850 rc
= spdk_ftl_dev_init(&opts
, bdev_ftl_create_cb
, ftl_bdev
);
852 SPDK_ERRLOG("Could not create FTL device\n");
859 if (ftl_bdev
->cache_bdev_desc
) {
860 spdk_bdev_module_release_bdev(cache_bdev
);
861 spdk_bdev_close(ftl_bdev
->cache_bdev_desc
);
864 free(ftl_bdev
->bdev
.name
);
866 bdev_ftl_remove_ctrlr(ftl_ctrlr
);
872 bdev_ftl_bdev_init_done(void)
874 pthread_mutex_lock(&g_ftl_bdev_lock
);
876 if (++g_num_init_bdevs
!= g_num_conf_bdevs
) {
877 pthread_mutex_unlock(&g_ftl_bdev_lock
);
881 pthread_mutex_unlock(&g_ftl_bdev_lock
);
883 spdk_bdev_module_init_done(&g_ftl_if
);
887 bdev_ftl_init_cb(const struct ftl_bdev_info
*info
, void *ctx
, int status
)
889 struct ftl_deferred_init
*opts
;
892 SPDK_ERRLOG("Failed to initialize FTL bdev\n");
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
);
904 bdev_ftl_bdev_init_done();
908 bdev_ftl_initialize_cb(void *ctx
, int status
)
910 struct spdk_conf_section
*sp
;
911 struct ftl_bdev_init_opts
*opts
= NULL
;
912 struct ftl_deferred_init
*defer_opts
;
916 SPDK_ERRLOG("Failed to initialize FTL module\n");
920 sp
= spdk_conf_find_section(NULL
, "Ftl");
925 opts
= calloc(FTL_MAX_BDEVS
, sizeof(*opts
));
927 SPDK_ERRLOG("Failed to allocate bdev init opts\n");
931 if (bdev_ftl_read_bdev_config(sp
, opts
, &g_num_conf_bdevs
)) {
935 for (i
= 0; i
< g_num_conf_bdevs
; ++i
) {
936 bool defer_init
= false;
938 LIST_FOREACH(defer_opts
, &g_deferred_init
, entry
) {
939 if (!strcmp(defer_opts
->opts
.name
, opts
[i
].name
)) {
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();
951 if (g_num_conf_bdevs
== 0) {
952 spdk_bdev_module_init_done(&g_ftl_if
);
959 bdev_ftl_initialize(void)
961 struct ftl_module_init_opts ftl_opts
= {};
962 pthread_mutexattr_t attr
;
965 if (pthread_mutexattr_init(&attr
)) {
966 SPDK_ERRLOG("Mutex initialization failed\n");
970 if (pthread_mutexattr_settype(&attr
, PTHREAD_MUTEX_RECURSIVE
)) {
971 SPDK_ERRLOG("Mutex initialization failed\n");
976 if (pthread_mutex_init(&g_ftl_bdev_lock
, &attr
)) {
977 SPDK_ERRLOG("Mutex initialization failed\n");
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
);
987 bdev_ftl_initialize_cb(NULL
, rc
);
991 pthread_mutexattr_destroy(&attr
);
996 bdev_ftl_init_bdev(struct ftl_bdev_init_opts
*opts
, ftl_bdev_init_fn cb
, void *cb_arg
)
998 struct nvme_bdev_ctrlr
*ftl_ctrlr
;
999 struct spdk_nvme_ctrlr
*ctrlr
;
1001 assert(opts
!= NULL
);
1004 pthread_mutex_lock(&g_bdev_nvme_mutex
);
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
);
1014 pthread_mutex_unlock(&g_bdev_nvme_mutex
);
1016 ctrlr
= spdk_nvme_connect(&opts
->trid
, NULL
, 0);
1021 if (!spdk_nvme_ctrlr_is_ocssd_supported(ctrlr
)) {
1022 spdk_nvme_detach(ctrlr
);
1026 return bdev_ftl_create(ctrlr
, opts
, cb
, cb_arg
);
1030 bdev_ftl_examine(struct spdk_bdev
*bdev
)
1032 struct ftl_deferred_init
*opts
;
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
);
1043 /* spdk_bdev_module_examine_done will be called by bdev_ftl_init_cb */
1048 spdk_bdev_module_examine_done(&g_ftl_if
);
1052 bdev_ftl_delete_bdev(const char *name
, spdk_bdev_unregister_cb cb_fn
, void *cb_arg
)
1054 struct ftl_bdev
*ftl_bdev
, *tmp
;
1056 pthread_mutex_lock(&g_ftl_bdev_lock
);
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
);
1066 pthread_mutex_unlock(&g_ftl_bdev_lock
);
1067 cb_fn(cb_arg
, -ENODEV
);
1071 bdev_ftl_ftl_module_fini_cb(void *ctx
, int status
)
1074 SPDK_ERRLOG("Failed to deinitialize FTL module\n");
1078 spdk_bdev_module_finish_done();
1082 bdev_ftl_finish_cb(void)
1084 if (spdk_ftl_module_fini(bdev_ftl_ftl_module_fini_cb
, NULL
)) {
1085 SPDK_ERRLOG("Failed to deinitialize FTL module\n");
1091 bdev_ftl_finish(void)
1093 pthread_mutex_lock(&g_ftl_bdev_lock
);
1095 if (LIST_EMPTY(&g_ftl_bdevs
)) {
1096 pthread_mutex_unlock(&g_ftl_bdev_lock
);
1097 bdev_ftl_finish_cb();
1101 g_finish_cb
= bdev_ftl_finish_cb
;
1102 pthread_mutex_unlock(&g_ftl_bdev_lock
);
1105 SPDK_LOG_REGISTER_COMPONENT("bdev_ftl", SPDK_LOG_BDEV_FTL
)