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 : :
21 : : struct rpc_spdk_kill_instance {
22 : : char *sig_name;
23 : : };
24 : :
25 : : static void
26 : 61 : free_rpc_spdk_kill_instance(struct rpc_spdk_kill_instance *req)
27 : : {
28 : 61 : free(req->sig_name);
29 : 61 : }
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 : 61 : 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 : 61 : struct rpc_spdk_kill_instance req = {};
53 : :
54 [ - + ]: 61 : 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 : 61 : sig_count = SPDK_COUNTOF(signals);
62 : 61 : signal = spdk_strtol(req.sig_name, 10);
63 [ + - ]: 122 : for (i = 0 ; i < sig_count; i++) {
64 [ + + - + : 122 : if (strcmp(req.sig_name, signals[i].signal_string) == 0 ||
+ + ]
65 [ + - ]: 61 : signal == signals[i].signal) {
66 : : break;
67 : : }
68 : : }
69 : :
70 [ - + ]: 61 : if (i == sig_count) {
71 : 0 : goto invalid;
72 : : }
73 : :
74 [ - + - + ]: 61 : SPDK_DEBUGLOG(app_rpc, "sending signal %d\n", signals[i].signal);
75 : 61 : free_rpc_spdk_kill_instance(&req);
76 : 61 : kill(getpid(), signals[i].signal);
77 : :
78 : 61 : spdk_jsonrpc_send_bool_response(request, true);
79 : 61 : 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 : 2957 : 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 : 2957 : 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 : 30 : rpc_thread_get_stats_done(void *arg)
135 : : {
136 : 30 : struct rpc_get_stats_ctx *ctx = arg;
137 : :
138 : 30 : spdk_json_write_array_end(ctx->w);
139 : 30 : spdk_json_write_object_end(ctx->w);
140 : 30 : spdk_jsonrpc_end_result(ctx->request, ctx->w);
141 : :
142 : 30 : free(ctx);
143 : 30 : }
144 : :
145 : : static void
146 : 30 : 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 : 30 : ctx = calloc(1, sizeof(*ctx));
151 [ - + ]: 30 : if (!ctx) {
152 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
153 : : "Memory allocation error");
154 : 0 : return;
155 : : }
156 : 30 : ctx->request = request;
157 : :
158 : 30 : ctx->w = spdk_jsonrpc_begin_result(ctx->request);
159 : 30 : spdk_json_write_object_begin(ctx->w);
160 : 30 : spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz());
161 : 30 : spdk_json_write_named_array_begin(ctx->w, "threads");
162 : :
163 : 30 : spdk_for_each_thread(fn, ctx, rpc_thread_get_stats_done);
164 : : }
165 : :
166 : : static void
167 : 118 : _rpc_thread_get_stats(void *arg)
168 : : {
169 : 118 : struct rpc_get_stats_ctx *ctx = arg;
170 : 118 : struct spdk_thread *thread = spdk_get_thread();
171 : 118 : struct spdk_cpuset tmp_mask = {};
172 : : struct spdk_poller *poller;
173 : 12 : struct spdk_thread_stats stats;
174 : 118 : uint64_t active_pollers_count = 0;
175 : 118 : uint64_t timed_pollers_count = 0;
176 : 118 : uint64_t paused_pollers_count = 0;
177 : :
178 [ + + ]: 214 : for (poller = spdk_thread_get_first_active_poller(thread); poller != NULL;
179 : 96 : poller = spdk_thread_get_next_active_poller(poller)) {
180 : 96 : active_pollers_count++;
181 : : }
182 : :
183 [ + + ]: 188 : for (poller = spdk_thread_get_first_timed_poller(thread); poller != NULL;
184 : 70 : poller = spdk_thread_get_next_timed_poller(poller)) {
185 : 70 : timed_pollers_count++;
186 : : }
187 : :
188 [ - + ]: 118 : 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 [ + - ]: 118 : if (0 == spdk_thread_get_stats(&stats)) {
194 : 118 : spdk_json_write_object_begin(ctx->w);
195 : 118 : spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
196 : 118 : spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
197 : 118 : spdk_cpuset_copy(&tmp_mask, spdk_app_get_core_mask());
198 : 118 : spdk_cpuset_and(&tmp_mask, spdk_thread_get_cpumask(thread));
199 : 118 : spdk_json_write_named_string(ctx->w, "cpumask", spdk_cpuset_fmt(&tmp_mask));
200 : 118 : spdk_json_write_named_uint64(ctx->w, "busy", stats.busy_tsc);
201 : 118 : spdk_json_write_named_uint64(ctx->w, "idle", stats.idle_tsc);
202 : 118 : spdk_json_write_named_uint64(ctx->w, "active_pollers_count", active_pollers_count);
203 : 118 : spdk_json_write_named_uint64(ctx->w, "timed_pollers_count", timed_pollers_count);
204 : 118 : spdk_json_write_named_uint64(ctx->w, "paused_pollers_count", paused_pollers_count);
205 : 118 : spdk_json_write_object_end(ctx->w);
206 : : }
207 : 118 : }
208 : :
209 : : static void
210 : 22 : rpc_thread_get_stats(struct spdk_jsonrpc_request *request,
211 : : const struct spdk_json_val *params)
212 : : {
213 [ - + ]: 22 : 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 : 22 : rpc_thread_get_stats_for_each(request, _rpc_thread_get_stats);
220 : : }
221 : :
222 : 2957 : SPDK_RPC_REGISTER("thread_get_stats", rpc_thread_get_stats, SPDK_RPC_RUNTIME)
223 : :
224 : : static void
225 : 8 : rpc_get_poller(struct spdk_poller *poller, struct spdk_json_write_ctx *w)
226 : : {
227 : 6 : struct spdk_poller_stats stats;
228 : : uint64_t period_ticks;
229 : :
230 : 8 : period_ticks = spdk_poller_get_period_ticks(poller);
231 : 8 : spdk_poller_get_stats(poller, &stats);
232 : :
233 : 8 : spdk_json_write_object_begin(w);
234 : 8 : spdk_json_write_named_string(w, "name", spdk_poller_get_name(poller));
235 : 8 : spdk_json_write_named_uint64(w, "id", spdk_poller_get_id(poller));
236 : 8 : spdk_json_write_named_string(w, "state", spdk_poller_get_state_str(poller));
237 : 8 : spdk_json_write_named_uint64(w, "run_count", stats.run_count);
238 : 8 : spdk_json_write_named_uint64(w, "busy_count", stats.busy_count);
239 [ + - ]: 8 : if (period_ticks) {
240 : 8 : spdk_json_write_named_uint64(w, "period_ticks", period_ticks);
241 : : }
242 : 8 : spdk_json_write_object_end(w);
243 : 8 : }
244 : :
245 : : static void
246 : 8 : _rpc_thread_get_pollers(void *arg)
247 : : {
248 : 8 : struct rpc_get_stats_ctx *ctx = arg;
249 : 8 : struct spdk_thread *thread = spdk_get_thread();
250 : : struct spdk_poller *poller;
251 : :
252 : 8 : spdk_json_write_object_begin(ctx->w);
253 : 8 : spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
254 : 8 : spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
255 : :
256 : 8 : spdk_json_write_named_array_begin(ctx->w, "active_pollers");
257 [ - + ]: 8 : 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 : 8 : spdk_json_write_array_end(ctx->w);
262 : :
263 : 8 : spdk_json_write_named_array_begin(ctx->w, "timed_pollers");
264 [ + + ]: 16 : for (poller = spdk_thread_get_first_timed_poller(thread); poller != NULL;
265 : 8 : poller = spdk_thread_get_next_timed_poller(poller)) {
266 : 8 : rpc_get_poller(poller, ctx->w);
267 : : }
268 : 8 : spdk_json_write_array_end(ctx->w);
269 : :
270 : 8 : spdk_json_write_named_array_begin(ctx->w, "paused_pollers");
271 [ - + ]: 8 : 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 : 8 : spdk_json_write_array_end(ctx->w);
276 : :
277 : 8 : spdk_json_write_object_end(ctx->w);
278 : 8 : }
279 : :
280 : : static void
281 : 8 : rpc_thread_get_pollers(struct spdk_jsonrpc_request *request,
282 : : const struct spdk_json_val *params)
283 : : {
284 [ - + ]: 8 : 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 : 8 : rpc_thread_get_stats_for_each(request, _rpc_thread_get_pollers);
291 : : }
292 : :
293 : 2957 : 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 : 2957 : SPDK_RPC_REGISTER("thread_get_io_channels", rpc_thread_get_io_channels, SPDK_RPC_RUNTIME);
338 : :
339 : : static void
340 : 12 : rpc_framework_get_reactors_done(void *arg1, void *arg2)
341 : : {
342 : 12 : struct rpc_get_stats_ctx *ctx = arg1;
343 : :
344 : 12 : spdk_json_write_array_end(ctx->w);
345 : 12 : spdk_json_write_object_end(ctx->w);
346 : 12 : spdk_jsonrpc_end_result(ctx->request, ctx->w);
347 : :
348 : 12 : free(ctx);
349 : 12 : }
350 : :
351 : : #define GET_DELTA(end, start) (end >= start ? end - start : 0)
352 : :
353 : : static void
354 : 96 : _rpc_framework_get_reactors(void *arg1, void *arg2)
355 : : {
356 : 96 : 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 : 96 : struct spdk_cpuset tmp_mask = {};
363 : : struct spdk_governor *governor;
364 : :
365 : 96 : current_core = spdk_env_get_current_core();
366 : 96 : reactor = spdk_reactor_get(current_core);
367 : :
368 [ - + ]: 96 : assert(reactor != NULL);
369 : :
370 : 96 : spdk_json_write_object_begin(ctx->w);
371 : 96 : spdk_json_write_named_uint32(ctx->w, "lcore", current_core);
372 : 96 : spdk_json_write_named_uint64(ctx->w, "busy", reactor->busy_tsc);
373 : 96 : spdk_json_write_named_uint64(ctx->w, "idle", reactor->idle_tsc);
374 [ - + ]: 96 : spdk_json_write_named_bool(ctx->w, "in_interrupt", reactor->in_interrupt);
375 : :
376 : 96 : governor = spdk_governor_get();
377 [ + - ]: 96 : if (governor != NULL) {
378 : : /* Governor returns core freqs in kHz, we want MHz. */
379 : 96 : curr_core_freq = governor->get_core_curr_freq(current_core) / 1000;
380 : 96 : spdk_json_write_named_uint32(ctx->w, "core_freq", curr_core_freq);
381 : : }
382 : :
383 : 96 : spdk_json_write_named_array_begin(ctx->w, "lw_threads");
384 [ + + ]: 203 : TAILQ_FOREACH(lw_thread, &reactor->threads, link) {
385 : 107 : thread = spdk_thread_get_from_ctx(lw_thread);
386 : :
387 : 107 : spdk_json_write_object_begin(ctx->w);
388 : 107 : spdk_json_write_named_string(ctx->w, "name", spdk_thread_get_name(thread));
389 : 107 : spdk_json_write_named_uint64(ctx->w, "id", spdk_thread_get_id(thread));
390 : 107 : spdk_cpuset_copy(&tmp_mask, spdk_app_get_core_mask());
391 : 107 : spdk_cpuset_and(&tmp_mask, spdk_thread_get_cpumask(thread));
392 : 107 : spdk_json_write_named_string(ctx->w, "cpumask", spdk_cpuset_fmt(&tmp_mask));
393 : 107 : spdk_json_write_named_uint64(ctx->w, "elapsed",
394 [ + - ]: 107 : GET_DELTA(ctx->now, lw_thread->tsc_start));
395 : 107 : spdk_json_write_object_end(ctx->w);
396 : : }
397 : 96 : spdk_json_write_array_end(ctx->w);
398 : :
399 : 96 : spdk_json_write_object_end(ctx->w);
400 : 96 : }
401 : :
402 : : static void
403 : 12 : 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 [ - + ]: 12 : 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 : 12 : ctx = calloc(1, sizeof(*ctx));
415 [ - + ]: 12 : 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 : 12 : ctx->now = spdk_get_ticks();
422 : 12 : ctx->request = request;
423 : 12 : ctx->w = spdk_jsonrpc_begin_result(ctx->request);
424 : :
425 : 12 : spdk_json_write_object_begin(ctx->w);
426 : 12 : spdk_json_write_named_uint64(ctx->w, "tick_rate", spdk_get_ticks_hz());
427 : 12 : spdk_json_write_named_array_begin(ctx->w, "reactors");
428 : :
429 : 12 : spdk_for_each_reactor(_rpc_framework_get_reactors, ctx, NULL,
430 : : rpc_framework_get_reactors_done);
431 : : }
432 : :
433 : 2957 : 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 : 42 : free_rpc_framework_set_scheduler(struct rpc_set_scheduler_ctx *r)
442 : : {
443 : 42 : free(r->name);
444 : 42 : }
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 : 42 : rpc_framework_set_scheduler(struct spdk_jsonrpc_request *request,
453 : : const struct spdk_json_val *params)
454 : : {
455 : 42 : struct rpc_set_scheduler_ctx req = {NULL};
456 : 42 : struct spdk_scheduler *scheduler = NULL;
457 : : int ret;
458 : :
459 : 42 : ret = spdk_json_decode_object_relaxed(params, rpc_set_scheduler_decoders,
460 : : SPDK_COUNTOF(rpc_set_scheduler_decoders),
461 : : &req);
462 [ - + ]: 42 : 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 : 42 : scheduler = spdk_scheduler_get();
469 : : /* SPDK does not support changing scheduler back to static. */
470 [ + + - + : 42 : if (scheduler != NULL && (strcmp(req.name, "static") == 0) &&
+ - ]
471 [ - + - + ]: 1 : 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 [ - + ]: 42 : if (req.period != 0) {
480 : 0 : spdk_scheduler_set_period(req.period);
481 : : }
482 : :
483 : 42 : ret = spdk_scheduler_set(req.name);
484 [ - + ]: 42 : 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 : 42 : scheduler = spdk_scheduler_get();
491 [ + - + - ]: 42 : if (scheduler != NULL && scheduler->set_opts != NULL) {
492 : 42 : ret = scheduler->set_opts(params);
493 : : }
494 [ - + ]: 42 : 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 : 42 : spdk_jsonrpc_send_bool_response(request, true);
500 : :
501 : 42 : end:
502 : 42 : free_rpc_framework_set_scheduler(&req);
503 : 42 : }
504 : 2957 : 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 : 2957 : 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 : 8 : rpc_thread_set_cpumask_done(void *_ctx)
550 : : {
551 : 8 : struct rpc_thread_set_cpumask_ctx *ctx = _ctx;
552 : :
553 [ + - ]: 8 : if (ctx->status == 0) {
554 : 8 : 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 : 8 : free(ctx);
561 : 8 : }
562 : :
563 : : static void
564 : 8 : _rpc_thread_set_cpumask(void *_ctx)
565 : : {
566 : 8 : struct rpc_thread_set_cpumask_ctx *ctx = _ctx;
567 : :
568 : 8 : ctx->status = spdk_thread_set_cpumask(&ctx->cpumask);
569 : :
570 : 8 : spdk_thread_send_msg(ctx->orig_thread, rpc_thread_set_cpumask_done, ctx);
571 : 8 : }
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 : 8 : rpc_thread_set_cpumask(struct spdk_jsonrpc_request *request,
585 : : const struct spdk_json_val *params)
586 : : {
587 : 8 : struct rpc_thread_set_cpumask req = {};
588 : : struct rpc_thread_set_cpumask_ctx *ctx;
589 : : const struct spdk_cpuset *coremask;
590 : 6 : struct spdk_cpuset tmp_mask;
591 : : struct spdk_thread *thread;
592 : : int rc;
593 : :
594 : 8 : ctx = calloc(1, sizeof(*ctx));
595 [ - + ]: 8 : 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 : 2 : return;
600 : : }
601 : :
602 [ - + ]: 8 : 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 : 8 : thread = spdk_thread_get_by_id(req.id);
612 [ - + ]: 8 : 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 : 8 : rc = spdk_app_parse_core_mask(req.cpumask, &ctx->cpumask);
620 [ - + ]: 8 : 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 [ - + ]: 8 : 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 [ - + ]: 8 : 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 : 8 : ctx->request = request;
659 : 8 : ctx->orig_thread = spdk_get_thread();
660 : :
661 : 8 : spdk_thread_send_msg(thread, _rpc_thread_set_cpumask, ctx);
662 : :
663 : 8 : free(req.cpumask);
664 : 8 : return;
665 : :
666 : 0 : err:
667 : 0 : free(req.cpumask);
668 : 0 : free(ctx);
669 : : }
670 : 2957 : SPDK_RPC_REGISTER("thread_set_cpumask", rpc_thread_set_cpumask, SPDK_RPC_RUNTIME)
671 : 2957 : SPDK_LOG_REGISTER_COMPONENT(app_rpc)
|