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 : 2882 : 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 : 2882 : 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 : 30 : rpc_thread_get_stats_done(void *arg)
136 : : {
137 : 30 : struct rpc_get_stats_ctx *ctx = arg;
138 : :
139 : 30 : spdk_json_write_array_end(ctx->w);
140 : 30 : spdk_json_write_object_end(ctx->w);
141 : 30 : spdk_jsonrpc_end_result(ctx->request, ctx->w);
142 : :
143 : 30 : free(ctx);
144 : 30 : }
145 : :
146 : : static void
147 : 30 : 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 : 30 : ctx = calloc(1, sizeof(*ctx));
152 [ - + ]: 30 : if (!ctx) {
153 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
154 : : "Memory allocation error");
155 : 0 : return;
156 : : }
157 : 30 : ctx->request = request;
158 : :
159 : 30 : ctx->w = spdk_jsonrpc_begin_result(ctx->request);
160 : 30 : spdk_json_write_object_begin(ctx->w);
161 : 30 : spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz());
162 : 30 : spdk_json_write_named_array_begin(ctx->w, "threads");
163 : :
164 : 30 : spdk_for_each_thread(fn, ctx, rpc_thread_get_stats_done);
165 : : }
166 : :
167 : : static void
168 : 118 : _rpc_thread_get_stats(void *arg)
169 : : {
170 : 118 : struct rpc_get_stats_ctx *ctx = arg;
171 : 118 : struct spdk_thread *thread = spdk_get_thread();
172 : 118 : struct spdk_cpuset tmp_mask = {};
173 : : struct spdk_poller *poller;
174 : 16 : struct spdk_thread_stats stats;
175 : 118 : uint64_t active_pollers_count = 0;
176 : 118 : uint64_t timed_pollers_count = 0;
177 : 118 : uint64_t paused_pollers_count = 0;
178 : :
179 [ + + ]: 214 : 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 [ + + ]: 188 : for (poller = spdk_thread_get_first_timed_poller(thread); poller != NULL;
185 : 70 : poller = spdk_thread_get_next_timed_poller(poller)) {
186 : 70 : timed_pollers_count++;
187 : : }
188 : :
189 [ - + ]: 118 : 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 [ + - ]: 118 : if (0 == spdk_thread_get_stats(&stats)) {
195 : 118 : spdk_json_write_object_begin(ctx->w);
196 : 118 : spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
197 : 118 : spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
198 : 118 : spdk_cpuset_copy(&tmp_mask, spdk_app_get_core_mask());
199 : 118 : spdk_cpuset_and(&tmp_mask, spdk_thread_get_cpumask(thread));
200 : 118 : spdk_json_write_named_string(ctx->w, "cpumask", spdk_cpuset_fmt(&tmp_mask));
201 : 118 : spdk_json_write_named_uint64(ctx->w, "busy", stats.busy_tsc);
202 : 118 : spdk_json_write_named_uint64(ctx->w, "idle", stats.idle_tsc);
203 : 118 : spdk_json_write_named_uint64(ctx->w, "active_pollers_count", active_pollers_count);
204 : 118 : spdk_json_write_named_uint64(ctx->w, "timed_pollers_count", timed_pollers_count);
205 : 118 : spdk_json_write_named_uint64(ctx->w, "paused_pollers_count", paused_pollers_count);
206 : 118 : spdk_json_write_object_end(ctx->w);
207 : : }
208 : 118 : }
209 : :
210 : : static void
211 : 22 : rpc_thread_get_stats(struct spdk_jsonrpc_request *request,
212 : : const struct spdk_json_val *params)
213 : : {
214 [ - + ]: 22 : 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 : 22 : rpc_thread_get_stats_for_each(request, _rpc_thread_get_stats);
221 : : }
222 : :
223 : 2882 : SPDK_RPC_REGISTER("thread_get_stats", rpc_thread_get_stats, SPDK_RPC_RUNTIME)
224 : :
225 : : static void
226 : 8 : 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 : 8 : period_ticks = spdk_poller_get_period_ticks(poller);
232 : 8 : spdk_poller_get_stats(poller, &stats);
233 : :
234 : 8 : spdk_json_write_object_begin(w);
235 : 8 : spdk_json_write_named_string(w, "name", spdk_poller_get_name(poller));
236 : 8 : spdk_json_write_named_uint64(w, "id", spdk_poller_get_id(poller));
237 : 8 : spdk_json_write_named_string(w, "state", spdk_poller_get_state_str(poller));
238 : 8 : spdk_json_write_named_uint64(w, "run_count", stats.run_count);
239 : 8 : spdk_json_write_named_uint64(w, "busy_count", stats.busy_count);
240 [ + - ]: 8 : if (period_ticks) {
241 : 8 : spdk_json_write_named_uint64(w, "period_ticks", period_ticks);
242 : : }
243 : 8 : spdk_json_write_object_end(w);
244 : 8 : }
245 : :
246 : : static void
247 : 8 : _rpc_thread_get_pollers(void *arg)
248 : : {
249 : 8 : struct rpc_get_stats_ctx *ctx = arg;
250 : 8 : struct spdk_thread *thread = spdk_get_thread();
251 : : struct spdk_poller *poller;
252 : :
253 : 8 : spdk_json_write_object_begin(ctx->w);
254 : 8 : spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
255 : 8 : spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
256 : :
257 : 8 : spdk_json_write_named_array_begin(ctx->w, "active_pollers");
258 [ - + ]: 8 : 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 : 8 : spdk_json_write_array_end(ctx->w);
263 : :
264 : 8 : spdk_json_write_named_array_begin(ctx->w, "timed_pollers");
265 [ + + ]: 16 : for (poller = spdk_thread_get_first_timed_poller(thread); poller != NULL;
266 : 8 : poller = spdk_thread_get_next_timed_poller(poller)) {
267 : 8 : rpc_get_poller(poller, ctx->w);
268 : : }
269 : 8 : spdk_json_write_array_end(ctx->w);
270 : :
271 : 8 : spdk_json_write_named_array_begin(ctx->w, "paused_pollers");
272 [ - + ]: 8 : 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 : 8 : spdk_json_write_array_end(ctx->w);
277 : :
278 : 8 : spdk_json_write_object_end(ctx->w);
279 : 8 : }
280 : :
281 : : static void
282 : 8 : rpc_thread_get_pollers(struct spdk_jsonrpc_request *request,
283 : : const struct spdk_json_val *params)
284 : : {
285 [ - + ]: 8 : 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 : 8 : rpc_thread_get_stats_for_each(request, _rpc_thread_get_pollers);
292 : : }
293 : :
294 : 2882 : 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 : 2882 : 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, "busy", reactor->busy_tsc);
375 : 96 : spdk_json_write_named_uint64(ctx->w, "idle", reactor->idle_tsc);
376 [ - + ]: 96 : spdk_json_write_named_bool(ctx->w, "in_interrupt", reactor->in_interrupt);
377 : :
378 [ - + ]: 96 : if (app_get_proc_stat(current_core, &usr, &sys, &irq) != 0) {
379 : 0 : irq = sys = usr = 0;
380 : : }
381 : 96 : spdk_json_write_named_uint64(ctx->w, "irq", irq);
382 : 96 : spdk_json_write_named_uint64(ctx->w, "sys", sys);
383 : 96 : spdk_json_write_named_uint64(ctx->w, "usr", usr);
384 : :
385 : 96 : governor = spdk_governor_get();
386 [ + - ]: 96 : if (governor != NULL) {
387 : : /* Governor returns core freqs in kHz, we want MHz. */
388 : 96 : curr_core_freq = governor->get_core_curr_freq(current_core) / 1000;
389 : 96 : spdk_json_write_named_uint32(ctx->w, "core_freq", curr_core_freq);
390 : : }
391 : :
392 : 96 : spdk_json_write_named_array_begin(ctx->w, "lw_threads");
393 [ + + ]: 203 : TAILQ_FOREACH(lw_thread, &reactor->threads, link) {
394 : 107 : thread = spdk_thread_get_from_ctx(lw_thread);
395 : :
396 : 107 : spdk_json_write_object_begin(ctx->w);
397 : 107 : spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
398 : 107 : spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
399 : 107 : spdk_cpuset_copy(&tmp_mask, spdk_app_get_core_mask());
400 : 107 : spdk_cpuset_and(&tmp_mask, spdk_thread_get_cpumask(thread));
401 : 107 : spdk_json_write_named_string(ctx->w, "cpumask", spdk_cpuset_fmt(&tmp_mask));
402 : 107 : spdk_json_write_named_uint64(ctx->w, "elapsed",
403 [ + - ]: 107 : GET_DELTA(ctx->now, lw_thread->tsc_start));
404 : 107 : spdk_json_write_object_end(ctx->w);
405 : : }
406 : 96 : spdk_json_write_array_end(ctx->w);
407 : :
408 : 96 : spdk_json_write_object_end(ctx->w);
409 : 96 : }
410 : :
411 : : static void
412 : 12 : rpc_framework_get_reactors(struct spdk_jsonrpc_request *request,
413 : : const struct spdk_json_val *params)
414 : : {
415 : : struct rpc_get_stats_ctx *ctx;
416 : :
417 [ - + ]: 12 : if (params) {
418 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
419 : : "`framework_get_reactors` requires no arguments");
420 : 0 : return;
421 : : }
422 : :
423 : 12 : ctx = calloc(1, sizeof(*ctx));
424 [ - + ]: 12 : if (!ctx) {
425 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
426 : : "Memory allocation error");
427 : 0 : return;
428 : : }
429 : :
430 : 12 : ctx->now = spdk_get_ticks();
431 : 12 : ctx->request = request;
432 : 12 : ctx->w = spdk_jsonrpc_begin_result(ctx->request);
433 : :
434 : 12 : spdk_json_write_object_begin(ctx->w);
435 : 12 : spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz());
436 : 12 : spdk_json_write_named_array_begin(ctx->w, "reactors");
437 : :
438 : 12 : spdk_for_each_reactor(_rpc_framework_get_reactors, ctx, NULL,
439 : : rpc_framework_get_reactors_done);
440 : : }
441 : :
442 : 2882 : SPDK_RPC_REGISTER("framework_get_reactors", rpc_framework_get_reactors, SPDK_RPC_RUNTIME)
443 : :
444 : : struct rpc_set_scheduler_ctx {
445 : : char *name;
446 : : uint64_t period;
447 : : };
448 : :
449 : : static void
450 : 65 : free_rpc_framework_set_scheduler(struct rpc_set_scheduler_ctx *r)
451 : : {
452 : 65 : free(r->name);
453 : 65 : }
454 : :
455 : : static const struct spdk_json_object_decoder rpc_set_scheduler_decoders[] = {
456 : : {"name", offsetof(struct rpc_set_scheduler_ctx, name), spdk_json_decode_string},
457 : : {"period", offsetof(struct rpc_set_scheduler_ctx, period), spdk_json_decode_uint64, true},
458 : : };
459 : :
460 : : static void
461 : 65 : rpc_framework_set_scheduler(struct spdk_jsonrpc_request *request,
462 : : const struct spdk_json_val *params)
463 : : {
464 : 65 : struct rpc_set_scheduler_ctx req = {NULL};
465 : 65 : struct spdk_scheduler *scheduler = NULL;
466 : : int ret;
467 : :
468 : 65 : ret = spdk_json_decode_object_relaxed(params, rpc_set_scheduler_decoders,
469 : : SPDK_COUNTOF(rpc_set_scheduler_decoders),
470 : : &req);
471 [ - + ]: 65 : if (ret) {
472 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
473 : : "Invalid parameters");
474 : 0 : goto end;
475 : : }
476 : :
477 : 65 : scheduler = spdk_scheduler_get();
478 : : /* SPDK does not support changing scheduler back to static. */
479 [ + + - + : 65 : if (scheduler != NULL && (strcmp(req.name, "static") == 0) &&
+ - ]
480 [ - + - + ]: 1 : strcmp(scheduler->name, "static") != 0) {
481 : 0 : spdk_jsonrpc_send_error_response(request,
482 : : SPDK_JSONRPC_ERROR_INVALID_PARAMS,
483 : : "Static scheduler cannot be re-enabled "
484 : : "after a different scheduler was selected");
485 : 0 : goto end;
486 : : }
487 : :
488 [ - + ]: 65 : if (req.period != 0) {
489 : 0 : spdk_scheduler_set_period(req.period);
490 [ + - ]: 65 : } else if (spdk_scheduler_get_period() == 0) {
491 : : /* User didn't specify a period, and no period has been set
492 : : * previously, so set it now to 1 second.
493 : : */
494 : 65 : spdk_scheduler_set_period(SPDK_SEC_TO_USEC);
495 : : }
496 : :
497 : 65 : ret = spdk_scheduler_set(req.name);
498 [ - + ]: 65 : if (ret) {
499 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
500 : : spdk_strerror(ret));
501 : 0 : goto end;
502 : : }
503 : :
504 : 65 : scheduler = spdk_scheduler_get();
505 [ + - + - ]: 65 : if (scheduler != NULL && scheduler->set_opts != NULL) {
506 : 65 : ret = scheduler->set_opts(params);
507 : : }
508 [ - + ]: 65 : if (ret) {
509 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, spdk_strerror(ret));
510 : 0 : goto end;
511 : : }
512 : :
513 : 65 : spdk_jsonrpc_send_bool_response(request, true);
514 : :
515 : 65 : end:
516 : 65 : free_rpc_framework_set_scheduler(&req);
517 : 65 : }
518 : 2882 : SPDK_RPC_REGISTER("framework_set_scheduler", rpc_framework_set_scheduler,
519 : : SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME)
520 : :
521 : : static void
522 : 0 : rpc_framework_get_scheduler(struct spdk_jsonrpc_request *request,
523 : : const struct spdk_json_val *params)
524 : : {
525 : : struct spdk_json_write_ctx *w;
526 : 0 : struct spdk_scheduler *scheduler = spdk_scheduler_get();
527 : 0 : uint64_t scheduler_period = spdk_scheduler_get_period();
528 : 0 : struct spdk_governor *governor = spdk_governor_get();
529 : :
530 [ # # ]: 0 : if (params) {
531 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
532 : : "'rpc_get_scheduler' requires no arguments");
533 : 0 : return;
534 : : }
535 : :
536 : 0 : w = spdk_jsonrpc_begin_result(request);
537 : 0 : spdk_json_write_object_begin(w);
538 [ # # ]: 0 : if (scheduler) {
539 : 0 : spdk_json_write_named_string(w, "scheduler_name", scheduler->name);
540 : : }
541 : 0 : spdk_json_write_named_uint64(w, "scheduler_period", scheduler_period);
542 [ # # ]: 0 : if (governor != NULL) {
543 : 0 : spdk_json_write_named_string(w, "governor_name", governor->name);
544 : : }
545 : :
546 [ # # # # ]: 0 : if (scheduler != NULL && scheduler->get_opts != NULL) {
547 : 0 : scheduler->get_opts(w);
548 : : }
549 : :
550 : 0 : spdk_json_write_object_end(w);
551 : 0 : spdk_jsonrpc_end_result(request, w);
552 : : }
553 : 2882 : SPDK_RPC_REGISTER("framework_get_scheduler", rpc_framework_get_scheduler, SPDK_RPC_RUNTIME)
554 : :
555 : : struct rpc_thread_set_cpumask_ctx {
556 : : struct spdk_jsonrpc_request *request;
557 : : struct spdk_cpuset cpumask;
558 : : int status;
559 : : struct spdk_thread *orig_thread;
560 : : };
561 : :
562 : : static void
563 : 8 : rpc_thread_set_cpumask_done(void *_ctx)
564 : : {
565 : 8 : struct rpc_thread_set_cpumask_ctx *ctx = _ctx;
566 : :
567 [ + - ]: 8 : if (ctx->status == 0) {
568 : 8 : spdk_jsonrpc_send_bool_response(ctx->request, true);
569 : : } else {
570 : 0 : spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
571 : 0 : spdk_strerror(-ctx->status));
572 : : }
573 : :
574 : 8 : free(ctx);
575 : 8 : }
576 : :
577 : : static void
578 : 8 : _rpc_thread_set_cpumask(void *_ctx)
579 : : {
580 : 8 : struct rpc_thread_set_cpumask_ctx *ctx = _ctx;
581 : :
582 : 8 : ctx->status = spdk_thread_set_cpumask(&ctx->cpumask);
583 : :
584 : 8 : spdk_thread_send_msg(ctx->orig_thread, rpc_thread_set_cpumask_done, ctx);
585 : 8 : }
586 : :
587 : : struct rpc_thread_set_cpumask {
588 : : uint64_t id;
589 : : char *cpumask;
590 : : };
591 : :
592 : : static const struct spdk_json_object_decoder rpc_thread_set_cpumask_decoders[] = {
593 : : {"id", offsetof(struct rpc_thread_set_cpumask, id), spdk_json_decode_uint64},
594 : : {"cpumask", offsetof(struct rpc_thread_set_cpumask, cpumask), spdk_json_decode_string},
595 : : };
596 : :
597 : : static void
598 : 8 : rpc_thread_set_cpumask(struct spdk_jsonrpc_request *request,
599 : : const struct spdk_json_val *params)
600 : : {
601 : 8 : struct rpc_thread_set_cpumask req = {};
602 : : struct rpc_thread_set_cpumask_ctx *ctx;
603 : : const struct spdk_cpuset *coremask;
604 : 8 : struct spdk_cpuset tmp_mask;
605 : : struct spdk_thread *thread;
606 : : int rc;
607 : :
608 : 8 : ctx = calloc(1, sizeof(*ctx));
609 [ - + ]: 8 : if (ctx == NULL) {
610 : 0 : SPDK_ERRLOG("Memory allocation failed\n");
611 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
612 : : "Memory allocation failed");
613 : 0 : return;
614 : : }
615 : :
616 [ - + ]: 8 : if (spdk_json_decode_object(params, rpc_thread_set_cpumask_decoders,
617 : : SPDK_COUNTOF(rpc_thread_set_cpumask_decoders),
618 : : &req)) {
619 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
620 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
621 : : "spdk_json_decode_object failed");
622 : 0 : goto err;
623 : : }
624 : :
625 : 8 : thread = spdk_thread_get_by_id(req.id);
626 [ - + ]: 8 : if (thread == NULL) {
627 : 0 : SPDK_ERRLOG("Thread %" PRIu64 " does not exist\n", req.id);
628 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
629 : : "Thread %" PRIu64 " does not exist", req.id);
630 : 0 : goto err;
631 : : }
632 : :
633 : 8 : rc = spdk_app_parse_core_mask(req.cpumask, &ctx->cpumask);
634 [ - + ]: 8 : if (rc != 0) {
635 : 0 : SPDK_ERRLOG("Invalid cpumask %s\n", req.cpumask);
636 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
637 : : "Invalid cpumask %s", req.cpumask);
638 : 0 : goto err;
639 : : }
640 : :
641 [ - + ]: 8 : if (spdk_cpuset_count(&ctx->cpumask) == 0) {
642 : 0 : coremask = spdk_app_get_core_mask();
643 : 0 : spdk_cpuset_copy(&tmp_mask, coremask);
644 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
645 : : "No CPU is selected from reactor mask %s\n",
646 : : spdk_cpuset_fmt(&tmp_mask));
647 : 0 : goto err;
648 : : }
649 : :
650 : : /* There may be any reactors running in interrupt mode. But currently,
651 : : * when interrupt ability of the spdk_thread is not enabled,
652 : : * spdk_thread can't get executed on reactor which runs in interrupt.
653 : : * Exclude the situation that reactors specified by the cpumask are
654 : : * all in interrupt mode.
655 : : */
656 [ - + ]: 8 : if (!spdk_interrupt_mode_is_enabled()) {
657 : 0 : struct spdk_reactor *local_reactor = spdk_reactor_get(spdk_env_get_current_core());
658 : 0 : struct spdk_cpuset tmp_cpuset;
659 : :
660 : : /* Masking off reactors which are in interrupt mode */
661 : 0 : spdk_cpuset_copy(&tmp_cpuset, &local_reactor->notify_cpuset);
662 : 0 : spdk_cpuset_negate(&tmp_cpuset);
663 : 0 : spdk_cpuset_and(&tmp_cpuset, &ctx->cpumask);
664 [ # # ]: 0 : if (spdk_cpuset_count(&tmp_cpuset) == 0) {
665 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
666 : : "cpumask %s are all in interrupt mode, and can't be scheduled yet\n",
667 : : req.cpumask);
668 : 0 : goto err;
669 : : }
670 : : }
671 : :
672 : 8 : ctx->request = request;
673 : 8 : ctx->orig_thread = spdk_get_thread();
674 : :
675 : 8 : spdk_thread_send_msg(thread, _rpc_thread_set_cpumask, ctx);
676 : :
677 : 8 : free(req.cpumask);
678 : 8 : return;
679 : :
680 : 0 : err:
681 : 0 : free(req.cpumask);
682 : 0 : free(ctx);
683 : : }
684 : 2882 : SPDK_RPC_REGISTER("thread_set_cpumask", rpc_thread_set_cpumask, SPDK_RPC_RUNTIME)
685 : 2882 : SPDK_LOG_REGISTER_COMPONENT(app_rpc)
|