Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2018 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/likely.h"
7 : : #include "spdk/stdinc.h"
8 : : #include "spdk/nvme.h"
9 : : #include "spdk/thread.h"
10 : : #include "spdk/bdev_module.h"
11 : : #include "spdk/string.h"
12 : : #include "spdk/ftl.h"
13 : : #include "spdk/crc32.h"
14 : :
15 : : #include "ftl_core.h"
16 : : #include "ftl_band.h"
17 : : #include "ftl_io.h"
18 : : #include "ftl_debug.h"
19 : : #include "ftl_internal.h"
20 : : #include "mngt/ftl_mngt.h"
21 : :
22 : :
23 : : size_t
24 : 3784 : spdk_ftl_io_size(void)
25 : : {
26 : 3784 : return sizeof(struct ftl_io);
27 : : }
28 : :
29 : : static void
30 : 1428449 : ftl_io_cmpl_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg)
31 : : {
32 : 1428449 : struct ftl_io *io = cb_arg;
33 : 1428449 : struct spdk_ftl_dev *dev = io->dev;
34 : :
35 : 1428449 : ftl_stats_bdev_io_completed(dev, FTL_STATS_TYPE_USER, bdev_io);
36 : :
37 [ - + ]: 1428449 : if (spdk_unlikely(!success)) {
38 : 0 : io->status = -EIO;
39 : : }
40 : :
41 : 1428449 : ftl_trace_completion(dev, io, FTL_TRACE_COMPLETION_DISK);
42 : :
43 : 1428449 : ftl_io_dec_req(io);
44 [ + - ]: 1428449 : if (ftl_io_done(io)) {
45 : 1428449 : ftl_io_complete(io);
46 : : }
47 : :
48 : 1428449 : spdk_bdev_free_io(bdev_io);
49 : 1428449 : }
50 : :
51 : : static void
52 : 6 : ftl_band_erase(struct ftl_band *band)
53 : : {
54 [ + - - + ]: 6 : assert(band->md->state == FTL_BAND_STATE_CLOSED ||
55 : : band->md->state == FTL_BAND_STATE_FREE);
56 : :
57 : 6 : ftl_band_set_state(band, FTL_BAND_STATE_PREP);
58 : 6 : }
59 : :
60 : : static size_t
61 : 18048007 : ftl_get_limit(const struct spdk_ftl_dev *dev, int type)
62 : : {
63 [ - + ]: 18048007 : assert(type < SPDK_FTL_LIMIT_MAX);
64 : 18048007 : return dev->conf.limits[type];
65 : : }
66 : :
67 : : static bool
68 : 151257 : ftl_shutdown_complete(struct spdk_ftl_dev *dev)
69 : : {
70 : : uint64_t i;
71 : :
72 [ - + ]: 151257 : if (dev->num_inflight) {
73 : 0 : return false;
74 : : }
75 : :
76 [ + + ]: 151257 : if (!ftl_nv_cache_is_halted(&dev->nv_cache)) {
77 : 7101 : ftl_nv_cache_halt(&dev->nv_cache);
78 : 7101 : return false;
79 : : }
80 : :
81 [ + + ]: 144156 : if (!ftl_writer_is_halted(&dev->writer_user)) {
82 : 142744 : ftl_writer_halt(&dev->writer_user);
83 : 142744 : return false;
84 : : }
85 : :
86 [ + + ]: 1412 : if (!ftl_reloc_is_halted(dev->reloc)) {
87 : 337 : ftl_reloc_halt(dev->reloc);
88 : 337 : return false;
89 : : }
90 : :
91 [ + + ]: 1075 : if (!ftl_writer_is_halted(&dev->writer_gc)) {
92 : 22 : ftl_writer_halt(&dev->writer_gc);
93 : 22 : return false;
94 : : }
95 : :
96 [ - + ]: 1053 : if (!ftl_nv_cache_chunks_busy(&dev->nv_cache)) {
97 : 0 : return false;
98 : : }
99 : :
100 [ + + ]: 6977 : for (i = 0; i < ftl_get_num_bands(dev); ++i) {
101 [ + + ]: 6933 : if (dev->bands[i].queue_depth ||
102 [ + + ]: 6090 : dev->bands[i].md->state == FTL_BAND_STATE_CLOSING) {
103 : 1009 : return false;
104 : : }
105 : : }
106 : :
107 [ + + ]: 44 : if (!ftl_l2p_is_halted(dev)) {
108 : 22 : ftl_l2p_halt(dev);
109 : 22 : return false;
110 : : }
111 : :
112 : 22 : return true;
113 : : }
114 : :
115 : : void
116 : 2057 : ftl_apply_limits(struct spdk_ftl_dev *dev)
117 : : {
118 : : size_t limit;
119 : 2057 : struct ftl_stats *stats = &dev->stats;
120 : : int i;
121 : :
122 : : /* Clear existing limit */
123 : 2057 : dev->limit = SPDK_FTL_LIMIT_MAX;
124 : :
125 [ + + ]: 9977 : for (i = SPDK_FTL_LIMIT_CRIT; i < SPDK_FTL_LIMIT_MAX; ++i) {
126 : 8030 : limit = ftl_get_limit(dev, i);
127 : :
128 [ + + ]: 8030 : if (dev->num_free <= limit) {
129 : 110 : stats->limits[i]++;
130 : 110 : dev->limit = i;
131 : 110 : break;
132 : : }
133 : : }
134 : :
135 : 2057 : ftl_trace_limits(dev, dev->limit, dev->num_free);
136 : 2057 : }
137 : :
138 : : void
139 : 1103995 : ftl_invalidate_addr(struct spdk_ftl_dev *dev, ftl_addr addr)
140 : : {
141 : : struct ftl_band *band;
142 : : struct ftl_p2l_map *p2l_map;
143 : :
144 [ + + ]: 1103995 : if (ftl_addr_in_nvc(dev, addr)) {
145 : 1103983 : ftl_bitmap_clear(dev->valid_map, addr);
146 : 1103983 : return;
147 : : }
148 : :
149 : 12 : band = ftl_band_from_addr(dev, addr);
150 : 12 : p2l_map = &band->p2l_map;
151 : :
152 : : /* The bit might be already cleared if two writes are scheduled to the */
153 : : /* same LBA at the same time */
154 [ + - ]: 12 : if (ftl_bitmap_get(dev->valid_map, addr)) {
155 [ - + ]: 12 : assert(p2l_map->num_valid > 0);
156 : 12 : ftl_bitmap_clear(dev->valid_map, addr);
157 : 12 : p2l_map->num_valid--;
158 : : }
159 : :
160 : : /* Invalidate open/full band p2l_map entry to keep p2l and l2p
161 : : * consistency when band is going to close state */
162 [ + - - + ]: 12 : if (FTL_BAND_STATE_OPEN == band->md->state || FTL_BAND_STATE_FULL == band->md->state) {
163 : 0 : p2l_map->band_map[ftl_band_block_offset_from_addr(band, addr)].lba = FTL_LBA_INVALID;
164 : 0 : p2l_map->band_map[ftl_band_block_offset_from_addr(band, addr)].seq_id = 0;
165 : : }
166 : : }
167 : :
168 : : static int
169 : 1448444 : ftl_read_canceled(int rc)
170 : : {
171 : 1448444 : return rc == -EFAULT;
172 : : }
173 : :
174 : : static int
175 : 1448444 : ftl_get_next_read_addr(struct ftl_io *io, ftl_addr *addr)
176 : : {
177 : 1448444 : struct spdk_ftl_dev *dev = io->dev;
178 : : ftl_addr next_addr;
179 : : size_t i;
180 : 1448444 : bool addr_cached = false;
181 : :
182 : 1448444 : *addr = ftl_l2p_get(dev, ftl_io_current_lba(io));
183 : 1448444 : io->map[io->pos] = *addr;
184 : :
185 : : /* If the address is invalid, skip it */
186 [ + + ]: 1448444 : if (*addr == FTL_ADDR_INVALID) {
187 : 19995 : return -EFAULT;
188 : : }
189 : :
190 : 1428449 : addr_cached = ftl_addr_in_nvc(dev, *addr);
191 : :
192 [ + + ]: 2505446 : for (i = 1; i < ftl_io_iovec_len_left(io); ++i) {
193 : 1076997 : next_addr = ftl_l2p_get(dev, ftl_io_get_lba(io, io->pos + i));
194 : :
195 [ - + ]: 1076997 : if (next_addr == FTL_ADDR_INVALID) {
196 : 0 : break;
197 : : }
198 : :
199 : : /* It's not enough to check for contiguity, if user data is on the last block
200 : : * of base device and first nvc, then they're 'contiguous', but can't be handled
201 : : * with one read request.
202 : : */
203 [ - + ]: 1076997 : if (addr_cached != ftl_addr_in_nvc(dev, next_addr)) {
204 : 0 : break;
205 : : }
206 : :
207 [ - + ]: 1076997 : if (*addr + i != next_addr) {
208 : 0 : break;
209 : : }
210 : :
211 : 1076997 : io->map[io->pos + i] = next_addr;
212 : : }
213 : :
214 : 1428449 : return i;
215 : : }
216 : :
217 : : static void ftl_submit_read(struct ftl_io *io);
218 : :
219 : : static void
220 : 0 : _ftl_submit_read(void *_io)
221 : : {
222 : 0 : struct ftl_io *io = _io;
223 : :
224 : 0 : ftl_submit_read(io);
225 : 0 : }
226 : :
227 : : static void
228 : 1448339 : ftl_submit_read(struct ftl_io *io)
229 : : {
230 : 1448339 : struct spdk_ftl_dev *dev = io->dev;
231 : 1448339 : ftl_addr addr;
232 : 1448339 : int rc = 0, num_blocks;
233 : :
234 [ + + ]: 2896783 : while (io->pos < io->num_blocks) {
235 : 1448444 : num_blocks = ftl_get_next_read_addr(io, &addr);
236 : 1448444 : rc = num_blocks;
237 : :
238 : : /* User LBA doesn't hold valid data (trimmed or never written to), fill with 0 and skip this block */
239 [ + + ]: 1448444 : if (ftl_read_canceled(rc)) {
240 [ - + ]: 19995 : memset(ftl_io_iovec_addr(io), 0, FTL_BLOCK_SIZE);
241 : 19995 : ftl_io_advance(io, 1);
242 : 19995 : continue;
243 : : }
244 : :
245 [ - + ]: 1428449 : assert(num_blocks > 0);
246 : :
247 : 1428449 : ftl_trace_submission(dev, io, addr, num_blocks);
248 : :
249 [ + + ]: 1428449 : if (ftl_addr_in_nvc(dev, addr)) {
250 : 1145049 : rc = ftl_nv_cache_read(io, addr, num_blocks, ftl_io_cmpl_cb, io);
251 : : } else {
252 : 283400 : rc = spdk_bdev_read_blocks(dev->base_bdev_desc, dev->base_ioch,
253 : : ftl_io_iovec_addr(io),
254 : : addr, num_blocks, ftl_io_cmpl_cb, io);
255 : : }
256 : :
257 [ - + ]: 1428449 : if (spdk_unlikely(rc)) {
258 [ # # ]: 0 : if (rc == -ENOMEM) {
259 : : struct spdk_bdev *bdev;
260 : : struct spdk_io_channel *ch;
261 : :
262 [ # # ]: 0 : if (ftl_addr_in_nvc(dev, addr)) {
263 : 0 : bdev = spdk_bdev_desc_get_bdev(dev->nv_cache.bdev_desc);
264 : 0 : ch = dev->nv_cache.cache_ioch;
265 : : } else {
266 : 0 : bdev = spdk_bdev_desc_get_bdev(dev->base_bdev_desc);
267 : 0 : ch = dev->base_ioch;
268 : : }
269 : 0 : io->bdev_io_wait.bdev = bdev;
270 : 0 : io->bdev_io_wait.cb_fn = _ftl_submit_read;
271 : 0 : io->bdev_io_wait.cb_arg = io;
272 : 0 : spdk_bdev_queue_io_wait(bdev, ch, &io->bdev_io_wait);
273 : 0 : return;
274 : : } else {
275 : 0 : ftl_abort();
276 : : }
277 : : }
278 : :
279 : 1428449 : ftl_io_inc_req(io);
280 : 1428449 : ftl_io_advance(io, num_blocks);
281 : : }
282 : :
283 : : /* If we didn't have to read anything from the device, */
284 : : /* complete the request right away */
285 [ + + ]: 1448339 : if (ftl_io_done(io)) {
286 : 19890 : ftl_io_complete(io);
287 : : }
288 : : }
289 : :
290 : : bool
291 : 18039977 : ftl_needs_reloc(struct spdk_ftl_dev *dev)
292 : : {
293 : 18039977 : size_t limit = ftl_get_limit(dev, SPDK_FTL_LIMIT_START);
294 : :
295 [ - + ]: 18039977 : if (dev->num_free <= limit) {
296 : 0 : return true;
297 : : }
298 : :
299 : 18039977 : return false;
300 : : }
301 : :
302 : : void
303 : 25 : spdk_ftl_dev_get_attrs(const struct spdk_ftl_dev *dev, struct spdk_ftl_attrs *attrs,
304 : : size_t attrs_size)
305 : : {
306 : 25 : attrs->num_blocks = dev->num_lbas;
307 : 25 : attrs->block_size = FTL_BLOCK_SIZE;
308 : 25 : attrs->optimum_io_size = dev->xfer_size;
309 : : /* NOTE: check any new fields in attrs against attrs_size */
310 : 25 : }
311 : :
312 : : static void
313 : 1448339 : ftl_io_pin_cb(struct spdk_ftl_dev *dev, int status, struct ftl_l2p_pin_ctx *pin_ctx)
314 : : {
315 : 1448339 : struct ftl_io *io = pin_ctx->cb_ctx;
316 : :
317 [ - + ]: 1448339 : if (spdk_unlikely(status != 0)) {
318 : : /* Retry on the internal L2P fault */
319 : 0 : io->status = -EAGAIN;
320 : 0 : ftl_io_complete(io);
321 : 0 : return;
322 : : }
323 : :
324 : 1448339 : io->flags |= FTL_IO_PINNED;
325 : 1448339 : ftl_submit_read(io);
326 : : }
327 : :
328 : : static void
329 : 1448339 : ftl_io_pin(struct ftl_io *io)
330 : : {
331 [ - + ]: 1448339 : if (spdk_unlikely(io->flags & FTL_IO_PINNED)) {
332 : : /*
333 : : * The IO is in a retry path and it had been pinned already.
334 : : * Continue with further processing.
335 : : */
336 : 0 : ftl_l2p_pin_skip(io->dev, ftl_io_pin_cb, io, &io->l2p_pin_ctx);
337 : : } else {
338 : : /* First time when pinning the IO */
339 : 1448339 : ftl_l2p_pin(io->dev, io->lba, io->num_blocks,
340 : : ftl_io_pin_cb, io, &io->l2p_pin_ctx);
341 : : }
342 : 1448339 : }
343 : :
344 : : static void
345 : 2575312 : start_io(struct ftl_io *io)
346 : : {
347 : 2575312 : struct ftl_io_channel *ioch = ftl_io_channel_get_ctx(io->ioch);
348 : 2575312 : struct spdk_ftl_dev *dev = io->dev;
349 : :
350 : 2575312 : io->map = ftl_mempool_get(ioch->map_pool);
351 [ - + ]: 2575312 : if (spdk_unlikely(!io->map)) {
352 : 0 : io->status = -ENOMEM;
353 : 0 : ftl_io_complete(io);
354 : 0 : return;
355 : : }
356 : :
357 [ + + + - ]: 2575312 : switch (io->type) {
358 : 1448338 : case FTL_IO_READ:
359 : 1448338 : TAILQ_INSERT_TAIL(&dev->rd_sq, io, queue_entry);
360 : 1448338 : break;
361 : 1126970 : case FTL_IO_WRITE:
362 : 1126970 : TAILQ_INSERT_TAIL(&dev->wr_sq, io, queue_entry);
363 : 1126970 : break;
364 : 4 : case FTL_IO_UNMAP:
365 : 4 : TAILQ_INSERT_TAIL(&dev->unmap_sq, io, queue_entry);
366 : 4 : break;
367 : 0 : default:
368 : 0 : io->status = -EOPNOTSUPP;
369 : 0 : ftl_io_complete(io);
370 : : }
371 : : }
372 : :
373 : : static int
374 : 2575312 : queue_io(struct spdk_ftl_dev *dev, struct ftl_io *io)
375 : : {
376 : : size_t result;
377 : 2575312 : struct ftl_io_channel *ioch = ftl_io_channel_get_ctx(io->ioch);
378 : :
379 : 2575312 : result = spdk_ring_enqueue(ioch->sq, (void **)&io, 1, NULL);
380 [ - + ]: 2575312 : if (spdk_unlikely(0 == result)) {
381 : 0 : return -EAGAIN;
382 : : }
383 : :
384 : 2575312 : return 0;
385 : : }
386 : :
387 : : int
388 : 1126970 : spdk_ftl_writev(struct spdk_ftl_dev *dev, struct ftl_io *io, struct spdk_io_channel *ch,
389 : : uint64_t lba, uint64_t lba_cnt, struct iovec *iov, size_t iov_cnt, spdk_ftl_fn cb_fn,
390 : : void *cb_arg)
391 : : {
392 : : int rc;
393 : :
394 [ - + ]: 1126970 : if (iov_cnt == 0) {
395 : 0 : return -EINVAL;
396 : : }
397 : :
398 [ - + ]: 1126970 : if (lba_cnt == 0) {
399 : 0 : return -EINVAL;
400 : : }
401 : :
402 [ - + ]: 1126970 : if (lba_cnt != ftl_iovec_num_blocks(iov, iov_cnt)) {
403 [ # # ]: 0 : FTL_ERRLOG(dev, "Invalid IO vector to handle, device %s, LBA %"PRIu64"\n",
404 : : dev->conf.name, lba);
405 : 0 : return -EINVAL;
406 : : }
407 : :
408 [ - + - + ]: 1126970 : if (!dev->initialized) {
409 : 0 : return -EBUSY;
410 : : }
411 : :
412 : 1126970 : rc = ftl_io_init(ch, io, lba, lba_cnt, iov, iov_cnt, cb_fn, cb_arg, FTL_IO_WRITE);
413 [ - + ]: 1126970 : if (rc) {
414 : 0 : return rc;
415 : : }
416 : :
417 : 1126970 : return queue_io(dev, io);
418 : : }
419 : :
420 : : int
421 : 1448338 : spdk_ftl_readv(struct spdk_ftl_dev *dev, struct ftl_io *io, struct spdk_io_channel *ch,
422 : : uint64_t lba, uint64_t lba_cnt, struct iovec *iov, size_t iov_cnt, spdk_ftl_fn cb_fn, void *cb_arg)
423 : : {
424 : : int rc;
425 : :
426 [ - + ]: 1448338 : if (iov_cnt == 0) {
427 : 0 : return -EINVAL;
428 : : }
429 : :
430 [ - + ]: 1448338 : if (lba_cnt == 0) {
431 : 0 : return -EINVAL;
432 : : }
433 : :
434 [ - + ]: 1448338 : if (lba_cnt != ftl_iovec_num_blocks(iov, iov_cnt)) {
435 [ # # ]: 0 : FTL_ERRLOG(dev, "Invalid IO vector to handle, device %s, LBA %"PRIu64"\n",
436 : : dev->conf.name, lba);
437 : 0 : return -EINVAL;
438 : : }
439 : :
440 [ - + - + ]: 1448338 : if (!dev->initialized) {
441 : 0 : return -EBUSY;
442 : : }
443 : :
444 : 1448338 : rc = ftl_io_init(ch, io, lba, lba_cnt, iov, iov_cnt, cb_fn, cb_arg, FTL_IO_READ);
445 [ - + ]: 1448338 : if (rc) {
446 : 0 : return rc;
447 : : }
448 : :
449 : 1448338 : return queue_io(dev, io);
450 : : }
451 : :
452 : : int
453 : 4 : ftl_unmap(struct spdk_ftl_dev *dev, struct ftl_io *io, struct spdk_io_channel *ch,
454 : : uint64_t lba, uint64_t lba_cnt, spdk_ftl_fn cb_fn, void *cb_arg)
455 : : {
456 : : int rc;
457 : :
458 : 4 : rc = ftl_io_init(ch, io, lba, lba_cnt, NULL, 0, cb_fn, cb_arg, FTL_IO_UNMAP);
459 [ - + ]: 4 : if (rc) {
460 : 0 : return rc;
461 : : }
462 : :
463 : 4 : return queue_io(dev, io);
464 : : }
465 : :
466 : : int
467 : 8 : spdk_ftl_unmap(struct spdk_ftl_dev *dev, struct ftl_io *io, struct spdk_io_channel *ch,
468 : : uint64_t lba, uint64_t lba_cnt, spdk_ftl_fn cb_fn, void *cb_arg)
469 : : {
470 : : int rc;
471 : 8 : uint64_t alignment = dev->layout.l2p.lbas_in_page;
472 : :
473 [ - + ]: 8 : if (lba_cnt == 0) {
474 : 0 : return -EINVAL;
475 : : }
476 : :
477 [ - + ]: 8 : if (lba + lba_cnt < lba_cnt) {
478 : 0 : return -EINVAL;
479 : : }
480 : :
481 [ - + ]: 8 : if (lba + lba_cnt > dev->num_lbas) {
482 : 0 : return -EINVAL;
483 : : }
484 : :
485 [ - + - + ]: 8 : if (!dev->initialized) {
486 : 0 : return -EBUSY;
487 : : }
488 : :
489 [ - + + - : 8 : if (lba % alignment || lba_cnt % alignment) {
- + - + ]
490 [ # # ]: 0 : if (!io) {
491 : : /* This is management/RPC path, its parameters must be aligned to 1MiB. */
492 : 0 : return -EINVAL;
493 : : }
494 : :
495 : : /* Otherwise unaligned IO requests are NOPs */
496 : 0 : rc = ftl_io_init(ch, io, lba, lba_cnt, NULL, 0, cb_fn, cb_arg, FTL_IO_UNMAP);
497 [ # # ]: 0 : if (rc) {
498 : 0 : return rc;
499 : : }
500 : :
501 : 0 : io->status = 0;
502 : 0 : ftl_io_complete(io);
503 : 0 : return 0;
504 : : }
505 : :
506 [ + + ]: 8 : if (io) {
507 : 4 : rc = ftl_unmap(dev, io, ch, lba, lba_cnt, cb_fn, cb_arg);
508 : : } else {
509 : 4 : rc = ftl_mngt_unmap(dev, lba, lba_cnt, cb_fn, cb_arg);
510 : : }
511 : :
512 : 8 : return rc;
513 : : }
514 : :
515 : : #define FTL_IO_QUEUE_BATCH 16
516 : : int
517 : 46131573 : ftl_io_channel_poll(void *arg)
518 : : {
519 : 46131573 : struct ftl_io_channel *ch = arg;
520 : 46131573 : void *ios[FTL_IO_QUEUE_BATCH];
521 : : uint64_t i, count;
522 : :
523 : 46131573 : count = spdk_ring_dequeue(ch->cq, ios, FTL_IO_QUEUE_BATCH);
524 [ + + ]: 46131573 : if (count == 0) {
525 : 44143557 : return SPDK_POLLER_IDLE;
526 : : }
527 : :
528 [ + + ]: 4563328 : for (i = 0; i < count; i++) {
529 : 2575312 : struct ftl_io *io = ios[i];
530 : 2575312 : io->user_fn(io->cb_ctx, io->status);
531 : : }
532 : :
533 : 1988016 : return SPDK_POLLER_BUSY;
534 : : }
535 : :
536 : : static void
537 : 22178103 : ftl_process_io_channel(struct spdk_ftl_dev *dev, struct ftl_io_channel *ioch)
538 : : {
539 : 22178103 : void *ios[FTL_IO_QUEUE_BATCH];
540 : : size_t count, i;
541 : :
542 : 22178103 : count = spdk_ring_dequeue(ioch->sq, ios, FTL_IO_QUEUE_BATCH);
543 [ + + ]: 22178103 : if (count == 0) {
544 : 20423646 : return;
545 : : }
546 : :
547 [ + + ]: 4329769 : for (i = 0; i < count; i++) {
548 : 2575312 : struct ftl_io *io = ios[i];
549 : 2575312 : start_io(io);
550 : : }
551 : : }
552 : :
553 : : static void
554 : 4 : ftl_process_unmap_cb(struct spdk_ftl_dev *dev, struct ftl_md *md, int status)
555 : : {
556 : 4 : struct ftl_io *io = md->owner.cb_ctx;
557 : :
558 : 4 : io->dev->unmap_qd--;
559 : :
560 [ - + ]: 4 : if (spdk_unlikely(status)) {
561 : : #ifdef SPDK_FTL_RETRY_ON_ERROR
562 : : TAILQ_INSERT_HEAD(&io->dev->unmap_sq, io, queue_entry);
563 : : return;
564 : : #else
565 : 0 : io->status = status;
566 : : #endif
567 : : }
568 : :
569 : 4 : ftl_io_complete(io);
570 : 4 : }
571 : :
572 : : void
573 : 4 : ftl_set_unmap_map(struct spdk_ftl_dev *dev, uint64_t lba, uint64_t num_blocks, uint64_t seq_id)
574 : : {
575 : : uint64_t first_page, num_pages;
576 : : uint64_t first_md_block, num_md_blocks, num_pages_in_block;
577 : 4 : uint32_t lbas_in_page = dev->layout.l2p.lbas_in_page;
578 : 4 : struct ftl_md *md = dev->layout.md[FTL_LAYOUT_REGION_TYPE_TRIM_MD];
579 : 4 : uint64_t *page = ftl_md_get_buffer(md);
580 : : union ftl_md_vss *page_vss;
581 : : size_t i;
582 : :
583 [ - + ]: 4 : first_page = lba / lbas_in_page;
584 [ - + ]: 4 : num_pages = num_blocks / lbas_in_page;
585 : :
586 [ + + ]: 8 : for (i = first_page; i < first_page + num_pages; ++i) {
587 : 4 : ftl_bitmap_set(dev->unmap_map, i);
588 : 4 : page[i] = seq_id;
589 : : }
590 : :
591 : 4 : num_pages_in_block = FTL_BLOCK_SIZE / sizeof(*page);
592 [ - + ]: 4 : first_md_block = first_page / num_pages_in_block;
593 : 4 : num_md_blocks = spdk_divide_round_up(num_pages, num_pages_in_block);
594 : 4 : page_vss = ftl_md_get_vss_buffer(md) + first_md_block;
595 [ + + ]: 6 : for (i = first_md_block; i < num_md_blocks; ++i, page_vss++) {
596 : 2 : page_vss->unmap.start_lba = lba;
597 : 2 : page_vss->unmap.num_blocks = num_blocks;
598 : 2 : page_vss->unmap.seq_id = seq_id;
599 : : }
600 : 4 : }
601 : :
602 : : static bool
603 : 4 : ftl_process_unmap(struct ftl_io *io)
604 : : {
605 : 4 : struct spdk_ftl_dev *dev = io->dev;
606 : 4 : struct ftl_md *md = dev->layout.md[FTL_LAYOUT_REGION_TYPE_TRIM_MD];
607 : : uint64_t seq_id;
608 : :
609 : 4 : seq_id = ftl_nv_cache_acquire_trim_seq_id(&dev->nv_cache);
610 [ - + ]: 4 : if (seq_id == 0) {
611 : 0 : return false;
612 : : }
613 : :
614 : 4 : dev->unmap_in_progress = true;
615 : 4 : dev->unmap_qd++;
616 : :
617 : 4 : dev->sb_shm->trim.start_lba = io->lba;
618 : 4 : dev->sb_shm->trim.num_blocks = io->num_blocks;
619 : 4 : dev->sb_shm->trim.seq_id = seq_id;
620 : 4 : dev->sb_shm->trim.in_progress = true;
621 : 4 : ftl_set_unmap_map(dev, io->lba, io->num_blocks, seq_id);
622 : 4 : ftl_debug_inject_unmap_error();
623 : 4 : dev->sb_shm->trim.in_progress = false;
624 : :
625 : 4 : md->owner.cb_ctx = io;
626 : 4 : md->cb = ftl_process_unmap_cb;
627 : :
628 : 4 : ftl_md_persist(md);
629 : :
630 : 4 : return true;
631 : : }
632 : :
633 : : static void
634 : 18185214 : ftl_process_io_queue(struct spdk_ftl_dev *dev)
635 : : {
636 : : struct ftl_io_channel *ioch;
637 : : struct ftl_io *io;
638 : :
639 : : /* TODO: Try to figure out a mechanism to batch more requests at the same time,
640 : : * with keeping enough resources (pinned pages), between reads, writes and gc/compaction
641 : : */
642 [ + + ]: 18185214 : if (!TAILQ_EMPTY(&dev->rd_sq)) {
643 : 1448339 : io = TAILQ_FIRST(&dev->rd_sq);
644 [ + + ]: 1448339 : TAILQ_REMOVE(&dev->rd_sq, io, queue_entry);
645 [ - + ]: 1448339 : assert(io->type == FTL_IO_READ);
646 : 1448339 : ftl_io_pin(io);
647 : 1448339 : ftl_add_io_activity(dev);
648 : : }
649 : :
650 [ + + + + ]: 19312184 : while (!TAILQ_EMPTY(&dev->wr_sq) && !ftl_nv_cache_throttle(dev)) {
651 : 1126970 : io = TAILQ_FIRST(&dev->wr_sq);
652 [ + + ]: 1126970 : TAILQ_REMOVE(&dev->wr_sq, io, queue_entry);
653 [ - + ]: 1126970 : assert(io->type == FTL_IO_WRITE);
654 [ - + ]: 1126970 : if (!ftl_nv_cache_write(io)) {
655 [ # # ]: 0 : TAILQ_INSERT_HEAD(&dev->wr_sq, io, queue_entry);
656 : 0 : break;
657 : : }
658 : 1126970 : ftl_add_io_activity(dev);
659 : : }
660 : :
661 [ + + + - ]: 18185214 : if (!TAILQ_EMPTY(&dev->unmap_sq) && dev->unmap_qd == 0) {
662 : 4 : io = TAILQ_FIRST(&dev->unmap_sq);
663 [ - + ]: 4 : TAILQ_REMOVE(&dev->unmap_sq, io, queue_entry);
664 [ - + ]: 4 : assert(io->type == FTL_IO_UNMAP);
665 : :
666 : : /*
667 : : * Unmap operation requires generating a sequence id for itself, which it gets based on the open chunk
668 : : * in nv cache. If there are no open chunks (because we're in the middle of state transition or compaction
669 : : * lagged behind), then we need to wait for the nv cache to resolve the situation - it's fine to just put the
670 : : * unmap and try again later.
671 : : */
672 [ - + ]: 4 : if (!ftl_process_unmap(io)) {
673 [ # # ]: 0 : TAILQ_INSERT_HEAD(&dev->unmap_sq, io, queue_entry);
674 : : } else {
675 : 4 : ftl_add_io_activity(dev);
676 : : }
677 : : }
678 : :
679 [ + + ]: 40363317 : TAILQ_FOREACH(ioch, &dev->ioch_queue, entry) {
680 : 22178103 : ftl_process_io_channel(dev, ioch);
681 : : }
682 : 18185214 : }
683 : :
684 : : int
685 : 18185236 : ftl_core_poller(void *ctx)
686 : : {
687 : 18185236 : struct spdk_ftl_dev *dev = ctx;
688 : 18185236 : uint64_t io_activity_total_old = dev->stats.io_activity_total;
689 : :
690 [ - + + + : 18185236 : if (dev->halt && ftl_shutdown_complete(dev)) {
+ + ]
691 : 22 : spdk_poller_unregister(&dev->core_poller);
692 : 22 : return SPDK_POLLER_IDLE;
693 : : }
694 : :
695 : 18185214 : ftl_process_io_queue(dev);
696 : 18185214 : ftl_writer_run(&dev->writer_user);
697 : 18185214 : ftl_writer_run(&dev->writer_gc);
698 : 18185214 : ftl_reloc(dev->reloc);
699 : 18185214 : ftl_nv_cache_process(dev);
700 : 18185214 : ftl_l2p_process(dev);
701 : :
702 [ + + ]: 18185214 : if (io_activity_total_old != dev->stats.io_activity_total) {
703 : 2022438 : return SPDK_POLLER_BUSY;
704 : : }
705 : :
706 : 16162776 : return SPDK_POLLER_IDLE;
707 : : }
708 : :
709 : : struct ftl_band *
710 : 6 : ftl_band_get_next_free(struct spdk_ftl_dev *dev)
711 : : {
712 : 6 : struct ftl_band *band = NULL;
713 : :
714 [ + - ]: 6 : if (!TAILQ_EMPTY(&dev->free_bands)) {
715 : 6 : band = TAILQ_FIRST(&dev->free_bands);
716 [ + - ]: 6 : TAILQ_REMOVE(&dev->free_bands, band, queue_entry);
717 : 6 : ftl_band_erase(band);
718 : : }
719 : :
720 : 6 : return band;
721 : : }
722 : :
723 : : void *g_ftl_write_buf;
724 : : void *g_ftl_read_buf;
725 : :
726 : : int
727 : 1892 : spdk_ftl_init(void)
728 : : {
729 : 1892 : g_ftl_write_buf = spdk_zmalloc(FTL_ZERO_BUFFER_SIZE, FTL_ZERO_BUFFER_SIZE, NULL,
730 : : SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
731 [ - + ]: 1892 : if (!g_ftl_write_buf) {
732 : 0 : return -ENOMEM;
733 : : }
734 : :
735 : 1892 : g_ftl_read_buf = spdk_zmalloc(FTL_ZERO_BUFFER_SIZE, FTL_ZERO_BUFFER_SIZE, NULL,
736 : : SPDK_ENV_LCORE_ID_ANY, SPDK_MALLOC_DMA);
737 [ - + ]: 1892 : if (!g_ftl_read_buf) {
738 : 0 : spdk_free(g_ftl_write_buf);
739 : 0 : g_ftl_write_buf = NULL;
740 : 0 : return -ENOMEM;
741 : : }
742 : 1892 : return 0;
743 : : }
744 : :
745 : : void
746 : 1892 : spdk_ftl_fini(void)
747 : : {
748 : 1892 : spdk_free(g_ftl_write_buf);
749 : 1892 : spdk_free(g_ftl_read_buf);
750 : 1892 : }
751 : :
752 : : void
753 : 4 : spdk_ftl_dev_set_fast_shutdown(struct spdk_ftl_dev *dev, bool fast_shutdown)
754 : : {
755 [ - + ]: 4 : assert(dev);
756 : 4 : dev->conf.fast_shutdown = fast_shutdown;
757 : 4 : }
758 : :
759 : : void
760 : 2807052 : ftl_stats_bdev_io_completed(struct spdk_ftl_dev *dev, enum ftl_stats_type type,
761 : : struct spdk_bdev_io *bdev_io)
762 : : {
763 : 2807052 : struct ftl_stats_entry *stats_entry = &dev->stats.entries[type];
764 : : struct ftl_stats_group *stats_group;
765 : 2807052 : uint32_t cdw0;
766 : 2807052 : int sct;
767 : 2807052 : int sc;
768 : :
769 [ + + - ]: 2807052 : switch (bdev_io->type) {
770 : 1557929 : case SPDK_BDEV_IO_TYPE_READ:
771 : 1557929 : stats_group = &stats_entry->read;
772 : 1557929 : break;
773 : 1249123 : case SPDK_BDEV_IO_TYPE_WRITE:
774 : : case SPDK_BDEV_IO_TYPE_WRITE_ZEROES:
775 : 1249123 : stats_group = &stats_entry->write;
776 : 1249123 : break;
777 : 0 : default:
778 : 0 : return;
779 : : }
780 : :
781 : 2807052 : spdk_bdev_io_get_nvme_status(bdev_io, &cdw0, &sct, &sc);
782 : :
783 [ + - + - ]: 2807052 : if (sct == SPDK_NVME_SCT_GENERIC && sc == SPDK_NVME_SC_SUCCESS) {
784 : 2807052 : stats_group->ios++;
785 : 2807052 : stats_group->blocks += bdev_io->u.bdev.num_blocks;
786 [ # # ]: 0 : } else if (sct == SPDK_NVME_SCT_MEDIA_ERROR) {
787 : 0 : stats_group->errors.media++;
788 : : } else {
789 : 0 : stats_group->errors.other++;
790 : : }
791 : : }
792 : :
793 : : struct spdk_io_channel *
794 : 42 : spdk_ftl_get_io_channel(struct spdk_ftl_dev *dev)
795 : : {
796 : 42 : return spdk_get_io_channel(dev);
797 : : }
798 : :
799 : : void
800 : 0 : ftl_stats_crc_error(struct spdk_ftl_dev *dev, enum ftl_stats_type type)
801 : : {
802 : :
803 : 0 : struct ftl_stats_entry *stats_entry = &dev->stats.entries[type];
804 : 0 : struct ftl_stats_group *stats_group = &stats_entry->read;
805 : :
806 : 0 : stats_group->errors.crc++;
807 : 0 : }
808 : :
809 : : struct ftl_get_stats_ctx {
810 : : struct spdk_ftl_dev *dev;
811 : : struct ftl_stats *stats;
812 : : struct spdk_thread *thread;
813 : : spdk_ftl_stats_fn cb_fn;
814 : : void *cb_arg;
815 : : };
816 : :
817 : : static void
818 : 1 : _ftl_get_stats_cb(void *_ctx)
819 : : {
820 : 1 : struct ftl_get_stats_ctx *stats_ctx = _ctx;
821 : :
822 : 1 : stats_ctx->cb_fn(stats_ctx->stats, stats_ctx->cb_arg);
823 : 1 : free(stats_ctx);
824 : 1 : }
825 : :
826 : : static void
827 : 1 : _ftl_get_stats(void *_ctx)
828 : : {
829 : 1 : struct ftl_get_stats_ctx *stats_ctx = _ctx;
830 : :
831 : 1 : *stats_ctx->stats = stats_ctx->dev->stats;
832 : :
833 [ - + ]: 1 : if (spdk_thread_send_msg(stats_ctx->thread, _ftl_get_stats_cb, stats_ctx)) {
834 : 0 : ftl_abort();
835 : : }
836 : 1 : }
837 : :
838 : : int
839 : 1 : spdk_ftl_get_stats(struct spdk_ftl_dev *dev, struct ftl_stats *stats, spdk_ftl_stats_fn cb_fn,
840 : : void *cb_arg)
841 : : {
842 : : struct ftl_get_stats_ctx *stats_ctx;
843 : : int rc;
844 : :
845 : 1 : stats_ctx = calloc(1, sizeof(struct ftl_get_stats_ctx));
846 [ - + ]: 1 : if (!stats_ctx) {
847 : 0 : return -ENOMEM;
848 : : }
849 : :
850 : 1 : stats_ctx->dev = dev;
851 : 1 : stats_ctx->stats = stats;
852 : 1 : stats_ctx->cb_fn = cb_fn;
853 : 1 : stats_ctx->cb_arg = cb_arg;
854 : 1 : stats_ctx->thread = spdk_get_thread();
855 : :
856 : 1 : rc = spdk_thread_send_msg(dev->core_thread, _ftl_get_stats, stats_ctx);
857 [ - + ]: 1 : if (rc) {
858 : 0 : goto stats_allocated;
859 : : }
860 : :
861 : 1 : return 0;
862 : :
863 : 0 : stats_allocated:
864 : 0 : free(stats_ctx);
865 : 0 : return rc;
866 : : }
867 : :
868 : 2050 : SPDK_LOG_REGISTER_COMPONENT(ftl_core)
|