LCOV - code coverage report
Current view: top level - lib/ftl/utils - ftl_property.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 146 0.0 %
Date: 2024-12-02 15:15:01 Functions: 0 15 0.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright 2023 Solidigm All Rights Reserved
       3             :  */
       4             : 
       5             : #include "spdk/queue.h"
       6             : #include "spdk/json.h"
       7             : #include "spdk/jsonrpc.h"
       8             : 
       9             : #include "ftl_core.h"
      10             : #include "ftl_property.h"
      11             : #include "mngt/ftl_mngt.h"
      12             : 
      13             : struct ftl_properties {
      14             :         LIST_HEAD(, ftl_property) list;
      15             : };
      16             : 
      17             : /**
      18             :  * @brief FTL property descriptor
      19             :  */
      20             : struct ftl_property {
      21             :         /** Name of the property */
      22             :         const char *name;
      23             : 
      24             :         /* Pointer to the value of property */
      25             :         void *value;
      26             : 
      27             :         /* The value size of the property */
      28             :         size_t size;
      29             : 
      30             :         /** The unit of the property value */
      31             :         const char *unit;
      32             : 
      33             :         /** The property description for user help */
      34             :         const char *desc;
      35             : 
      36             :         /* The function to dump the value of property into the specified JSON RPC request */
      37             :         ftl_property_dump_fn dump;
      38             : 
      39             :         /* Decode property value and store it in output */
      40             :         ftl_property_decode_fn decode;
      41             : 
      42             :         /* Set the FTL property */
      43             :         ftl_property_set_fn set;
      44             : 
      45             :         /* It indicates the property is available in verbose mode only */
      46             :         bool verbose_mode;
      47             : 
      48             :         /** Link to put the property to the list */
      49             :         LIST_ENTRY(ftl_property) entry;
      50             : };
      51             : 
      52             : static struct ftl_property *
      53           0 : get_property(struct ftl_properties *properties, const char *name)
      54             : {
      55             :         struct ftl_property *entry;
      56             : 
      57           0 :         LIST_FOREACH(entry, &properties->list, entry) {
      58             :                 /* TODO think about strncmp */
      59           0 :                 if (0 == strcmp(entry->name, name)) {
      60           0 :                         return entry;
      61             :                 }
      62             :         }
      63             : 
      64           0 :         return NULL;
      65             : }
      66             : 
      67             : void
      68           0 : ftl_property_register(struct spdk_ftl_dev *dev,
      69             :                       const char *name, void *value, size_t size,
      70             :                       const char *unit, const char *desc,
      71             :                       ftl_property_dump_fn dump,
      72             :                       ftl_property_decode_fn decode,
      73             :                       ftl_property_set_fn set,
      74             :                       bool verbose_mode)
      75             : {
      76           0 :         struct ftl_properties *properties = dev->properties;
      77             : 
      78           0 :         if (get_property(properties, name)) {
      79           0 :                 FTL_ERRLOG(dev, "FTL property registration ERROR, already exist, name %s\n", name);
      80           0 :                 ftl_abort();
      81             :         } else {
      82           0 :                 struct ftl_property *prop = calloc(1, sizeof(*prop));
      83           0 :                 if (NULL == prop) {
      84           0 :                         FTL_ERRLOG(dev, "FTL property registration ERROR, out of memory, name %s\n", name);
      85           0 :                         ftl_abort();
      86             :                 }
      87             : 
      88           0 :                 prop->name = name;
      89           0 :                 prop->value = value;
      90           0 :                 prop->size = size;
      91           0 :                 prop->unit = unit;
      92           0 :                 prop->desc = desc;
      93           0 :                 prop->dump = dump;
      94           0 :                 prop->decode = decode;
      95           0 :                 prop->set = set;
      96           0 :                 prop->verbose_mode = verbose_mode;
      97           0 :                 LIST_INSERT_HEAD(&properties->list, prop, entry);
      98             :         }
      99           0 : }
     100             : 
     101             : int
     102           0 : ftl_properties_init(struct spdk_ftl_dev *dev)
     103             : {
     104           0 :         dev->properties = calloc(1, sizeof(*dev->properties));
     105           0 :         if (!dev->properties) {
     106           0 :                 return -ENOMEM;
     107             :         }
     108             : 
     109           0 :         LIST_INIT(&dev->properties->list);
     110           0 :         return 0;
     111             : }
     112             : 
     113             : void
     114           0 : ftl_properties_deinit(struct spdk_ftl_dev *dev)
     115             : {
     116           0 :         struct ftl_properties *properties = dev->properties;
     117             :         struct ftl_property *prop;
     118             : 
     119           0 :         if (!properties) {
     120           0 :                 return;
     121             :         }
     122             : 
     123           0 :         while (!LIST_EMPTY(&properties->list)) {
     124           0 :                 prop = LIST_FIRST(&properties->list);
     125           0 :                 LIST_REMOVE(prop, entry);
     126           0 :                 free(prop);
     127             :         }
     128             : 
     129           0 :         free(dev->properties);
     130             : }
     131             : 
     132             : static bool
     133           0 : is_property_visible(struct spdk_ftl_dev *dev, struct ftl_property *prop)
     134             : {
     135           0 :         if (prop->verbose_mode && !dev->conf.verbose_mode) {
     136           0 :                 return false;
     137             :         }
     138             : 
     139           0 :         return true;
     140             : }
     141             : 
     142             : static void
     143           0 : ftl_property_dump_common_begin(const struct ftl_property *property,
     144             :                                struct spdk_json_write_ctx *w)
     145             : {
     146           0 :         spdk_json_write_named_string(w, "name", property->name);
     147           0 : }
     148             : 
     149             : static void
     150           0 : ftl_property_dump_common_end(const struct ftl_property *property,
     151             :                              struct spdk_json_write_ctx *w)
     152             : {
     153           0 :         if (property->unit) {
     154           0 :                 spdk_json_write_named_string(w, "unit", property->unit);
     155             :         }
     156           0 :         if (property->desc) {
     157           0 :                 spdk_json_write_named_string(w, "desc", property->desc);
     158             :         }
     159             : 
     160           0 :         if (!property->decode || !property->set) {
     161           0 :                 spdk_json_write_named_bool(w, "read-only", true);
     162             :         }
     163           0 : }
     164             : 
     165             : void
     166           0 : ftl_property_dump(struct spdk_ftl_dev *dev, struct spdk_jsonrpc_request *request)
     167             : {
     168           0 :         struct ftl_properties *properties = dev->properties;
     169             :         struct ftl_property *prop;
     170             :         struct spdk_json_write_ctx *w;
     171             : 
     172           0 :         w = spdk_jsonrpc_begin_result(request);
     173             : 
     174           0 :         spdk_json_write_object_begin(w);
     175           0 :         spdk_json_write_named_string(w, "name", dev->conf.name);
     176             : 
     177           0 :         spdk_json_write_named_array_begin(w, "properties");
     178           0 :         LIST_FOREACH(prop, &properties->list, entry) {
     179           0 :                 if (!is_property_visible(dev, prop)) {
     180           0 :                         continue;
     181             :                 }
     182             : 
     183           0 :                 spdk_json_write_object_begin(w);
     184           0 :                 ftl_property_dump_common_begin(prop, w);
     185           0 :                 prop->dump(dev, prop, w);
     186           0 :                 ftl_property_dump_common_end(prop, w);
     187           0 :                 spdk_json_write_object_end(w);
     188             :         }
     189           0 :         spdk_json_write_array_end(w);
     190             : 
     191           0 :         spdk_json_write_object_end(w);
     192           0 :         spdk_jsonrpc_end_result(request, w);
     193           0 : }
     194             : 
     195             : void
     196           0 : ftl_property_dump_bool(struct spdk_ftl_dev *dev, const struct ftl_property *property,
     197             :                        struct spdk_json_write_ctx *w)
     198             : {
     199           0 :         bool *value = property->value;
     200             : 
     201           0 :         assert(property->size == sizeof(*value));
     202           0 :         spdk_json_write_named_bool(w, "value", *value);
     203           0 : }
     204             : 
     205             : void
     206           0 : ftl_property_dump_uint64(struct spdk_ftl_dev *dev, const struct ftl_property *property,
     207             :                          struct spdk_json_write_ctx *w)
     208             : {
     209           0 :         uint64_t *value = property->value;
     210             : 
     211           0 :         assert(property->size == sizeof(*value));
     212           0 :         spdk_json_write_named_uint64(w, "value", *value);
     213           0 : }
     214             : 
     215             : void
     216           0 : ftl_property_dump_uint32(struct spdk_ftl_dev *dev, const struct ftl_property *property,
     217             :                          struct spdk_json_write_ctx *w)
     218             : {
     219           0 :         uint32_t *value = property->value;
     220             : 
     221           0 :         assert(property->size == sizeof(*value));
     222           0 :         spdk_json_write_named_uint32(w, "value", *value);
     223           0 : }
     224             : 
     225             : int
     226           0 : ftl_property_decode(struct spdk_ftl_dev *dev, const char *name, const char *value,
     227             :                     size_t value_size, void **output, size_t *output_size)
     228             : {
     229           0 :         struct ftl_properties *properties = dev->properties;
     230           0 :         struct ftl_property *prop = get_property(properties, name);
     231             :         int rc;
     232             : 
     233           0 :         if (!prop) {
     234           0 :                 FTL_ERRLOG(dev, "Property doesn't exist, name %s\n", name);
     235           0 :                 return -ENOENT;
     236             :         }
     237             : 
     238           0 :         if (!prop->decode) {
     239           0 :                 FTL_ERRLOG(dev, "Property is read only, name %s\n", name);
     240           0 :                 return -EACCES;
     241             :         }
     242             : 
     243           0 :         if (!is_property_visible(dev, prop)) {
     244           0 :                 FTL_ERRLOG(dev, "Property is inactive, enable verbose mode to access it, name %s.\n", name);
     245           0 :                 return -EACCES;
     246             :         }
     247             : 
     248           0 :         assert(prop->size);
     249           0 :         assert(NULL == *output);
     250             : 
     251             :         /* Allocate buffer for the new value of the property */
     252           0 :         *output = calloc(1, prop->size);
     253           0 :         if (NULL == *output) {
     254           0 :                 FTL_ERRLOG(dev, "Property allocation memory error, name %s\n", name);
     255           0 :                 return -EACCES;
     256             :         }
     257           0 :         *output_size = prop->size;
     258             : 
     259           0 :         rc = prop->decode(dev, prop, value, value_size, *output, *output_size);
     260           0 :         if (rc) {
     261           0 :                 FTL_ERRLOG(dev, "Property decode error, name %s\n", name);
     262           0 :                 free(*output);
     263           0 :                 *output = NULL;
     264           0 :                 return rc;
     265             :         }
     266             : 
     267           0 :         return 0;
     268             : }
     269             : 
     270             : int
     271           0 : ftl_property_set(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt,
     272             :                  const char *name, void *value, size_t value_size)
     273             : {
     274           0 :         struct ftl_properties *properties = dev->properties;
     275           0 :         struct ftl_property *prop = get_property(properties, name);
     276             : 
     277           0 :         if (!prop) {
     278           0 :                 FTL_ERRLOG(dev, "Property doesn't exist, name %s\n", name);
     279           0 :                 return -ENOENT;
     280             :         }
     281             : 
     282           0 :         if (!prop->set) {
     283           0 :                 FTL_ERRLOG(dev, "Property is read only, name %s\n", name);
     284           0 :                 return -EACCES;
     285             :         }
     286             : 
     287           0 :         if (!is_property_visible(dev, prop)) {
     288           0 :                 FTL_ERRLOG(dev, "Property is inactive, enable verbose mode to access it, name %s\n", name);
     289           0 :                 return -EACCES;
     290             :         }
     291             : 
     292           0 :         prop->set(dev, mngt, prop, value, value_size);
     293           0 :         return 0;
     294             : }
     295             : 
     296             : void
     297           0 : ftl_property_set_generic(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt,
     298             :                          const struct ftl_property *property, void *new_value, size_t new_value_size)
     299             : {
     300           0 :         ftl_bug(property->size != new_value_size);
     301           0 :         memcpy(property->value, new_value, property->size);
     302           0 :         ftl_mngt_next_step(mngt);
     303           0 : }
     304             : 
     305             : int
     306           0 : ftl_property_decode_bool(struct spdk_ftl_dev *dev, struct ftl_property *property,
     307             :                          const char *value, size_t value_size, void *output, size_t output_size)
     308             : {
     309           0 :         bool *out = output;
     310             : 
     311           0 :         if (sizeof(bool) != output_size) {
     312           0 :                 return -ENOBUFS;
     313             :         }
     314             : 
     315           0 :         if (strnlen(value, value_size) == value_size) {
     316           0 :                 return -EINVAL;
     317             :         }
     318             : 
     319           0 :         if (0 == strncmp(value, "true", strlen("true"))) {
     320           0 :                 *out = true;
     321           0 :                 return 0;
     322             :         }
     323             : 
     324           0 :         if (0 == strncmp(value, "false", strlen("false"))) {
     325           0 :                 *out = false;
     326           0 :                 return 0;
     327             :         }
     328             : 
     329           0 :         return -EINVAL;
     330             : }

Generated by: LCOV version 1.15