1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright (C) 2018 Intel Corporation.
3 * All rights reserved.
4 */
5
6 #include "vbdev_ocf.h"
7 #include "stats.h"
8 #include "utils.h"
9 #include "spdk/log.h"
10 #include "spdk/rpc.h"
11 #include "spdk/string.h"
12
13 /* Common structure to hold the name parameter for RPC methods using bdev name only. */
14 struct rpc_bdev_ocf_name {
15 char *name; /* main vbdev name */
16 };
17
18 /* Common free function for RPC methods using bdev name only. */
19 static void
free_rpc_bdev_ocf_name(struct rpc_bdev_ocf_name * r)20 free_rpc_bdev_ocf_name(struct rpc_bdev_ocf_name *r)
21 {
22 free(r->name);
23 }
24
25 /* Common function to decode the name input parameter for RPC methods using bdev name only. */
26 static const struct spdk_json_object_decoder rpc_bdev_ocf_name_decoders[] = {
27 {"name", offsetof(struct rpc_bdev_ocf_name, name), spdk_json_decode_string},
28 };
29
30
31 /* Structure to hold the parameters for this RPC method. */
32 struct rpc_bdev_ocf_create {
33 char *name; /* main vbdev */
34 char *mode; /* OCF mode (choose one) */
35 uint64_t cache_line_size; /* OCF cache line size */
36 char *cache_bdev_name; /* sub bdev */
37 char *core_bdev_name; /* sub bdev */
38 };
39
40 static void
free_rpc_bdev_ocf_create(struct rpc_bdev_ocf_create * r)41 free_rpc_bdev_ocf_create(struct rpc_bdev_ocf_create *r)
42 {
43 free(r->name);
44 free(r->core_bdev_name);
45 free(r->cache_bdev_name);
46 free(r->mode);
47 }
48
49 /* Structure to decode the input parameters for this RPC method. */
50 static const struct spdk_json_object_decoder rpc_bdev_ocf_create_decoders[] = {
51 {"name", offsetof(struct rpc_bdev_ocf_create, name), spdk_json_decode_string},
52 {"mode", offsetof(struct rpc_bdev_ocf_create, mode), spdk_json_decode_string},
53 {"cache_line_size", offsetof(struct rpc_bdev_ocf_create, cache_line_size), spdk_json_decode_uint64, true},
54 {"cache_bdev_name", offsetof(struct rpc_bdev_ocf_create, cache_bdev_name), spdk_json_decode_string},
55 {"core_bdev_name", offsetof(struct rpc_bdev_ocf_create, core_bdev_name), spdk_json_decode_string},
56 };
57
58 static void
construct_cb(int status,struct vbdev_ocf * vbdev,void * cb_arg)59 construct_cb(int status, struct vbdev_ocf *vbdev, void *cb_arg)
60 {
61 struct spdk_jsonrpc_request *request = cb_arg;
62 struct spdk_json_write_ctx *w;
63
64 if (status) {
65 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
66 "Could not create OCF vbdev: %d",
67 status);
68 } else {
69 w = spdk_jsonrpc_begin_result(request);
70 spdk_json_write_string(w, vbdev->name);
71 spdk_jsonrpc_end_result(request, w);
72 }
73 }
74
75 static void
rpc_bdev_ocf_create(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)76 rpc_bdev_ocf_create(struct spdk_jsonrpc_request *request,
77 const struct spdk_json_val *params)
78 {
79 struct rpc_bdev_ocf_create req = {NULL};
80 int ret;
81
82 ret = spdk_json_decode_object(params, rpc_bdev_ocf_create_decoders,
83 SPDK_COUNTOF(rpc_bdev_ocf_create_decoders),
84 &req);
85 if (ret) {
86 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
87 "Invalid parameters");
88 free_rpc_bdev_ocf_create(&req);
89 return;
90 }
91
92 vbdev_ocf_construct(req.name, req.mode, req.cache_line_size, req.cache_bdev_name,
93 req.core_bdev_name, false, construct_cb, request);
94 free_rpc_bdev_ocf_create(&req);
95 }
96 SPDK_RPC_REGISTER("bdev_ocf_create", rpc_bdev_ocf_create, SPDK_RPC_RUNTIME)
97
98 static void
delete_cb(void * cb_arg,int status)99 delete_cb(void *cb_arg, int status)
100 {
101 struct spdk_jsonrpc_request *request = cb_arg;
102
103 if (status) {
104 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
105 "Could not delete OCF vbdev: %d",
106 status);
107 } else {
108 spdk_jsonrpc_send_bool_response(request, true);
109 }
110 }
111
112 static void
rpc_bdev_ocf_delete(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)113 rpc_bdev_ocf_delete(struct spdk_jsonrpc_request *request,
114 const struct spdk_json_val *params)
115 {
116 struct rpc_bdev_ocf_name req = {NULL};
117 struct vbdev_ocf *vbdev;
118 int status;
119
120 status = spdk_json_decode_object(params, rpc_bdev_ocf_name_decoders,
121 SPDK_COUNTOF(rpc_bdev_ocf_name_decoders),
122 &req);
123 if (status) {
124 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
125 "Invalid parameters");
126 goto end;
127 }
128
129 vbdev = vbdev_ocf_get_by_name(req.name);
130 if (vbdev == NULL) {
131 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
132 spdk_strerror(ENODEV));
133 goto end;
134 }
135
136 status = vbdev_ocf_delete_clean(vbdev, delete_cb, request);
137 if (status) {
138 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
139 "Could not delete OCF vbdev: %s",
140 spdk_strerror(-status));
141 goto end;
142 }
143
144 end:
145 free_rpc_bdev_ocf_name(&req);
146 }
147 SPDK_RPC_REGISTER("bdev_ocf_delete", rpc_bdev_ocf_delete, SPDK_RPC_RUNTIME)
148
149 struct get_ocf_stats_ctx {
150 struct spdk_jsonrpc_request *request;
151 char *core_name;
152 };
153
154 static void
rpc_bdev_ocf_get_stats_cmpl(ocf_cache_t cache,void * priv,int error)155 rpc_bdev_ocf_get_stats_cmpl(ocf_cache_t cache, void *priv, int error)
156 {
157 struct get_ocf_stats_ctx *ctx = (struct get_ocf_stats_ctx *) priv;
158 struct spdk_json_write_ctx *w;
159 struct vbdev_ocf_stats stats;
160
161 if (error) {
162 goto end;
163 }
164
165 error = vbdev_ocf_stats_get(cache, ctx->core_name, &stats);
166
167 ocf_mngt_cache_read_unlock(cache);
168
169 if (error) {
170 goto end;
171 }
172
173 w = spdk_jsonrpc_begin_result(ctx->request);
174 vbdev_ocf_stats_write_json(w, &stats);
175 spdk_jsonrpc_end_result(ctx->request, w);
176
177 end:
178 if (error) {
179 spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
180 "Could not get stats: %s",
181 spdk_strerror(-error));
182 }
183 free(ctx);
184 }
185
186 static void
rpc_bdev_ocf_get_stats(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)187 rpc_bdev_ocf_get_stats(struct spdk_jsonrpc_request *request,
188 const struct spdk_json_val *params)
189 {
190 struct rpc_bdev_ocf_name req = {NULL};
191 struct vbdev_ocf *vbdev;
192 struct get_ocf_stats_ctx *ctx;
193
194 ctx = calloc(1, sizeof(*ctx));
195 if (!ctx) {
196 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
197 "Not enough memory to process request");
198 goto end;
199 }
200
201 if (spdk_json_decode_object(params, rpc_bdev_ocf_name_decoders,
202 SPDK_COUNTOF(rpc_bdev_ocf_name_decoders),
203 &req)) {
204 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
205 "Invalid parameters");
206 free(ctx);
207 goto end;
208 }
209
210 vbdev = vbdev_ocf_get_by_name(req.name);
211 if (vbdev == NULL) {
212 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
213 spdk_strerror(ENODEV));
214 free(ctx);
215 goto end;
216 }
217
218 ctx->core_name = vbdev->core.name;
219 ctx->request = request;
220 ocf_mngt_cache_read_lock(vbdev->ocf_cache, rpc_bdev_ocf_get_stats_cmpl, ctx);
221
222 end:
223 free_rpc_bdev_ocf_name(&req);
224 }
225 SPDK_RPC_REGISTER("bdev_ocf_get_stats", rpc_bdev_ocf_get_stats, SPDK_RPC_RUNTIME)
226
227 static void
rpc_bdev_ocf_reset_stats_cmpl(ocf_cache_t cache,void * priv,int error)228 rpc_bdev_ocf_reset_stats_cmpl(ocf_cache_t cache, void *priv, int error)
229 {
230 struct get_ocf_stats_ctx *ctx = (struct get_ocf_stats_ctx *) priv;
231
232 if (error) {
233 goto end;
234 }
235
236 error = vbdev_ocf_stats_reset(cache, ctx->core_name);
237
238 ocf_mngt_cache_read_unlock(cache);
239
240 end:
241 if (error) {
242 spdk_jsonrpc_send_error_response_fmt(ctx->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
243 "Could not reset stats: %s",
244 spdk_strerror(-error));
245 } else {
246 spdk_jsonrpc_send_bool_response(ctx->request, true);
247 }
248 free(ctx);
249 }
250
251 static void
rpc_bdev_ocf_reset_stats(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)252 rpc_bdev_ocf_reset_stats(struct spdk_jsonrpc_request *request,
253 const struct spdk_json_val *params)
254 {
255 struct rpc_bdev_ocf_name req = {NULL};
256 struct vbdev_ocf *vbdev;
257 struct get_ocf_stats_ctx *ctx;
258
259 ctx = calloc(1, sizeof(*ctx));
260 if (!ctx) {
261 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
262 "Not enough memory to process request");
263 goto end;
264 }
265
266 if (spdk_json_decode_object(params, rpc_bdev_ocf_name_decoders,
267 SPDK_COUNTOF(rpc_bdev_ocf_name_decoders),
268 &req)) {
269 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
270 "Invalid parameters");
271 free(ctx);
272 goto end;
273 }
274
275 vbdev = vbdev_ocf_get_by_name(req.name);
276 if (vbdev == NULL) {
277 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
278 spdk_strerror(ENODEV));
279 free(ctx);
280 goto end;
281 }
282
283 ctx->core_name = vbdev->core.name;
284 ctx->request = request;
285 ocf_mngt_cache_read_lock(vbdev->ocf_cache, rpc_bdev_ocf_reset_stats_cmpl, ctx);
286
287 end:
288 free_rpc_bdev_ocf_name(&req);
289 }
290 SPDK_RPC_REGISTER("bdev_ocf_reset_stats", rpc_bdev_ocf_reset_stats, SPDK_RPC_RUNTIME)
291
292 /* Structure to decode the input parameters for this RPC method. */
293 static const struct spdk_json_object_decoder rpc_bdev_ocf_get_bdevs_decoders[] = {
294 {"name", offsetof(struct rpc_bdev_ocf_name, name), spdk_json_decode_string, true},
295 };
296
297 struct bdev_get_bdevs_ctx {
298 char *name;
299 struct spdk_json_write_ctx *w;
300 };
301
302 static void
bdev_get_bdevs_fn(struct vbdev_ocf * vbdev,void * ctx)303 bdev_get_bdevs_fn(struct vbdev_ocf *vbdev, void *ctx)
304 {
305 struct bdev_get_bdevs_ctx *cctx = ctx;
306 struct spdk_json_write_ctx *w = cctx->w;
307
308 if (cctx->name != NULL &&
309 strcmp(vbdev->name, cctx->name) &&
310 strcmp(vbdev->cache.name, cctx->name) &&
311 strcmp(vbdev->core.name, cctx->name)) {
312 return;
313 }
314
315 spdk_json_write_object_begin(w);
316 spdk_json_write_named_string(w, "name", vbdev->name);
317 spdk_json_write_named_bool(w, "started", vbdev->state.started);
318
319 spdk_json_write_named_object_begin(w, "cache");
320 spdk_json_write_named_string(w, "name", vbdev->cache.name);
321 spdk_json_write_named_bool(w, "attached", vbdev->cache.attached);
322 spdk_json_write_object_end(w);
323
324 spdk_json_write_named_object_begin(w, "core");
325 spdk_json_write_named_string(w, "name", vbdev->core.name);
326 spdk_json_write_named_bool(w, "attached", vbdev->core.attached);
327 spdk_json_write_object_end(w);
328
329 spdk_json_write_object_end(w);
330 }
331
332 static void
rpc_bdev_ocf_get_bdevs(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)333 rpc_bdev_ocf_get_bdevs(struct spdk_jsonrpc_request *request,
334 const struct spdk_json_val *params)
335 {
336 struct spdk_json_write_ctx *w;
337 struct rpc_bdev_ocf_name req = {NULL};
338 struct bdev_get_bdevs_ctx cctx;
339
340 if (params && spdk_json_decode_object(params, rpc_bdev_ocf_get_bdevs_decoders,
341 SPDK_COUNTOF(rpc_bdev_ocf_get_bdevs_decoders),
342 &req)) {
343 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
344 "Invalid parameters");
345 goto end;
346 }
347
348 if (req.name) {
349 if (!(vbdev_ocf_get_by_name(req.name) || vbdev_ocf_get_base_by_name(req.name))) {
350 spdk_jsonrpc_send_error_response(request,
351 SPDK_JSONRPC_ERROR_INVALID_PARAMS,
352 spdk_strerror(ENODEV));
353 goto end;
354 }
355 }
356
357 w = spdk_jsonrpc_begin_result(request);
358
359 cctx.name = req.name;
360 cctx.w = w;
361
362 spdk_json_write_array_begin(w);
363 vbdev_ocf_foreach(bdev_get_bdevs_fn, &cctx);
364 spdk_json_write_array_end(w);
365 spdk_jsonrpc_end_result(request, w);
366
367 end:
368 free_rpc_bdev_ocf_name(&req);
369 }
370 SPDK_RPC_REGISTER("bdev_ocf_get_bdevs", rpc_bdev_ocf_get_bdevs, SPDK_RPC_RUNTIME)
371
372 /* Structure to hold the parameters for this RPC method. */
373 struct rpc_bdev_ocf_set_cache_mode {
374 char *name; /* main vbdev name */
375 char *mode; /* OCF cache mode to switch to */
376 };
377
378 static void
free_rpc_bdev_ocf_set_cache_mode(struct rpc_bdev_ocf_set_cache_mode * r)379 free_rpc_bdev_ocf_set_cache_mode(struct rpc_bdev_ocf_set_cache_mode *r)
380 {
381 free(r->name);
382 free(r->mode);
383 }
384
385 /* Structure to decode the input parameters for this RPC method. */
386 static const struct spdk_json_object_decoder rpc_bdev_ocf_set_cache_mode_decoders[] = {
387 {"name", offsetof(struct rpc_bdev_ocf_set_cache_mode, name), spdk_json_decode_string},
388 {"mode", offsetof(struct rpc_bdev_ocf_set_cache_mode, mode), spdk_json_decode_string},
389 };
390
391 static void
cache_mode_cb(int status,struct vbdev_ocf * vbdev,void * cb_arg)392 cache_mode_cb(int status, struct vbdev_ocf *vbdev, void *cb_arg)
393 {
394 struct spdk_jsonrpc_request *request = cb_arg;
395 struct spdk_json_write_ctx *w;
396
397 if (status) {
398 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
399 "Could not change OCF vbdev cache mode: %d",
400 status);
401 } else {
402 w = spdk_jsonrpc_begin_result(request);
403 spdk_json_write_string(w, ocf_get_cache_modename(
404 ocf_cache_get_mode(vbdev->ocf_cache)));
405 spdk_jsonrpc_end_result(request, w);
406 }
407 }
408
409 static void
rpc_bdev_ocf_set_cache_mode(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)410 rpc_bdev_ocf_set_cache_mode(struct spdk_jsonrpc_request *request,
411 const struct spdk_json_val *params)
412 {
413 struct rpc_bdev_ocf_set_cache_mode req = {NULL};
414 struct vbdev_ocf *vbdev;
415 int status;
416
417 status = spdk_json_decode_object(params, rpc_bdev_ocf_set_cache_mode_decoders,
418 SPDK_COUNTOF(rpc_bdev_ocf_set_cache_mode_decoders),
419 &req);
420 if (status) {
421 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
422 "Invalid parameters");
423 goto end;
424 }
425
426 vbdev = vbdev_ocf_get_by_name(req.name);
427 if (vbdev == NULL) {
428 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
429 spdk_strerror(ENODEV));
430 goto end;
431 }
432
433 vbdev_ocf_set_cache_mode(vbdev, req.mode, cache_mode_cb, request);
434
435 end:
436 free_rpc_bdev_ocf_set_cache_mode(&req);
437 }
438 SPDK_RPC_REGISTER("bdev_ocf_set_cache_mode", rpc_bdev_ocf_set_cache_mode, SPDK_RPC_RUNTIME)
439
440 static void
seqcutoff_cb(int status,void * cb_arg)441 seqcutoff_cb(int status, void *cb_arg)
442 {
443 struct spdk_jsonrpc_request *request = cb_arg;
444
445 if (status) {
446 spdk_jsonrpc_send_error_response_fmt(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
447 "OCF could not set sequential cutoff parameters: %d", status);
448 } else {
449 spdk_jsonrpc_send_bool_response(request, true);
450 }
451 }
452
453 /* Structure to hold the parameters for this RPC method. */
454 struct rpc_bdev_ocf_set_seqcutoff {
455 char *name; /* main vbdev name */
456 char *policy;
457 uint32_t threshold;
458 uint32_t promotion_count;
459 };
460
461 static void
free_rpc_bdev_ocf_set_seqcutoff(struct rpc_bdev_ocf_set_seqcutoff * r)462 free_rpc_bdev_ocf_set_seqcutoff(struct rpc_bdev_ocf_set_seqcutoff *r)
463 {
464 free(r->name);
465 free(r->policy);
466 }
467
468 /* Structure to decode the input parameters for this RPC method. */
469 static const struct spdk_json_object_decoder rpc_bdev_ocf_set_seqcutoff_decoders[] = {
470 {"name", offsetof(struct rpc_bdev_ocf_set_seqcutoff, name), spdk_json_decode_string},
471 {"policy", offsetof(struct rpc_bdev_ocf_set_seqcutoff, policy), spdk_json_decode_string},
472 {"threshold", offsetof(struct rpc_bdev_ocf_set_seqcutoff, threshold), spdk_json_decode_uint32, true},
473 {"promotion_count", offsetof(struct rpc_bdev_ocf_set_seqcutoff, promotion_count), spdk_json_decode_uint32, true},
474 };
475
476 static void
rpc_bdev_ocf_set_seqcutoff(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)477 rpc_bdev_ocf_set_seqcutoff(struct spdk_jsonrpc_request *request,
478 const struct spdk_json_val *params)
479 {
480 struct rpc_bdev_ocf_set_seqcutoff req = {NULL};
481 struct vbdev_ocf *vbdev;
482 int ret;
483
484 ret = spdk_json_decode_object(params, rpc_bdev_ocf_set_seqcutoff_decoders,
485 SPDK_COUNTOF(rpc_bdev_ocf_set_seqcutoff_decoders), &req);
486 if (ret) {
487 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
488 "Invalid parameters");
489 goto end;
490 }
491
492 vbdev = vbdev_ocf_get_by_name(req.name);
493 if (vbdev == NULL) {
494 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
495 spdk_strerror(ENODEV));
496 goto end;
497 }
498
499 vbdev_ocf_set_seqcutoff(vbdev, req.policy, req.threshold, req.promotion_count, seqcutoff_cb,
500 request);
501
502 end:
503 free_rpc_bdev_ocf_set_seqcutoff(&req);
504 }
505 SPDK_RPC_REGISTER("bdev_ocf_set_seqcutoff", rpc_bdev_ocf_set_seqcutoff, SPDK_RPC_RUNTIME)
506
507 struct get_ocf_flush_start_ctx {
508 struct spdk_jsonrpc_request *request;
509 struct vbdev_ocf *vbdev;
510 };
511
512 static void
rpc_bdev_ocf_flush_start_cmpl(ocf_cache_t cache,void * priv,int error)513 rpc_bdev_ocf_flush_start_cmpl(ocf_cache_t cache, void *priv, int error)
514 {
515 struct get_ocf_flush_start_ctx *ctx = priv;
516
517 ctx->vbdev->flush.in_progress = false;
518 ctx->vbdev->flush.status = error;
519
520 ocf_mngt_cache_read_unlock(cache);
521
522 free(ctx);
523 }
524
525 static void
rpc_bdev_ocf_flush_start_lock_cmpl(ocf_cache_t cache,void * priv,int error)526 rpc_bdev_ocf_flush_start_lock_cmpl(ocf_cache_t cache, void *priv, int error)
527 {
528 struct get_ocf_flush_start_ctx *ctx = priv;
529
530 if (error) {
531 spdk_jsonrpc_send_error_response_fmt(ctx->request,
532 SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
533 "Could not lock cache: %d", error);
534 free(ctx);
535 return;
536 }
537
538 ctx->vbdev->flush.in_progress = true;
539 ocf_mngt_cache_flush(cache, rpc_bdev_ocf_flush_start_cmpl, ctx);
540
541 spdk_jsonrpc_send_bool_response(ctx->request, true);
542 }
543
544 static void
rpc_bdev_ocf_flush_start(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)545 rpc_bdev_ocf_flush_start(struct spdk_jsonrpc_request *request,
546 const struct spdk_json_val *params)
547 {
548 struct rpc_bdev_ocf_name req = {NULL};
549 struct get_ocf_flush_start_ctx *ctx;
550 int status;
551
552 ctx = calloc(1, sizeof(*ctx));
553 if (!ctx) {
554 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
555 "Not enough memory to process request");
556 goto end;
557 }
558
559 status = spdk_json_decode_object(params, rpc_bdev_ocf_name_decoders,
560 SPDK_COUNTOF(rpc_bdev_ocf_name_decoders),
561 &req);
562 if (status) {
563 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
564 "Invalid parameters");
565 free(ctx);
566 goto end;
567 }
568
569 ctx->vbdev = vbdev_ocf_get_by_name(req.name);
570 if (ctx->vbdev == NULL) {
571 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
572 spdk_strerror(ENODEV));
573 free(ctx);
574 goto end;
575 }
576
577 if (!ctx->vbdev->ocf_cache) {
578 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
579 "Couldn't flush cache: device not attached");
580 free(ctx);
581 goto end;
582 }
583
584 ctx->request = request;
585 ocf_mngt_cache_read_lock(ctx->vbdev->ocf_cache, rpc_bdev_ocf_flush_start_lock_cmpl, ctx);
586
587 end:
588 free_rpc_bdev_ocf_name(&req);
589 }
590 SPDK_RPC_REGISTER("bdev_ocf_flush_start", rpc_bdev_ocf_flush_start, SPDK_RPC_RUNTIME)
591
592 static void
rpc_bdev_ocf_flush_status(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)593 rpc_bdev_ocf_flush_status(struct spdk_jsonrpc_request *request,
594 const struct spdk_json_val *params)
595 {
596 struct rpc_bdev_ocf_name req = {NULL};
597 struct spdk_json_write_ctx *w;
598 struct vbdev_ocf *vbdev;
599 int status;
600
601 status = spdk_json_decode_object(params, rpc_bdev_ocf_name_decoders,
602 SPDK_COUNTOF(rpc_bdev_ocf_name_decoders),
603 &req);
604 if (status) {
605 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
606 "Invalid parameters");
607 goto end;
608 }
609
610 vbdev = vbdev_ocf_get_by_name(req.name);
611 if (vbdev == NULL) {
612 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
613 spdk_strerror(ENODEV));
614 goto end;
615 }
616
617 w = spdk_jsonrpc_begin_result(request);
618
619 spdk_json_write_object_begin(w);
620 spdk_json_write_named_bool(w, "in_progress", vbdev->flush.in_progress);
621 if (!vbdev->flush.in_progress) {
622 spdk_json_write_named_int32(w, "status", vbdev->flush.status);
623 }
624 spdk_json_write_object_end(w);
625
626 spdk_jsonrpc_end_result(request, w);
627
628 end:
629 free_rpc_bdev_ocf_name(&req);
630 }
631 SPDK_RPC_REGISTER("bdev_ocf_flush_status", rpc_bdev_ocf_flush_status, SPDK_RPC_RUNTIME)
632