LCOV - code coverage report
Current view: top level - module/accel/error - accel_error.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 120 0.0 %
Date: 2024-07-12 02:49:39 Functions: 0 17 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: BSD-3-Clause
       2             :  * Copyright (C) 2023 Intel Corporation. All rights reserved.
       3             :  */
       4             : 
       5             : #include "accel_error.h"
       6             : #include "spdk/accel.h"
       7             : #include "spdk/accel_module.h"
       8             : #include "spdk/json.h"
       9             : #include "spdk/thread.h"
      10             : 
      11             : struct accel_error_inject_info {
      12             :         /* Error injection options */
      13             :         struct accel_error_inject_opts  opts;
      14             :         /* Number of errors already injected on this channel */
      15             :         uint64_t                        count;
      16             :         /* Number of operations executed since last error injection */
      17             :         uint64_t                        interval;
      18             : };
      19             : 
      20             : struct accel_error_channel {
      21             :         struct spdk_io_channel          *swch;
      22             :         struct accel_error_inject_info  injects[SPDK_ACCEL_OPC_LAST];
      23             : };
      24             : 
      25             : struct accel_error_task {
      26             :         struct accel_error_channel      *ch;
      27             :         spdk_accel_completion_cb        cb_fn;
      28             :         void                            *cb_arg;
      29             : };
      30             : 
      31             : static struct spdk_accel_module_if *g_sw_module;
      32             : static struct accel_error_inject_opts g_injects[SPDK_ACCEL_OPC_LAST];
      33             : static size_t g_task_offset;
      34             : 
      35             : static struct accel_error_task *
      36           0 : accel_error_get_task_ctx(struct spdk_accel_task *task)
      37             : {
      38           0 :         return (void *)((uint8_t *)task + g_task_offset);
      39             : }
      40             : 
      41             : static void
      42           0 : accel_error_corrupt_task(struct spdk_accel_task *task)
      43             : {
      44           0 :         switch (task->op_code) {
      45           0 :         case SPDK_ACCEL_OPC_CRC32C:
      46           0 :                 *task->crc_dst += 1;
      47           0 :                 break;
      48           0 :         default:
      49           0 :                 break;
      50             :         }
      51           0 : }
      52             : 
      53             : static void
      54           0 : accel_error_task_complete_cb(void *arg, int status)
      55             : {
      56           0 :         struct spdk_accel_task *task = arg;
      57           0 :         struct accel_error_task *errtask = accel_error_get_task_ctx(task);
      58           0 :         struct accel_error_channel *ch = errtask->ch;
      59           0 :         struct accel_error_inject_info *info = &ch->injects[task->op_code];
      60           0 :         spdk_accel_completion_cb cb_fn = errtask->cb_fn;
      61           0 :         void *cb_arg = errtask->cb_arg;
      62             : 
      63           0 :         info->interval++;
      64           0 :         if (info->interval >= info->opts.interval) {
      65           0 :                 info->interval = 0;
      66           0 :                 info->count++;
      67             : 
      68           0 :                 if (info->count <= info->opts.count) {
      69           0 :                         switch (info->opts.type) {
      70           0 :                         case ACCEL_ERROR_INJECT_CORRUPT:
      71           0 :                                 accel_error_corrupt_task(task);
      72           0 :                                 break;
      73           0 :                         case ACCEL_ERROR_INJECT_FAILURE:
      74           0 :                                 status = info->opts.errcode;
      75           0 :                                 break;
      76           0 :                         default:
      77           0 :                                 break;
      78             :                         }
      79             :                 } else {
      80           0 :                         info->opts.type = ACCEL_ERROR_INJECT_DISABLE;
      81             :                 }
      82             :         }
      83             : 
      84           0 :         cb_fn(cb_arg, status);
      85           0 : }
      86             : 
      87             : static int
      88           0 : accel_error_submit_tasks(struct spdk_io_channel *ch, struct spdk_accel_task *task)
      89             : {
      90           0 :         struct accel_error_channel *errch = spdk_io_channel_get_ctx(ch);
      91           0 :         struct accel_error_task *errtask = accel_error_get_task_ctx(task);
      92             : 
      93           0 :         errtask->ch = errch;
      94           0 :         errtask->cb_fn = task->cb_fn;
      95           0 :         errtask->cb_arg = task->cb_arg;
      96           0 :         task->cb_fn = accel_error_task_complete_cb;
      97           0 :         task->cb_arg = task;
      98             : 
      99           0 :         return g_sw_module->submit_tasks(errch->swch, task);
     100             : }
     101             : 
     102             : static void
     103           0 : accel_error_inject_channel(struct spdk_io_channel_iter *iter)
     104             : {
     105           0 :         struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(iter);
     106           0 :         struct accel_error_channel *errch = spdk_io_channel_get_ctx(ch);
     107           0 :         struct accel_error_inject_opts *opts = spdk_io_channel_iter_get_ctx(iter);
     108           0 :         struct accel_error_inject_info *info = &errch->injects[opts->opcode];
     109             : 
     110           0 :         info->count = 0;
     111           0 :         memcpy(&info->opts, opts, sizeof(info->opts));
     112             : 
     113           0 :         spdk_for_each_channel_continue(iter, 0);
     114           0 : }
     115             : 
     116             : static bool accel_error_supports_opcode(enum spdk_accel_opcode opcode);
     117             : 
     118             : int
     119           0 : accel_error_inject_error(struct accel_error_inject_opts *opts)
     120             : {
     121           0 :         struct accel_error_inject_opts *curr = &g_injects[opts->opcode];
     122             : 
     123           0 :         if (!accel_error_supports_opcode(opts->opcode)) {
     124           0 :                 return -EINVAL;
     125             :         }
     126             : 
     127           0 :         memcpy(curr, opts, sizeof(*opts));
     128           0 :         if (curr->type == ACCEL_ERROR_INJECT_DISABLE) {
     129           0 :                 curr->count = 0;
     130             :         }
     131           0 :         if (curr->count == 0) {
     132           0 :                 curr->type = ACCEL_ERROR_INJECT_DISABLE;
     133             :         }
     134             : 
     135           0 :         spdk_for_each_channel(&g_sw_module, accel_error_inject_channel, curr, NULL);
     136             : 
     137           0 :         return 0;
     138             : }
     139             : 
     140             : static int
     141           0 : accel_error_channel_create_cb(void *io_device, void *ctx)
     142             : {
     143           0 :         struct accel_error_channel *errch = ctx;
     144             :         size_t i;
     145             : 
     146           0 :         errch->swch = g_sw_module->get_io_channel();
     147           0 :         if (errch->swch == NULL) {
     148           0 :                 return -ENOMEM;
     149             :         }
     150             : 
     151           0 :         for (i = 0; i < SPDK_COUNTOF(errch->injects); ++i) {
     152           0 :                 memcpy(&errch->injects[i].opts, &g_injects[i], sizeof(g_injects[i]));
     153           0 :                 errch->injects[i].count = 0;
     154             :         }
     155             : 
     156           0 :         return 0;
     157             : }
     158             : 
     159             : static void
     160           0 : accel_error_channel_destroy_cb(void *io_device, void *ctx)
     161             : {
     162           0 :         struct accel_error_channel *errch = ctx;
     163             : 
     164           0 :         spdk_put_io_channel(errch->swch);
     165           0 : }
     166             : 
     167             : static int
     168           0 : accel_error_module_init(void)
     169             : {
     170           0 :         g_sw_module = spdk_accel_get_module("software");
     171           0 :         if (g_sw_module == NULL) {
     172             :                 /* Should never really happen */
     173           0 :                 return -ENOTSUP;
     174             :         }
     175             : 
     176           0 :         g_task_offset = g_sw_module->get_ctx_size();
     177             : 
     178           0 :         spdk_io_device_register(&g_sw_module, accel_error_channel_create_cb,
     179             :                                 accel_error_channel_destroy_cb,
     180             :                                 sizeof(struct accel_error_channel), "accel_error");
     181             : 
     182           0 :         return 0;
     183             : }
     184             : 
     185             : static void
     186           0 : accel_error_unregister_cb(void *unused)
     187             : {
     188           0 :         spdk_accel_module_finish();
     189           0 : }
     190             : 
     191             : static void
     192           0 : accel_error_module_fini(void *unused)
     193             : {
     194           0 :         spdk_io_device_unregister(&g_sw_module, accel_error_unregister_cb);
     195           0 : }
     196             : 
     197             : static bool
     198           0 : accel_error_supports_opcode(enum spdk_accel_opcode opcode)
     199             : {
     200           0 :         switch (opcode) {
     201           0 :         case SPDK_ACCEL_OPC_CRC32C:
     202           0 :                 return true;
     203           0 :         default:
     204           0 :                 return false;
     205             :         }
     206             : }
     207             : 
     208             : static struct spdk_io_channel *
     209           0 : accel_error_get_io_channel(void)
     210             : {
     211           0 :         return spdk_get_io_channel(&g_sw_module);
     212             : }
     213             : 
     214             : static size_t
     215           0 : accel_error_get_ctx_size(void)
     216             : {
     217           0 :         return g_task_offset + sizeof(struct accel_error_task);
     218             : }
     219             : 
     220             : const char *
     221           0 : accel_error_get_type_name(enum accel_error_inject_type type)
     222             : {
     223           0 :         const char *typenames[] = {
     224             :                 [ACCEL_ERROR_INJECT_DISABLE] = "disable",
     225             :                 [ACCEL_ERROR_INJECT_CORRUPT] = "corrupt",
     226             :                 [ACCEL_ERROR_INJECT_FAILURE] = "failure",
     227             :                 [ACCEL_ERROR_INJECT_MAX] = NULL
     228             :         };
     229             : 
     230           0 :         if ((int)type >= ACCEL_ERROR_INJECT_MAX) {
     231           0 :                 return NULL;
     232             :         }
     233             : 
     234           0 :         return typenames[type];
     235             : }
     236             : 
     237             : static void
     238           0 : accel_error_write_config_json(struct spdk_json_write_ctx *w)
     239             : {
     240             :         struct accel_error_inject_opts *opts;
     241             :         int opcode;
     242             : 
     243           0 :         for (opcode = 0; opcode < SPDK_ACCEL_OPC_LAST; ++opcode) {
     244           0 :                 opts = &g_injects[opcode];
     245           0 :                 if (opts->type == ACCEL_ERROR_INJECT_DISABLE) {
     246           0 :                         continue;
     247             :                 }
     248           0 :                 spdk_json_write_object_begin(w);
     249           0 :                 spdk_json_write_named_string(w, "method", "accel_error_inject_error");
     250           0 :                 spdk_json_write_named_object_begin(w, "params");
     251           0 :                 spdk_json_write_named_string(w, "opcode", spdk_accel_get_opcode_name(opcode));
     252           0 :                 spdk_json_write_named_string(w, "type", accel_error_get_type_name(opts->type));
     253           0 :                 spdk_json_write_named_uint64(w, "count", opts->count);
     254           0 :                 spdk_json_write_named_uint64(w, "interval", opts->interval);
     255           0 :                 spdk_json_write_object_end(w);
     256           0 :                 spdk_json_write_object_end(w);
     257             :         }
     258           0 : }
     259             : 
     260             : static struct spdk_accel_module_if g_accel_error_module = {
     261             :         .name                   = "error",
     262             :         .priority               = INT_MIN,
     263             :         .module_init            = accel_error_module_init,
     264             :         .module_fini            = accel_error_module_fini,
     265             :         .supports_opcode        = accel_error_supports_opcode,
     266             :         .get_ctx_size           = accel_error_get_ctx_size,
     267             :         .get_io_channel         = accel_error_get_io_channel,
     268             :         .submit_tasks           = accel_error_submit_tasks,
     269             :         .write_config_json      = accel_error_write_config_json,
     270             : };
     271           0 : SPDK_ACCEL_MODULE_REGISTER(error, &g_accel_error_module)

Generated by: LCOV version 1.15