LCOV - code coverage report
Current view: top level - lib/ftl/mngt - ftl_mngt_self_test.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 83 0.0 %
Date: 2024-07-14 09:59:02 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2022 Intel Corporation.
       3             :  *   All rights reserved.
       4             :  */
       5             : 
       6             : #include "ftl_mngt.h"
       7             : #include "ftl_mngt_steps.h"
       8             : #include "ftl_internal.h"
       9             : #include "ftl_core.h"
      10             : #include "ftl_band.h"
      11             : 
      12             : struct ftl_validate_ctx {
      13             :         struct {
      14             :                 struct ftl_bitmap *bitmap;
      15             :                 void *buffer;
      16             :                 uint64_t buffer_size;
      17             :                 uint64_t bit_count;
      18             :                 uint64_t base_valid_count;
      19             :                 uint64_t cache_valid_count;
      20             :         } valid_map;
      21             : 
      22             :         int status;
      23             : };
      24             : 
      25             : static void
      26           0 : ftl_mngt_test_prepare(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
      27             : {
      28           0 :         struct ftl_validate_ctx *cntx = ftl_mngt_get_process_ctx(mngt);
      29             : 
      30           0 :         cntx->valid_map.bit_count = dev->layout.base.total_blocks +
      31           0 :                                     dev->layout.nvc.total_blocks;
      32           0 :         cntx->valid_map.buffer_size = spdk_divide_round_up(cntx->valid_map.bit_count, 8);
      33           0 :         cntx->valid_map.buffer_size = SPDK_ALIGN_CEIL(cntx->valid_map.buffer_size,
      34             :                                       ftl_bitmap_buffer_alignment);
      35             : 
      36           0 :         cntx->valid_map.buffer = calloc(cntx->valid_map.buffer_size, 1);
      37           0 :         if (!cntx->valid_map.buffer) {
      38           0 :                 ftl_mngt_fail_step(mngt);
      39           0 :                 return;
      40             :         }
      41             : 
      42           0 :         cntx->valid_map.bitmap = ftl_bitmap_create(cntx->valid_map.buffer,
      43             :                                  cntx->valid_map.buffer_size);
      44           0 :         if (!cntx->valid_map.bitmap) {
      45           0 :                 ftl_mngt_fail_step(mngt);
      46           0 :                 return;
      47             :         }
      48             : 
      49           0 :         ftl_mngt_next_step(mngt);
      50             : }
      51             : 
      52             : static void
      53           0 : ftl_mngt_test_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
      54             : {
      55           0 :         struct ftl_validate_ctx *cntx = ftl_mngt_get_process_ctx(mngt);
      56             : 
      57           0 :         ftl_bitmap_destroy(cntx->valid_map.bitmap);
      58           0 :         cntx->valid_map.bitmap = NULL;
      59             : 
      60           0 :         free(cntx->valid_map.buffer);
      61           0 :         cntx->valid_map.buffer = NULL;
      62             : 
      63           0 :         ftl_mngt_next_step(mngt);
      64           0 : }
      65             : 
      66             : static void
      67           0 : test_valid_map_pin_cb(struct spdk_ftl_dev *dev, int status,
      68             :                       struct ftl_l2p_pin_ctx *pin_ctx)
      69             : {
      70           0 :         struct ftl_mngt_process *mngt = pin_ctx->cb_ctx;
      71           0 :         struct ftl_validate_ctx *ctx = ftl_mngt_get_process_ctx(mngt);
      72             :         uint64_t lba, end;
      73             : 
      74           0 :         if (status) {
      75           0 :                 FTL_ERRLOG(dev, "L2P pin ERROR when testing valid map\n");
      76           0 :                 ftl_mngt_fail_step(mngt);
      77           0 :                 return;
      78             :         }
      79             : 
      80           0 :         lba = pin_ctx->lba;
      81           0 :         end = pin_ctx->lba + pin_ctx->count;
      82             : 
      83           0 :         for (; lba < end; ++lba) {
      84           0 :                 ftl_addr addr = ftl_l2p_get(dev, lba);
      85             :                 bool valid;
      86             : 
      87           0 :                 if (FTL_ADDR_INVALID == addr) {
      88           0 :                         continue;
      89             :                 }
      90             : 
      91           0 :                 if (ftl_bitmap_get(ctx->valid_map.bitmap, addr)) {
      92           0 :                         status = -EINVAL;
      93           0 :                         FTL_ERRLOG(dev, "L2P mapping ERROR, double reference, "
      94             :                                    "address 0x%.16"PRIX64"\n", addr);
      95           0 :                         break;
      96             :                 } else {
      97           0 :                         ftl_bitmap_set(ctx->valid_map.bitmap, addr);
      98             :                 }
      99             : 
     100           0 :                 if (ftl_addr_in_nvc(dev, addr)) {
     101           0 :                         ctx->valid_map.cache_valid_count++;
     102             :                 } else {
     103           0 :                         ctx->valid_map.base_valid_count++;
     104             :                 }
     105             : 
     106           0 :                 valid = ftl_bitmap_get(dev->valid_map, addr);
     107           0 :                 if (!valid) {
     108           0 :                         status = -EINVAL;
     109           0 :                         FTL_ERRLOG(dev, "L2P and valid map mismatch"
     110             :                                    ", LBA 0x%.16"PRIX64
     111             :                                    ", address 0x%.16"PRIX64" unset\n",
     112             :                                    lba, addr);
     113           0 :                         break;
     114             :                 }
     115             :         }
     116             : 
     117           0 :         ftl_l2p_unpin(dev, pin_ctx->lba, pin_ctx->count);
     118           0 :         pin_ctx->lba += pin_ctx->count;
     119             : 
     120           0 :         if (!status) {
     121           0 :                 ftl_mngt_continue_step(mngt);
     122             :         } else {
     123           0 :                 ftl_mngt_fail_step(mngt);
     124             :         }
     125             : }
     126             : 
     127             : static void
     128           0 : ftl_mngt_test_valid_map(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     129             : {
     130             :         struct ftl_l2p_pin_ctx *pin_ctx;
     131           0 :         struct ftl_validate_ctx *ctx = ftl_mngt_get_process_ctx(mngt);
     132             :         uint64_t left;
     133             : 
     134           0 :         pin_ctx = ftl_mngt_get_step_ctx(mngt);
     135           0 :         if (!pin_ctx) {
     136           0 :                 if (ftl_mngt_alloc_step_ctx(mngt, sizeof(*pin_ctx))) {
     137           0 :                         ftl_mngt_fail_step(mngt);
     138           0 :                         return;
     139             :                 }
     140           0 :                 pin_ctx = ftl_mngt_get_step_ctx(mngt);
     141           0 :                 assert(pin_ctx);
     142             : 
     143           0 :                 pin_ctx->lba = 0;
     144           0 :                 memset(ctx->valid_map.buffer, 0, ctx->valid_map.buffer_size);
     145             :         }
     146             : 
     147           0 :         left = dev->num_lbas - pin_ctx->lba;
     148           0 :         pin_ctx->count = spdk_min(left, 4096);
     149             : 
     150           0 :         if (pin_ctx->count) {
     151           0 :                 ftl_l2p_pin(dev, pin_ctx->lba, pin_ctx->count,
     152             :                             test_valid_map_pin_cb, mngt, pin_ctx);
     153             :         } else {
     154           0 :                 if (!ctx->status) {
     155           0 :                         uint64_t valid = ctx->valid_map.base_valid_count +
     156           0 :                                          ctx->valid_map.cache_valid_count;
     157             : 
     158           0 :                         if (ftl_bitmap_count_set(dev->valid_map) != valid) {
     159           0 :                                 ctx->status = -EINVAL;
     160             :                         }
     161             :                 }
     162             : 
     163             :                 /* All done */
     164           0 :                 if (ctx->status) {
     165           0 :                         ftl_mngt_fail_step(mngt);
     166             :                 } else {
     167           0 :                         ftl_mngt_next_step(mngt);
     168             :                 }
     169             :         }
     170             : }
     171             : 
     172             : /*
     173             :  * Verifies the contents of L2P versus valid map. Makes sure any physical addresses in the L2P
     174             :  * have their corresponding valid bits set and that two different logical addresses don't point
     175             :  * to the same physical address.
     176             :  *
     177             :  * For debugging purposes only, directed via environment variable - whole L2P needs to be loaded in
     178             :  * and checked.
     179             :  */
     180             : static const struct ftl_mngt_process_desc desc_self_test = {
     181             :         .name = "[Test] Startup Test",
     182             :         .ctx_size = sizeof(struct ftl_validate_ctx),
     183             :         .steps = {
     184             :                 {
     185             :                         .name = "[TEST] Initialize selftest",
     186             : 
     187             :                         .action = ftl_mngt_test_prepare,
     188             :                         .cleanup = ftl_mngt_test_cleanup
     189             :                 },
     190             :                 {
     191             :                         .name = "[TEST] Validate map and L2P consistency",
     192             :                         .action = ftl_mngt_test_valid_map
     193             :                 },
     194             :                 {
     195             :                         .name = "[TEST] Deinitialize cleanup",
     196             :                         .action = ftl_mngt_test_cleanup
     197             :                 },
     198             :                 {}
     199             :         }
     200             : };
     201             : 
     202             : void
     203           0 : ftl_mngt_self_test(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt)
     204             : {
     205           0 :         if (getenv("FTL_SELF_TEST")) {
     206           0 :                 ftl_mngt_call_process(mngt, &desc_self_test);
     207             :         } else {
     208           0 :                 FTL_NOTICELOG(dev, "Self test skipped\n");
     209           0 :                 ftl_mngt_next_step(mngt);
     210             :         }
     211           0 : }

Generated by: LCOV version 1.15