LCOV - code coverage report
Current view: top level - lib/trace - trace_flags.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 37 203 18.2 %
Date: 2024-07-11 02:30:26 Functions: 3 21 14.3 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2017 Intel Corporation.
       3             :  *   All rights reserved.
       4             :  */
       5             : 
       6             : #include "spdk/stdinc.h"
       7             : 
       8             : #include "spdk/env.h"
       9             : #include "spdk/trace.h"
      10             : #include "spdk/log.h"
      11             : #include "spdk/util.h"
      12             : 
      13             : struct spdk_trace_flags *g_trace_flags = NULL;
      14             : static struct spdk_trace_register_fn *g_reg_fn_head = NULL;
      15             : 
      16          40 : SPDK_LOG_REGISTER_COMPONENT(trace)
      17             : 
      18             : uint64_t
      19           0 : spdk_trace_get_tpoint_mask(uint32_t group_id)
      20             : {
      21           0 :         if (group_id >= SPDK_TRACE_MAX_GROUP_ID) {
      22           0 :                 SPDK_ERRLOG("invalid group ID %d\n", group_id);
      23           0 :                 return 0ULL;
      24             :         }
      25             : 
      26           0 :         if (g_trace_flags == NULL) {
      27           0 :                 return 0ULL;
      28             :         }
      29             : 
      30           0 :         return g_trace_flags->tpoint_mask[group_id];
      31             : }
      32             : 
      33             : void
      34           0 : spdk_trace_set_tpoints(uint32_t group_id, uint64_t tpoint_mask)
      35             : {
      36           0 :         if (g_trace_flags == NULL) {
      37           0 :                 SPDK_ERRLOG("trace is not initialized\n");
      38           0 :                 return;
      39             :         }
      40             : 
      41           0 :         if (group_id >= SPDK_TRACE_MAX_GROUP_ID) {
      42           0 :                 SPDK_ERRLOG("invalid group ID %d\n", group_id);
      43           0 :                 return;
      44             :         }
      45             : 
      46           0 :         g_trace_flags->tpoint_mask[group_id] |= tpoint_mask;
      47             : }
      48             : 
      49             : void
      50           0 : spdk_trace_clear_tpoints(uint32_t group_id, uint64_t tpoint_mask)
      51             : {
      52           0 :         if (g_trace_flags == NULL) {
      53           0 :                 SPDK_ERRLOG("trace is not initialized\n");
      54           0 :                 return;
      55             :         }
      56             : 
      57           0 :         if (group_id >= SPDK_TRACE_MAX_GROUP_ID) {
      58           0 :                 SPDK_ERRLOG("invalid group ID %d\n", group_id);
      59           0 :                 return;
      60             :         }
      61             : 
      62           0 :         g_trace_flags->tpoint_mask[group_id] &= ~tpoint_mask;
      63             : }
      64             : 
      65             : uint64_t
      66           0 : spdk_trace_get_tpoint_group_mask(void)
      67             : {
      68           0 :         uint64_t mask = 0x0;
      69             :         int i;
      70             : 
      71           0 :         for (i = 0; i < SPDK_TRACE_MAX_GROUP_ID; i++) {
      72           0 :                 if (spdk_trace_get_tpoint_mask(i) != 0) {
      73           0 :                         mask |= (1ULL << i);
      74             :                 }
      75             :         }
      76             : 
      77           0 :         return mask;
      78             : }
      79             : 
      80             : void
      81           0 : spdk_trace_set_tpoint_group_mask(uint64_t tpoint_group_mask)
      82             : {
      83             :         int i;
      84             : 
      85           0 :         if (g_trace_flags == NULL) {
      86           0 :                 SPDK_ERRLOG("trace is not initialized\n");
      87           0 :                 return;
      88             :         }
      89             : 
      90           0 :         for (i = 0; i < SPDK_TRACE_MAX_GROUP_ID; i++) {
      91           0 :                 if (tpoint_group_mask & (1ULL << i)) {
      92           0 :                         spdk_trace_set_tpoints(i, -1ULL);
      93             :                 }
      94             :         }
      95             : }
      96             : 
      97             : void
      98           0 : spdk_trace_clear_tpoint_group_mask(uint64_t tpoint_group_mask)
      99             : {
     100             :         int i;
     101             : 
     102           0 :         if (g_trace_flags == NULL) {
     103           0 :                 SPDK_ERRLOG("trace is not initialized\n");
     104           0 :                 return;
     105             :         }
     106             : 
     107           0 :         for (i = 0; i < SPDK_TRACE_MAX_GROUP_ID; i++) {
     108           0 :                 if (tpoint_group_mask & (1ULL << i)) {
     109           0 :                         spdk_trace_clear_tpoints(i, -1ULL);
     110             :                 }
     111             :         }
     112             : }
     113             : 
     114             : struct spdk_trace_register_fn *
     115           0 : spdk_trace_get_first_register_fn(void)
     116             : {
     117           0 :         return g_reg_fn_head;
     118             : }
     119             : 
     120             : struct spdk_trace_register_fn *
     121           0 : spdk_trace_get_next_register_fn(struct spdk_trace_register_fn *register_fn)
     122             : {
     123           0 :         return register_fn->next;
     124             : }
     125             : 
     126             : uint64_t
     127           0 : spdk_trace_create_tpoint_group_mask(const char *group_name)
     128             : {
     129           0 :         uint64_t tpoint_group_mask = 0;
     130             :         struct spdk_trace_register_fn *register_fn;
     131             : 
     132           0 :         register_fn = spdk_trace_get_first_register_fn();
     133           0 :         if (strcmp(group_name, "all") == 0) {
     134           0 :                 while (register_fn) {
     135           0 :                         tpoint_group_mask |= (1UL << register_fn->tgroup_id);
     136             : 
     137           0 :                         register_fn = spdk_trace_get_next_register_fn(register_fn);
     138             :                 }
     139             :         } else {
     140           0 :                 while (register_fn) {
     141           0 :                         if (strcmp(group_name, register_fn->name) == 0) {
     142           0 :                                 break;
     143             :                         }
     144             : 
     145           0 :                         register_fn = spdk_trace_get_next_register_fn(register_fn);
     146             :                 }
     147             : 
     148           0 :                 if (register_fn != NULL) {
     149           0 :                         tpoint_group_mask |= (1UL << register_fn->tgroup_id);
     150             :                 }
     151             :         }
     152             : 
     153           0 :         return tpoint_group_mask;
     154             : }
     155             : 
     156             : int
     157           0 : spdk_trace_enable_tpoint_group(const char *group_name)
     158             : {
     159           0 :         uint64_t tpoint_group_mask = 0;
     160             : 
     161           0 :         if (g_trace_flags == NULL) {
     162           0 :                 return -1;
     163             :         }
     164             : 
     165           0 :         tpoint_group_mask = spdk_trace_create_tpoint_group_mask(group_name);
     166           0 :         if (tpoint_group_mask == 0) {
     167           0 :                 return -1;
     168             :         }
     169             : 
     170           0 :         spdk_trace_set_tpoint_group_mask(tpoint_group_mask);
     171           0 :         return 0;
     172             : }
     173             : 
     174             : int
     175           0 : spdk_trace_disable_tpoint_group(const char *group_name)
     176             : {
     177           0 :         uint64_t tpoint_group_mask = 0;
     178             : 
     179           0 :         if (g_trace_flags == NULL) {
     180           0 :                 return -1;
     181             :         }
     182             : 
     183           0 :         tpoint_group_mask = spdk_trace_create_tpoint_group_mask(group_name);
     184           0 :         if (tpoint_group_mask == 0) {
     185           0 :                 return -1;
     186             :         }
     187             : 
     188           0 :         spdk_trace_clear_tpoint_group_mask(tpoint_group_mask);
     189           0 :         return 0;
     190             : }
     191             : 
     192             : void
     193           3 : spdk_trace_mask_usage(FILE *f, const char *tmask_arg)
     194             : {
     195             :         struct spdk_trace_register_fn *register_fn;
     196           3 :         bool first_group_name = true;
     197             : 
     198           3 :         fprintf(f, " %s, --tpoint-group <group-name>[:<tpoint_mask>]\n", tmask_arg);
     199           3 :         fprintf(f, "                           group_name - tracepoint group name ");
     200           3 :         fprintf(f, "for spdk trace buffers (");
     201             : 
     202           3 :         register_fn = g_reg_fn_head;
     203           6 :         while (register_fn) {
     204           3 :                 if (first_group_name) {
     205           3 :                         fprintf(f, "%s", register_fn->name);
     206           3 :                         first_group_name = false;
     207             :                 } else {
     208           0 :                         fprintf(f, ", %s", register_fn->name);
     209             :                 }
     210           3 :                 register_fn = register_fn->next;
     211             :         }
     212             : 
     213           3 :         fprintf(f, ", all)\n");
     214           3 :         fprintf(f, "                           tpoint_mask - tracepoint mask for enabling individual");
     215           3 :         fprintf(f, " tpoints inside a tracepoint group.");
     216           3 :         fprintf(f, " First tpoint inside a group can be");
     217           3 :         fprintf(f, " enabled by setting tpoint_mask to 1 (e.g. bdev:0x1).\n");
     218           3 :         fprintf(f, "                            Groups and masks can be combined (e.g.");
     219           3 :         fprintf(f, " thread,bdev:0x1).\n");
     220           3 :         fprintf(f, "                            All available tpoints can be found in");
     221           3 :         fprintf(f, " /include/spdk_internal/trace_defs.h\n");
     222           3 : }
     223             : 
     224             : void
     225           0 : spdk_trace_register_owner(uint8_t type, char id_prefix)
     226             : {
     227             :         struct spdk_trace_owner *owner;
     228             : 
     229           0 :         assert(type != OWNER_NONE);
     230             : 
     231           0 :         if (g_trace_flags == NULL) {
     232           0 :                 SPDK_ERRLOG("trace is not initialized\n");
     233           0 :                 return;
     234             :         }
     235             : 
     236             :         /* 'owner' has 256 entries and since 'type' is a uint8_t, it
     237             :          * can't overrun the array.
     238             :          */
     239           0 :         owner = &g_trace_flags->owner[type];
     240           0 :         assert(owner->type == 0);
     241             : 
     242           0 :         owner->type = type;
     243           0 :         owner->id_prefix = id_prefix;
     244             : }
     245             : 
     246             : void
     247           0 : spdk_trace_register_object(uint8_t type, char id_prefix)
     248             : {
     249             :         struct spdk_trace_object *object;
     250             : 
     251           0 :         assert(type != OBJECT_NONE);
     252             : 
     253           0 :         if (g_trace_flags == NULL) {
     254           0 :                 SPDK_ERRLOG("trace is not initialized\n");
     255           0 :                 return;
     256             :         }
     257             : 
     258             :         /* 'object' has 256 entries and since 'type' is a uint8_t, it
     259             :          * can't overrun the array.
     260             :          */
     261           0 :         object = &g_trace_flags->object[type];
     262           0 :         assert(object->type == 0);
     263             : 
     264           0 :         object->type = type;
     265           0 :         object->id_prefix = id_prefix;
     266             : }
     267             : 
     268             : static void
     269           0 : trace_register_description(const struct spdk_trace_tpoint_opts *opts)
     270             : {
     271             :         struct spdk_trace_tpoint *tpoint;
     272             :         size_t i, max_name_length;
     273             : 
     274           0 :         assert(opts->tpoint_id != 0);
     275           0 :         assert(opts->tpoint_id < SPDK_TRACE_MAX_TPOINT_ID);
     276             : 
     277           0 :         if (strnlen(opts->name, sizeof(tpoint->name)) == sizeof(tpoint->name)) {
     278           0 :                 SPDK_ERRLOG("name (%s) too long\n", opts->name);
     279             :         }
     280             : 
     281           0 :         tpoint = &g_trace_flags->tpoint[opts->tpoint_id];
     282           0 :         assert(tpoint->tpoint_id == 0);
     283             : 
     284           0 :         snprintf(tpoint->name, sizeof(tpoint->name), "%s", opts->name);
     285           0 :         tpoint->tpoint_id = opts->tpoint_id;
     286           0 :         tpoint->object_type = opts->object_type;
     287           0 :         tpoint->owner_type = opts->owner_type;
     288           0 :         tpoint->new_object = opts->new_object;
     289             : 
     290           0 :         max_name_length = sizeof(tpoint->args[0].name);
     291           0 :         for (i = 0; i < SPDK_TRACE_MAX_ARGS_COUNT; ++i) {
     292           0 :                 if (!opts->args[i].name || opts->args[i].name[0] == '\0') {
     293             :                         break;
     294             :                 }
     295             : 
     296           0 :                 switch (opts->args[i].type) {
     297           0 :                 case SPDK_TRACE_ARG_TYPE_INT:
     298             :                 case SPDK_TRACE_ARG_TYPE_PTR:
     299             :                         /* The integers and pointers have to be exactly 4 or 8 bytes */
     300           0 :                         assert(opts->args[i].size == 4 || opts->args[i].size == 8);
     301           0 :                         break;
     302           0 :                 case SPDK_TRACE_ARG_TYPE_STR:
     303             :                         /* Strings need to have at least one byte for the NULL terminator */
     304           0 :                         assert(opts->args[i].size > 0);
     305           0 :                         break;
     306           0 :                 default:
     307           0 :                         assert(0 && "invalid trace argument type");
     308             :                         break;
     309             :                 }
     310             : 
     311           0 :                 if (strnlen(opts->args[i].name, max_name_length) == max_name_length) {
     312           0 :                         SPDK_ERRLOG("argument name (%s) is too long\n", opts->args[i].name);
     313             :                 }
     314             : 
     315           0 :                 snprintf(tpoint->args[i].name, sizeof(tpoint->args[i].name),
     316             :                          "%s", opts->args[i].name);
     317           0 :                 tpoint->args[i].type = opts->args[i].type;
     318           0 :                 tpoint->args[i].size = opts->args[i].size;
     319             :         }
     320             : 
     321           0 :         tpoint->num_args = i;
     322           0 : }
     323             : 
     324             : void
     325           0 : spdk_trace_register_description_ext(const struct spdk_trace_tpoint_opts *opts, size_t num_opts)
     326             : {
     327             :         size_t i;
     328             : 
     329           0 :         if (g_trace_flags == NULL) {
     330           0 :                 SPDK_ERRLOG("trace is not initialized\n");
     331           0 :                 return;
     332             :         }
     333             : 
     334           0 :         for (i = 0; i < num_opts; ++i) {
     335           0 :                 trace_register_description(&opts[i]);
     336             :         }
     337             : }
     338             : 
     339             : void
     340           0 : spdk_trace_register_description(const char *name, uint16_t tpoint_id, uint8_t owner_type,
     341             :                                 uint8_t object_type, uint8_t new_object,
     342             :                                 uint8_t arg1_type, const char *arg1_name)
     343             : {
     344           0 :         struct spdk_trace_tpoint_opts opts = {
     345             :                 .name = name,
     346             :                 .tpoint_id = tpoint_id,
     347             :                 .owner_type = owner_type,
     348             :                 .object_type = object_type,
     349             :                 .new_object = new_object,
     350             :                 .args = {{
     351             :                                 .name = arg1_name,
     352             :                                 .type = arg1_type,
     353             :                                 .size = sizeof(uint64_t)
     354             :                         }
     355             :                 }
     356             :         };
     357             : 
     358           0 :         spdk_trace_register_description_ext(&opts, 1);
     359           0 : }
     360             : 
     361             : void
     362           0 : spdk_trace_tpoint_register_relation(uint16_t tpoint_id, uint8_t object_type, uint8_t arg_index)
     363             : {
     364             :         struct spdk_trace_tpoint *tpoint;
     365             :         uint16_t i;
     366             : 
     367           0 :         assert(object_type != OBJECT_NONE);
     368           0 :         assert(tpoint_id != OBJECT_NONE);
     369             : 
     370           0 :         if (g_trace_flags == NULL) {
     371           0 :                 SPDK_ERRLOG("trace is not initialized\n");
     372           0 :                 return;
     373             :         }
     374             : 
     375             :         /* We do not check whether a tpoint_id exists here, because
     376             :          * there is no order in which trace definitions are registered.
     377             :          * This way we can create relations between tpoint and objects
     378             :          * that will be declared later. */
     379           0 :         tpoint = &g_trace_flags->tpoint[tpoint_id];
     380           0 :         for (i = 0; i < SPDK_COUNTOF(tpoint->related_objects); ++i) {
     381           0 :                 if (tpoint->related_objects[i].object_type == OBJECT_NONE) {
     382           0 :                         tpoint->related_objects[i].object_type = object_type;
     383           0 :                         tpoint->related_objects[i].arg_index = arg_index;
     384           0 :                         return;
     385             :                 }
     386             :         }
     387           0 :         SPDK_ERRLOG("Unable to register new relation for tpoint %" PRIu16 ", object %" PRIu8 "\n",
     388             :                     tpoint_id, object_type);
     389             : }
     390             : 
     391             : void
     392          50 : spdk_trace_add_register_fn(struct spdk_trace_register_fn *reg_fn)
     393             : {
     394             :         struct spdk_trace_register_fn *_reg_fn;
     395             : 
     396          50 :         if (reg_fn->name == NULL) {
     397           0 :                 SPDK_ERRLOG("missing name for registering spdk trace tpoint group\n");
     398           0 :                 assert(false);
     399             :                 return;
     400             :         }
     401             : 
     402          50 :         if (strcmp(reg_fn->name, "all") == 0) {
     403           0 :                 SPDK_ERRLOG("illegal name (%s) for tpoint group\n", reg_fn->name);
     404           0 :                 assert(false);
     405             :                 return;
     406             :         }
     407             : 
     408             :         /* Ensure that no trace point group IDs and names are ever duplicated */
     409          60 :         for (_reg_fn = g_reg_fn_head; _reg_fn; _reg_fn = _reg_fn->next) {
     410          10 :                 if (reg_fn->tgroup_id == _reg_fn->tgroup_id) {
     411           0 :                         SPDK_ERRLOG("group %d, %s has duplicate tgroup_id with %s\n",
     412             :                                     reg_fn->tgroup_id, reg_fn->name, _reg_fn->name);
     413           0 :                         assert(false);
     414             :                         return;
     415             :                 }
     416             : 
     417          10 :                 if (strcmp(reg_fn->name, _reg_fn->name) == 0) {
     418           0 :                         SPDK_ERRLOG("name %s is duplicated between groups with ids %d and %d\n",
     419             :                                     reg_fn->name, reg_fn->tgroup_id, _reg_fn->tgroup_id);
     420           0 :                         assert(false);
     421             :                         return;
     422             :                 }
     423             :         }
     424             : 
     425             :         /* Arrange trace registration in order on tgroup_id */
     426          50 :         if (g_reg_fn_head == NULL || reg_fn->tgroup_id < g_reg_fn_head->tgroup_id) {
     427          41 :                 reg_fn->next = g_reg_fn_head;
     428          41 :                 g_reg_fn_head = reg_fn;
     429          41 :                 return;
     430             :         }
     431             : 
     432           9 :         for (_reg_fn = g_reg_fn_head; _reg_fn; _reg_fn = _reg_fn->next) {
     433           9 :                 if (_reg_fn->next == NULL || reg_fn->tgroup_id < _reg_fn->next->tgroup_id) {
     434           9 :                         reg_fn->next = _reg_fn->next;
     435           9 :                         _reg_fn->next = reg_fn;
     436           9 :                         return;
     437             :                 }
     438             :         }
     439             : }
     440             : 
     441             : void
     442           0 : spdk_trace_flags_init(void)
     443             : {
     444             :         struct spdk_trace_register_fn *reg_fn;
     445             : 
     446           0 :         reg_fn = g_reg_fn_head;
     447           0 :         while (reg_fn) {
     448           0 :                 reg_fn->reg_fn();
     449           0 :                 reg_fn = reg_fn->next;
     450             :         }
     451           0 : }

Generated by: LCOV version 1.15