xref: /spdk/module/bdev/ocf/vbdev_ocf_rpc.c (revision 60982c759db49b4f4579f16e3b24df0725ba4b94)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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