]> git.proxmox.com Git - ceph.git/blob - ceph/src/spdk/lib/ftl/ftl_restore.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / lib / ftl / ftl_restore.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/ftl.h"
36 #include "spdk/util.h"
37 #include "spdk/likely.h"
38 #include "spdk/string.h"
39
40 #include "ftl_core.h"
41 #include "ftl_band.h"
42 #include "ftl_io.h"
43
44 struct ftl_restore_band {
45 struct ftl_restore *parent;
46
47 struct ftl_band *band;
48
49 enum ftl_md_status md_status;
50
51 STAILQ_ENTRY(ftl_restore_band) stailq;
52 };
53
54 struct ftl_restore {
55 struct spdk_ftl_dev *dev;
56
57 ftl_restore_fn cb;
58
59 unsigned int num_ios;
60
61 unsigned int current;
62
63 struct ftl_restore_band *bands;
64
65 STAILQ_HEAD(, ftl_restore_band) pad_bands;
66
67 size_t num_pad_bands;
68
69 int pad_status;
70
71 void *md_buf;
72
73 void *lba_map;
74
75 bool l2p_phase;
76 };
77
78 static int
79 ftl_restore_tail_md(struct ftl_restore_band *rband);
80 static void
81 ftl_pad_chunk_cb(struct ftl_io *io, void *arg, int status);
82 static void
83 ftl_restore_pad_band(struct ftl_restore_band *rband);
84
85 static void
86 ftl_restore_free(struct ftl_restore *restore)
87 {
88 if (!restore) {
89 return;
90 }
91
92 spdk_dma_free(restore->md_buf);
93 free(restore->lba_map);
94 free(restore->bands);
95 free(restore);
96 }
97
98 static struct ftl_restore *
99 ftl_restore_init(struct spdk_ftl_dev *dev, ftl_restore_fn cb)
100 {
101 struct ftl_restore *restore;
102 struct ftl_restore_band *rband;
103 size_t i, md_size;
104
105 restore = calloc(1, sizeof(*restore));
106 if (!restore) {
107 goto error;
108 }
109
110 restore->dev = dev;
111 restore->cb = cb;
112 restore->l2p_phase = false;
113
114 restore->bands = calloc(ftl_dev_num_bands(dev), sizeof(*restore->bands));
115 if (!restore->bands) {
116 goto error;
117 }
118
119 STAILQ_INIT(&restore->pad_bands);
120
121 for (i = 0; i < ftl_dev_num_bands(dev); ++i) {
122 rband = &restore->bands[i];
123 rband->band = &dev->bands[i];
124 rband->parent = restore;
125 rband->md_status = FTL_MD_NO_MD;
126 }
127
128 /* Allocate buffer capable of holding either tail md or head mds of all bands */
129 md_size = spdk_max(ftl_dev_num_bands(dev) * ftl_head_md_num_lbks(dev) * FTL_BLOCK_SIZE,
130 ftl_tail_md_num_lbks(dev) * FTL_BLOCK_SIZE);
131
132 restore->md_buf = spdk_dma_zmalloc(md_size, FTL_BLOCK_SIZE, NULL);
133 if (!restore->md_buf) {
134 goto error;
135 }
136
137 restore->lba_map = calloc(ftl_num_band_lbks(dev), sizeof(uint64_t));
138 if (!restore->lba_map) {
139 goto error;
140 }
141
142 return restore;
143 error:
144 ftl_restore_free(restore);
145 return NULL;
146 }
147
148 static void
149 ftl_restore_complete(struct ftl_restore *restore, int status)
150 {
151 struct ftl_restore *ctx = status ? NULL : restore;
152 bool l2p_phase = restore->l2p_phase;
153
154 restore->cb(restore->dev, ctx, status);
155 if (status || l2p_phase) {
156 ftl_restore_free(restore);
157 }
158 }
159
160 static int
161 ftl_band_cmp(const void *lband, const void *rband)
162 {
163 uint64_t lseq = ((struct ftl_restore_band *)lband)->band->seq;
164 uint64_t rseq = ((struct ftl_restore_band *)rband)->band->seq;
165
166 if (lseq < rseq) {
167 return -1;
168 } else {
169 return 1;
170 }
171 }
172
173 static int
174 ftl_restore_check_seq(const struct ftl_restore *restore)
175 {
176 const struct spdk_ftl_dev *dev = restore->dev;
177 const struct ftl_restore_band *rband;
178 const struct ftl_band *next_band;
179 size_t i;
180
181 for (i = 0; i < ftl_dev_num_bands(dev); ++i) {
182 rband = &restore->bands[i];
183
184 if (rband->md_status != FTL_MD_SUCCESS) {
185 continue;
186 }
187
188 next_band = LIST_NEXT(rband->band, list_entry);
189 if (next_band && rband->band->seq == next_band->seq) {
190 return -1;
191 }
192 }
193
194 return 0;
195 }
196
197 static bool
198 ftl_restore_head_valid(struct spdk_ftl_dev *dev, struct ftl_restore *restore, size_t *num_valid)
199 {
200 struct ftl_restore_band *rband;
201 size_t i;
202
203 for (i = 0; i < ftl_dev_num_bands(dev); ++i) {
204 rband = &restore->bands[i];
205
206 if (rband->md_status != FTL_MD_SUCCESS &&
207 rband->md_status != FTL_MD_NO_MD &&
208 rband->md_status != FTL_MD_IO_FAILURE) {
209 SPDK_ERRLOG("Inconsistent head metadata found on band %u\n",
210 rband->band->id);
211 return false;
212 }
213
214 if (rband->md_status == FTL_MD_SUCCESS) {
215 (*num_valid)++;
216 }
217 }
218
219 return true;
220 }
221
222 static void
223 ftl_restore_head_complete(struct ftl_restore *restore)
224 {
225 struct spdk_ftl_dev *dev = restore->dev;
226 size_t num_valid = 0;
227 int status = -EIO;
228
229 if (!ftl_restore_head_valid(dev, restore, &num_valid)) {
230 goto out;
231 }
232
233 if (num_valid == 0) {
234 SPDK_ERRLOG("Couldn't find any valid bands\n");
235 goto out;
236 }
237
238 /* Sort bands in sequence number ascending order */
239 qsort(restore->bands, ftl_dev_num_bands(dev), sizeof(struct ftl_restore_band),
240 ftl_band_cmp);
241
242 if (ftl_restore_check_seq(restore)) {
243 SPDK_ERRLOG("Band sequence consistency failed\n");
244 goto out;
245 }
246
247 dev->num_lbas = dev->global_md.num_lbas;
248 status = 0;
249 out:
250 ftl_restore_complete(restore, status);
251 }
252
253 static void
254 ftl_restore_head_cb(struct ftl_io *io, void *ctx, int status)
255 {
256 struct ftl_restore_band *rband = ctx;
257 struct ftl_restore *restore = rband->parent;
258 unsigned int num_ios;
259
260 rband->md_status = status;
261 num_ios = __atomic_fetch_sub(&restore->num_ios, 1, __ATOMIC_SEQ_CST);
262 assert(num_ios > 0);
263
264 if (num_ios == 1) {
265 ftl_restore_head_complete(restore);
266 }
267 }
268
269 static int
270 ftl_restore_head_md(struct ftl_restore *restore)
271 {
272 struct spdk_ftl_dev *dev = restore->dev;
273 struct ftl_restore_band *rband;
274 struct ftl_lba_map *lba_map;
275 unsigned int num_failed = 0, num_ios;
276 size_t i;
277
278 restore->num_ios = ftl_dev_num_bands(dev);
279
280 for (i = 0; i < ftl_dev_num_bands(dev); ++i) {
281 rband = &restore->bands[i];
282 lba_map = &rband->band->lba_map;
283
284 lba_map->dma_buf = restore->md_buf + i * ftl_head_md_num_lbks(dev) * FTL_BLOCK_SIZE;
285
286 if (ftl_band_read_head_md(rband->band, ftl_restore_head_cb, rband)) {
287 if (spdk_likely(rband->band->num_chunks)) {
288 SPDK_ERRLOG("Failed to read metadata on band %zu\n", i);
289
290 rband->md_status = FTL_MD_INVALID_CRC;
291
292 /* If the first IO fails, don't bother sending anything else */
293 if (i == 0) {
294 ftl_restore_free(restore);
295 return -EIO;
296 }
297 }
298
299 num_failed++;
300 }
301 }
302
303 if (spdk_unlikely(num_failed > 0)) {
304 num_ios = __atomic_fetch_sub(&restore->num_ios, num_failed, __ATOMIC_SEQ_CST);
305 if (num_ios == num_failed) {
306 ftl_restore_free(restore);
307 return -EIO;
308 }
309 }
310
311 return 0;
312 }
313
314 int
315 ftl_restore_md(struct spdk_ftl_dev *dev, ftl_restore_fn cb)
316 {
317 struct ftl_restore *restore;
318
319 restore = ftl_restore_init(dev, cb);
320 if (!restore) {
321 return -ENOMEM;
322 }
323
324 return ftl_restore_head_md(restore);
325 }
326
327 static int
328 ftl_restore_l2p(struct ftl_band *band)
329 {
330 struct spdk_ftl_dev *dev = band->dev;
331 struct ftl_ppa ppa;
332 uint64_t lba;
333 size_t i;
334
335 for (i = 0; i < ftl_num_band_lbks(band->dev); ++i) {
336 if (!spdk_bit_array_get(band->lba_map.vld, i)) {
337 continue;
338 }
339
340 lba = band->lba_map.map[i];
341 if (lba >= dev->num_lbas) {
342 return -1;
343 }
344
345 ppa = ftl_l2p_get(dev, lba);
346 if (!ftl_ppa_invalid(ppa)) {
347 ftl_invalidate_addr(dev, ppa);
348 }
349
350 ppa = ftl_band_ppa_from_lbkoff(band, i);
351
352 ftl_band_set_addr(band, lba, ppa);
353 ftl_l2p_set(dev, lba, ppa);
354 }
355
356 band->lba_map.map = NULL;
357 return 0;
358 }
359
360 static struct ftl_restore_band *
361 ftl_restore_next_band(struct ftl_restore *restore)
362 {
363 struct ftl_restore_band *rband;
364
365 for (; restore->current < ftl_dev_num_bands(restore->dev); ++restore->current) {
366 rband = &restore->bands[restore->current];
367
368 if (spdk_likely(rband->band->num_chunks) &&
369 rband->md_status == FTL_MD_SUCCESS) {
370 restore->current++;
371 return rband;
372 }
373 }
374
375 return NULL;
376 }
377
378 static bool
379 ftl_pad_chunk_pad_finish(struct ftl_restore_band *rband, bool direct_access)
380 {
381 struct ftl_restore *restore = rband->parent;
382 size_t i, num_pad_chunks = 0;
383
384 if (spdk_unlikely(restore->pad_status && !restore->num_ios)) {
385 if (direct_access) {
386 /* In case of any errors found we want to clear direct access. */
387 /* Direct access bands have their own allocated md, which would be lost */
388 /* on restore complete otherwise. */
389 rband->band->state = FTL_BAND_STATE_CLOSED;
390 ftl_band_set_direct_access(rband->band, false);
391 }
392 ftl_restore_complete(restore, restore->pad_status);
393 return true;
394 }
395
396 for (i = 0; i < rband->band->num_chunks; ++i) {
397 if (rband->band->chunk_buf[i].state != FTL_CHUNK_STATE_CLOSED) {
398 num_pad_chunks++;
399 }
400 }
401
402 /* Finished all chunks in a band, check if all bands are done */
403 if (num_pad_chunks == 0) {
404 if (direct_access) {
405 rband->band->state = FTL_BAND_STATE_CLOSED;
406 ftl_band_set_direct_access(rband->band, false);
407 }
408 if (--restore->num_pad_bands == 0) {
409 ftl_restore_complete(restore, restore->pad_status);
410 return true;
411 } else {
412 /* Start off padding in the next band */
413 ftl_restore_pad_band(STAILQ_NEXT(rband, stailq));
414 return true;
415 }
416 }
417
418 return false;
419 }
420
421 static struct ftl_io *
422 ftl_restore_init_pad_io(struct ftl_restore_band *rband, void *buffer,
423 struct ftl_ppa ppa)
424 {
425 struct ftl_band *band = rband->band;
426 struct spdk_ftl_dev *dev = band->dev;
427 int flags = FTL_IO_PAD | FTL_IO_INTERNAL | FTL_IO_PPA_MODE | FTL_IO_MD |
428 FTL_IO_DIRECT_ACCESS;
429 struct ftl_io_init_opts opts = {
430 .dev = dev,
431 .io = NULL,
432 .rwb_batch = NULL,
433 .band = band,
434 .size = sizeof(struct ftl_io),
435 .flags = flags,
436 .type = FTL_IO_WRITE,
437 .lbk_cnt = dev->xfer_size,
438 .cb_fn = ftl_pad_chunk_cb,
439 .cb_ctx = rband,
440 .data = buffer,
441 .parent = NULL,
442 };
443 struct ftl_io *io;
444
445 io = ftl_io_init_internal(&opts);
446 if (spdk_unlikely(!io)) {
447 return NULL;
448 }
449
450 io->ppa = ppa;
451 rband->parent->num_ios++;
452
453 return io;
454 }
455
456 static void
457 ftl_pad_chunk_cb(struct ftl_io *io, void *arg, int status)
458 {
459 struct ftl_restore_band *rband = arg;
460 struct ftl_restore *restore = rband->parent;
461 struct ftl_band *band = io->band;
462 struct ftl_chunk *chunk;
463 struct ftl_io *new_io;
464
465 restore->num_ios--;
466 /* TODO check for next unit error vs early close error */
467 if (status) {
468 restore->pad_status = status;
469 goto end;
470 }
471
472 if (io->ppa.lbk + io->lbk_cnt == band->dev->geo.clba) {
473 chunk = ftl_band_chunk_from_ppa(band, io->ppa);
474 chunk->state = FTL_CHUNK_STATE_CLOSED;
475 } else {
476 struct ftl_ppa ppa = io->ppa;
477 ppa.lbk += io->lbk_cnt;
478 new_io = ftl_restore_init_pad_io(rband, io->iov[0].iov_base, ppa);
479 if (spdk_unlikely(!new_io)) {
480 restore->pad_status = -ENOMEM;
481 goto end;
482 }
483
484 ftl_io_write(new_io);
485 return;
486 }
487
488 end:
489 spdk_dma_free(io->iov[0].iov_base);
490 ftl_pad_chunk_pad_finish(rband, true);
491 }
492
493 static void
494 ftl_restore_pad_band(struct ftl_restore_band *rband)
495 {
496 struct spdk_ocssd_chunk_information_entry info;
497 struct ftl_restore *restore = rband->parent;
498 struct ftl_band *band = rband->band;
499 struct spdk_ftl_dev *dev = band->dev;
500 void *buffer = NULL;
501 struct ftl_io *io;
502 struct ftl_ppa ppa;
503 size_t i;
504 int rc = 0;
505
506 /* Check if some chunks are not closed */
507 if (ftl_pad_chunk_pad_finish(rband, false)) {
508 /* If we're here, end meta wasn't recognized, but the whole band is written */
509 /* Assume the band was padded and ignore it */
510 return;
511 }
512
513 /* The LBA map was assigned from restore pool */
514 band->lba_map.map = NULL;
515 band->state = FTL_BAND_STATE_OPEN;
516 rc = ftl_band_set_direct_access(band, true);
517 if (rc) {
518 restore->pad_status = rc;
519 if (--restore->num_pad_bands == 0) {
520 ftl_restore_complete(restore, restore->pad_status);
521 }
522 return;
523 }
524
525 for (i = 0; i < band->num_chunks; ++i) {
526 if (band->chunk_buf[i].state == FTL_CHUNK_STATE_CLOSED) {
527 continue;
528 }
529
530 rc = ftl_retrieve_chunk_info(dev, band->chunk_buf[i].start_ppa, &info, 1);
531 if (spdk_unlikely(rc)) {
532 goto error;
533 }
534 ppa = band->chunk_buf[i].start_ppa;
535 ppa.lbk = info.wp;
536
537 buffer = spdk_dma_zmalloc(FTL_BLOCK_SIZE * dev->xfer_size, sizeof(uint32_t), NULL);
538 if (spdk_unlikely(!buffer)) {
539 rc = -ENOMEM;
540 goto error;
541 }
542
543 io = ftl_restore_init_pad_io(rband, buffer, ppa);
544 if (spdk_unlikely(!io)) {
545 rc = -ENOMEM;
546 spdk_dma_free(buffer);
547 goto error;
548 }
549
550 ftl_io_write(io);
551 }
552
553 return;
554
555 error:
556 restore->pad_status = rc;
557 ftl_pad_chunk_pad_finish(rband, true);
558 }
559
560 static void
561 ftl_restore_pad_open_bands(void *ctx)
562 {
563 struct ftl_restore *restore = ctx;
564
565 ftl_restore_pad_band(STAILQ_FIRST(&restore->pad_bands));
566 }
567
568 static void
569 ftl_restore_tail_md_cb(struct ftl_io *io, void *ctx, int status)
570 {
571 struct ftl_restore_band *rband = ctx;
572 struct ftl_restore *restore = rband->parent;
573 struct spdk_ftl_dev *dev = rband->band->dev;
574
575 if (status) {
576 if (!dev->conf.allow_open_bands) {
577 SPDK_ERRLOG("%s while restoring tail md in band %u.\n",
578 spdk_strerror(-status), rband->band->id);
579 ftl_restore_complete(restore, status);
580 return;
581 } else {
582 SPDK_ERRLOG("%s while restoring tail md. Will attempt to pad band %u.\n",
583 spdk_strerror(-status), rband->band->id);
584 STAILQ_INSERT_TAIL(&restore->pad_bands, rband, stailq);
585 restore->num_pad_bands++;
586 }
587 }
588
589 if (!status && ftl_restore_l2p(rband->band)) {
590 ftl_restore_complete(restore, -ENOTRECOVERABLE);
591 return;
592 }
593
594 rband = ftl_restore_next_band(restore);
595 if (!rband) {
596 if (!STAILQ_EMPTY(&restore->pad_bands)) {
597 spdk_thread_send_msg(ftl_get_core_thread(dev), ftl_restore_pad_open_bands,
598 restore);
599 } else {
600 ftl_restore_complete(restore, status);
601 }
602 return;
603 }
604
605 ftl_restore_tail_md(rband);
606 }
607
608 static int
609 ftl_restore_tail_md(struct ftl_restore_band *rband)
610 {
611 struct ftl_restore *restore = rband->parent;
612 struct ftl_band *band = rband->band;
613
614 band->tail_md_ppa = ftl_band_tail_md_ppa(band);
615 band->lba_map.map = restore->lba_map;
616 band->lba_map.dma_buf = restore->md_buf;
617
618 if (ftl_band_read_tail_md(band, band->tail_md_ppa, ftl_restore_tail_md_cb, rband)) {
619 SPDK_ERRLOG("Failed to send tail metadata read\n");
620 ftl_restore_complete(restore, -EIO);
621 return -EIO;
622 }
623
624 return 0;
625 }
626
627 int
628 ftl_restore_device(struct ftl_restore *restore, ftl_restore_fn cb)
629 {
630 struct ftl_restore_band *rband;
631
632 restore->l2p_phase = true;
633 restore->current = 0;
634 restore->cb = cb;
635
636 /* If restore_device is called, there must be at least one valid band */
637 rband = ftl_restore_next_band(restore);
638 return ftl_restore_tail_md(rband);
639 }