Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2008-2012 Daisuke Aoyama <aoyama@peach.ne.jp>.
3 : : * Copyright (C) 2016 Intel Corporation.
4 : : * All rights reserved.
5 : : */
6 : :
7 : : #include "iscsi/iscsi.h"
8 : : #include "iscsi/conn.h"
9 : : #include "iscsi/tgt_node.h"
10 : : #include "iscsi/portal_grp.h"
11 : : #include "iscsi/init_grp.h"
12 : :
13 : : #include "spdk/rpc.h"
14 : : #include "spdk/util.h"
15 : : #include "spdk/string.h"
16 : : #include "spdk/log.h"
17 : : #include "spdk/base64.h"
18 : : #include "spdk/histogram_data.h"
19 : :
20 : : static void
21 : 180 : rpc_iscsi_get_initiator_groups(struct spdk_jsonrpc_request *request,
22 : : const struct spdk_json_val *params)
23 : : {
24 : : struct spdk_json_write_ctx *w;
25 : :
26 [ - + ]: 180 : if (params != NULL) {
27 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
28 : : "iscsi_get_initiator_groups requires no parameters");
29 : 0 : return;
30 : : }
31 : :
32 : 180 : w = spdk_jsonrpc_begin_result(request);
33 : 180 : spdk_json_write_array_begin(w);
34 : 180 : iscsi_init_grps_info_json(w);
35 : 180 : spdk_json_write_array_end(w);
36 : :
37 : 180 : spdk_jsonrpc_end_result(request, w);
38 : : }
39 : 667 : SPDK_RPC_REGISTER("iscsi_get_initiator_groups", rpc_iscsi_get_initiator_groups,
40 : : SPDK_RPC_RUNTIME)
41 : :
42 : : struct rpc_initiator_list {
43 : : size_t num_initiators;
44 : : char *initiators[MAX_INITIATOR];
45 : : };
46 : :
47 : : static int
48 : 118 : decode_rpc_initiator_list(const struct spdk_json_val *val, void *out)
49 : : {
50 : 118 : struct rpc_initiator_list *list = out;
51 : :
52 : 118 : return spdk_json_decode_array(val, spdk_json_decode_string, list->initiators, MAX_INITIATOR,
53 : : &list->num_initiators, sizeof(char *));
54 : : }
55 : :
56 : : static void
57 : 118 : free_rpc_initiator_list(struct rpc_initiator_list *list)
58 : : {
59 : : size_t i;
60 : :
61 [ + + ]: 236 : for (i = 0; i < list->num_initiators; i++) {
62 : 118 : free(list->initiators[i]);
63 : : }
64 : 118 : }
65 : :
66 : : struct rpc_netmask_list {
67 : : size_t num_netmasks;
68 : : char *netmasks[MAX_NETMASK];
69 : : };
70 : :
71 : : static int
72 : 118 : decode_rpc_netmask_list(const struct spdk_json_val *val, void *out)
73 : : {
74 : 118 : struct rpc_netmask_list *list = out;
75 : :
76 : 118 : return spdk_json_decode_array(val, spdk_json_decode_string, list->netmasks, MAX_NETMASK,
77 : : &list->num_netmasks, sizeof(char *));
78 : : }
79 : :
80 : : static void
81 : 118 : free_rpc_netmask_list(struct rpc_netmask_list *list)
82 : : {
83 : : size_t i;
84 : :
85 [ + + ]: 236 : for (i = 0; i < list->num_netmasks; i++) {
86 : 118 : free(list->netmasks[i]);
87 : : }
88 : 118 : }
89 : :
90 : : struct rpc_initiator_group {
91 : : int32_t tag;
92 : : struct rpc_initiator_list initiator_list;
93 : : struct rpc_netmask_list netmask_list;
94 : : };
95 : :
96 : : static void
97 : 118 : free_rpc_initiator_group(struct rpc_initiator_group *ig)
98 : : {
99 : 118 : free_rpc_initiator_list(&ig->initiator_list);
100 : 118 : free_rpc_netmask_list(&ig->netmask_list);
101 : 118 : }
102 : :
103 : : static const struct spdk_json_object_decoder rpc_initiator_group_decoders[] = {
104 : : {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32},
105 : : {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list},
106 : : {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list},
107 : : };
108 : :
109 : : static void
110 : 70 : rpc_iscsi_create_initiator_group(struct spdk_jsonrpc_request *request,
111 : : const struct spdk_json_val *params)
112 : : {
113 : 70 : struct rpc_initiator_group req = {};
114 : :
115 [ - + ]: 70 : if (spdk_json_decode_object(params, rpc_initiator_group_decoders,
116 : : SPDK_COUNTOF(rpc_initiator_group_decoders), &req)) {
117 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
118 : 0 : goto invalid;
119 : : }
120 : :
121 [ + - ]: 70 : if (req.initiator_list.num_initiators == 0 ||
122 [ - + ]: 70 : req.netmask_list.num_netmasks == 0) {
123 : 0 : goto invalid;
124 : : }
125 : :
126 [ - + ]: 70 : if (iscsi_init_grp_create_from_initiator_list(req.tag,
127 : 70 : req.initiator_list.num_initiators,
128 : : req.initiator_list.initiators,
129 : 70 : req.netmask_list.num_netmasks,
130 : : req.netmask_list.netmasks)) {
131 : 0 : SPDK_ERRLOG("create_from_initiator_list failed\n");
132 : 0 : goto invalid;
133 : : }
134 : :
135 : 70 : free_rpc_initiator_group(&req);
136 : :
137 : 70 : spdk_jsonrpc_send_bool_response(request, true);
138 : 70 : return;
139 : :
140 : 0 : invalid:
141 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
142 : 0 : free_rpc_initiator_group(&req);
143 : : }
144 : 667 : SPDK_RPC_REGISTER("iscsi_create_initiator_group", rpc_iscsi_create_initiator_group,
145 : : SPDK_RPC_RUNTIME)
146 : :
147 : : static const struct spdk_json_object_decoder rpc_add_or_delete_initiators_decoders[] = {
148 : : {"tag", offsetof(struct rpc_initiator_group, tag), spdk_json_decode_int32},
149 : : {"initiators", offsetof(struct rpc_initiator_group, initiator_list), decode_rpc_initiator_list, true},
150 : : {"netmasks", offsetof(struct rpc_initiator_group, netmask_list), decode_rpc_netmask_list, true},
151 : : };
152 : :
153 : : static void
154 : 24 : rpc_iscsi_initiator_group_add_initiators(struct spdk_jsonrpc_request *request,
155 : : const struct spdk_json_val *params)
156 : : {
157 : 24 : struct rpc_initiator_group req = {};
158 : :
159 [ - + ]: 24 : if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders,
160 : : SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) {
161 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
162 : 0 : goto invalid;
163 : : }
164 : :
165 [ - + ]: 24 : if (iscsi_init_grp_add_initiators_from_initiator_list(req.tag,
166 : 24 : req.initiator_list.num_initiators,
167 : : req.initiator_list.initiators,
168 : 24 : req.netmask_list.num_netmasks,
169 : : req.netmask_list.netmasks)) {
170 : 0 : SPDK_ERRLOG("add_initiators_from_initiator_list failed\n");
171 : 0 : goto invalid;
172 : : }
173 : :
174 : 24 : free_rpc_initiator_group(&req);
175 : :
176 : 24 : spdk_jsonrpc_send_bool_response(request, true);
177 : 24 : return;
178 : :
179 : 0 : invalid:
180 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
181 : 0 : free_rpc_initiator_group(&req);
182 : : }
183 : 667 : SPDK_RPC_REGISTER("iscsi_initiator_group_add_initiators",
184 : : rpc_iscsi_initiator_group_add_initiators, SPDK_RPC_RUNTIME)
185 : :
186 : : static void
187 : 24 : rpc_iscsi_initiator_group_remove_initiators(struct spdk_jsonrpc_request *request,
188 : : const struct spdk_json_val *params)
189 : : {
190 : 24 : struct rpc_initiator_group req = {};
191 : :
192 [ - + ]: 24 : if (spdk_json_decode_object(params, rpc_add_or_delete_initiators_decoders,
193 : : SPDK_COUNTOF(rpc_add_or_delete_initiators_decoders), &req)) {
194 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
195 : 0 : goto invalid;
196 : : }
197 : :
198 [ - + ]: 24 : if (iscsi_init_grp_delete_initiators_from_initiator_list(req.tag,
199 : 24 : req.initiator_list.num_initiators,
200 : : req.initiator_list.initiators,
201 : 24 : req.netmask_list.num_netmasks,
202 : : req.netmask_list.netmasks)) {
203 : 0 : SPDK_ERRLOG("delete_initiators_from_initiator_list failed\n");
204 : 0 : goto invalid;
205 : : }
206 : :
207 : 24 : free_rpc_initiator_group(&req);
208 : :
209 : 24 : spdk_jsonrpc_send_bool_response(request, true);
210 : 24 : return;
211 : :
212 : 0 : invalid:
213 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
214 : 0 : free_rpc_initiator_group(&req);
215 : : }
216 : 667 : SPDK_RPC_REGISTER("iscsi_initiator_group_remove_initiators",
217 : : rpc_iscsi_initiator_group_remove_initiators, SPDK_RPC_RUNTIME)
218 : :
219 : : struct rpc_iscsi_delete_initiator_group {
220 : : int32_t tag;
221 : : };
222 : :
223 : : static const struct spdk_json_object_decoder rpc_iscsi_delete_initiator_group_decoders[] = {
224 : : {"tag", offsetof(struct rpc_iscsi_delete_initiator_group, tag), spdk_json_decode_int32},
225 : : };
226 : :
227 : : static void
228 : 34 : rpc_iscsi_delete_initiator_group(struct spdk_jsonrpc_request *request,
229 : : const struct spdk_json_val *params)
230 : : {
231 : 34 : struct rpc_iscsi_delete_initiator_group req = {};
232 : : struct spdk_iscsi_init_grp *ig;
233 : :
234 [ - + ]: 34 : if (spdk_json_decode_object(params, rpc_iscsi_delete_initiator_group_decoders,
235 : : SPDK_COUNTOF(rpc_iscsi_delete_initiator_group_decoders),
236 : : &req)) {
237 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
238 : 0 : goto invalid;
239 : : }
240 : :
241 : 34 : ig = iscsi_init_grp_unregister(req.tag);
242 [ - + ]: 34 : if (!ig) {
243 : 0 : goto invalid;
244 : : }
245 : 34 : iscsi_tgt_node_delete_map(NULL, ig);
246 : 34 : iscsi_init_grp_destroy(ig);
247 : :
248 : 34 : spdk_jsonrpc_send_bool_response(request, true);
249 : 34 : return;
250 : :
251 : 0 : invalid:
252 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
253 : : }
254 : 667 : SPDK_RPC_REGISTER("iscsi_delete_initiator_group", rpc_iscsi_delete_initiator_group,
255 : : SPDK_RPC_RUNTIME)
256 : :
257 : : static void
258 : 142 : rpc_iscsi_get_target_nodes(struct spdk_jsonrpc_request *request,
259 : : const struct spdk_json_val *params)
260 : : {
261 : : struct spdk_json_write_ctx *w;
262 : :
263 [ - + ]: 142 : if (params != NULL) {
264 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
265 : : "iscsi_get_target_nodes requires no parameters");
266 : 0 : return;
267 : : }
268 : :
269 : 142 : w = spdk_jsonrpc_begin_result(request);
270 : 142 : spdk_json_write_array_begin(w);
271 : 142 : iscsi_tgt_nodes_info_json(w);
272 : 142 : spdk_json_write_array_end(w);
273 : :
274 : 142 : spdk_jsonrpc_end_result(request, w);
275 : : }
276 : 667 : SPDK_RPC_REGISTER("iscsi_get_target_nodes", rpc_iscsi_get_target_nodes, SPDK_RPC_RUNTIME)
277 : :
278 : : struct rpc_pg_ig_map {
279 : : int32_t pg_tag;
280 : : int32_t ig_tag;
281 : : };
282 : :
283 : : static const struct spdk_json_object_decoder rpc_pg_ig_map_decoders[] = {
284 : : {"pg_tag", offsetof(struct rpc_pg_ig_map, pg_tag), spdk_json_decode_int32},
285 : : {"ig_tag", offsetof(struct rpc_pg_ig_map, ig_tag), spdk_json_decode_int32},
286 : : };
287 : :
288 : : static int
289 : 146 : decode_rpc_pg_ig_map(const struct spdk_json_val *val, void *out)
290 : : {
291 : 146 : struct rpc_pg_ig_map *pg_ig_map = out;
292 : :
293 : 146 : return spdk_json_decode_object(val, rpc_pg_ig_map_decoders,
294 : : SPDK_COUNTOF(rpc_pg_ig_map_decoders),
295 : : pg_ig_map);
296 : : }
297 : :
298 : : struct rpc_pg_ig_maps {
299 : : size_t num_maps;
300 : : struct rpc_pg_ig_map maps[MAX_TARGET_MAP];
301 : : };
302 : :
303 : : static int
304 : 142 : decode_rpc_pg_ig_maps(const struct spdk_json_val *val, void *out)
305 : : {
306 : 142 : struct rpc_pg_ig_maps *pg_ig_maps = out;
307 : :
308 : 142 : return spdk_json_decode_array(val, decode_rpc_pg_ig_map, pg_ig_maps->maps,
309 : : MAX_TARGET_MAP, &pg_ig_maps->num_maps,
310 : : sizeof(struct rpc_pg_ig_map));
311 : : }
312 : :
313 : : #define RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN 64
314 : :
315 : : struct rpc_lun {
316 : : char *bdev_name;
317 : : int32_t lun_id;
318 : : };
319 : :
320 : : static const struct spdk_json_object_decoder rpc_lun_decoders[] = {
321 : : {"bdev_name", offsetof(struct rpc_lun, bdev_name), spdk_json_decode_string},
322 : : {"lun_id", offsetof(struct rpc_lun, lun_id), spdk_json_decode_int32},
323 : : };
324 : :
325 : : static int
326 : 146 : decode_rpc_lun(const struct spdk_json_val *val, void *out)
327 : : {
328 : 146 : struct rpc_lun *lun = out;
329 : :
330 : 146 : return spdk_json_decode_object(val, rpc_lun_decoders,
331 : : SPDK_COUNTOF(rpc_lun_decoders), lun);
332 : : }
333 : :
334 : : struct rpc_luns {
335 : : size_t num_luns;
336 : : struct rpc_lun luns[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN];
337 : : };
338 : :
339 : : static int
340 : 138 : decode_rpc_luns(const struct spdk_json_val *val, void *out)
341 : : {
342 : 138 : struct rpc_luns *luns = out;
343 : :
344 : 138 : return spdk_json_decode_array(val, decode_rpc_lun, luns->luns,
345 : : RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN,
346 : : &luns->num_luns, sizeof(struct rpc_lun));
347 : : }
348 : :
349 : : static void
350 : 138 : free_rpc_luns(struct rpc_luns *p)
351 : : {
352 : : size_t i;
353 : :
354 [ + + ]: 284 : for (i = 0; i < p->num_luns; i++) {
355 : 146 : free(p->luns[i].bdev_name);
356 : : }
357 : 138 : }
358 : :
359 : : struct rpc_target_node {
360 : : char *name;
361 : : char *alias_name;
362 : :
363 : : struct rpc_pg_ig_maps pg_ig_maps;
364 : : struct rpc_luns luns;
365 : :
366 : : int32_t queue_depth;
367 : : bool disable_chap;
368 : : bool require_chap;
369 : : bool mutual_chap;
370 : : int32_t chap_group;
371 : :
372 : : bool header_digest;
373 : : bool data_digest;
374 : : };
375 : :
376 : : static void
377 : 138 : free_rpc_target_node(struct rpc_target_node *req)
378 : : {
379 : 138 : free(req->name);
380 : 138 : free(req->alias_name);
381 : 138 : free_rpc_luns(&req->luns);
382 : 138 : }
383 : :
384 : : static const struct spdk_json_object_decoder rpc_target_node_decoders[] = {
385 : : {"name", offsetof(struct rpc_target_node, name), spdk_json_decode_string},
386 : : {"alias_name", offsetof(struct rpc_target_node, alias_name), spdk_json_decode_string},
387 : : {"pg_ig_maps", offsetof(struct rpc_target_node, pg_ig_maps), decode_rpc_pg_ig_maps},
388 : : {"luns", offsetof(struct rpc_target_node, luns), decode_rpc_luns},
389 : : {"queue_depth", offsetof(struct rpc_target_node, queue_depth), spdk_json_decode_int32},
390 : : {"disable_chap", offsetof(struct rpc_target_node, disable_chap), spdk_json_decode_bool, true},
391 : : {"require_chap", offsetof(struct rpc_target_node, require_chap), spdk_json_decode_bool, true},
392 : : {"mutual_chap", offsetof(struct rpc_target_node, mutual_chap), spdk_json_decode_bool, true},
393 : : {"chap_group", offsetof(struct rpc_target_node, chap_group), spdk_json_decode_int32, true},
394 : : {"header_digest", offsetof(struct rpc_target_node, header_digest), spdk_json_decode_bool, true},
395 : : {"data_digest", offsetof(struct rpc_target_node, data_digest), spdk_json_decode_bool, true},
396 : : };
397 : :
398 : : static void
399 : 138 : rpc_iscsi_create_target_node(struct spdk_jsonrpc_request *request,
400 : : const struct spdk_json_val *params)
401 : : {
402 : 138 : struct rpc_target_node req = {};
403 : : struct spdk_iscsi_tgt_node *target;
404 : 138 : int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
405 : 138 : char *bdev_names[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0};
406 : 138 : int32_t lun_ids[RPC_ISCSI_CREATE_TARGET_NODE_MAX_LUN] = {0};
407 : : size_t i;
408 : :
409 [ - + ]: 138 : if (spdk_json_decode_object(params, rpc_target_node_decoders,
410 : : SPDK_COUNTOF(rpc_target_node_decoders),
411 : : &req)) {
412 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
413 : 0 : goto invalid;
414 : : }
415 : :
416 [ + + ]: 276 : for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
417 : 138 : pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
418 : 138 : ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
419 : : }
420 : :
421 [ + + ]: 284 : for (i = 0; i < req.luns.num_luns; i++) {
422 : 146 : bdev_names[i] = req.luns.luns[i].bdev_name;
423 : 146 : lun_ids[i] = req.luns.luns[i].lun_id;
424 : : }
425 : :
426 : : /*
427 : : * Use default parameters in a few places:
428 : : * index = -1 : automatically pick an index for the new target node
429 : : * alias = NULL
430 : : */
431 : 690 : target = iscsi_tgt_node_construct(-1, req.name, req.alias_name,
432 : : pg_tags,
433 : : ig_tags,
434 : 138 : req.pg_ig_maps.num_maps,
435 : : (const char **)bdev_names,
436 : : lun_ids,
437 : 138 : req.luns.num_luns,
438 : : req.queue_depth,
439 : 138 : req.disable_chap,
440 [ - + ]: 138 : req.require_chap,
441 [ - + ]: 138 : req.mutual_chap,
442 : : req.chap_group,
443 [ - + ]: 138 : req.header_digest,
444 [ - + - + ]: 138 : req.data_digest);
445 : :
446 [ - + ]: 138 : if (target == NULL) {
447 : 0 : goto invalid;
448 : : }
449 : :
450 : 138 : free_rpc_target_node(&req);
451 : :
452 : 138 : spdk_jsonrpc_send_bool_response(request, true);
453 : 138 : return;
454 : :
455 : 0 : invalid:
456 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
457 : 0 : free_rpc_target_node(&req);
458 : : }
459 : 667 : SPDK_RPC_REGISTER("iscsi_create_target_node", rpc_iscsi_create_target_node, SPDK_RPC_RUNTIME)
460 : :
461 : : struct rpc_tgt_node_pg_ig_maps {
462 : : char *name;
463 : : struct rpc_pg_ig_maps pg_ig_maps;
464 : : };
465 : :
466 : : static const struct spdk_json_object_decoder rpc_tgt_node_pg_ig_maps_decoders[] = {
467 : : {"name", offsetof(struct rpc_tgt_node_pg_ig_maps, name), spdk_json_decode_string},
468 : : {"pg_ig_maps", offsetof(struct rpc_tgt_node_pg_ig_maps, pg_ig_maps), decode_rpc_pg_ig_maps},
469 : : };
470 : :
471 : : static void
472 : 2 : rpc_iscsi_target_node_add_pg_ig_maps(struct spdk_jsonrpc_request *request,
473 : : const struct spdk_json_val *params)
474 : : {
475 : 2 : struct rpc_tgt_node_pg_ig_maps req = {};
476 : : struct spdk_iscsi_tgt_node *target;
477 : 2 : int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
478 : : size_t i;
479 : : int rc;
480 : :
481 [ - + ]: 2 : if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders,
482 : : SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders),
483 : : &req)) {
484 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
485 : 0 : goto invalid;
486 : : }
487 : :
488 : 2 : target = iscsi_find_tgt_node(req.name);
489 [ - + ]: 2 : if (target == NULL) {
490 : 0 : SPDK_ERRLOG("target is not found\n");
491 : 0 : goto invalid;
492 : : }
493 : :
494 [ + + ]: 6 : for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
495 : 4 : pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
496 : 4 : ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
497 : : }
498 : :
499 : 2 : rc = iscsi_target_node_add_pg_ig_maps(target, pg_tags, ig_tags,
500 : 2 : req.pg_ig_maps.num_maps);
501 [ - + ]: 2 : if (rc < 0) {
502 : 0 : SPDK_ERRLOG("add pg-ig maps failed\n");
503 : 0 : goto invalid;
504 : : }
505 : :
506 : 2 : free(req.name);
507 : :
508 : 2 : spdk_jsonrpc_send_bool_response(request, true);
509 : 2 : return;
510 : :
511 : 0 : invalid:
512 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
513 : : "Invalid parameters");
514 : 0 : free(req.name);
515 : : }
516 : 667 : SPDK_RPC_REGISTER("iscsi_target_node_add_pg_ig_maps",
517 : : rpc_iscsi_target_node_add_pg_ig_maps, SPDK_RPC_RUNTIME)
518 : :
519 : : static void
520 : 2 : rpc_iscsi_target_node_remove_pg_ig_maps(struct spdk_jsonrpc_request *request,
521 : : const struct spdk_json_val *params)
522 : : {
523 : 2 : struct rpc_tgt_node_pg_ig_maps req = {};
524 : : struct spdk_iscsi_tgt_node *target;
525 : 2 : int32_t pg_tags[MAX_TARGET_MAP] = {0}, ig_tags[MAX_TARGET_MAP] = {0};
526 : : size_t i;
527 : : int rc;
528 : :
529 [ - + ]: 2 : if (spdk_json_decode_object(params, rpc_tgt_node_pg_ig_maps_decoders,
530 : : SPDK_COUNTOF(rpc_tgt_node_pg_ig_maps_decoders),
531 : : &req)) {
532 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
533 : 0 : goto invalid;
534 : : }
535 : :
536 : 2 : target = iscsi_find_tgt_node(req.name);
537 [ - + ]: 2 : if (target == NULL) {
538 : 0 : SPDK_ERRLOG("target is not found\n");
539 : 0 : goto invalid;
540 : : }
541 : :
542 [ + + ]: 6 : for (i = 0; i < req.pg_ig_maps.num_maps; i++) {
543 : 4 : pg_tags[i] = req.pg_ig_maps.maps[i].pg_tag;
544 : 4 : ig_tags[i] = req.pg_ig_maps.maps[i].ig_tag;
545 : : }
546 : :
547 : 2 : rc = iscsi_target_node_remove_pg_ig_maps(target, pg_tags, ig_tags,
548 : 2 : req.pg_ig_maps.num_maps);
549 [ - + ]: 2 : if (rc < 0) {
550 : 0 : SPDK_ERRLOG("remove pg-ig maps failed\n");
551 : 0 : goto invalid;
552 : : }
553 : :
554 : 2 : free(req.name);
555 : :
556 : 2 : spdk_jsonrpc_send_bool_response(request, true);
557 : 2 : return;
558 : :
559 : 0 : invalid:
560 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
561 : : "Invalid parameters");
562 : 0 : free(req.name);
563 : : }
564 : 667 : SPDK_RPC_REGISTER("iscsi_target_node_remove_pg_ig_maps",
565 : : rpc_iscsi_target_node_remove_pg_ig_maps, SPDK_RPC_RUNTIME)
566 : :
567 : : struct rpc_iscsi_delete_target_node {
568 : : char *name;
569 : : };
570 : :
571 : : static void
572 : 52 : free_rpc_iscsi_delete_target_node(struct rpc_iscsi_delete_target_node *r)
573 : : {
574 : 52 : free(r->name);
575 : 52 : }
576 : :
577 : : static const struct spdk_json_object_decoder rpc_iscsi_delete_target_node_decoders[] = {
578 : : {"name", offsetof(struct rpc_iscsi_delete_target_node, name), spdk_json_decode_string},
579 : : };
580 : :
581 : : struct rpc_iscsi_delete_target_node_ctx {
582 : : struct rpc_iscsi_delete_target_node req;
583 : : struct spdk_jsonrpc_request *request;
584 : : };
585 : :
586 : : static void
587 : 52 : rpc_iscsi_delete_target_node_done(void *cb_arg, int rc)
588 : : {
589 : 52 : struct rpc_iscsi_delete_target_node_ctx *ctx = cb_arg;
590 : :
591 : 52 : free_rpc_iscsi_delete_target_node(&ctx->req);
592 [ + - ]: 52 : if (rc == 0) {
593 : 52 : spdk_jsonrpc_send_bool_response(ctx->request, true);
594 : : } else {
595 : 0 : spdk_jsonrpc_send_error_response(ctx->request, rc, spdk_strerror(-rc));
596 : : }
597 : 52 : free(ctx);
598 : 52 : }
599 : :
600 : : static void
601 : 52 : rpc_iscsi_delete_target_node(struct spdk_jsonrpc_request *request,
602 : : const struct spdk_json_val *params)
603 : : {
604 : : struct rpc_iscsi_delete_target_node_ctx *ctx;
605 : :
606 : 52 : ctx = calloc(1, sizeof(*ctx));
607 [ - + ]: 52 : if (!ctx) {
608 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
609 : : spdk_strerror(ENOMEM));
610 : 0 : return;
611 : : }
612 : :
613 [ - + ]: 52 : if (spdk_json_decode_object(params, rpc_iscsi_delete_target_node_decoders,
614 : : SPDK_COUNTOF(rpc_iscsi_delete_target_node_decoders),
615 : 52 : &ctx->req)) {
616 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
617 : 0 : goto invalid;
618 : : }
619 : :
620 [ - + ]: 52 : if (ctx->req.name == NULL) {
621 : 0 : SPDK_ERRLOG("missing name param\n");
622 : 0 : goto invalid;
623 : : }
624 : :
625 : 52 : ctx->request = request;
626 : :
627 : 52 : iscsi_shutdown_tgt_node_by_name(ctx->req.name,
628 : : rpc_iscsi_delete_target_node_done, ctx);
629 : 52 : return;
630 : :
631 : 0 : invalid:
632 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
633 : 0 : free_rpc_iscsi_delete_target_node(&ctx->req);
634 : 0 : free(ctx);
635 : : }
636 : 667 : SPDK_RPC_REGISTER("iscsi_delete_target_node", rpc_iscsi_delete_target_node, SPDK_RPC_RUNTIME)
637 : :
638 : : static void
639 : 136 : rpc_iscsi_get_portal_groups(struct spdk_jsonrpc_request *request,
640 : : const struct spdk_json_val *params)
641 : : {
642 : : struct spdk_json_write_ctx *w;
643 : :
644 [ - + ]: 136 : if (params != NULL) {
645 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
646 : : "iscsi_get_portal_groups requires no parameters");
647 : 0 : return;
648 : : }
649 : :
650 : 136 : w = spdk_jsonrpc_begin_result(request);
651 : 136 : spdk_json_write_array_begin(w);
652 : 136 : iscsi_portal_grps_info_json(w);
653 : 136 : spdk_json_write_array_end(w);
654 : :
655 : 136 : spdk_jsonrpc_end_result(request, w);
656 : : }
657 : 667 : SPDK_RPC_REGISTER("iscsi_get_portal_groups", rpc_iscsi_get_portal_groups, SPDK_RPC_RUNTIME)
658 : :
659 : : struct rpc_portal {
660 : : char *host;
661 : : char *port;
662 : : };
663 : :
664 : : struct rpc_portal_list {
665 : : size_t num_portals;
666 : : struct rpc_portal portals[MAX_PORTAL];
667 : : };
668 : :
669 : : struct rpc_portal_group {
670 : : int32_t tag;
671 : : struct rpc_portal_list portal_list;
672 : : bool is_private;
673 : : bool wait;
674 : : };
675 : :
676 : : static void
677 : 52 : free_rpc_portal(struct rpc_portal *portal)
678 : : {
679 : 52 : free(portal->host);
680 : 52 : free(portal->port);
681 : 52 : }
682 : :
683 : : static void
684 : 50 : free_rpc_portal_list(struct rpc_portal_list *pl)
685 : : {
686 : : size_t i;
687 : :
688 [ + + ]: 102 : for (i = 0; i < pl->num_portals; i++) {
689 : 52 : free_rpc_portal(&pl->portals[i]);
690 : : }
691 : 50 : pl->num_portals = 0;
692 : 50 : }
693 : :
694 : : static void
695 : 50 : free_rpc_portal_group(struct rpc_portal_group *pg)
696 : : {
697 : 50 : free_rpc_portal_list(&pg->portal_list);
698 : 50 : }
699 : :
700 : : static const struct spdk_json_object_decoder rpc_portal_decoders[] = {
701 : : {"host", offsetof(struct rpc_portal, host), spdk_json_decode_string},
702 : : {"port", offsetof(struct rpc_portal, port), spdk_json_decode_string},
703 : : };
704 : :
705 : : static int
706 : 52 : decode_rpc_portal(const struct spdk_json_val *val, void *out)
707 : : {
708 : 52 : struct rpc_portal *portal = out;
709 : :
710 : 52 : return spdk_json_decode_object(val, rpc_portal_decoders,
711 : : SPDK_COUNTOF(rpc_portal_decoders),
712 : : portal);
713 : : }
714 : :
715 : : static int
716 : 50 : decode_rpc_portal_list(const struct spdk_json_val *val, void *out)
717 : : {
718 : 50 : struct rpc_portal_list *list = out;
719 : :
720 : 50 : return spdk_json_decode_array(val, decode_rpc_portal, list->portals, MAX_PORTAL, &list->num_portals,
721 : : sizeof(struct rpc_portal));
722 : : }
723 : :
724 : : static const struct spdk_json_object_decoder rpc_portal_group_decoders[] = {
725 : : {"tag", offsetof(struct rpc_portal_group, tag), spdk_json_decode_int32},
726 : : {"portals", offsetof(struct rpc_portal_group, portal_list), decode_rpc_portal_list},
727 : : {"private", offsetof(struct rpc_portal_group, is_private), spdk_json_decode_bool, true},
728 : : {"wait", offsetof(struct rpc_portal_group, wait), spdk_json_decode_bool, true},
729 : : };
730 : :
731 : : static void
732 : 50 : rpc_iscsi_create_portal_group(struct spdk_jsonrpc_request *request,
733 : : const struct spdk_json_val *params)
734 : : {
735 : 50 : struct rpc_portal_group req = {};
736 : 50 : struct spdk_iscsi_portal_grp *pg = NULL;
737 : : struct spdk_iscsi_portal *portal;
738 : 50 : size_t i = 0;
739 : 50 : int rc = -1;
740 : :
741 [ - + ]: 50 : if (spdk_json_decode_object(params, rpc_portal_group_decoders,
742 : : SPDK_COUNTOF(rpc_portal_group_decoders),
743 : : &req)) {
744 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
745 : 0 : goto out;
746 : : }
747 : :
748 [ - + ]: 50 : pg = iscsi_portal_grp_create(req.tag, req.is_private);
749 [ - + ]: 50 : if (pg == NULL) {
750 : 0 : SPDK_ERRLOG("portal_grp_create failed\n");
751 : 0 : goto out;
752 : : }
753 [ + + ]: 102 : for (i = 0; i < req.portal_list.num_portals; i++) {
754 : 52 : portal = iscsi_portal_create(req.portal_list.portals[i].host,
755 : 52 : req.portal_list.portals[i].port);
756 [ - + ]: 52 : if (portal == NULL) {
757 : 0 : SPDK_ERRLOG("portal_create failed\n");
758 : 0 : goto out;
759 : : }
760 : 52 : iscsi_portal_grp_add_portal(pg, portal);
761 : : }
762 : :
763 [ - + ]: 50 : rc = iscsi_portal_grp_open(pg, req.wait);
764 [ - + ]: 50 : if (rc != 0) {
765 : 0 : SPDK_ERRLOG("portal_grp_open failed\n");
766 : 0 : goto out;
767 : : }
768 : :
769 : 50 : rc = iscsi_portal_grp_register(pg);
770 [ + - ]: 50 : if (rc != 0) {
771 : 0 : SPDK_ERRLOG("portal_grp_register failed\n");
772 : : }
773 : :
774 : 50 : out:
775 [ + - ]: 50 : if (rc == 0) {
776 : 50 : spdk_jsonrpc_send_bool_response(request, true);
777 : : } else {
778 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
779 : :
780 [ # # ]: 0 : if (pg != NULL) {
781 : 0 : iscsi_portal_grp_release(pg);
782 : : }
783 : : }
784 : 50 : free_rpc_portal_group(&req);
785 : 50 : }
786 : 667 : SPDK_RPC_REGISTER("iscsi_create_portal_group", rpc_iscsi_create_portal_group, SPDK_RPC_RUNTIME)
787 : :
788 : : struct rpc_iscsi_change_portal_group {
789 : : int32_t tag;
790 : : };
791 : :
792 : : static const struct spdk_json_object_decoder rpc_iscsi_change_portal_group_decoders[] = {
793 : : {"tag", offsetof(struct rpc_iscsi_change_portal_group, tag), spdk_json_decode_int32},
794 : : };
795 : :
796 : : typedef int (*iscsi_change_portal_grp_fn)(int pg_tag);
797 : :
798 : : static void
799 : 16 : _rpc_iscsi_change_portal_group(struct spdk_jsonrpc_request *request,
800 : : const struct spdk_json_val *params,
801 : : iscsi_change_portal_grp_fn fn)
802 : : {
803 : 16 : struct rpc_iscsi_change_portal_group req = {};
804 : : int rc;
805 : :
806 [ - + ]: 16 : if (spdk_json_decode_object(params, rpc_iscsi_change_portal_group_decoders,
807 : : SPDK_COUNTOF(rpc_iscsi_change_portal_group_decoders),
808 : : &req)) {
809 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
810 : 0 : goto invalid;
811 : : }
812 : :
813 : 16 : rc = fn(req.tag);
814 [ - + ]: 16 : if (rc != 0) {
815 : 0 : goto invalid;
816 : : }
817 : :
818 : 16 : spdk_jsonrpc_send_bool_response(request, true);
819 : 16 : return;
820 : :
821 : 0 : invalid:
822 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, "Invalid parameters");
823 : : }
824 : :
825 : : static int
826 : 16 : _rpc_iscsi_delete_portal_group(int pg_tag)
827 : : {
828 : : struct spdk_iscsi_portal_grp *pg;
829 : :
830 : 16 : pg = iscsi_portal_grp_unregister(pg_tag);
831 [ - + ]: 16 : if (!pg) {
832 : 0 : return -ENODEV;
833 : : }
834 : :
835 : 16 : iscsi_tgt_node_delete_map(pg, NULL);
836 : 16 : iscsi_portal_grp_release(pg);
837 : 16 : return 0;
838 : : }
839 : :
840 : : static void
841 : 16 : rpc_iscsi_delete_portal_group(struct spdk_jsonrpc_request *request,
842 : : const struct spdk_json_val *params)
843 : : {
844 : 16 : _rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_delete_portal_group);
845 : 16 : }
846 : 667 : SPDK_RPC_REGISTER("iscsi_delete_portal_group", rpc_iscsi_delete_portal_group, SPDK_RPC_RUNTIME)
847 : :
848 : : static int
849 : 0 : _rpc_iscsi_start_portal_group(int pg_tag)
850 : : {
851 : : struct spdk_iscsi_portal_grp *pg;
852 : :
853 : 0 : pg = iscsi_portal_grp_find_by_tag(pg_tag);
854 [ # # ]: 0 : if (!pg) {
855 : 0 : return -ENODEV;
856 : : }
857 : :
858 : 0 : iscsi_portal_grp_resume(pg);
859 : 0 : return 0;
860 : : }
861 : :
862 : : static void
863 : 0 : rpc_iscsi_start_portal_group(struct spdk_jsonrpc_request *request,
864 : : const struct spdk_json_val *params)
865 : : {
866 : 0 : _rpc_iscsi_change_portal_group(request, params, _rpc_iscsi_start_portal_group);
867 : 0 : }
868 : 667 : SPDK_RPC_REGISTER("iscsi_start_portal_group", rpc_iscsi_start_portal_group, SPDK_RPC_RUNTIME)
869 : :
870 : : struct rpc_portal_group_auth {
871 : : int32_t tag;
872 : : bool disable_chap;
873 : : bool require_chap;
874 : : bool mutual_chap;
875 : : int32_t chap_group;
876 : : };
877 : :
878 : : static const struct spdk_json_object_decoder rpc_portal_group_auth_decoders[] = {
879 : : {"tag", offsetof(struct rpc_portal_group_auth, tag), spdk_json_decode_int32},
880 : : {"disable_chap", offsetof(struct rpc_portal_group_auth, disable_chap), spdk_json_decode_bool, true},
881 : : {"require_chap", offsetof(struct rpc_portal_group_auth, require_chap), spdk_json_decode_bool, true},
882 : : {"mutual_chap", offsetof(struct rpc_portal_group_auth, mutual_chap), spdk_json_decode_bool, true},
883 : : {"chap_group", offsetof(struct rpc_portal_group_auth, chap_group), spdk_json_decode_int32, true},
884 : : };
885 : :
886 : : static void
887 : 0 : rpc_iscsi_portal_group_set_auth(struct spdk_jsonrpc_request *request,
888 : : const struct spdk_json_val *params)
889 : : {
890 : 0 : struct rpc_portal_group_auth req = {};
891 : : struct spdk_iscsi_portal_grp *pg;
892 : : int rc;
893 : :
894 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_portal_group_auth_decoders,
895 : : SPDK_COUNTOF(rpc_portal_group_auth_decoders), &req)) {
896 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
897 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
898 : : "Invalid parameters");
899 : 0 : return;
900 : : }
901 : :
902 [ # # ]: 0 : pthread_mutex_lock(&g_iscsi.mutex);
903 : :
904 : 0 : pg = iscsi_portal_grp_find_by_tag(req.tag);
905 [ # # ]: 0 : if (pg == NULL) {
906 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
907 : : "Could not find portal group %d", req.tag);
908 : 0 : goto exit;
909 : : }
910 : :
911 [ # # ]: 0 : rc = iscsi_portal_grp_set_chap_params(pg, req.disable_chap, req.require_chap,
912 [ # # # # ]: 0 : req.mutual_chap, req.chap_group);
913 [ # # ]: 0 : if (rc < 0) {
914 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
915 : : "Invalid combination of auth params");
916 : 0 : goto exit;
917 : : }
918 : :
919 [ # # ]: 0 : pthread_mutex_unlock(&g_iscsi.mutex);
920 : :
921 : 0 : spdk_jsonrpc_send_bool_response(request, true);
922 : 0 : return;
923 : :
924 : 0 : exit:
925 [ # # ]: 0 : pthread_mutex_unlock(&g_iscsi.mutex);
926 : : }
927 : 667 : SPDK_RPC_REGISTER("iscsi_portal_group_set_auth", rpc_iscsi_portal_group_set_auth,
928 : : SPDK_RPC_RUNTIME)
929 : :
930 : : struct rpc_iscsi_get_connections_ctx {
931 : : struct spdk_jsonrpc_request *request;
932 : : struct spdk_json_write_ctx *w;
933 : : };
934 : :
935 : : static void
936 : 136 : _rpc_iscsi_get_connections_done(struct spdk_io_channel_iter *i, int status)
937 : : {
938 : 136 : struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
939 : :
940 : 136 : spdk_json_write_array_end(ctx->w);
941 : 136 : spdk_jsonrpc_end_result(ctx->request, ctx->w);
942 : :
943 : 136 : free(ctx);
944 : 136 : }
945 : :
946 : : static void
947 : 248 : _rpc_iscsi_get_connections(struct spdk_io_channel_iter *i)
948 : : {
949 : 248 : struct rpc_iscsi_get_connections_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
950 : 248 : struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
951 : 248 : struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch);
952 : : struct spdk_iscsi_conn *conn;
953 : :
954 [ + + ]: 256 : STAILQ_FOREACH(conn, &pg->connections, pg_link) {
955 : 8 : iscsi_conn_info_json(ctx->w, conn);
956 : : }
957 : :
958 : 248 : spdk_for_each_channel_continue(i, 0);
959 : 248 : }
960 : :
961 : : static void
962 : 136 : rpc_iscsi_get_connections(struct spdk_jsonrpc_request *request,
963 : : const struct spdk_json_val *params)
964 : : {
965 : : struct rpc_iscsi_get_connections_ctx *ctx;
966 : :
967 [ - + ]: 136 : if (params != NULL) {
968 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
969 : : "iscsi_get_connections requires no parameters");
970 : 0 : return;
971 : : }
972 : :
973 : 136 : ctx = calloc(1, sizeof(struct rpc_iscsi_get_connections_ctx));
974 [ - + ]: 136 : if (ctx == NULL) {
975 : 0 : SPDK_ERRLOG("Failed to allocate rpc_get_iscsi_conns_ctx struct\n");
976 : 0 : spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
977 : 0 : return;
978 : : }
979 : :
980 : 136 : ctx->request = request;
981 : 136 : ctx->w = spdk_jsonrpc_begin_result(request);
982 : :
983 : 136 : spdk_json_write_array_begin(ctx->w);
984 : :
985 : 136 : spdk_for_each_channel(&g_iscsi,
986 : : _rpc_iscsi_get_connections,
987 : : ctx,
988 : : _rpc_iscsi_get_connections_done);
989 : : }
990 : 667 : SPDK_RPC_REGISTER("iscsi_get_connections", rpc_iscsi_get_connections, SPDK_RPC_RUNTIME)
991 : :
992 : : struct rpc_target_lun {
993 : : char *name;
994 : : char *bdev_name;
995 : : int32_t lun_id;
996 : : };
997 : :
998 : : struct rpc_iscsi_get_stats_ctx {
999 : : struct spdk_jsonrpc_request *request;
1000 : : uint32_t invalid;
1001 : : uint32_t running;
1002 : : uint32_t exiting;
1003 : : uint32_t exited;
1004 : : };
1005 : :
1006 : : static void
1007 : 0 : _rpc_iscsi_get_stats_done(struct spdk_io_channel_iter *i, int status)
1008 : : {
1009 : : struct spdk_json_write_ctx *w;
1010 : 0 : struct rpc_iscsi_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
1011 : :
1012 : 0 : w = spdk_jsonrpc_begin_result(ctx->request);
1013 : 0 : spdk_json_write_object_begin(w);
1014 : :
1015 : 0 : spdk_json_write_named_uint32(w, "invalid", ctx->invalid);
1016 : 0 : spdk_json_write_named_uint32(w, "running", ctx->running);
1017 : 0 : spdk_json_write_named_uint32(w, "exiting", ctx->exiting);
1018 : 0 : spdk_json_write_named_uint32(w, "exited", ctx->exited);
1019 : :
1020 : 0 : spdk_json_write_object_end(w);
1021 : 0 : spdk_jsonrpc_end_result(ctx->request, w);
1022 : :
1023 : 0 : free(ctx);
1024 : 0 : }
1025 : :
1026 : : static void
1027 : 0 : _iscsi_get_stats(struct rpc_iscsi_get_stats_ctx *ctx,
1028 : : struct spdk_iscsi_conn *conn)
1029 : : {
1030 [ # # # # : 0 : switch (conn->state) {
# ]
1031 : 0 : case ISCSI_CONN_STATE_INVALID:
1032 : 0 : ctx->invalid += 1;
1033 : 0 : break;
1034 : 0 : case ISCSI_CONN_STATE_RUNNING:
1035 : 0 : ctx->running += 1;
1036 : 0 : break;
1037 : 0 : case ISCSI_CONN_STATE_EXITING:
1038 : 0 : ctx->exiting += 1;
1039 : 0 : break;
1040 : 0 : case ISCSI_CONN_STATE_EXITED:
1041 : 0 : ctx->exited += 1;
1042 : 0 : break;
1043 : : }
1044 : 0 : }
1045 : :
1046 : : static void
1047 : 0 : _rpc_iscsi_get_stats(struct spdk_io_channel_iter *i)
1048 : : {
1049 : 0 : struct rpc_iscsi_get_stats_ctx *ctx = spdk_io_channel_iter_get_ctx(i);
1050 : 0 : struct spdk_io_channel *ch = spdk_io_channel_iter_get_channel(i);
1051 : 0 : struct spdk_iscsi_poll_group *pg = spdk_io_channel_get_ctx(ch);
1052 : : struct spdk_iscsi_conn *conn;
1053 : :
1054 [ # # ]: 0 : STAILQ_FOREACH(conn, &pg->connections, pg_link) {
1055 : 0 : _iscsi_get_stats(ctx, conn);
1056 : : }
1057 : :
1058 : 0 : spdk_for_each_channel_continue(i, 0);
1059 : 0 : }
1060 : :
1061 : :
1062 : :
1063 : : static void
1064 : 0 : rpc_iscsi_get_stats(struct spdk_jsonrpc_request *request,
1065 : : const struct spdk_json_val *params)
1066 : : {
1067 : : struct rpc_iscsi_get_stats_ctx *ctx;
1068 : :
1069 [ # # ]: 0 : if (params != NULL) {
1070 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1071 : : "iscsi_get_stats requires no parameters");
1072 : 0 : return;
1073 : : }
1074 : :
1075 : 0 : ctx = calloc(1, sizeof(struct rpc_iscsi_get_stats_ctx));
1076 [ # # ]: 0 : if (ctx == NULL) {
1077 : 0 : SPDK_ERRLOG("Failed to allocate rpc_iscsi_get_stats_ctx struct\n");
1078 : 0 : spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM));
1079 : 0 : return;
1080 : : }
1081 : :
1082 : 0 : ctx->request = request;
1083 : :
1084 : 0 : spdk_for_each_channel(&g_iscsi,
1085 : : _rpc_iscsi_get_stats,
1086 : : ctx,
1087 : : _rpc_iscsi_get_stats_done);
1088 : :
1089 : : }
1090 : 667 : SPDK_RPC_REGISTER("iscsi_get_stats", rpc_iscsi_get_stats, SPDK_RPC_RUNTIME)
1091 : :
1092 : : static void
1093 : 4 : free_rpc_target_lun(struct rpc_target_lun *req)
1094 : : {
1095 : 4 : free(req->name);
1096 : 4 : free(req->bdev_name);
1097 : 4 : }
1098 : :
1099 : : static const struct spdk_json_object_decoder rpc_target_lun_decoders[] = {
1100 : : {"name", offsetof(struct rpc_target_lun, name), spdk_json_decode_string},
1101 : : {"bdev_name", offsetof(struct rpc_target_lun, bdev_name), spdk_json_decode_string},
1102 : : {"lun_id", offsetof(struct rpc_target_lun, lun_id), spdk_json_decode_int32, true},
1103 : : };
1104 : :
1105 : : static void
1106 : 4 : rpc_iscsi_target_node_add_lun(struct spdk_jsonrpc_request *request,
1107 : : const struct spdk_json_val *params)
1108 : : {
1109 : 4 : struct rpc_target_lun req = {};
1110 : : struct spdk_iscsi_tgt_node *target;
1111 : : int rc;
1112 : :
1113 : 4 : req.lun_id = -1;
1114 : :
1115 [ - + ]: 4 : if (spdk_json_decode_object(params, rpc_target_lun_decoders,
1116 : : SPDK_COUNTOF(rpc_target_lun_decoders), &req)) {
1117 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1118 : 0 : goto invalid;
1119 : : }
1120 : :
1121 : 4 : target = iscsi_find_tgt_node(req.name);
1122 [ - + ]: 4 : if (target == NULL) {
1123 : 0 : SPDK_ERRLOG("target is not found\n");
1124 : 0 : goto invalid;
1125 : : }
1126 : :
1127 : 4 : rc = iscsi_tgt_node_add_lun(target, req.bdev_name, req.lun_id);
1128 [ - + ]: 4 : if (rc < 0) {
1129 : 0 : SPDK_ERRLOG("add lun failed\n");
1130 : 0 : goto invalid;
1131 : : }
1132 : :
1133 : 4 : free_rpc_target_lun(&req);
1134 : :
1135 : 4 : spdk_jsonrpc_send_bool_response(request, true);
1136 : 4 : return;
1137 : :
1138 : 0 : invalid:
1139 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1140 : : "Invalid parameters");
1141 : 0 : free_rpc_target_lun(&req);
1142 : : }
1143 : 667 : SPDK_RPC_REGISTER("iscsi_target_node_add_lun", rpc_iscsi_target_node_add_lun, SPDK_RPC_RUNTIME)
1144 : :
1145 : : struct rpc_target_auth {
1146 : : char *name;
1147 : : bool disable_chap;
1148 : : bool require_chap;
1149 : : bool mutual_chap;
1150 : : int32_t chap_group;
1151 : : };
1152 : :
1153 : : static void
1154 : 2 : free_rpc_target_auth(struct rpc_target_auth *req)
1155 : : {
1156 : 2 : free(req->name);
1157 : 2 : }
1158 : :
1159 : : static const struct spdk_json_object_decoder rpc_target_auth_decoders[] = {
1160 : : {"name", offsetof(struct rpc_target_auth, name), spdk_json_decode_string},
1161 : : {"disable_chap", offsetof(struct rpc_target_auth, disable_chap), spdk_json_decode_bool, true},
1162 : : {"require_chap", offsetof(struct rpc_target_auth, require_chap), spdk_json_decode_bool, true},
1163 : : {"mutual_chap", offsetof(struct rpc_target_auth, mutual_chap), spdk_json_decode_bool, true},
1164 : : {"chap_group", offsetof(struct rpc_target_auth, chap_group), spdk_json_decode_int32, true},
1165 : : };
1166 : :
1167 : : static void
1168 : 2 : rpc_iscsi_target_node_set_auth(struct spdk_jsonrpc_request *request,
1169 : : const struct spdk_json_val *params)
1170 : : {
1171 : 2 : struct rpc_target_auth req = {};
1172 : : struct spdk_iscsi_tgt_node *target;
1173 : : int rc;
1174 : :
1175 [ - + ]: 2 : if (spdk_json_decode_object(params, rpc_target_auth_decoders,
1176 : : SPDK_COUNTOF(rpc_target_auth_decoders), &req)) {
1177 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1178 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1179 : : "Invalid parameters");
1180 : 0 : goto exit;
1181 : : }
1182 : :
1183 : 2 : target = iscsi_find_tgt_node(req.name);
1184 [ - + ]: 2 : if (target == NULL) {
1185 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1186 : : "Could not find target %s", req.name);
1187 : 0 : goto exit;
1188 : : }
1189 : :
1190 [ - + ]: 2 : rc = iscsi_tgt_node_set_chap_params(target, req.disable_chap, req.require_chap,
1191 [ - + - + ]: 2 : req.mutual_chap, req.chap_group);
1192 [ - + ]: 2 : if (rc < 0) {
1193 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1194 : : "Invalid combination of auth params");
1195 : 0 : goto exit;
1196 : : }
1197 : :
1198 : 2 : free_rpc_target_auth(&req);
1199 : :
1200 : 2 : spdk_jsonrpc_send_bool_response(request, true);
1201 : 2 : return;
1202 : :
1203 : 0 : exit:
1204 : 0 : free_rpc_target_auth(&req);
1205 : : }
1206 : 667 : SPDK_RPC_REGISTER("iscsi_target_node_set_auth", rpc_iscsi_target_node_set_auth,
1207 : : SPDK_RPC_RUNTIME)
1208 : :
1209 : : struct rpc_target_redirect {
1210 : : char *name;
1211 : : int32_t pg_tag;
1212 : : char *redirect_host;
1213 : : char *redirect_port;
1214 : : };
1215 : :
1216 : : static void
1217 : 4 : free_rpc_target_redirect(struct rpc_target_redirect *req)
1218 : : {
1219 : 4 : free(req->name);
1220 : 4 : free(req->redirect_host);
1221 : 4 : free(req->redirect_port);
1222 : 4 : }
1223 : :
1224 : : static const struct spdk_json_object_decoder rpc_target_redirect_decoders[] = {
1225 : : {"name", offsetof(struct rpc_target_redirect, name), spdk_json_decode_string},
1226 : : {"pg_tag", offsetof(struct rpc_target_redirect, pg_tag), spdk_json_decode_int32},
1227 : : {"redirect_host", offsetof(struct rpc_target_redirect, redirect_host), spdk_json_decode_string, true},
1228 : : {"redirect_port", offsetof(struct rpc_target_redirect, redirect_port), spdk_json_decode_string, true},
1229 : : };
1230 : :
1231 : : static void
1232 : 4 : rpc_iscsi_target_node_set_redirect(struct spdk_jsonrpc_request *request,
1233 : : const struct spdk_json_val *params)
1234 : : {
1235 : 4 : struct rpc_target_redirect req = {};
1236 : : struct spdk_iscsi_tgt_node *target;
1237 : : int rc;
1238 : :
1239 [ - + ]: 4 : if (spdk_json_decode_object(params, rpc_target_redirect_decoders,
1240 : : SPDK_COUNTOF(rpc_target_redirect_decoders),
1241 : : &req)) {
1242 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1243 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1244 : : "Invalid parameters");
1245 : 0 : free_rpc_target_redirect(&req);
1246 : 0 : return;
1247 : : }
1248 : :
1249 : 4 : target = iscsi_find_tgt_node(req.name);
1250 [ - + ]: 4 : if (target == NULL) {
1251 : 0 : SPDK_ERRLOG("target %s is not found\n", req.name);
1252 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1253 : : "Target %s is not found", req.name);
1254 : 0 : free_rpc_target_redirect(&req);
1255 : 0 : return;
1256 : : }
1257 : :
1258 : 4 : rc = iscsi_tgt_node_redirect(target, req.pg_tag, req.redirect_host, req.redirect_port);
1259 [ - + ]: 4 : if (rc != 0) {
1260 : 0 : SPDK_ERRLOG("failed to redirect target %s\n", req.name);
1261 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1262 : : "Failed to redirect target %s, (%d): %s",
1263 : : req.name, rc, spdk_strerror(-rc));
1264 : 0 : free_rpc_target_redirect(&req);
1265 : 0 : return;
1266 : : }
1267 : :
1268 : 4 : free_rpc_target_redirect(&req);
1269 : :
1270 : 4 : spdk_jsonrpc_send_bool_response(request, true);
1271 : : }
1272 : 667 : SPDK_RPC_REGISTER("iscsi_target_node_set_redirect", rpc_iscsi_target_node_set_redirect,
1273 : : SPDK_RPC_RUNTIME)
1274 : :
1275 : : struct rpc_target_logout {
1276 : : char *name;
1277 : : int32_t pg_tag;
1278 : : };
1279 : :
1280 : : static void
1281 : 4 : free_rpc_target_logout(struct rpc_target_logout *req)
1282 : : {
1283 : 4 : free(req->name);
1284 : 4 : }
1285 : :
1286 : : static const struct spdk_json_object_decoder rpc_target_logout_decoders[] = {
1287 : : {"name", offsetof(struct rpc_target_logout, name), spdk_json_decode_string},
1288 : : {"pg_tag", offsetof(struct rpc_target_logout, pg_tag), spdk_json_decode_int32, true},
1289 : : };
1290 : :
1291 : : static void
1292 : 4 : rpc_iscsi_target_node_request_logout(struct spdk_jsonrpc_request *request,
1293 : : const struct spdk_json_val *params)
1294 : : {
1295 : 4 : struct rpc_target_logout req = {};
1296 : : struct spdk_iscsi_tgt_node *target;
1297 : :
1298 : : /* If pg_tag is omitted, request all connections to the specified target
1299 : : * to logout.
1300 : : */
1301 : 4 : req.pg_tag = -1;
1302 : :
1303 [ - + ]: 4 : if (spdk_json_decode_object(params, rpc_target_logout_decoders,
1304 : : SPDK_COUNTOF(rpc_target_logout_decoders),
1305 : : &req)) {
1306 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1307 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1308 : : "Invalid parameters");
1309 : 0 : free_rpc_target_logout(&req);
1310 : 0 : return;
1311 : : }
1312 : :
1313 : 4 : target = iscsi_find_tgt_node(req.name);
1314 [ - + ]: 4 : if (target == NULL) {
1315 : 0 : SPDK_ERRLOG("target %s is not found\n", req.name);
1316 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1317 : : "Target %s is not found", req.name);
1318 : 0 : free_rpc_target_logout(&req);
1319 : 0 : return;
1320 : : }
1321 : :
1322 : 4 : iscsi_conns_request_logout(target, req.pg_tag);
1323 : :
1324 : 4 : free_rpc_target_logout(&req);
1325 : :
1326 : 4 : spdk_jsonrpc_send_bool_response(request, true);
1327 : : }
1328 : 667 : SPDK_RPC_REGISTER("iscsi_target_node_request_logout", rpc_iscsi_target_node_request_logout,
1329 : : SPDK_RPC_RUNTIME)
1330 : :
1331 : : static void
1332 : 124 : rpc_iscsi_get_options(struct spdk_jsonrpc_request *request,
1333 : : const struct spdk_json_val *params)
1334 : : {
1335 : : struct spdk_json_write_ctx *w;
1336 : :
1337 [ - + ]: 124 : if (params != NULL) {
1338 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1339 : : "iscsi_get_options requires no parameters");
1340 : 0 : return;
1341 : : }
1342 : :
1343 : 124 : w = spdk_jsonrpc_begin_result(request);
1344 : 124 : iscsi_opts_info_json(w);
1345 : :
1346 : 124 : spdk_jsonrpc_end_result(request, w);
1347 : : }
1348 : 667 : SPDK_RPC_REGISTER("iscsi_get_options", rpc_iscsi_get_options, SPDK_RPC_RUNTIME)
1349 : :
1350 : : struct rpc_discovery_auth {
1351 : : bool disable_chap;
1352 : : bool require_chap;
1353 : : bool mutual_chap;
1354 : : int32_t chap_group;
1355 : : };
1356 : :
1357 : : static const struct spdk_json_object_decoder rpc_discovery_auth_decoders[] = {
1358 : : {"disable_chap", offsetof(struct rpc_discovery_auth, disable_chap), spdk_json_decode_bool, true},
1359 : : {"require_chap", offsetof(struct rpc_discovery_auth, require_chap), spdk_json_decode_bool, true},
1360 : : {"mutual_chap", offsetof(struct rpc_discovery_auth, mutual_chap), spdk_json_decode_bool, true},
1361 : : {"chap_group", offsetof(struct rpc_discovery_auth, chap_group), spdk_json_decode_int32, true},
1362 : : };
1363 : :
1364 : : static void
1365 : 4 : rpc_iscsi_set_discovery_auth(struct spdk_jsonrpc_request *request,
1366 : : const struct spdk_json_val *params)
1367 : : {
1368 : 4 : struct rpc_discovery_auth req = {};
1369 : : int rc;
1370 : :
1371 [ - + ]: 4 : if (spdk_json_decode_object(params, rpc_discovery_auth_decoders,
1372 : : SPDK_COUNTOF(rpc_discovery_auth_decoders), &req)) {
1373 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1374 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1375 : : "Invalid parameters");
1376 : 0 : return;
1377 : : }
1378 : :
1379 [ - + ]: 4 : rc = iscsi_set_discovery_auth(req.disable_chap, req.require_chap,
1380 [ - + - + ]: 4 : req.mutual_chap, req.chap_group);
1381 [ - + ]: 4 : if (rc < 0) {
1382 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1383 : : "Invalid combination of CHAP params");
1384 : 0 : return;
1385 : : }
1386 : :
1387 : 4 : spdk_jsonrpc_send_bool_response(request, true);
1388 : : }
1389 : 667 : SPDK_RPC_REGISTER("iscsi_set_discovery_auth", rpc_iscsi_set_discovery_auth, SPDK_RPC_RUNTIME)
1390 : :
1391 : : #define MAX_AUTH_SECRETS 64
1392 : :
1393 : : struct rpc_auth_secret {
1394 : : char *user;
1395 : : char *secret;
1396 : : char *muser;
1397 : : char *msecret;
1398 : : };
1399 : :
1400 : : static void
1401 : 8 : free_rpc_auth_secret(struct rpc_auth_secret *_secret)
1402 : : {
1403 : 8 : free(_secret->user);
1404 : 8 : free(_secret->secret);
1405 : 8 : free(_secret->muser);
1406 : 8 : free(_secret->msecret);
1407 : 8 : }
1408 : :
1409 : : static const struct spdk_json_object_decoder rpc_auth_secret_decoders[] = {
1410 : : {"user", offsetof(struct rpc_auth_secret, user), spdk_json_decode_string},
1411 : : {"secret", offsetof(struct rpc_auth_secret, secret), spdk_json_decode_string},
1412 : : {"muser", offsetof(struct rpc_auth_secret, muser), spdk_json_decode_string, true},
1413 : : {"msecret", offsetof(struct rpc_auth_secret, msecret), spdk_json_decode_string, true},
1414 : : };
1415 : :
1416 : : static int
1417 : 8 : decode_rpc_auth_secret(const struct spdk_json_val *val, void *out)
1418 : : {
1419 : 8 : struct rpc_auth_secret *_secret = out;
1420 : :
1421 : 8 : return spdk_json_decode_object(val, rpc_auth_secret_decoders,
1422 : : SPDK_COUNTOF(rpc_auth_secret_decoders), _secret);
1423 : : }
1424 : :
1425 : : struct rpc_auth_secrets {
1426 : : size_t num_secret;
1427 : : struct rpc_auth_secret secrets[MAX_AUTH_SECRETS];
1428 : : };
1429 : :
1430 : : static void
1431 : 6 : free_rpc_auth_secrets(struct rpc_auth_secrets *secrets)
1432 : : {
1433 : : size_t i;
1434 : :
1435 [ + + ]: 14 : for (i = 0; i < secrets->num_secret; i++) {
1436 : 8 : free_rpc_auth_secret(&secrets->secrets[i]);
1437 : : }
1438 : 6 : }
1439 : :
1440 : : static int
1441 : 6 : decode_rpc_auth_secrets(const struct spdk_json_val *val, void *out)
1442 : : {
1443 : 6 : struct rpc_auth_secrets *secrets = out;
1444 : :
1445 : 6 : return spdk_json_decode_array(val, decode_rpc_auth_secret, secrets->secrets,
1446 : : MAX_AUTH_SECRETS, &secrets->num_secret,
1447 : : sizeof(struct rpc_auth_secret));
1448 : : }
1449 : :
1450 : : struct rpc_auth_group {
1451 : : int32_t tag;
1452 : : struct rpc_auth_secrets secrets;
1453 : : };
1454 : :
1455 : : static void
1456 : 6 : free_rpc_auth_group(struct rpc_auth_group *group)
1457 : : {
1458 : 6 : free_rpc_auth_secrets(&group->secrets);
1459 : 6 : }
1460 : :
1461 : : static const struct spdk_json_object_decoder rpc_auth_group_decoders[] = {
1462 : : {"tag", offsetof(struct rpc_auth_group, tag), spdk_json_decode_int32},
1463 : : {"secrets", offsetof(struct rpc_auth_group, secrets), decode_rpc_auth_secrets, true},
1464 : : };
1465 : :
1466 : : static void
1467 : 6 : rpc_iscsi_create_auth_group(struct spdk_jsonrpc_request *request,
1468 : : const struct spdk_json_val *params)
1469 : : {
1470 : 6 : struct rpc_auth_group req = {};
1471 : : struct rpc_auth_secret *_secret;
1472 : 6 : struct spdk_iscsi_auth_group *group = NULL;
1473 : : int rc;
1474 : : size_t i;
1475 : :
1476 [ - + ]: 6 : if (spdk_json_decode_object(params, rpc_auth_group_decoders,
1477 : : SPDK_COUNTOF(rpc_auth_group_decoders), &req)) {
1478 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1479 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1480 : : "Invalid parameters");
1481 : 0 : free_rpc_auth_group(&req);
1482 : 0 : return;
1483 : : }
1484 : :
1485 [ - + ]: 6 : pthread_mutex_lock(&g_iscsi.mutex);
1486 : :
1487 : 6 : rc = iscsi_add_auth_group(req.tag, &group);
1488 [ - + ]: 6 : if (rc != 0) {
1489 [ # # ]: 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1490 : :
1491 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1492 : : "Could not add auth group (%d), %s",
1493 : : req.tag, spdk_strerror(-rc));
1494 : 0 : free_rpc_auth_group(&req);
1495 : 0 : return;
1496 : : }
1497 : :
1498 [ + + ]: 14 : for (i = 0; i < req.secrets.num_secret; i++) {
1499 : 8 : _secret = &req.secrets.secrets[i];
1500 : 8 : rc = iscsi_auth_group_add_secret(group, _secret->user, _secret->secret,
1501 : 8 : _secret->muser, _secret->msecret);
1502 [ - + ]: 8 : if (rc != 0) {
1503 : 0 : iscsi_delete_auth_group(group);
1504 [ # # ]: 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1505 : :
1506 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1507 : : "Could not add secret to auth group (%d), %s",
1508 : : req.tag, spdk_strerror(-rc));
1509 : 0 : free_rpc_auth_group(&req);
1510 : 0 : return;
1511 : : }
1512 : : }
1513 : :
1514 [ - + ]: 6 : pthread_mutex_unlock(&g_iscsi.mutex);
1515 : :
1516 : 6 : free_rpc_auth_group(&req);
1517 : :
1518 : 6 : spdk_jsonrpc_send_bool_response(request, true);
1519 : : }
1520 : 667 : SPDK_RPC_REGISTER("iscsi_create_auth_group", rpc_iscsi_create_auth_group, SPDK_RPC_RUNTIME)
1521 : :
1522 : : struct rpc_delete_auth_group {
1523 : : int32_t tag;
1524 : : };
1525 : :
1526 : : static const struct spdk_json_object_decoder rpc_delete_auth_group_decoders[] = {
1527 : : {"tag", offsetof(struct rpc_delete_auth_group, tag), spdk_json_decode_int32},
1528 : : };
1529 : :
1530 : : static void
1531 : 4 : rpc_iscsi_delete_auth_group(struct spdk_jsonrpc_request *request,
1532 : : const struct spdk_json_val *params)
1533 : : {
1534 : 4 : struct rpc_delete_auth_group req = {};
1535 : : struct spdk_iscsi_auth_group *group;
1536 : :
1537 [ - + ]: 4 : if (spdk_json_decode_object(params, rpc_delete_auth_group_decoders,
1538 : : SPDK_COUNTOF(rpc_delete_auth_group_decoders), &req)) {
1539 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1540 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1541 : : "Invalid parameters");
1542 : 0 : return;
1543 : : }
1544 : :
1545 [ - + ]: 4 : pthread_mutex_lock(&g_iscsi.mutex);
1546 : :
1547 : 4 : group = iscsi_find_auth_group_by_tag(req.tag);
1548 [ - + ]: 4 : if (group == NULL) {
1549 [ # # ]: 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1550 : :
1551 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1552 : : "Could not find auth group (%d)", req.tag);
1553 : 0 : return;
1554 : : }
1555 : :
1556 : 4 : iscsi_delete_auth_group(group);
1557 : :
1558 [ - + ]: 4 : pthread_mutex_unlock(&g_iscsi.mutex);
1559 : :
1560 : 4 : spdk_jsonrpc_send_bool_response(request, true);
1561 : : }
1562 : 667 : SPDK_RPC_REGISTER("iscsi_delete_auth_group", rpc_iscsi_delete_auth_group, SPDK_RPC_RUNTIME)
1563 : :
1564 : : struct rpc_add_auth_secret {
1565 : : int32_t tag;
1566 : : char *user;
1567 : : char *secret;
1568 : : char *muser;
1569 : : char *msecret;
1570 : : };
1571 : :
1572 : : static void
1573 : 2 : free_rpc_add_auth_secret(struct rpc_add_auth_secret *_secret)
1574 : : {
1575 : 2 : free(_secret->user);
1576 : 2 : free(_secret->secret);
1577 : 2 : free(_secret->muser);
1578 : 2 : free(_secret->msecret);
1579 : 2 : }
1580 : :
1581 : : static const struct spdk_json_object_decoder rpc_add_auth_secret_decoders[] = {
1582 : : {"tag", offsetof(struct rpc_add_auth_secret, tag), spdk_json_decode_int32},
1583 : : {"user", offsetof(struct rpc_add_auth_secret, user), spdk_json_decode_string},
1584 : : {"secret", offsetof(struct rpc_add_auth_secret, secret), spdk_json_decode_string},
1585 : : {"muser", offsetof(struct rpc_add_auth_secret, muser), spdk_json_decode_string, true},
1586 : : {"msecret", offsetof(struct rpc_add_auth_secret, msecret), spdk_json_decode_string, true},
1587 : : };
1588 : :
1589 : : static void
1590 : 2 : rpc_iscsi_auth_group_add_secret(struct spdk_jsonrpc_request *request,
1591 : : const struct spdk_json_val *params)
1592 : : {
1593 : 2 : struct rpc_add_auth_secret req = {};
1594 : : struct spdk_iscsi_auth_group *group;
1595 : : int rc;
1596 : :
1597 [ - + ]: 2 : if (spdk_json_decode_object(params, rpc_add_auth_secret_decoders,
1598 : : SPDK_COUNTOF(rpc_add_auth_secret_decoders), &req)) {
1599 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1600 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1601 : : "Invalid parameters");
1602 : 0 : free_rpc_add_auth_secret(&req);
1603 : 0 : return;
1604 : : }
1605 : :
1606 [ - + ]: 2 : pthread_mutex_lock(&g_iscsi.mutex);
1607 : :
1608 : 2 : group = iscsi_find_auth_group_by_tag(req.tag);
1609 [ - + ]: 2 : if (group == NULL) {
1610 [ # # ]: 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1611 : :
1612 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1613 : : "Could not find auth group (%d)", req.tag);
1614 : 0 : free_rpc_add_auth_secret(&req);
1615 : 0 : return;
1616 : : }
1617 : :
1618 : 2 : rc = iscsi_auth_group_add_secret(group, req.user, req.secret, req.muser, req.msecret);
1619 [ - + ]: 2 : if (rc != 0) {
1620 [ # # ]: 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1621 : :
1622 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1623 : : "Could not add secret to auth group (%d), %s",
1624 : : req.tag, spdk_strerror(-rc));
1625 : 0 : free_rpc_add_auth_secret(&req);
1626 : 0 : return;
1627 : : }
1628 : :
1629 [ - + ]: 2 : pthread_mutex_unlock(&g_iscsi.mutex);
1630 : :
1631 : 2 : free_rpc_add_auth_secret(&req);
1632 : :
1633 : 2 : spdk_jsonrpc_send_bool_response(request, true);
1634 : : }
1635 : 667 : SPDK_RPC_REGISTER("iscsi_auth_group_add_secret", rpc_iscsi_auth_group_add_secret,
1636 : : SPDK_RPC_RUNTIME)
1637 : :
1638 : :
1639 : : struct rpc_remove_auth_secret {
1640 : : int32_t tag;
1641 : : char *user;
1642 : : };
1643 : :
1644 : : static void
1645 : 6 : free_rpc_remove_auth_secret(struct rpc_remove_auth_secret *_secret)
1646 : : {
1647 : 6 : free(_secret->user);
1648 : 6 : }
1649 : :
1650 : : static const struct spdk_json_object_decoder rpc_remove_auth_secret_decoders[] = {
1651 : : {"tag", offsetof(struct rpc_remove_auth_secret, tag), spdk_json_decode_int32},
1652 : : {"user", offsetof(struct rpc_remove_auth_secret, user), spdk_json_decode_string},
1653 : : };
1654 : :
1655 : : static void
1656 : 6 : rpc_iscsi_auth_group_remove_secret(struct spdk_jsonrpc_request *request,
1657 : : const struct spdk_json_val *params)
1658 : : {
1659 : 6 : struct rpc_remove_auth_secret req = {};
1660 : : struct spdk_iscsi_auth_group *group;
1661 : : int rc;
1662 : :
1663 [ - + ]: 6 : if (spdk_json_decode_object(params, rpc_remove_auth_secret_decoders,
1664 : : SPDK_COUNTOF(rpc_remove_auth_secret_decoders), &req)) {
1665 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1666 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1667 : : "Invalid parameters");
1668 : 0 : free_rpc_remove_auth_secret(&req);
1669 : 0 : return;
1670 : : }
1671 : :
1672 [ - + ]: 6 : pthread_mutex_lock(&g_iscsi.mutex);
1673 : :
1674 : 6 : group = iscsi_find_auth_group_by_tag(req.tag);
1675 [ - + ]: 6 : if (group == NULL) {
1676 [ # # ]: 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1677 : :
1678 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1679 : : "Could not find auth group (%d)", req.tag);
1680 : 0 : free_rpc_remove_auth_secret(&req);
1681 : 0 : return;
1682 : : }
1683 : :
1684 : 6 : rc = iscsi_auth_group_delete_secret(group, req.user);
1685 [ - + ]: 6 : if (rc != 0) {
1686 [ # # ]: 0 : pthread_mutex_unlock(&g_iscsi.mutex);
1687 : :
1688 : 0 : spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1689 : : "Could not delete secret from CHAP group (%d), %s",
1690 : : req.tag, spdk_strerror(-rc));
1691 : 0 : free_rpc_remove_auth_secret(&req);
1692 : 0 : return;
1693 : : }
1694 : :
1695 [ - + ]: 6 : pthread_mutex_unlock(&g_iscsi.mutex);
1696 : :
1697 : 6 : free_rpc_remove_auth_secret(&req);
1698 : :
1699 : 6 : spdk_jsonrpc_send_bool_response(request, true);
1700 : : }
1701 : 667 : SPDK_RPC_REGISTER("iscsi_auth_group_remove_secret",
1702 : : rpc_iscsi_auth_group_remove_secret, SPDK_RPC_RUNTIME)
1703 : :
1704 : : static void
1705 : 132 : rpc_iscsi_get_auth_groups(struct spdk_jsonrpc_request *request,
1706 : : const struct spdk_json_val *params)
1707 : : {
1708 : : struct spdk_json_write_ctx *w;
1709 : :
1710 [ - + ]: 132 : if (params != NULL) {
1711 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1712 : : "iscsi_get_auth_groups requires no parameters");
1713 : 0 : return;
1714 : : }
1715 : :
1716 : 132 : w = spdk_jsonrpc_begin_result(request);
1717 : 132 : spdk_json_write_array_begin(w);
1718 : 132 : iscsi_auth_groups_info_json(w);
1719 : 132 : spdk_json_write_array_end(w);
1720 : :
1721 : 132 : spdk_jsonrpc_end_result(request, w);
1722 : : }
1723 : 667 : SPDK_RPC_REGISTER("iscsi_get_auth_groups", rpc_iscsi_get_auth_groups, SPDK_RPC_RUNTIME)
1724 : :
1725 : : static const struct spdk_json_object_decoder rpc_set_iscsi_opts_decoders[] = {
1726 : : {"auth_file", offsetof(struct spdk_iscsi_opts, authfile), spdk_json_decode_string, true},
1727 : : {"node_base", offsetof(struct spdk_iscsi_opts, nodebase), spdk_json_decode_string, true},
1728 : : {"nop_timeout", offsetof(struct spdk_iscsi_opts, timeout), spdk_json_decode_int32, true},
1729 : : {"nop_in_interval", offsetof(struct spdk_iscsi_opts, nopininterval), spdk_json_decode_int32, true},
1730 : : {"no_discovery_auth", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true},
1731 : : {"req_discovery_auth", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true},
1732 : : {"req_discovery_auth_mutual", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true},
1733 : : {"discovery_auth_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true},
1734 : : {"disable_chap", offsetof(struct spdk_iscsi_opts, disable_chap), spdk_json_decode_bool, true},
1735 : : {"require_chap", offsetof(struct spdk_iscsi_opts, require_chap), spdk_json_decode_bool, true},
1736 : : {"mutual_chap", offsetof(struct spdk_iscsi_opts, mutual_chap), spdk_json_decode_bool, true},
1737 : : {"chap_group", offsetof(struct spdk_iscsi_opts, chap_group), spdk_json_decode_int32, true},
1738 : : {"max_sessions", offsetof(struct spdk_iscsi_opts, MaxSessions), spdk_json_decode_uint32, true},
1739 : : {"max_queue_depth", offsetof(struct spdk_iscsi_opts, MaxQueueDepth), spdk_json_decode_uint32, true},
1740 : : {"max_connections_per_session", offsetof(struct spdk_iscsi_opts, MaxConnectionsPerSession), spdk_json_decode_uint32, true},
1741 : : {"default_time2wait", offsetof(struct spdk_iscsi_opts, DefaultTime2Wait), spdk_json_decode_uint32, true},
1742 : : {"default_time2retain", offsetof(struct spdk_iscsi_opts, DefaultTime2Retain), spdk_json_decode_uint32, true},
1743 : : {"first_burst_length", offsetof(struct spdk_iscsi_opts, FirstBurstLength), spdk_json_decode_uint32, true},
1744 : : {"immediate_data", offsetof(struct spdk_iscsi_opts, ImmediateData), spdk_json_decode_bool, true},
1745 : : {"error_recovery_level", offsetof(struct spdk_iscsi_opts, ErrorRecoveryLevel), spdk_json_decode_uint32, true},
1746 : : {"allow_duplicated_isid", offsetof(struct spdk_iscsi_opts, AllowDuplicateIsid), spdk_json_decode_bool, true},
1747 : : {"max_large_datain_per_connection", offsetof(struct spdk_iscsi_opts, MaxLargeDataInPerConnection), spdk_json_decode_uint32, true},
1748 : : {"max_r2t_per_connection", offsetof(struct spdk_iscsi_opts, MaxR2TPerConnection), spdk_json_decode_uint32, true},
1749 : : {"pdu_pool_size", offsetof(struct spdk_iscsi_opts, pdu_pool_size), spdk_json_decode_uint32, true},
1750 : : {"immediate_data_pool_size", offsetof(struct spdk_iscsi_opts, immediate_data_pool_size), spdk_json_decode_uint32, true},
1751 : : {"data_out_pool_size", offsetof(struct spdk_iscsi_opts, data_out_pool_size), spdk_json_decode_uint32, true},
1752 : : };
1753 : :
1754 : : static void
1755 : 63 : rpc_iscsi_set_options(struct spdk_jsonrpc_request *request,
1756 : : const struct spdk_json_val *params)
1757 : : {
1758 : : struct spdk_iscsi_opts *opts;
1759 : :
1760 [ - + ]: 63 : if (g_spdk_iscsi_opts != NULL) {
1761 : 0 : SPDK_ERRLOG("this RPC must not be called more than once.\n");
1762 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1763 : : "Must not call more than once");
1764 : 0 : return;
1765 : : }
1766 : :
1767 : 63 : opts = iscsi_opts_alloc();
1768 [ - + ]: 63 : if (opts == NULL) {
1769 : 0 : SPDK_ERRLOG("iscsi_opts_alloc() failed.\n");
1770 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1771 : : "Out of memory");
1772 : 0 : return;
1773 : : }
1774 : :
1775 [ + - ]: 63 : if (params != NULL) {
1776 [ - + ]: 63 : if (spdk_json_decode_object(params, rpc_set_iscsi_opts_decoders,
1777 : : SPDK_COUNTOF(rpc_set_iscsi_opts_decoders), opts)) {
1778 : 0 : SPDK_ERRLOG("spdk_json_decode_object() failed\n");
1779 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1780 : : "Invalid parameters");
1781 : 0 : iscsi_opts_free(opts);
1782 : 0 : return;
1783 : : }
1784 : : }
1785 : :
1786 : 63 : g_spdk_iscsi_opts = iscsi_opts_copy(opts);
1787 : 63 : iscsi_opts_free(opts);
1788 : :
1789 [ - + ]: 63 : if (g_spdk_iscsi_opts == NULL) {
1790 : 0 : SPDK_ERRLOG("iscsi_opts_copy() failed\n");
1791 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1792 : : "Out of memory");
1793 : 0 : return;
1794 : : }
1795 : :
1796 : 63 : spdk_jsonrpc_send_bool_response(request, true);
1797 : : }
1798 : 667 : SPDK_RPC_REGISTER("iscsi_set_options", rpc_iscsi_set_options, SPDK_RPC_STARTUP)
1799 : :
1800 : : struct rpc_iscsi_enable_histogram_request {
1801 : : char *name;
1802 : : bool enable;
1803 : : };
1804 : :
1805 : : static const struct spdk_json_object_decoder rpc_iscsi_enable_histogram_request_decoders[] = {
1806 : : {"name", offsetof(struct rpc_iscsi_enable_histogram_request, name), spdk_json_decode_string},
1807 : : {"enable", offsetof(struct rpc_iscsi_enable_histogram_request, enable), spdk_json_decode_bool},
1808 : : };
1809 : :
1810 : : struct iscsi_enable_histogram_ctx {
1811 : : struct spdk_jsonrpc_request *request;
1812 : : struct spdk_iscsi_tgt_node *target;
1813 : : bool enable;
1814 : : int status;
1815 : : struct spdk_thread *orig_thread;
1816 : : };
1817 : :
1818 : : static void
1819 : 0 : rpc_iscsi_enable_histogram_done(void *_ctx)
1820 : : {
1821 : 0 : struct iscsi_enable_histogram_ctx *ctx = _ctx;
1822 : :
1823 [ # # ]: 0 : if (ctx->status == 0) {
1824 : 0 : spdk_jsonrpc_send_bool_response(ctx->request, true);
1825 : : } else {
1826 : 0 : spdk_jsonrpc_send_error_response(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1827 : 0 : spdk_strerror(-ctx->status));
1828 : : }
1829 : :
1830 : 0 : free(ctx);
1831 : 0 : }
1832 : :
1833 : : static void
1834 : 0 : _iscsi_enable_histogram(void *_ctx)
1835 : : {
1836 : 0 : struct iscsi_enable_histogram_ctx *ctx = _ctx;
1837 : :
1838 [ # # ]: 0 : ctx->status = iscsi_tgt_node_enable_histogram(ctx->target, ctx->enable);
1839 : 0 : }
1840 : :
1841 : : static void
1842 : 0 : _rpc_iscsi_enable_histogram(void *_ctx)
1843 : : {
1844 : 0 : struct iscsi_enable_histogram_ctx *ctx = _ctx;
1845 : :
1846 [ # # ]: 0 : pthread_mutex_lock(&ctx->target->mutex);
1847 : 0 : _iscsi_enable_histogram(ctx);
1848 : 0 : ctx->target->num_active_conns--;
1849 [ # # ]: 0 : pthread_mutex_unlock(&ctx->target->mutex);
1850 : :
1851 : 0 : spdk_thread_send_msg(ctx->orig_thread, rpc_iscsi_enable_histogram_done, ctx);
1852 : 0 : }
1853 : :
1854 : : static void
1855 : 0 : rpc_iscsi_enable_histogram(struct spdk_jsonrpc_request *request,
1856 : : const struct spdk_json_val *params)
1857 : : {
1858 : 0 : struct rpc_iscsi_enable_histogram_request req = {NULL};
1859 : : struct iscsi_enable_histogram_ctx *ctx;
1860 : : struct spdk_iscsi_tgt_node *target;
1861 : : struct spdk_thread *thread;
1862 : : spdk_msg_fn fn;
1863 : :
1864 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_iscsi_enable_histogram_request_decoders,
1865 : : SPDK_COUNTOF(rpc_iscsi_enable_histogram_request_decoders),
1866 : : &req)) {
1867 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1868 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1869 : : "spdk_json_decode_object failed");
1870 : 0 : return;
1871 : : }
1872 : :
1873 : 0 : ctx = calloc(1, sizeof(*ctx));
1874 [ # # ]: 0 : if (ctx == NULL) {
1875 : 0 : SPDK_ERRLOG("Memory allocation failed\n");
1876 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1877 : : "Memory allocation failed");
1878 : 0 : return;
1879 : : }
1880 : :
1881 : 0 : target = iscsi_find_tgt_node(req.name);
1882 : :
1883 : 0 : free(req.name);
1884 : :
1885 [ # # ]: 0 : if (target == NULL) {
1886 : 0 : SPDK_ERRLOG("target is not found\n");
1887 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1888 : : "Invalid parameters");
1889 : 0 : free(ctx);
1890 : 0 : return;
1891 : : }
1892 : :
1893 : 0 : ctx->request = request;
1894 : 0 : ctx->target = target;
1895 [ # # ]: 0 : ctx->enable = req.enable;
1896 : 0 : ctx->orig_thread = spdk_get_thread();
1897 : :
1898 [ # # ]: 0 : pthread_mutex_lock(&ctx->target->mutex);
1899 [ # # ]: 0 : if (target->pg == NULL) {
1900 : 0 : _iscsi_enable_histogram(ctx);
1901 : 0 : thread = ctx->orig_thread;
1902 : 0 : fn = rpc_iscsi_enable_histogram_done;
1903 : : } else {
1904 : : /**
1905 : : * We get spdk thread of the target by using target->pg.
1906 : : * If target->num_active_conns >= 1, target->pg will not change.
1907 : : * So, It is safer to increase and decrease target->num_active_conns
1908 : : * while updating target->histogram.
1909 : : */
1910 : 0 : target->num_active_conns++;
1911 : 0 : thread = spdk_io_channel_get_thread(spdk_io_channel_from_ctx(target->pg));
1912 : 0 : fn = _rpc_iscsi_enable_histogram;
1913 : : }
1914 [ # # ]: 0 : pthread_mutex_unlock(&ctx->target->mutex);
1915 : :
1916 : 0 : spdk_thread_send_msg(thread, fn, ctx);
1917 : : }
1918 : :
1919 : 667 : SPDK_RPC_REGISTER("iscsi_enable_histogram", rpc_iscsi_enable_histogram, SPDK_RPC_RUNTIME)
1920 : :
1921 : : struct rpc_iscsi_get_histogram_request {
1922 : : char *name;
1923 : : };
1924 : :
1925 : : static const struct spdk_json_object_decoder rpc_iscsi_get_histogram_request_decoders[] = {
1926 : : {"name", offsetof(struct rpc_iscsi_get_histogram_request, name), spdk_json_decode_string}
1927 : : };
1928 : :
1929 : : static void
1930 : 0 : free_rpc_iscsi_get_histogram_request(struct rpc_iscsi_get_histogram_request *r)
1931 : : {
1932 : 0 : free(r->name);
1933 : 0 : }
1934 : :
1935 : : static void
1936 : 0 : rpc_iscsi_get_histogram(struct spdk_jsonrpc_request *request,
1937 : : const struct spdk_json_val *params)
1938 : : {
1939 : 0 : struct rpc_iscsi_get_histogram_request req = {NULL};
1940 : : struct spdk_iscsi_tgt_node *target;
1941 : : struct spdk_json_write_ctx *w;
1942 : : char *encoded_histogram;
1943 : : size_t src_len, dst_len;
1944 : : int rc;
1945 : :
1946 [ # # ]: 0 : if (spdk_json_decode_object(params, rpc_iscsi_get_histogram_request_decoders,
1947 : : SPDK_COUNTOF(rpc_iscsi_get_histogram_request_decoders),
1948 : : &req)) {
1949 : 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
1950 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1951 : : "spdk_json_decode_object failed");
1952 : 0 : goto free_req;
1953 : : }
1954 : :
1955 : 0 : target = iscsi_find_tgt_node(req.name);
1956 [ # # ]: 0 : if (target == NULL) {
1957 : 0 : SPDK_ERRLOG("target is not found\n");
1958 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1959 : : "target not found");
1960 : 0 : goto free_req;
1961 : : }
1962 : :
1963 [ # # ]: 0 : if (!target->histogram) {
1964 : 0 : SPDK_ERRLOG("target's histogram function is not enabled\n");
1965 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
1966 : : "target's histogram function is not enabled");
1967 : 0 : goto free_req;
1968 : : }
1969 : :
1970 [ # # ]: 0 : src_len = SPDK_HISTOGRAM_NUM_BUCKETS(target->histogram) * sizeof(uint64_t);
1971 : 0 : dst_len = spdk_base64_get_encoded_strlen(src_len) + 1;
1972 : 0 : encoded_histogram = malloc(dst_len);
1973 [ # # ]: 0 : if (encoded_histogram == NULL) {
1974 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1975 : : spdk_strerror(ENOMEM));
1976 : 0 : goto free_req;
1977 : : }
1978 : :
1979 : 0 : rc = spdk_base64_encode(encoded_histogram, target->histogram->bucket, src_len);
1980 [ # # ]: 0 : if (rc != 0) {
1981 : 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
1982 : : spdk_strerror(-rc));
1983 : 0 : goto free_encoded_histogram;
1984 : : }
1985 : :
1986 : 0 : w = spdk_jsonrpc_begin_result(request);
1987 : :
1988 : 0 : spdk_json_write_object_begin(w);
1989 : 0 : spdk_json_write_named_string(w, "histogram", encoded_histogram);
1990 : 0 : spdk_json_write_named_int64(w, "bucket_shift", target->histogram->bucket_shift);
1991 : 0 : spdk_json_write_named_int64(w, "tsc_rate", spdk_get_ticks_hz());
1992 : :
1993 : 0 : spdk_json_write_object_end(w);
1994 : 0 : spdk_jsonrpc_end_result(request, w);
1995 : :
1996 : 0 : free_encoded_histogram:
1997 : 0 : free(encoded_histogram);
1998 : 0 : free_req:
1999 : 0 : free_rpc_iscsi_get_histogram_request(&req);
2000 : 0 : }
2001 : :
2002 : 667 : SPDK_RPC_REGISTER("iscsi_get_histogram", rpc_iscsi_get_histogram, SPDK_RPC_RUNTIME)
|