Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright 2023 Solidigm All Rights Reserved
3 : : */
4 : :
5 : : #include "ftl_nvc_dev.h"
6 : : #include "ftl_core.h"
7 : : #include "ftl_layout.h"
8 : : #include "utils/ftl_layout_tracker_bdev.h"
9 : : #include "mngt/ftl_mngt.h"
10 : : #include "ftl_nvc_bdev_common.h"
11 : :
12 : : static bool
13 : 27 : is_bdev_compatible(struct spdk_ftl_dev *dev, struct spdk_bdev *bdev)
14 : : {
15 [ - + ]: 27 : if (!spdk_bdev_is_md_separate(bdev)) {
16 : : /* It doesn't support separate metadata buffer IO */
17 : 0 : return false;
18 : : }
19 : :
20 [ - + ]: 27 : if (spdk_bdev_get_md_size(bdev) != sizeof(union ftl_md_vss)) {
21 : : /* Bdev's metadata is invalid size */
22 : 0 : return false;
23 : : }
24 : :
25 [ - + ]: 27 : if (spdk_bdev_get_dif_type(bdev) != SPDK_DIF_DISABLE) {
26 : : /* Unsupported DIF type used by bdev */
27 : 0 : return false;
28 : : }
29 : :
30 [ - + ]: 27 : if (ftl_md_xfer_blocks(dev) * spdk_bdev_get_md_size(bdev) > FTL_ZERO_BUFFER_SIZE) {
31 [ # # # # : 0 : FTL_ERRLOG(dev, "Zero buffer too small for bdev %s metadata transfer\n",
# # # # ]
32 : : spdk_bdev_get_name(bdev));
33 : 0 : return false;
34 : : }
35 : :
36 : 27 : return true;
37 : 0 : }
38 : :
39 : : static void
40 : 1636041 : write_io_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
41 : : {
42 : 1636041 : struct ftl_io *io = cb_arg;
43 [ # # # # : 1636041 : struct ftl_nv_cache *nv_cache = &io->dev->nv_cache;
# # ]
44 : :
45 [ # # # # ]: 1636041 : ftl_stats_bdev_io_completed(io->dev, FTL_STATS_TYPE_USER, bdev_io);
46 : :
47 : 1636041 : spdk_bdev_free_io(bdev_io);
48 : :
49 [ # # # # : 1636041 : ftl_mempool_put(nv_cache->md_pool, io->md);
# # # # ]
50 : :
51 [ # # ]: 1636041 : ftl_nv_cache_write_complete(io, success);
52 : 1636041 : }
53 : :
54 : : static void write_io(struct ftl_io *io);
55 : :
56 : : static void
57 : 0 : _nvc_vss_write(void *io)
58 : : {
59 : 0 : write_io(io);
60 : 0 : }
61 : :
62 : : static void
63 : 1636041 : write_io(struct ftl_io *io)
64 : : {
65 [ # # # # ]: 1636041 : struct spdk_ftl_dev *dev = io->dev;
66 [ # # ]: 1636041 : struct ftl_nv_cache *nv_cache = &dev->nv_cache;
67 : : int rc;
68 : :
69 [ # # # # : 1636041 : io->md = ftl_mempool_get(dev->nv_cache.md_pool);
# # # # #
# ]
70 [ - + # # : 1636041 : if (spdk_unlikely(!io->md)) {
# # ]
71 [ # # ]: 0 : ftl_abort();
72 : 0 : }
73 : :
74 : 1636041 : ftl_nv_cache_fill_md(io);
75 : :
76 [ # # # # : 3272082 : rc = spdk_bdev_writev_blocks_with_md(nv_cache->bdev_desc, nv_cache->cache_ioch,
# # # # ]
77 [ # # # # : 1636041 : io->iov, io->iov_cnt, io->md,
# # # # #
# # # ]
78 [ # # # # : 0 : ftl_addr_to_nvc_offset(dev, io->addr), io->num_blocks,
# # # # ]
79 : 0 : write_io_cb, io);
80 [ - + ]: 1636041 : if (spdk_unlikely(rc)) {
81 [ # # ]: 0 : if (rc == -ENOMEM) {
82 : : struct spdk_bdev *bdev;
83 : :
84 [ # # # # : 0 : ftl_mempool_put(nv_cache->md_pool, io->md);
# # # # ]
85 [ # # # # ]: 0 : io->md = NULL;
86 : :
87 [ # # # # ]: 0 : bdev = spdk_bdev_desc_get_bdev(nv_cache->bdev_desc);
88 [ # # # # : 0 : io->bdev_io_wait.bdev = bdev;
# # ]
89 [ # # # # : 0 : io->bdev_io_wait.cb_fn = _nvc_vss_write;
# # ]
90 [ # # # # : 0 : io->bdev_io_wait.cb_arg = io;
# # ]
91 [ # # # # : 0 : spdk_bdev_queue_io_wait(bdev, nv_cache->cache_ioch, &io->bdev_io_wait);
# # ]
92 : 0 : } else {
93 [ # # ]: 0 : ftl_abort();
94 : : }
95 : 0 : }
96 : 1636041 : }
97 : :
98 : : struct nvc_recover_open_chunk_ctx {
99 : : struct ftl_nv_cache_chunk *chunk;
100 : : struct ftl_rq *rq;
101 : : uint64_t addr;
102 : : uint64_t to_read;
103 : : };
104 : :
105 : : static void
106 : 2046 : nvc_recover_open_chunk_read_vss_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
107 : : {
108 : 2046 : struct ftl_mngt_process *mngt = cb_arg;
109 : 2046 : struct spdk_ftl_dev *dev = ftl_mngt_get_dev(mngt);
110 : 2046 : struct nvc_recover_open_chunk_ctx *ctx = ftl_mngt_get_process_ctx(mngt);
111 [ # # # # ]: 2046 : struct ftl_nv_cache_chunk *chunk = ctx->chunk;
112 [ # # # # ]: 2046 : struct ftl_rq *rq = ctx->rq;
113 : : union ftl_md_vss *md;
114 [ # # # # : 2046 : uint64_t cache_offset = bdev_io->u.bdev.offset_blocks;
# # # # ]
115 [ # # # # : 2046 : uint64_t blocks = bdev_io->u.bdev.num_blocks;
# # # # ]
116 : 2046 : ftl_addr addr = ftl_addr_from_nvc_offset(dev, cache_offset);
117 : :
118 : 2046 : spdk_bdev_free_io(bdev_io);
119 [ - + # # ]: 2046 : if (!success) {
120 : 0 : ftl_mngt_fail_step(mngt);
121 : 0 : return;
122 : : }
123 : :
124 : : /* Rebuild P2L map */
125 [ + + # # : 525822 : for (rq->iter.idx = 0; rq->iter.idx < blocks; rq->iter.idx++) {
# # # # #
# # # # #
# # # # ]
126 [ # # # # : 523776 : md = rq->entries[rq->iter.idx].io_md;
# # # # #
# # # #
# ]
127 [ + - # # : 523776 : if (md->nv_cache.seq_id != chunk->md->seq_id) {
# # # # #
# # # # #
# # ]
128 [ # # # # : 523776 : md->nv_cache.lba = FTL_LBA_INVALID;
# # ]
129 [ # # # # : 523776 : md->nv_cache.seq_id = 0;
# # ]
130 : 0 : }
131 : :
132 [ # # # # : 523776 : ftl_nv_cache_chunk_set_addr(chunk, md->nv_cache.lba, addr + rq->iter.idx);
# # # # #
# # # ]
133 : 0 : }
134 : :
135 [ - + # # : 2046 : assert(ctx->to_read >= blocks);
# # # # ]
136 [ # # # # ]: 2046 : ctx->addr += blocks;
137 [ # # # # ]: 2046 : ctx->to_read -= blocks;
138 : 2046 : ftl_mngt_continue_step(mngt);
139 : :
140 : 0 : }
141 : :
142 : : static void
143 : 2048 : nvc_recover_open_chunk_read_vss(struct spdk_ftl_dev *dev,
144 : : struct ftl_mngt_process *mngt)
145 : : {
146 : 2048 : struct nvc_recover_open_chunk_ctx *ctx = ftl_mngt_get_process_ctx(mngt);
147 [ # # # # : 2048 : uint64_t blocks = spdk_min(ctx->rq->num_blocks, ctx->to_read);
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
148 : : int rc;
149 : :
150 [ + + ]: 2048 : if (blocks) {
151 [ # # # # : 6138 : rc = spdk_bdev_read_blocks_with_md(dev->nv_cache.bdev_desc, dev->nv_cache.cache_ioch,
# # # # #
# # # ]
152 [ # # # # : 4092 : ctx->rq->io_payload, ctx->rq->io_md, ctx->addr, blocks,
# # # # #
# # # # #
# # # # #
# ]
153 : 0 : nvc_recover_open_chunk_read_vss_cb, mngt);
154 [ - + ]: 2046 : if (rc) {
155 : 0 : ftl_mngt_fail_step(mngt);
156 : 0 : return;
157 : : }
158 : 0 : } else {
159 : 2 : ftl_mngt_next_step(mngt);
160 : : }
161 : 0 : }
162 : :
163 : : static int
164 : 2 : nvc_recover_open_chunk_init_handler(struct spdk_ftl_dev *dev,
165 : : struct ftl_mngt_process *mngt, void *init_ctx)
166 : : {
167 : 2 : struct nvc_recover_open_chunk_ctx *ctx = ftl_mngt_get_process_ctx(mngt);
168 : :
169 [ # # # # ]: 2 : ctx->chunk = init_ctx;
170 [ # # # # : 2 : ctx->rq = ftl_rq_new(dev, dev->nv_cache.md_size);
# # # # #
# ]
171 [ - + # # : 2 : if (NULL == ctx->rq) {
# # ]
172 : 0 : return -ENOMEM;
173 : : }
174 : :
175 [ # # # # : 2 : ctx->addr = ctx->chunk->offset;
# # # # #
# # # ]
176 [ # # # # : 2 : ctx->to_read = chunk_tail_md_offset(&dev->nv_cache);
# # ]
177 : :
178 : 2 : return 0;
179 : 0 : }
180 : :
181 : : static void
182 : 2 : nvc_recover_open_chunk_deinit_handler(struct spdk_ftl_dev *dev,
183 : : struct ftl_mngt_process *mngt)
184 : : {
185 : 2 : struct nvc_recover_open_chunk_ctx *ctx = ftl_mngt_get_process_ctx(mngt);
186 : :
187 [ # # # # ]: 2 : ftl_rq_del(ctx->rq);
188 : 2 : }
189 : :
190 : : static const struct ftl_mngt_process_desc desc_recover_open_chunk = {
191 : : .name = "Recover open chunk",
192 : : .ctx_size = sizeof(struct nvc_recover_open_chunk_ctx),
193 : : .init_handler = nvc_recover_open_chunk_init_handler,
194 : : .deinit_handler = nvc_recover_open_chunk_deinit_handler,
195 : : .steps = {
196 : : {
197 : : .name = "Chunk recovery, read vss",
198 : : .action = nvc_recover_open_chunk_read_vss
199 : : },
200 : : {}
201 : : }
202 : : };
203 : :
204 : : static void
205 : 2 : nvc_recover_open_chunk(struct spdk_ftl_dev *dev,
206 : : struct ftl_mngt_process *mngt,
207 : : struct ftl_nv_cache_chunk *chunk)
208 : : {
209 : 2 : ftl_mngt_call_process(mngt, &desc_recover_open_chunk, chunk);
210 : 2 : }
211 : :
212 : : struct ftl_nv_cache_device_type nvc_bdev_vss = {
213 : : .name = "bdev",
214 : : .features = {
215 : : },
216 : : .ops = {
217 : : .is_bdev_compatible = is_bdev_compatible,
218 : : .is_chunk_active = ftl_nvc_bdev_common_is_chunk_active,
219 : : .md_layout_ops = {
220 : : .region_create = ftl_nvc_bdev_common_region_create,
221 : : .region_open = ftl_nvc_bdev_common_region_open,
222 : : },
223 : : .write = write_io,
224 : : .recover_open_chunk = nvc_recover_open_chunk,
225 : : }
226 : : };
227 : 2080 : FTL_NV_CACHE_DEVICE_TYPE_REGISTER(nvc_bdev_vss)
|