LCOV - code coverage report
Current view: top level - lib/ftl - ftl_p2l_log.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 231 0.0 %
Date: 2024-11-05 10:06:02 Functions: 0 29 0.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright 2023 Solidigm All Rights Reserved
       3             :  */
       4             : 
       5             : #include "ftl_core.h"
       6             : #include "ftl_io.h"
       7             : #include "ftl_layout.h"
       8             : #include "utils/ftl_defs.h"
       9             : 
      10             : struct ftl_pl2_log_item {
      11             :         uint64_t lba;
      12             :         uint64_t num_blocks;
      13             :         uint64_t seq_id;
      14             :         ftl_addr addr;
      15             : };
      16             : #define FTL_P2L_LOG_ITEMS_IN_PAGE ((FTL_BLOCK_SIZE - sizeof(union ftl_md_vss)) / sizeof(struct ftl_pl2_log_item))
      17             : #define FTL_P2L_LOG_PAGE_COUNT_DEFAULT 128
      18             : 
      19             : struct ftl_p2l_log_page {
      20             :         union ftl_md_vss hdr;
      21             :         struct ftl_pl2_log_item items[FTL_P2L_LOG_ITEMS_IN_PAGE];
      22             : };
      23             : SPDK_STATIC_ASSERT(sizeof(struct ftl_p2l_log_page) == FTL_BLOCK_SIZE, "Invalid size of P2L page");
      24             : 
      25             : struct ftl_p2l_log_page_ctrl {
      26             :         struct ftl_p2l_log_page page;
      27             :         struct ftl_p2l_log *p2l;
      28             :         uint64_t entry_idx;
      29             :         TAILQ_HEAD(, ftl_io) ios;
      30             :         struct ftl_md_io_entry_ctx md_ctx;
      31             : };
      32             : 
      33             : struct ftl_p2l_log {
      34             :         struct spdk_ftl_dev             *dev;
      35             :         TAILQ_ENTRY(ftl_p2l_log)        link;
      36             :         TAILQ_HEAD(, ftl_io)            ios;
      37             :         struct ftl_md                   *md;
      38             :         uint64_t                        seq_id;
      39             :         struct ftl_mempool              *page_pool;
      40             :         uint64_t                        entry_idx;
      41             :         uint64_t                        entry_max;
      42             :         ftl_p2l_log_cb                  cb_fn;
      43             :         uint32_t                        ref_cnt;
      44             :         bool                            in_use;
      45             : 
      46             :         struct {
      47             :                 spdk_ftl_fn cb_fn;
      48             :                 void *cb_arg;
      49             :                 ftl_p2l_log_rd_cb cb_rd;
      50             :                 uint64_t qd;
      51             :                 uint64_t idx;
      52             :                 uint64_t seq_id;
      53             :                 int result;
      54             :         } read_ctx;
      55             : };
      56             : 
      57             : static void p2l_log_page_io(struct ftl_p2l_log *p2l, struct ftl_p2l_log_page_ctrl *ctrl);
      58             : static void ftl_p2l_log_read_process(struct ftl_p2l_log *p2l);
      59             : 
      60             : static struct ftl_p2l_log *
      61           0 : p2l_log_create(struct spdk_ftl_dev *dev, uint32_t region_type)
      62             : {
      63             :         struct ftl_p2l_log *p2l;
      64             : 
      65           0 :         p2l = calloc(1, sizeof(struct ftl_p2l_log));
      66           0 :         if (!p2l) {
      67           0 :                 return NULL;
      68             :         }
      69             : 
      70           0 :         TAILQ_INIT(&p2l->ios);
      71           0 :         p2l->dev = dev;
      72           0 :         p2l->md = dev->layout.md[region_type];
      73           0 :         p2l->entry_max = ftl_md_get_buffer_size(p2l->md) / FTL_BLOCK_SIZE;
      74           0 :         p2l->page_pool = ftl_mempool_create(FTL_P2L_LOG_PAGE_COUNT_DEFAULT,
      75             :                                             sizeof(struct ftl_p2l_log_page_ctrl),
      76             :                                             FTL_BLOCK_SIZE, SPDK_ENV_SOCKET_ID_ANY);
      77           0 :         if (!p2l->page_pool) {
      78           0 :                 goto ERROR;
      79             :         }
      80             : 
      81           0 :         return p2l;
      82           0 : ERROR:
      83           0 :         free(p2l);
      84           0 :         return NULL;
      85             : }
      86             : 
      87             : static void
      88           0 : p2l_log_destroy(struct ftl_p2l_log *p2l)
      89             : {
      90           0 :         if (!p2l) {
      91           0 :                 return;
      92             :         }
      93             : 
      94           0 :         ftl_mempool_destroy(p2l->page_pool);
      95           0 :         free(p2l);
      96             : }
      97             : 
      98             : static struct ftl_p2l_log_page_ctrl *
      99           0 : p2l_log_get_page(struct ftl_p2l_log *p2l)
     100             : {
     101             :         struct ftl_p2l_log_page_ctrl *ctrl;
     102             : 
     103           0 :         ctrl = ftl_mempool_get(p2l->page_pool);
     104           0 :         if (!ctrl) {
     105           0 :                 return NULL;
     106             :         }
     107             : 
     108             :         /* Initialize P2L header */
     109           0 :         ctrl->page.hdr.p2l_ckpt.seq_id = p2l->seq_id;
     110           0 :         ctrl->page.hdr.p2l_ckpt.count = 0;
     111           0 :         ctrl->page.hdr.p2l_ckpt.p2l_checksum = 0;
     112           0 :         ctrl->page.hdr.p2l_ckpt.idx = ctrl->entry_idx = p2l->entry_idx;
     113             : 
     114             :         /* Initialize the page control structure */
     115           0 :         ctrl->p2l = p2l;
     116           0 :         TAILQ_INIT(&ctrl->ios);
     117             : 
     118             :         /* Increase P2L page index */
     119           0 :         p2l->entry_idx++;
     120             : 
     121             :         /* Check if the index exceeding the buffer size */
     122           0 :         ftl_bug(p2l->entry_idx > p2l->entry_max);
     123             : 
     124           0 :         return ctrl;
     125             : }
     126             : 
     127             : static bool
     128           0 : l2p_log_page_is_full(struct ftl_p2l_log_page_ctrl *ctrl)
     129             : {
     130           0 :         return ctrl->page.hdr.p2l_ckpt.count == FTL_P2L_LOG_ITEMS_IN_PAGE;
     131             : }
     132             : 
     133             : static void
     134           0 : p2l_log_page_free(struct ftl_p2l_log *p2l, struct ftl_p2l_log_page_ctrl *ctrl)
     135             : {
     136           0 :         ftl_mempool_put(p2l->page_pool, ctrl);
     137           0 : }
     138             : 
     139             : static void
     140           0 : p2l_log_handle_io_error(struct ftl_p2l_log *p2l, struct ftl_p2l_log_page_ctrl *ctrl)
     141             : {
     142             : #ifdef SPDK_FTL_RETRY_ON_ERROR
     143             :         p2l_log_page_io(p2l, ctrl);
     144             : #else
     145           0 :         ftl_abort();
     146             : #endif
     147             : }
     148             : 
     149             : static uint32_t
     150           0 : p2l_log_page_crc(struct ftl_p2l_log_page *page)
     151             : {
     152           0 :         uint32_t crc = 0;
     153           0 :         void *buffer = page;
     154           0 :         size_t size = sizeof(*page);
     155           0 :         size_t offset = offsetof(struct ftl_p2l_log_page, hdr.p2l_ckpt.p2l_checksum);
     156             : 
     157           0 :         crc = spdk_crc32c_update(buffer, offset, crc);
     158           0 :         buffer += offset + sizeof(page->hdr.p2l_ckpt.p2l_checksum);
     159           0 :         size -= offset + sizeof(page->hdr.p2l_ckpt.p2l_checksum);
     160             : 
     161           0 :         return spdk_crc32c_update(buffer, size, crc);
     162             : }
     163             : 
     164             : static void
     165           0 : p2l_log_page_io_cb(int status, void *arg)
     166             : {
     167           0 :         struct ftl_p2l_log_page_ctrl *ctrl = arg;
     168           0 :         struct ftl_p2l_log *p2l = ctrl->p2l;
     169             :         struct ftl_io *io;
     170             : 
     171           0 :         if (status) {
     172           0 :                 p2l_log_handle_io_error(p2l, ctrl);
     173           0 :                 return;
     174             :         }
     175             : 
     176           0 :         while ((io = TAILQ_FIRST(&ctrl->ios))) {
     177           0 :                 TAILQ_REMOVE(&ctrl->ios, io, queue_entry);
     178           0 :                 p2l->cb_fn(io);
     179             :         }
     180             : 
     181           0 :         p2l_log_page_free(p2l, ctrl);
     182             : }
     183             : 
     184             : static void
     185           0 : p2l_log_page_io(struct ftl_p2l_log *p2l, struct ftl_p2l_log_page_ctrl *ctrl)
     186             : {
     187           0 :         ctrl->page.hdr.p2l_ckpt.p2l_checksum = p2l_log_page_crc(&ctrl->page);
     188             : 
     189           0 :         ftl_md_persist_entries(p2l->md, ctrl->page.hdr.p2l_ckpt.idx, 1, &ctrl->page, NULL,
     190             :                                p2l_log_page_io_cb,
     191             :                                ctrl, &ctrl->md_ctx);
     192           0 : }
     193             : 
     194             : static void
     195           0 : p2l_log_add_io(struct ftl_p2l_log *p2l, struct ftl_p2l_log_page_ctrl *ctrl, struct ftl_io *io)
     196             : {
     197           0 :         uint64_t i = ctrl->page.hdr.p2l_ckpt.count++;
     198             : 
     199           0 :         assert(i < FTL_P2L_LOG_ITEMS_IN_PAGE);
     200           0 :         ctrl->page.items[i].lba = io->lba;
     201           0 :         ctrl->page.items[i].num_blocks = io->num_blocks;
     202           0 :         ctrl->page.items[i].seq_id = io->nv_cache_chunk->md->seq_id;
     203           0 :         ctrl->page.items[i].addr = io->addr;
     204             : 
     205             :         /* TODO Make sure P2L map is updated respectively */
     206             : 
     207           0 :         TAILQ_REMOVE(&p2l->ios, io, queue_entry);
     208           0 :         TAILQ_INSERT_TAIL(&ctrl->ios, io, queue_entry);
     209           0 : }
     210             : 
     211             : void
     212           0 : ftl_p2l_log_io(struct ftl_p2l_log *p2l, struct ftl_io *io)
     213             : {
     214           0 :         TAILQ_INSERT_TAIL(&p2l->ios, io, queue_entry);
     215           0 : }
     216             : 
     217             : static void
     218           0 : p2l_log_flush(struct ftl_p2l_log *p2l)
     219             : {
     220           0 :         struct ftl_p2l_log_page_ctrl *ctrl = NULL;
     221             :         struct ftl_io *io;
     222             : 
     223           0 :         while ((io = TAILQ_FIRST(&p2l->ios))) {
     224           0 :                 if (!ctrl) {
     225           0 :                         ctrl = p2l_log_get_page(p2l);
     226           0 :                         if (!ctrl) {
     227             :                                 /* No page at the moment, try next time */
     228           0 :                                 break;
     229             :                         }
     230             :                 }
     231             : 
     232           0 :                 p2l_log_add_io(p2l, ctrl, io);
     233             : 
     234           0 :                 if (l2p_log_page_is_full(ctrl)) {
     235           0 :                         p2l_log_page_io(p2l, ctrl);
     236           0 :                         ctrl = NULL;
     237             :                 }
     238             :         }
     239             : 
     240           0 :         if (ctrl) {
     241           0 :                 p2l_log_page_io(p2l, ctrl);
     242             :         }
     243           0 : }
     244             : 
     245             : void
     246           0 : ftl_p2l_log_flush(struct spdk_ftl_dev *dev)
     247             : {
     248             :         struct ftl_p2l_log *p2l;
     249             : 
     250           0 :         TAILQ_FOREACH(p2l, &dev->p2l_ckpt.log.inuse, link) {
     251           0 :                 p2l_log_flush(p2l);
     252             :         }
     253           0 : }
     254             : 
     255             : uint64_t
     256           0 : ftl_p2l_log_get_md_blocks_required(struct spdk_ftl_dev *dev, uint64_t write_unit_blocks,
     257             :                                    uint64_t max_user_data_blocks)
     258             : {
     259           0 :         return spdk_divide_round_up(max_user_data_blocks, write_unit_blocks);
     260             : }
     261             : 
     262             : int
     263           0 : ftl_p2l_log_init(struct spdk_ftl_dev *dev)
     264             : {
     265             :         struct ftl_p2l_log *p2l;
     266             :         uint32_t region_type;
     267             : 
     268           0 :         TAILQ_INIT(&dev->p2l_ckpt.log.free);
     269           0 :         TAILQ_INIT(&dev->p2l_ckpt.log.inuse);
     270             : 
     271           0 :         for (region_type = FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MIN;
     272           0 :              region_type <= FTL_LAYOUT_REGION_TYPE_P2L_LOG_IO_MAX;
     273           0 :              region_type++) {
     274           0 :                 p2l = p2l_log_create(dev, region_type);
     275           0 :                 if (!p2l) {
     276           0 :                         return -ENOMEM;
     277             :                 }
     278             : 
     279           0 :                 TAILQ_INSERT_TAIL(&dev->p2l_ckpt.log.free, p2l, link);
     280             :         }
     281             : 
     282           0 :         return 0;
     283             : }
     284             : 
     285             : void
     286           0 : ftl_p2l_log_deinit(struct spdk_ftl_dev *dev)
     287             : {
     288             :         struct ftl_p2l_log *p2l, *p2l_next;
     289             : 
     290           0 :         TAILQ_FOREACH_SAFE(p2l, &dev->p2l_ckpt.log.free, link, p2l_next) {
     291           0 :                 TAILQ_REMOVE(&dev->p2l_ckpt.log.free, p2l, link);
     292           0 :                 p2l_log_destroy(p2l);
     293             :         }
     294             : 
     295           0 :         TAILQ_FOREACH_SAFE(p2l, &dev->p2l_ckpt.log.inuse, link, p2l_next) {
     296           0 :                 TAILQ_REMOVE(&dev->p2l_ckpt.log.inuse, p2l, link);
     297           0 :                 p2l_log_destroy(p2l);
     298             :         }
     299           0 : }
     300             : 
     301             : enum ftl_layout_region_type
     302           0 : ftl_p2l_log_type(struct ftl_p2l_log *p2l) {
     303           0 :         return p2l->md->region->type;
     304             : }
     305             : 
     306             : struct ftl_p2l_log *
     307           0 : ftl_p2l_log_acquire(struct spdk_ftl_dev *dev, uint64_t seq_id, ftl_p2l_log_cb cb)
     308             : {
     309             :         struct ftl_p2l_log *p2l;
     310             : 
     311           0 :         p2l = TAILQ_FIRST(&dev->p2l_ckpt.log.free);
     312           0 :         assert(p2l);
     313           0 :         TAILQ_REMOVE(&dev->p2l_ckpt.log.free, p2l, link);
     314           0 :         TAILQ_INSERT_TAIL(&dev->p2l_ckpt.log.inuse, p2l, link);
     315             : 
     316           0 :         p2l->entry_idx = 0;
     317           0 :         p2l->seq_id = seq_id;
     318           0 :         p2l->cb_fn = cb;
     319             : 
     320           0 :         return p2l;
     321             : }
     322             : 
     323             : void
     324           0 : ftl_p2l_log_release(struct spdk_ftl_dev *dev, struct ftl_p2l_log *p2l)
     325             : {
     326           0 :         assert(p2l);
     327             : 
     328             :         /* TODO: Add assert if no ongoing IOs on the P2L log */
     329             :         /* TODO: Add assert if the P2L log already open */
     330             : 
     331           0 :         TAILQ_REMOVE(&dev->p2l_ckpt.log.inuse, p2l, link);
     332           0 :         TAILQ_INSERT_TAIL(&dev->p2l_ckpt.log.free, p2l, link);
     333           0 : }
     334             : 
     335             : static struct ftl_p2l_log *
     336           0 : p2l_log_get(struct spdk_ftl_dev *dev, enum ftl_layout_region_type type)
     337             : {
     338             :         struct ftl_p2l_log *p2l_Log;
     339             : 
     340           0 :         TAILQ_FOREACH(p2l_Log, &dev->p2l_ckpt.log.free, link) {
     341           0 :                 if (type == p2l_Log->md->region->type) {
     342           0 :                         return p2l_Log;
     343             :                 }
     344             :         }
     345             : 
     346           0 :         TAILQ_FOREACH(p2l_Log, &dev->p2l_ckpt.log.inuse, link) {
     347           0 :                 if (type == p2l_Log->md->region->type) {
     348           0 :                         return p2l_Log;
     349             :                 }
     350             :         }
     351             : 
     352           0 :         return NULL;
     353             : }
     354             : 
     355             : static bool
     356           0 : p2l_log_read_in_progress(struct ftl_p2l_log *p2l)
     357             : {
     358           0 :         return p2l->read_ctx.cb_fn ? true : false;
     359             : }
     360             : 
     361             : static bool
     362           0 : ftl_p2l_log_read_is_next(struct ftl_p2l_log *p2l)
     363             : {
     364           0 :         if (p2l->read_ctx.result) {
     365           0 :                 return false;
     366             :         }
     367             : 
     368           0 :         return p2l->read_ctx.idx < p2l->entry_max;
     369             : }
     370             : 
     371             : static bool
     372           0 : ftl_p2l_log_read_is_qd(struct ftl_p2l_log *p2l)
     373             : {
     374           0 :         return p2l->read_ctx.qd > 0;
     375             : }
     376             : 
     377             : static bool
     378           0 : ftl_p2l_log_read_is_finished(struct ftl_p2l_log *p2l)
     379             : {
     380           0 :         if (ftl_p2l_log_read_is_next(p2l) || ftl_p2l_log_read_is_qd(p2l)) {
     381           0 :                 return false;
     382             :         }
     383             : 
     384           0 :         return true;
     385             : }
     386             : 
     387             : static void
     388           0 : ftl_p2l_log_read_finish(struct ftl_p2l_log *p2l)
     389             : {
     390           0 :         spdk_ftl_fn cb_fn = p2l->read_ctx.cb_fn;
     391           0 :         void *cb_arg = p2l->read_ctx.cb_arg;
     392           0 :         int result = p2l->read_ctx.result;
     393             : 
     394           0 :         memset(&p2l->read_ctx, 0, sizeof(p2l->read_ctx));
     395           0 :         cb_fn(cb_arg, result);
     396           0 : }
     397             : 
     398             : static void
     399           0 : ftl_p2l_log_read_visit(struct ftl_p2l_log *p2l, struct ftl_p2l_log_page_ctrl *ctrl)
     400             : {
     401           0 :         struct ftl_p2l_log_page *page = &ctrl->page;
     402           0 :         struct spdk_ftl_dev *dev = p2l->dev;
     403           0 :         ftl_p2l_log_rd_cb cb_rd = p2l->read_ctx.cb_rd;
     404           0 :         void *cb_arg = p2l->read_ctx.cb_arg;
     405           0 :         uint64_t crc = p2l_log_page_crc(&ctrl->page);
     406             :         uint64_t i, j;
     407           0 :         int rc = 0;
     408             : 
     409           0 :         ftl_bug(ctrl->entry_idx > p2l->entry_max);
     410             : 
     411           0 :         if (p2l->read_ctx.seq_id != page->hdr.p2l_ckpt.seq_id) {
     412             :                 /* This page contains entires older than the owner's sequence ID */
     413           0 :                 return;
     414             :         }
     415             : 
     416           0 :         if (ctrl->entry_idx != page->hdr.p2l_ckpt.idx) {
     417           0 :                 FTL_ERRLOG(p2l->dev, "Read P2L IO Logs ERROR, invalid index, type %d\n",
     418             :                            p2l->md->region->type);
     419           0 :                 p2l->read_ctx.result = -EINVAL;
     420           0 :                 return;
     421             :         }
     422             : 
     423           0 :         if (crc != page->hdr.p2l_ckpt.p2l_checksum) {
     424           0 :                 FTL_ERRLOG(p2l->dev, "Read P2L IO Log ERROR, CRC problem, type %d\n",
     425             :                            p2l->md->region->type);
     426           0 :                 p2l->read_ctx.result = -EINVAL;
     427           0 :                 return;
     428             :         }
     429             : 
     430           0 :         if (page->hdr.p2l_ckpt.count > SPDK_COUNTOF(page->items)) {
     431           0 :                 FTL_ERRLOG(p2l->dev, "Read P2L IO Log ERROR, inconsistent format, type %d\n",
     432             :                            p2l->md->region->type);
     433           0 :                 p2l->read_ctx.result = -EINVAL;
     434           0 :                 return;
     435             :         }
     436             : 
     437           0 :         for (i = 0; i < page->hdr.p2l_ckpt.count; i++) {
     438           0 :                 struct ftl_pl2_log_item *item = &page->items[i];
     439             : 
     440           0 :                 for (j = 0; j < item->num_blocks; j++) {
     441           0 :                         rc = cb_rd(dev, cb_arg, item->lba + j, item->addr + j, item->seq_id);
     442           0 :                         if (rc) {
     443           0 :                                 p2l->read_ctx.result = rc;
     444           0 :                                 break;
     445             :                         }
     446             :                 }
     447             : 
     448           0 :                 if (rc) {
     449           0 :                         break;
     450             :                 }
     451             :         }
     452             : }
     453             : 
     454             : static void
     455           0 : ftl_p2l_log_read_cb(int status, void *arg)
     456             : {
     457           0 :         struct ftl_p2l_log_page_ctrl *ctrl = arg;
     458           0 :         struct ftl_p2l_log *p2l = ctrl->p2l;
     459             : 
     460           0 :         assert(p2l->read_ctx.qd > 0);
     461           0 :         p2l->read_ctx.qd--;
     462             : 
     463           0 :         if (status) {
     464           0 :                 p2l->read_ctx.result = status;
     465             :         } else {
     466           0 :                 ftl_p2l_log_read_visit(p2l, ctrl);
     467             :         }
     468             : 
     469             :         /* Release page control */
     470           0 :         ftl_mempool_put(p2l->page_pool, ctrl);
     471           0 :         ftl_p2l_log_read_process(p2l);
     472           0 : }
     473             : 
     474             : static void
     475           0 : ftl_p2l_log_read_process(struct ftl_p2l_log *p2l)
     476             : {
     477             :         struct ftl_p2l_log_page_ctrl *ctrl;
     478             : 
     479           0 :         while (ftl_p2l_log_read_is_next(p2l)) {
     480           0 :                 ctrl = ftl_mempool_get(p2l->page_pool);
     481           0 :                 if (!ctrl) {
     482           0 :                         break;
     483             :                 }
     484             : 
     485           0 :                 ctrl->p2l = p2l;
     486           0 :                 ctrl->entry_idx = p2l->read_ctx.idx++;
     487             : 
     488             :                 /* Check if the index exceeding the buffer size */
     489           0 :                 ftl_bug(p2l->read_ctx.idx > p2l->entry_max);
     490             : 
     491           0 :                 p2l->read_ctx.qd++;
     492           0 :                 ftl_md_read_entry(p2l->md, ctrl->entry_idx, &ctrl->page, NULL,
     493             :                                   ftl_p2l_log_read_cb, ctrl, &ctrl->md_ctx);
     494             :         }
     495             : 
     496           0 :         if (ftl_p2l_log_read_is_finished(p2l)) {
     497           0 :                 ftl_p2l_log_read_finish(p2l);
     498             :         }
     499           0 : }
     500             : 
     501             : int
     502           0 : ftl_p2l_log_read(struct spdk_ftl_dev *dev, enum ftl_layout_region_type type, uint64_t seq_id,
     503             :                  spdk_ftl_fn cb_fn, void *cb_arg, ftl_p2l_log_rd_cb cb_rd)
     504             : {
     505           0 :         struct ftl_p2l_log *p2l_log = p2l_log_get(dev, type);
     506             : 
     507           0 :         if (!p2l_log) {
     508           0 :                 FTL_ERRLOG(dev, "Read P2L IO Log ERROR, no such log, type %d\n", type);
     509           0 :                 return -ENODEV;
     510             :         }
     511           0 :         if (p2l_log_read_in_progress(p2l_log)) {
     512           0 :                 FTL_ERRLOG(dev, "Read P2L IO Log ERROR, read busy, type %d\n", type);
     513           0 :                 return -EBUSY;
     514             :         }
     515             : 
     516           0 :         memset(&p2l_log->read_ctx, 0, sizeof(p2l_log->read_ctx));
     517           0 :         p2l_log->read_ctx.cb_fn = cb_fn;
     518           0 :         p2l_log->read_ctx.cb_arg = cb_arg;
     519           0 :         p2l_log->read_ctx.cb_rd = cb_rd;
     520           0 :         p2l_log->read_ctx.seq_id = seq_id;
     521             : 
     522           0 :         ftl_p2l_log_read_process(p2l_log);
     523           0 :         if (ftl_p2l_log_read_is_qd(p2l_log)) {
     524             :                 /* Read in progress */
     525           0 :                 return 0;
     526             :         } else {
     527           0 :                 FTL_ERRLOG(dev, "Read P2L IO Log ERROR, operation not started, type %d\n", type);
     528           0 :                 return -EINVAL;
     529             :         }
     530             : }

Generated by: LCOV version 1.15