LCOV - code coverage report
Current view: top level - lib/event - app_rpc.c (source / functions) Hit Total Coverage
Test: ut_cov_unit.info Lines: 0 323 0.0 %
Date: 2024-07-15 16:19:09 Functions: 0 32 0.0 %

          Line data    Source code
       1             : /*   SPDX-License-Identifier: BSD-3-Clause
       2             :  *   Copyright (C) 2016 Intel Corporation. All rights reserved.
       3             :  *   Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved.
       4             :  */
       5             : 
       6             : #include "spdk/stdinc.h"
       7             : 
       8             : #include "spdk/event.h"
       9             : #include "spdk/rpc.h"
      10             : #include "spdk/string.h"
      11             : #include "spdk/util.h"
      12             : #include "spdk/env.h"
      13             : #include "spdk/scheduler.h"
      14             : #include "spdk/thread.h"
      15             : #include "spdk/json.h"
      16             : 
      17             : #include "spdk/log.h"
      18             : #include "spdk_internal/event.h"
      19             : #include "spdk_internal/thread.h"
      20             : 
      21             : struct rpc_spdk_kill_instance {
      22             :         char *sig_name;
      23             : };
      24             : 
      25             : static void
      26           0 : free_rpc_spdk_kill_instance(struct rpc_spdk_kill_instance *req)
      27             : {
      28           0 :         free(req->sig_name);
      29           0 : }
      30             : 
      31             : static const struct spdk_json_object_decoder rpc_spdk_kill_instance_decoders[] = {
      32             :         {"sig_name", offsetof(struct rpc_spdk_kill_instance, sig_name), spdk_json_decode_string},
      33             : };
      34             : 
      35             : static void
      36           0 : rpc_spdk_kill_instance(struct spdk_jsonrpc_request *request,
      37             :                        const struct spdk_json_val *params)
      38             : {
      39             :         static const struct {
      40             :                 const char      *signal_string;
      41             :                 int32_t         signal;
      42             :         } signals[] = {
      43             :                 {"SIGINT",    SIGINT},
      44             :                 {"SIGTERM",   SIGTERM},
      45             :                 {"SIGQUIT",   SIGQUIT},
      46             :                 {"SIGHUP",    SIGHUP},
      47             :                 {"SIGKILL",   SIGKILL},
      48             :                 {"SIGUSR1",   SIGUSR1},
      49             :         };
      50             :         size_t i, sig_count;
      51             :         int signal;
      52           0 :         struct rpc_spdk_kill_instance req = {};
      53             : 
      54           0 :         if (spdk_json_decode_object(params, rpc_spdk_kill_instance_decoders,
      55             :                                     SPDK_COUNTOF(rpc_spdk_kill_instance_decoders),
      56             :                                     &req)) {
      57           0 :                 SPDK_DEBUGLOG(app_rpc, "spdk_json_decode_object failed\n");
      58           0 :                 goto invalid;
      59             :         }
      60             : 
      61           0 :         sig_count = SPDK_COUNTOF(signals);
      62           0 :         signal = spdk_strtol(req.sig_name, 10);
      63           0 :         for (i = 0 ; i < sig_count; i++) {
      64           0 :                 if (strcmp(req.sig_name, signals[i].signal_string) == 0 ||
      65           0 :                     signal == signals[i].signal) {
      66             :                         break;
      67             :                 }
      68             :         }
      69             : 
      70           0 :         if (i == sig_count) {
      71           0 :                 goto invalid;
      72             :         }
      73             : 
      74           0 :         SPDK_DEBUGLOG(app_rpc, "sending signal %d\n", signals[i].signal);
      75           0 :         free_rpc_spdk_kill_instance(&req);
      76           0 :         kill(getpid(), signals[i].signal);
      77             : 
      78           0 :         spdk_jsonrpc_send_bool_response(request, true);
      79           0 :         return;
      80             : 
      81           0 : invalid:
      82           0 :         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
      83           0 :         free_rpc_spdk_kill_instance(&req);
      84             : }
      85           0 : SPDK_RPC_REGISTER("spdk_kill_instance", rpc_spdk_kill_instance, SPDK_RPC_RUNTIME)
      86             : 
      87             : 
      88             : struct rpc_framework_monitor_context_switch {
      89             :         bool enabled;
      90             : };
      91             : 
      92             : static const struct spdk_json_object_decoder rpc_framework_monitor_context_switch_decoders[] = {
      93             :         {"enabled", offsetof(struct rpc_framework_monitor_context_switch, enabled), spdk_json_decode_bool},
      94             : };
      95             : 
      96             : static void
      97           0 : rpc_framework_monitor_context_switch(struct spdk_jsonrpc_request *request,
      98             :                                      const struct spdk_json_val *params)
      99             : {
     100           0 :         struct rpc_framework_monitor_context_switch req = {};
     101             :         struct spdk_json_write_ctx *w;
     102             : 
     103           0 :         if (params != NULL) {
     104           0 :                 if (spdk_json_decode_object(params, rpc_framework_monitor_context_switch_decoders,
     105             :                                             SPDK_COUNTOF(rpc_framework_monitor_context_switch_decoders),
     106             :                                             &req)) {
     107           0 :                         SPDK_DEBUGLOG(app_rpc, "spdk_json_decode_object failed\n");
     108           0 :                         spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
     109           0 :                         return;
     110             :                 }
     111             : 
     112           0 :                 spdk_framework_enable_context_switch_monitor(req.enabled);
     113             :         }
     114             : 
     115           0 :         w = spdk_jsonrpc_begin_result(request);
     116           0 :         spdk_json_write_object_begin(w);
     117             : 
     118           0 :         spdk_json_write_named_bool(w, "enabled", spdk_framework_context_switch_monitor_enabled());
     119             : 
     120           0 :         spdk_json_write_object_end(w);
     121           0 :         spdk_jsonrpc_end_result(request, w);
     122             : }
     123             : 
     124           0 : SPDK_RPC_REGISTER("framework_monitor_context_switch", rpc_framework_monitor_context_switch,
     125             :                   SPDK_RPC_RUNTIME)
     126             : 
     127             : struct rpc_get_stats_ctx {
     128             :         struct spdk_jsonrpc_request *request;
     129             :         struct spdk_json_write_ctx *w;
     130             :         uint64_t now;
     131             : };
     132             : 
     133             : static void
     134           0 : rpc_thread_get_stats_done(void *arg)
     135             : {
     136           0 :         struct rpc_get_stats_ctx *ctx = arg;
     137             : 
     138           0 :         spdk_json_write_array_end(ctx->w);
     139           0 :         spdk_json_write_object_end(ctx->w);
     140           0 :         spdk_jsonrpc_end_result(ctx->request, ctx->w);
     141             : 
     142           0 :         free(ctx);
     143           0 : }
     144             : 
     145             : static void
     146           0 : rpc_thread_get_stats_for_each(struct spdk_jsonrpc_request *request, spdk_msg_fn fn)
     147             : {
     148             :         struct rpc_get_stats_ctx *ctx;
     149             : 
     150           0 :         ctx = calloc(1, sizeof(*ctx));
     151           0 :         if (!ctx) {
     152           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     153             :                                                  "Memory allocation error");
     154           0 :                 return;
     155             :         }
     156           0 :         ctx->request = request;
     157             : 
     158           0 :         ctx->w = spdk_jsonrpc_begin_result(ctx->request);
     159           0 :         spdk_json_write_object_begin(ctx->w);
     160           0 :         spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz());
     161           0 :         spdk_json_write_named_array_begin(ctx->w, "threads");
     162             : 
     163           0 :         spdk_for_each_thread(fn, ctx, rpc_thread_get_stats_done);
     164             : }
     165             : 
     166             : static void
     167           0 : _rpc_thread_get_stats(void *arg)
     168             : {
     169           0 :         struct rpc_get_stats_ctx *ctx = arg;
     170           0 :         struct spdk_thread *thread = spdk_get_thread();
     171           0 :         struct spdk_cpuset tmp_mask = {};
     172             :         struct spdk_poller *poller;
     173           0 :         struct spdk_thread_stats stats;
     174           0 :         uint64_t active_pollers_count = 0;
     175           0 :         uint64_t timed_pollers_count = 0;
     176           0 :         uint64_t paused_pollers_count = 0;
     177             : 
     178           0 :         for (poller = spdk_thread_get_first_active_poller(thread); poller != NULL;
     179           0 :              poller = spdk_thread_get_next_active_poller(poller)) {
     180           0 :                 active_pollers_count++;
     181             :         }
     182             : 
     183           0 :         for (poller = spdk_thread_get_first_timed_poller(thread); poller != NULL;
     184           0 :              poller = spdk_thread_get_next_timed_poller(poller)) {
     185           0 :                 timed_pollers_count++;
     186             :         }
     187             : 
     188           0 :         for (poller = spdk_thread_get_first_paused_poller(thread); poller != NULL;
     189           0 :              poller = spdk_thread_get_next_paused_poller(poller)) {
     190           0 :                 paused_pollers_count++;
     191             :         }
     192             : 
     193           0 :         if (0 == spdk_thread_get_stats(&stats)) {
     194           0 :                 spdk_json_write_object_begin(ctx->w);
     195           0 :                 spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
     196           0 :                 spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
     197           0 :                 spdk_cpuset_copy(&tmp_mask, spdk_app_get_core_mask());
     198           0 :                 spdk_cpuset_and(&tmp_mask, spdk_thread_get_cpumask(thread));
     199           0 :                 spdk_json_write_named_string(ctx->w, "cpumask", spdk_cpuset_fmt(&tmp_mask));
     200           0 :                 spdk_json_write_named_uint64(ctx->w, "busy", stats.busy_tsc);
     201           0 :                 spdk_json_write_named_uint64(ctx->w, "idle", stats.idle_tsc);
     202           0 :                 spdk_json_write_named_uint64(ctx->w, "active_pollers_count", active_pollers_count);
     203           0 :                 spdk_json_write_named_uint64(ctx->w, "timed_pollers_count", timed_pollers_count);
     204           0 :                 spdk_json_write_named_uint64(ctx->w, "paused_pollers_count", paused_pollers_count);
     205           0 :                 spdk_json_write_object_end(ctx->w);
     206             :         }
     207           0 : }
     208             : 
     209             : static void
     210           0 : rpc_thread_get_stats(struct spdk_jsonrpc_request *request,
     211             :                      const struct spdk_json_val *params)
     212             : {
     213           0 :         if (params) {
     214           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     215             :                                                  "'thread_get_stats' requires no arguments");
     216           0 :                 return;
     217             :         }
     218             : 
     219           0 :         rpc_thread_get_stats_for_each(request, _rpc_thread_get_stats);
     220             : }
     221             : 
     222           0 : SPDK_RPC_REGISTER("thread_get_stats", rpc_thread_get_stats, SPDK_RPC_RUNTIME)
     223             : 
     224             : static void
     225           0 : rpc_get_poller(struct spdk_poller *poller, struct spdk_json_write_ctx *w)
     226             : {
     227           0 :         struct spdk_poller_stats stats;
     228             :         uint64_t period_ticks;
     229             : 
     230           0 :         period_ticks = spdk_poller_get_period_ticks(poller);
     231           0 :         spdk_poller_get_stats(poller, &stats);
     232             : 
     233           0 :         spdk_json_write_object_begin(w);
     234           0 :         spdk_json_write_named_string(w, "name", spdk_poller_get_name(poller));
     235           0 :         spdk_json_write_named_uint64(w, "id", spdk_poller_get_id(poller));
     236           0 :         spdk_json_write_named_string(w, "state", spdk_poller_get_state_str(poller));
     237           0 :         spdk_json_write_named_uint64(w, "run_count", stats.run_count);
     238           0 :         spdk_json_write_named_uint64(w, "busy_count", stats.busy_count);
     239           0 :         if (period_ticks) {
     240           0 :                 spdk_json_write_named_uint64(w, "period_ticks", period_ticks);
     241             :         }
     242           0 :         spdk_json_write_object_end(w);
     243           0 : }
     244             : 
     245             : static void
     246           0 : _rpc_thread_get_pollers(void *arg)
     247             : {
     248           0 :         struct rpc_get_stats_ctx *ctx = arg;
     249           0 :         struct spdk_thread *thread = spdk_get_thread();
     250             :         struct spdk_poller *poller;
     251             : 
     252           0 :         spdk_json_write_object_begin(ctx->w);
     253           0 :         spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
     254           0 :         spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
     255             : 
     256           0 :         spdk_json_write_named_array_begin(ctx->w, "active_pollers");
     257           0 :         for (poller = spdk_thread_get_first_active_poller(thread); poller != NULL;
     258           0 :              poller = spdk_thread_get_next_active_poller(poller)) {
     259           0 :                 rpc_get_poller(poller, ctx->w);
     260             :         }
     261           0 :         spdk_json_write_array_end(ctx->w);
     262             : 
     263           0 :         spdk_json_write_named_array_begin(ctx->w, "timed_pollers");
     264           0 :         for (poller = spdk_thread_get_first_timed_poller(thread); poller != NULL;
     265           0 :              poller = spdk_thread_get_next_timed_poller(poller)) {
     266           0 :                 rpc_get_poller(poller, ctx->w);
     267             :         }
     268           0 :         spdk_json_write_array_end(ctx->w);
     269             : 
     270           0 :         spdk_json_write_named_array_begin(ctx->w, "paused_pollers");
     271           0 :         for (poller = spdk_thread_get_first_paused_poller(thread); poller != NULL;
     272           0 :              poller = spdk_thread_get_next_paused_poller(poller)) {
     273           0 :                 rpc_get_poller(poller, ctx->w);
     274             :         }
     275           0 :         spdk_json_write_array_end(ctx->w);
     276             : 
     277           0 :         spdk_json_write_object_end(ctx->w);
     278           0 : }
     279             : 
     280             : static void
     281           0 : rpc_thread_get_pollers(struct spdk_jsonrpc_request *request,
     282             :                        const struct spdk_json_val *params)
     283             : {
     284           0 :         if (params) {
     285           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     286             :                                                  "'thread_get_pollers' requires no arguments");
     287           0 :                 return;
     288             :         }
     289             : 
     290           0 :         rpc_thread_get_stats_for_each(request, _rpc_thread_get_pollers);
     291             : }
     292             : 
     293           0 : SPDK_RPC_REGISTER("thread_get_pollers", rpc_thread_get_pollers, SPDK_RPC_RUNTIME)
     294             : 
     295             : static void
     296           0 : rpc_get_io_channel(struct spdk_io_channel *ch, struct spdk_json_write_ctx *w)
     297             : {
     298           0 :         spdk_json_write_object_begin(w);
     299           0 :         spdk_json_write_named_string(w, "name", spdk_io_channel_get_io_device_name(ch));
     300           0 :         spdk_json_write_named_uint32(w, "ref", spdk_io_channel_get_ref_count(ch));
     301           0 :         spdk_json_write_object_end(w);
     302           0 : }
     303             : 
     304             : static void
     305           0 : _rpc_thread_get_io_channels(void *arg)
     306             : {
     307           0 :         struct rpc_get_stats_ctx *ctx = arg;
     308           0 :         struct spdk_thread *thread = spdk_get_thread();
     309             :         struct spdk_io_channel *ch;
     310             : 
     311           0 :         spdk_json_write_object_begin(ctx->w);
     312           0 :         spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
     313             : 
     314           0 :         spdk_json_write_named_array_begin(ctx->w, "io_channels");
     315           0 :         for (ch = spdk_thread_get_first_io_channel(thread); ch != NULL;
     316           0 :              ch = spdk_thread_get_next_io_channel(ch)) {
     317           0 :                 rpc_get_io_channel(ch, ctx->w);
     318             :         }
     319           0 :         spdk_json_write_array_end(ctx->w);
     320             : 
     321           0 :         spdk_json_write_object_end(ctx->w);
     322           0 : }
     323             : 
     324             : static void
     325           0 : rpc_thread_get_io_channels(struct spdk_jsonrpc_request *request,
     326             :                            const struct spdk_json_val *params)
     327             : {
     328           0 :         if (params) {
     329           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     330             :                                                  "'thread_get_io_channels' requires no arguments");
     331           0 :                 return;
     332             :         }
     333             : 
     334           0 :         rpc_thread_get_stats_for_each(request, _rpc_thread_get_io_channels);
     335             : }
     336             : 
     337           0 : SPDK_RPC_REGISTER("thread_get_io_channels", rpc_thread_get_io_channels, SPDK_RPC_RUNTIME);
     338             : 
     339             : static void
     340           0 : rpc_framework_get_reactors_done(void *arg1, void *arg2)
     341             : {
     342           0 :         struct rpc_get_stats_ctx *ctx = arg1;
     343             : 
     344           0 :         spdk_json_write_array_end(ctx->w);
     345           0 :         spdk_json_write_object_end(ctx->w);
     346           0 :         spdk_jsonrpc_end_result(ctx->request, ctx->w);
     347             : 
     348           0 :         free(ctx);
     349           0 : }
     350             : 
     351             : #define GET_DELTA(end, start)   (end >= start ? end - start : 0)
     352             : 
     353             : static void
     354           0 : _rpc_framework_get_reactors(void *arg1, void *arg2)
     355             : {
     356           0 :         struct rpc_get_stats_ctx *ctx = arg1;
     357             :         uint32_t current_core;
     358             :         uint32_t curr_core_freq;
     359             :         struct spdk_reactor *reactor;
     360             :         struct spdk_lw_thread *lw_thread;
     361             :         struct spdk_thread *thread;
     362           0 :         struct spdk_cpuset tmp_mask = {};
     363             :         struct spdk_governor *governor;
     364             : 
     365           0 :         current_core = spdk_env_get_current_core();
     366           0 :         reactor = spdk_reactor_get(current_core);
     367             : 
     368           0 :         assert(reactor != NULL);
     369             : 
     370           0 :         spdk_json_write_object_begin(ctx->w);
     371           0 :         spdk_json_write_named_uint32(ctx->w, "lcore", current_core);
     372           0 :         spdk_json_write_named_uint64(ctx->w, "busy", reactor->busy_tsc);
     373           0 :         spdk_json_write_named_uint64(ctx->w, "idle", reactor->idle_tsc);
     374           0 :         spdk_json_write_named_bool(ctx->w, "in_interrupt", reactor->in_interrupt);
     375             : 
     376           0 :         governor = spdk_governor_get();
     377           0 :         if (governor != NULL) {
     378             :                 /* Governor returns core freqs in kHz, we want MHz. */
     379           0 :                 curr_core_freq = governor->get_core_curr_freq(current_core) / 1000;
     380           0 :                 spdk_json_write_named_uint32(ctx->w, "core_freq", curr_core_freq);
     381             :         }
     382             : 
     383           0 :         spdk_json_write_named_array_begin(ctx->w, "lw_threads");
     384           0 :         TAILQ_FOREACH(lw_thread, &reactor->threads, link) {
     385           0 :                 thread = spdk_thread_get_from_ctx(lw_thread);
     386             : 
     387           0 :                 spdk_json_write_object_begin(ctx->w);
     388           0 :                 spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
     389           0 :                 spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
     390           0 :                 spdk_cpuset_copy(&tmp_mask, spdk_app_get_core_mask());
     391           0 :                 spdk_cpuset_and(&tmp_mask, spdk_thread_get_cpumask(thread));
     392           0 :                 spdk_json_write_named_string(ctx->w, "cpumask", spdk_cpuset_fmt(&tmp_mask));
     393           0 :                 spdk_json_write_named_uint64(ctx->w, "elapsed",
     394           0 :                                              GET_DELTA(ctx->now, lw_thread->tsc_start));
     395           0 :                 spdk_json_write_object_end(ctx->w);
     396             :         }
     397           0 :         spdk_json_write_array_end(ctx->w);
     398             : 
     399           0 :         spdk_json_write_object_end(ctx->w);
     400           0 : }
     401             : 
     402             : static void
     403           0 : rpc_framework_get_reactors(struct spdk_jsonrpc_request *request,
     404             :                            const struct spdk_json_val *params)
     405             : {
     406             :         struct rpc_get_stats_ctx *ctx;
     407             : 
     408           0 :         if (params) {
     409           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     410             :                                                  "`framework_get_reactors` requires no arguments");
     411           0 :                 return;
     412             :         }
     413             : 
     414           0 :         ctx = calloc(1, sizeof(*ctx));
     415           0 :         if (!ctx) {
     416           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     417             :                                                  "Memory allocation error");
     418           0 :                 return;
     419             :         }
     420             : 
     421           0 :         ctx->now = spdk_get_ticks();
     422           0 :         ctx->request = request;
     423           0 :         ctx->w = spdk_jsonrpc_begin_result(ctx->request);
     424             : 
     425           0 :         spdk_json_write_object_begin(ctx->w);
     426           0 :         spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz());
     427           0 :         spdk_json_write_named_array_begin(ctx->w, "reactors");
     428             : 
     429           0 :         spdk_for_each_reactor(_rpc_framework_get_reactors, ctx, NULL,
     430             :                               rpc_framework_get_reactors_done);
     431             : }
     432             : 
     433           0 : SPDK_RPC_REGISTER("framework_get_reactors", rpc_framework_get_reactors, SPDK_RPC_RUNTIME)
     434             : 
     435             : struct rpc_set_scheduler_ctx {
     436             :         char *name;
     437             :         uint64_t period;
     438             : };
     439             : 
     440             : static void
     441           0 : free_rpc_framework_set_scheduler(struct rpc_set_scheduler_ctx *r)
     442             : {
     443           0 :         free(r->name);
     444           0 : }
     445             : 
     446             : static const struct spdk_json_object_decoder rpc_set_scheduler_decoders[] = {
     447             :         {"name", offsetof(struct rpc_set_scheduler_ctx, name), spdk_json_decode_string},
     448             :         {"period", offsetof(struct rpc_set_scheduler_ctx, period), spdk_json_decode_uint64, true},
     449             : };
     450             : 
     451             : static void
     452           0 : rpc_framework_set_scheduler(struct spdk_jsonrpc_request *request,
     453             :                             const struct spdk_json_val *params)
     454             : {
     455           0 :         struct rpc_set_scheduler_ctx req = {NULL};
     456           0 :         struct spdk_scheduler *scheduler = NULL;
     457             :         int ret;
     458             : 
     459           0 :         ret = spdk_json_decode_object_relaxed(params, rpc_set_scheduler_decoders,
     460             :                                               SPDK_COUNTOF(rpc_set_scheduler_decoders),
     461             :                                               &req);
     462           0 :         if (ret) {
     463           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     464             :                                                  "Invalid parameters");
     465           0 :                 goto end;
     466             :         }
     467             : 
     468           0 :         scheduler = spdk_scheduler_get();
     469             :         /* SPDK does not support changing scheduler back to static. */
     470           0 :         if (scheduler != NULL && (strcmp(req.name, "static") == 0) &&
     471           0 :             strcmp(scheduler->name, "static") != 0) {
     472           0 :                 spdk_jsonrpc_send_error_response(request,
     473             :                                                  SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     474             :                                                  "Static scheduler cannot be re-enabled "
     475             :                                                  "after a different scheduler was selected");
     476           0 :                 goto end;
     477             :         }
     478             : 
     479           0 :         if (req.period != 0) {
     480           0 :                 spdk_scheduler_set_period(req.period);
     481             :         }
     482             : 
     483           0 :         ret = spdk_scheduler_set(req.name);
     484           0 :         if (ret) {
     485           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     486             :                                                  spdk_strerror(ret));
     487           0 :                 goto end;
     488             :         }
     489             : 
     490           0 :         scheduler = spdk_scheduler_get();
     491           0 :         if (scheduler != NULL && scheduler->set_opts != NULL) {
     492           0 :                 ret = scheduler->set_opts(params);
     493             :         }
     494           0 :         if (ret) {
     495           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(ret));
     496           0 :                 goto end;
     497             :         }
     498             : 
     499           0 :         spdk_jsonrpc_send_bool_response(request, true);
     500             : 
     501           0 : end:
     502           0 :         free_rpc_framework_set_scheduler(&req);
     503           0 : }
     504           0 : SPDK_RPC_REGISTER("framework_set_scheduler", rpc_framework_set_scheduler,
     505             :                   SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME)
     506             : 
     507             : static void
     508           0 : rpc_framework_get_scheduler(struct spdk_jsonrpc_request *request,
     509             :                             const struct spdk_json_val *params)
     510             : {
     511             :         struct spdk_json_write_ctx *w;
     512           0 :         struct spdk_scheduler *scheduler = spdk_scheduler_get();
     513           0 :         uint64_t scheduler_period = spdk_scheduler_get_period();
     514           0 :         struct spdk_governor *governor = spdk_governor_get();
     515             : 
     516           0 :         if (params) {
     517           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     518             :                                                  "'rpc_get_scheduler' requires no arguments");
     519           0 :                 return;
     520             :         }
     521             : 
     522           0 :         w = spdk_jsonrpc_begin_result(request);
     523           0 :         spdk_json_write_object_begin(w);
     524           0 :         if (scheduler) {
     525           0 :                 spdk_json_write_named_string(w, "scheduler_name", scheduler->name);
     526             :         }
     527           0 :         spdk_json_write_named_uint64(w, "scheduler_period", scheduler_period);
     528           0 :         if (governor != NULL) {
     529           0 :                 spdk_json_write_named_string(w, "governor_name", governor->name);
     530             :         }
     531             : 
     532           0 :         if (scheduler != NULL && scheduler->get_opts != NULL) {
     533           0 :                 scheduler->get_opts(w);
     534             :         }
     535             : 
     536           0 :         spdk_json_write_object_end(w);
     537           0 :         spdk_jsonrpc_end_result(request, w);
     538             : }
     539           0 : SPDK_RPC_REGISTER("framework_get_scheduler", rpc_framework_get_scheduler, SPDK_RPC_RUNTIME)
     540             : 
     541             : struct rpc_thread_set_cpumask_ctx {
     542             :         struct spdk_jsonrpc_request *request;
     543             :         struct spdk_cpuset cpumask;
     544             :         int status;
     545             :         struct spdk_thread *orig_thread;
     546             : };
     547             : 
     548             : static void
     549           0 : rpc_thread_set_cpumask_done(void *_ctx)
     550             : {
     551           0 :         struct rpc_thread_set_cpumask_ctx *ctx = _ctx;
     552             : 
     553           0 :         if (ctx->status == 0) {
     554           0 :                 spdk_jsonrpc_send_bool_response(ctx->request, true);
     555             :         } else {
     556           0 :                 spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     557           0 :                                                  spdk_strerror(-ctx->status));
     558             :         }
     559             : 
     560           0 :         free(ctx);
     561           0 : }
     562             : 
     563             : static void
     564           0 : _rpc_thread_set_cpumask(void *_ctx)
     565             : {
     566           0 :         struct rpc_thread_set_cpumask_ctx *ctx = _ctx;
     567             : 
     568           0 :         ctx->status = spdk_thread_set_cpumask(&ctx->cpumask);
     569             : 
     570           0 :         spdk_thread_send_msg(ctx->orig_thread, rpc_thread_set_cpumask_done, ctx);
     571           0 : }
     572             : 
     573             : struct rpc_thread_set_cpumask {
     574             :         uint64_t id;
     575             :         char *cpumask;
     576             : };
     577             : 
     578             : static const struct spdk_json_object_decoder rpc_thread_set_cpumask_decoders[] = {
     579             :         {"id", offsetof(struct rpc_thread_set_cpumask, id), spdk_json_decode_uint64},
     580             :         {"cpumask", offsetof(struct rpc_thread_set_cpumask, cpumask), spdk_json_decode_string},
     581             : };
     582             : 
     583             : static void
     584           0 : rpc_thread_set_cpumask(struct spdk_jsonrpc_request *request,
     585             :                        const struct spdk_json_val *params)
     586             : {
     587           0 :         struct rpc_thread_set_cpumask req = {};
     588             :         struct rpc_thread_set_cpumask_ctx *ctx;
     589             :         const struct spdk_cpuset *coremask;
     590           0 :         struct spdk_cpuset tmp_mask;
     591             :         struct spdk_thread *thread;
     592             :         int rc;
     593             : 
     594           0 :         ctx = calloc(1, sizeof(*ctx));
     595           0 :         if (ctx == NULL) {
     596           0 :                 SPDK_ERRLOG("Memory allocation failed\n");
     597           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     598             :                                                  "Memory allocation failed");
     599           0 :                 return;
     600             :         }
     601             : 
     602           0 :         if (spdk_json_decode_object(params, rpc_thread_set_cpumask_decoders,
     603             :                                     SPDK_COUNTOF(rpc_thread_set_cpumask_decoders),
     604             :                                     &req)) {
     605           0 :                 SPDK_ERRLOG("spdk_json_decode_object failed\n");
     606           0 :                 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     607             :                                                  "spdk_json_decode_object failed");
     608           0 :                 goto err;
     609             :         }
     610             : 
     611           0 :         thread = spdk_thread_get_by_id(req.id);
     612           0 :         if (thread == NULL) {
     613           0 :                 SPDK_ERRLOG("Thread %" PRIu64 " does not exist\n", req.id);
     614           0 :                 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
     615             :                                                      "Thread %" PRIu64 " does not exist", req.id);
     616           0 :                 goto err;
     617             :         }
     618             : 
     619           0 :         rc = spdk_app_parse_core_mask(req.cpumask, &ctx->cpumask);
     620           0 :         if (rc != 0) {
     621           0 :                 SPDK_ERRLOG("Invalid cpumask %s\n", req.cpumask);
     622           0 :                 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     623             :                                                      "Invalid cpumask %s", req.cpumask);
     624           0 :                 goto err;
     625             :         }
     626             : 
     627           0 :         if (spdk_cpuset_count(&ctx->cpumask) == 0) {
     628           0 :                 coremask = spdk_app_get_core_mask();
     629           0 :                 spdk_cpuset_copy(&tmp_mask, coremask);
     630           0 :                 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     631             :                                                      "No CPU is selected from reactor mask %s\n",
     632             :                                                      spdk_cpuset_fmt(&tmp_mask));
     633           0 :                 goto err;
     634             :         }
     635             : 
     636             :         /* There may be any reactors running in interrupt mode. But currently,
     637             :          * when interrupt ability of the spdk_thread is not enabled,
     638             :          * spdk_thread can't get executed on reactor which runs in interrupt.
     639             :          * Exclude the situation that reactors specified by the cpumask are
     640             :          * all in interrupt mode.
     641             :          */
     642           0 :         if (!spdk_interrupt_mode_is_enabled()) {
     643           0 :                 struct spdk_reactor *local_reactor = spdk_reactor_get(spdk_env_get_current_core());
     644           0 :                 struct spdk_cpuset tmp_cpuset;
     645             : 
     646             :                 /* Masking off reactors which are in interrupt mode */
     647           0 :                 spdk_cpuset_copy(&tmp_cpuset, &local_reactor->notify_cpuset);
     648           0 :                 spdk_cpuset_negate(&tmp_cpuset);
     649           0 :                 spdk_cpuset_and(&tmp_cpuset, &ctx->cpumask);
     650           0 :                 if (spdk_cpuset_count(&tmp_cpuset) == 0) {
     651           0 :                         spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
     652             :                                                              "cpumask %s are all in interrupt mode, and can't be scheduled yet\n",
     653             :                                                              req.cpumask);
     654           0 :                         goto err;
     655             :                 }
     656             :         }
     657             : 
     658           0 :         ctx->request = request;
     659           0 :         ctx->orig_thread = spdk_get_thread();
     660             : 
     661           0 :         spdk_thread_send_msg(thread, _rpc_thread_set_cpumask, ctx);
     662             : 
     663           0 :         free(req.cpumask);
     664           0 :         return;
     665             : 
     666           0 : err:
     667           0 :         free(req.cpumask);
     668           0 :         free(ctx);
     669             : }
     670           0 : SPDK_RPC_REGISTER("thread_set_cpumask", rpc_thread_set_cpumask, SPDK_RPC_RUNTIME)
     671           0 : SPDK_LOG_REGISTER_COMPONENT(app_rpc)

Generated by: LCOV version 1.15