Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2020 Intel Corporation.
3 : : * All rights reserved.
4 : : */
5 : :
6 : : #include "spdk/stdinc.h"
7 : : #include "spdk/conf.h"
8 : : #include "spdk/event.h"
9 : : #include "spdk/vhost.h"
10 : : #include "spdk/json.h"
11 : : #include "spdk/jsonrpc.h"
12 : : #include "spdk/rpc.h"
13 : : #include "spdk/env.h"
14 : : #include "spdk/scheduler.h"
15 : :
16 : : #include "spdk_internal/event.h"
17 : :
18 : : struct rpc_reactor_set_interrupt_mode {
19 : : int32_t lcore;
20 : : bool disable_interrupt;
21 : : int rc;
22 : : struct spdk_thread *rpc_thread;
23 : : struct spdk_jsonrpc_request *request;
24 : : };
25 : :
26 : : static const struct spdk_json_object_decoder rpc_reactor_set_interrupt_mode_decoders[] = {
27 : : {"lcore", offsetof(struct rpc_reactor_set_interrupt_mode, lcore), spdk_json_decode_int32},
28 : : {"disable_interrupt", offsetof(struct rpc_reactor_set_interrupt_mode, disable_interrupt), spdk_json_decode_bool},
29 : : };
30 : :
31 : : static void
32 : 24 : rpc_reactor_set_interrupt_mode_cb(void *cb_arg)
33 : : {
34 : 24 : struct rpc_reactor_set_interrupt_mode *req = cb_arg;
35 : :
36 : 24 : SPDK_NOTICELOG("complete reactor switch\n");
37 : :
38 : 24 : spdk_jsonrpc_send_bool_response(req->request, true);
39 : 24 : free(req);
40 : 24 : }
41 : :
42 : : static void
43 : 24 : set_interrupt_mode_cb(void *arg)
44 : : {
45 : 24 : struct rpc_reactor_set_interrupt_mode *req = arg;
46 : :
47 : 24 : spdk_thread_send_msg(req->rpc_thread, rpc_reactor_set_interrupt_mode_cb, req);
48 : 24 : }
49 : :
50 : : static void
51 : 24 : set_interrupt_mode(void *arg1, void *arg2)
52 : : {
53 : 24 : struct rpc_reactor_set_interrupt_mode *req = arg1;
54 : : int rc;
55 : :
56 [ - + ]: 40 : rc = spdk_reactor_set_interrupt_mode(req->lcore, !req->disable_interrupt,
57 : 24 : set_interrupt_mode_cb, req);
58 [ - + ]: 24 : if (rc) {
59 : 0 : req->rc = rc;
60 : 0 : set_interrupt_mode_cb(req);
61 : : }
62 : 24 : }
63 : :
64 : : static void
65 : 24 : rpc_reactor_set_interrupt_mode(struct spdk_jsonrpc_request *request,
66 : : const struct spdk_json_val *params)
67 : : {
68 : : struct rpc_reactor_set_interrupt_mode *req;
69 : :
70 : 24 : req = calloc(1, sizeof(*req));
71 [ - + ]: 24 : if (req == NULL) {
72 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
73 : : "Out of memory");
74 : 0 : return;
75 : : }
76 : :
77 : 24 : req->request = request;
78 : 24 : req->rpc_thread = spdk_get_thread();
79 : :
80 [ - + ]: 24 : if (spdk_json_decode_object(params, rpc_reactor_set_interrupt_mode_decoders,
81 : : SPDK_COUNTOF(rpc_reactor_set_interrupt_mode_decoders),
82 : : req)) {
83 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
84 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
85 : : "spdk_json_decode_object failed");
86 : 0 : free(req);
87 : 0 : return;
88 : : }
89 : :
90 [ - + ]: 24 : if (!spdk_interrupt_mode_is_enabled()) {
91 : 0 : SPDK_ERRLOG("Interrupt mode is not set when staring the application\n");
92 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
93 : : "spdk_json_decode_object failed");
94 : 0 : free(req);
95 : 0 : return;
96 : : }
97 : :
98 : :
99 [ + + + + ]: 24 : SPDK_NOTICELOG("RPC Start to %s interrupt mode on reactor %d.\n",
100 : : req->disable_interrupt ? "disable" : "enable", req->lcore);
101 [ + - ]: 24 : if (req->lcore >= (int64_t)spdk_env_get_first_core() &&
102 [ + - ]: 48 : req->lcore <= (int64_t)spdk_env_get_last_core()) {
103 : : struct spdk_event *e;
104 : :
105 : 24 : e = spdk_event_allocate(spdk_scheduler_get_scheduling_lcore(),
106 : : set_interrupt_mode, req, NULL);
107 : 24 : spdk_event_call(e);
108 : : } else {
109 : 0 : free(req);
110 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
111 : : "Invalid parameters");
112 : : }
113 : : }
114 : 9 : /* private */ SPDK_RPC_REGISTER("reactor_set_interrupt_mode", rpc_reactor_set_interrupt_mode,
115 : : SPDK_RPC_RUNTIME)
116 : :
117 : : static void
118 : 0 : interrupt_tgt_usage(void)
119 : : {
120 [ # # ]: 0 : printf(" -E Set interrupt mode\n");
121 [ # # ]: 0 : printf(" -S <path> directory where to create vhost sockets (default: pwd)\n");
122 : 0 : }
123 : :
124 : : static int
125 : 9 : interrupt_tgt_parse_arg(int ch, char *arg)
126 : : {
127 [ - + - ]: 9 : switch (ch) {
128 : 0 : case 'S':
129 : 0 : spdk_vhost_set_socket_path(arg);
130 : 0 : break;
131 : 9 : case 'E':
132 : 9 : spdk_interrupt_mode_enable();
133 : 9 : break;
134 : 0 : default:
135 : 0 : return -EINVAL;
136 : : }
137 : 9 : return 0;
138 : : }
139 : :
140 : : static void
141 : 9 : interrupt_tgt_started(void *arg1)
142 : : {
143 : 9 : }
144 : :
145 : : int
146 : 9 : main(int argc, char *argv[])
147 : : {
148 : 9 : struct spdk_app_opts opts = {};
149 : : int rc;
150 : :
151 : 9 : spdk_app_opts_init(&opts, sizeof(opts));
152 : 9 : opts.name = "interrupt_tgt";
153 : :
154 [ - + ]: 9 : if ((rc = spdk_app_parse_args(argc, argv, &opts, "S:E", NULL,
155 : : interrupt_tgt_parse_arg, interrupt_tgt_usage)) !=
156 : : SPDK_APP_PARSE_ARGS_SUCCESS) {
157 : 0 : exit(rc);
158 : : }
159 : :
160 : : /* Blocks until the application is exiting */
161 : 9 : rc = spdk_app_start(&opts, interrupt_tgt_started, NULL);
162 : :
163 : 9 : spdk_app_fini();
164 : :
165 : 9 : return rc;
166 : : }
|