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