1488570ebSJim Harris /* SPDX-License-Identifier: BSD-3-Clause 2a6dbe372Spaul luse * Copyright (C) 2018 Intel Corporation. 3c77bc554SShuhei Matsumoto * Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 407fe6a43SSeth Howell * All rights reserved. 507fe6a43SSeth Howell */ 607fe6a43SSeth Howell 707fe6a43SSeth Howell #include "vbdev_compress.h" 807fe6a43SSeth Howell #include "spdk/rpc.h" 907fe6a43SSeth Howell #include "spdk/util.h" 1007fe6a43SSeth Howell #include "spdk/string.h" 114e8e97c8STomasz Zawadzki #include "spdk/log.h" 1207fe6a43SSeth Howell 1307fe6a43SSeth Howell struct rpc_bdev_compress_get_orphans { 1407fe6a43SSeth Howell char *name; 1507fe6a43SSeth Howell }; 1607fe6a43SSeth Howell 1707fe6a43SSeth Howell static void 1807fe6a43SSeth Howell free_rpc_bdev_compress_get_orphans(struct rpc_bdev_compress_get_orphans *r) 1907fe6a43SSeth Howell { 2007fe6a43SSeth Howell free(r->name); 2107fe6a43SSeth Howell } 2207fe6a43SSeth Howell 2307fe6a43SSeth Howell static const struct spdk_json_object_decoder rpc_bdev_compress_get_orphans_decoders[] = { 2407fe6a43SSeth Howell {"name", offsetof(struct rpc_bdev_compress_get_orphans, name), spdk_json_decode_string, true}, 2507fe6a43SSeth Howell }; 2607fe6a43SSeth Howell 2707fe6a43SSeth Howell static void 28347499e7SSeth Howell rpc_bdev_compress_get_orphans(struct spdk_jsonrpc_request *request, 2907fe6a43SSeth Howell const struct spdk_json_val *params) 3007fe6a43SSeth Howell { 3107fe6a43SSeth Howell struct rpc_bdev_compress_get_orphans req = {}; 3207fe6a43SSeth Howell struct spdk_json_write_ctx *w; 3307fe6a43SSeth Howell struct vbdev_compress *comp_bdev; 3407fe6a43SSeth Howell bool found = false; 3507fe6a43SSeth Howell 3607fe6a43SSeth Howell 3707fe6a43SSeth Howell if (params && spdk_json_decode_object(params, rpc_bdev_compress_get_orphans_decoders, 3807fe6a43SSeth Howell SPDK_COUNTOF(rpc_bdev_compress_get_orphans_decoders), 3907fe6a43SSeth Howell &req)) { 4007fe6a43SSeth Howell SPDK_ERRLOG("spdk_json_decode_object failed\n"); 4107fe6a43SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 4207fe6a43SSeth Howell "spdk_json_decode_object failed"); 4307fe6a43SSeth Howell free_rpc_bdev_compress_get_orphans(&req); 4407fe6a43SSeth Howell return; 4507fe6a43SSeth Howell } 4607fe6a43SSeth Howell 4707fe6a43SSeth Howell if (req.name) { 4807fe6a43SSeth Howell if (compress_has_orphan(req.name) == false) { 4907fe6a43SSeth Howell spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 5007fe6a43SSeth Howell free_rpc_bdev_compress_get_orphans(&req); 5107fe6a43SSeth Howell return; 5207fe6a43SSeth Howell } 5307fe6a43SSeth Howell found = true; 5407fe6a43SSeth Howell } 5507fe6a43SSeth Howell 5607fe6a43SSeth Howell w = spdk_jsonrpc_begin_result(request); 5707fe6a43SSeth Howell spdk_json_write_array_begin(w); 5807fe6a43SSeth Howell if (found) { 5907fe6a43SSeth Howell spdk_json_write_string(w, req.name); 6007fe6a43SSeth Howell } else { 6107fe6a43SSeth Howell for (comp_bdev = compress_bdev_first(); comp_bdev != NULL; 6207fe6a43SSeth Howell comp_bdev = compress_bdev_next(comp_bdev)) { 6307fe6a43SSeth Howell if (compress_has_orphan(compress_get_name(comp_bdev))) { 6407fe6a43SSeth Howell spdk_json_write_string(w, compress_get_name(comp_bdev)); 6507fe6a43SSeth Howell } 6607fe6a43SSeth Howell } 6707fe6a43SSeth Howell } 6807fe6a43SSeth Howell spdk_json_write_array_end(w); 6907fe6a43SSeth Howell spdk_jsonrpc_end_result(request, w); 7007fe6a43SSeth Howell free_rpc_bdev_compress_get_orphans(&req); 7107fe6a43SSeth Howell } 72347499e7SSeth Howell SPDK_RPC_REGISTER("bdev_compress_get_orphans", rpc_bdev_compress_get_orphans, SPDK_RPC_RUNTIME) 7307fe6a43SSeth Howell 7407fe6a43SSeth Howell /* Structure to hold the parameters for this RPC method. */ 7507fe6a43SSeth Howell struct rpc_construct_compress { 7607fe6a43SSeth Howell char *base_bdev_name; 7707fe6a43SSeth Howell char *pm_path; 7862b3b171Spaul luse uint32_t lb_size; 79*ddd4603cSYankun Li enum spdk_accel_comp_algo comp_algo; 80*ddd4603cSYankun Li uint32_t comp_level; 8107fe6a43SSeth Howell }; 8207fe6a43SSeth Howell 83*ddd4603cSYankun Li static int 84*ddd4603cSYankun Li rpc_decode_comp_algo(const struct spdk_json_val *val, void *out) 85*ddd4603cSYankun Li { 86*ddd4603cSYankun Li enum spdk_accel_comp_algo *algo = out; 87*ddd4603cSYankun Li char *name = NULL; 88*ddd4603cSYankun Li int rc; 89*ddd4603cSYankun Li 90*ddd4603cSYankun Li rc = spdk_json_decode_string(val, &name); 91*ddd4603cSYankun Li if (rc != 0) { 92*ddd4603cSYankun Li return rc; 93*ddd4603cSYankun Li } 94*ddd4603cSYankun Li 95*ddd4603cSYankun Li if (strcmp(name, "deflate") == 0) { 96*ddd4603cSYankun Li *algo = SPDK_ACCEL_COMP_ALGO_DEFLATE; 97*ddd4603cSYankun Li } else if (strcmp(name, "lz4") == 0) { 98*ddd4603cSYankun Li *algo = SPDK_ACCEL_COMP_ALGO_LZ4; 99*ddd4603cSYankun Li } else { 100*ddd4603cSYankun Li rc = -EINVAL; 101*ddd4603cSYankun Li } 102*ddd4603cSYankun Li 103*ddd4603cSYankun Li free(name); 104*ddd4603cSYankun Li 105*ddd4603cSYankun Li return rc; 106*ddd4603cSYankun Li } 107*ddd4603cSYankun Li 108f3cda926SYankun Li struct rpc_bdev_compress_create_ctx { 109f3cda926SYankun Li struct rpc_construct_compress req; 110f3cda926SYankun Li struct spdk_jsonrpc_request *request; 111f3cda926SYankun Li }; 112f3cda926SYankun Li 11307fe6a43SSeth Howell /* Free the allocated memory resource after the RPC handling. */ 11407fe6a43SSeth Howell static void 115f3cda926SYankun Li free_rpc_construct_compress(struct rpc_bdev_compress_create_ctx *ctx) 11607fe6a43SSeth Howell { 117f3cda926SYankun Li struct rpc_construct_compress *req; 118f3cda926SYankun Li 119f3cda926SYankun Li assert(ctx != NULL); 120f3cda926SYankun Li 121f3cda926SYankun Li req = &ctx->req; 122f3cda926SYankun Li 123f3cda926SYankun Li free(req->base_bdev_name); 124f3cda926SYankun Li free(req->pm_path); 125f3cda926SYankun Li 126f3cda926SYankun Li free(ctx); 12707fe6a43SSeth Howell } 12807fe6a43SSeth Howell 12907fe6a43SSeth Howell /* Structure to decode the input parameters for this RPC method. */ 13007fe6a43SSeth Howell static const struct spdk_json_object_decoder rpc_construct_compress_decoders[] = { 13107fe6a43SSeth Howell {"base_bdev_name", offsetof(struct rpc_construct_compress, base_bdev_name), spdk_json_decode_string}, 13207fe6a43SSeth Howell {"pm_path", offsetof(struct rpc_construct_compress, pm_path), spdk_json_decode_string}, 1330e25e2a6SKonrad Sztyber {"lb_size", offsetof(struct rpc_construct_compress, lb_size), spdk_json_decode_uint32, true}, 134*ddd4603cSYankun Li {"comp_algo", offsetof(struct rpc_construct_compress, comp_algo), rpc_decode_comp_algo, true}, 135*ddd4603cSYankun Li {"comp_level", offsetof(struct rpc_construct_compress, comp_level), spdk_json_decode_uint32, true}, 13607fe6a43SSeth Howell }; 13707fe6a43SSeth Howell 138f3cda926SYankun Li static void 139f3cda926SYankun Li rpc_bdev_compress_create_cb(void *_ctx, int status) 140f3cda926SYankun Li { 141f3cda926SYankun Li struct rpc_bdev_compress_create_ctx *ctx = _ctx; 142f3cda926SYankun Li struct rpc_construct_compress *req = &ctx->req; 143f3cda926SYankun Li struct spdk_jsonrpc_request *request = ctx->request; 144f3cda926SYankun Li struct spdk_json_write_ctx *w; 145f3cda926SYankun Li char *name; 146f3cda926SYankun Li 147f3cda926SYankun Li if (status != 0) { 148f3cda926SYankun Li spdk_jsonrpc_send_error_response(request, status, spdk_strerror(-status)); 149f3cda926SYankun Li } else { 150f3cda926SYankun Li w = spdk_jsonrpc_begin_result(request); 151f3cda926SYankun Li name = spdk_sprintf_alloc("COMP_%s", req->base_bdev_name); 152f3cda926SYankun Li spdk_json_write_string(w, name); 153f3cda926SYankun Li spdk_jsonrpc_end_result(request, w); 154f3cda926SYankun Li free(name); 155f3cda926SYankun Li } 156f3cda926SYankun Li 157f3cda926SYankun Li free_rpc_construct_compress(ctx); 158f3cda926SYankun Li } 159f3cda926SYankun Li 16007fe6a43SSeth Howell /* Decode the parameters for this RPC method and properly construct the compress 16107fe6a43SSeth Howell * device. Error status returned in the failed cases. 16207fe6a43SSeth Howell */ 16307fe6a43SSeth Howell static void 164347499e7SSeth Howell rpc_bdev_compress_create(struct spdk_jsonrpc_request *request, 16507fe6a43SSeth Howell const struct spdk_json_val *params) 16607fe6a43SSeth Howell { 167f3cda926SYankun Li struct rpc_bdev_compress_create_ctx *ctx; 168f3cda926SYankun Li struct rpc_construct_compress *req; 16907fe6a43SSeth Howell int rc; 17007fe6a43SSeth Howell 171f3cda926SYankun Li ctx = calloc(1, sizeof(*ctx)); 172f3cda926SYankun Li if (ctx == NULL) { 173f3cda926SYankun Li SPDK_ERRLOG("failed to alloc compress bdev creation contexts\n"); 174f3cda926SYankun Li spdk_jsonrpc_send_error_response(request, -ENOMEM, spdk_strerror(ENOMEM)); 175f3cda926SYankun Li return; 176f3cda926SYankun Li } 177f3cda926SYankun Li 178f3cda926SYankun Li req = &ctx->req; 179*ddd4603cSYankun Li req->comp_algo = SPDK_ACCEL_COMP_ALGO_DEFLATE; 180*ddd4603cSYankun Li req->comp_level = 1; 18107fe6a43SSeth Howell if (spdk_json_decode_object(params, rpc_construct_compress_decoders, 18207fe6a43SSeth Howell SPDK_COUNTOF(rpc_construct_compress_decoders), 183f3cda926SYankun Li req)) { 1842172c432STomasz Zawadzki SPDK_DEBUGLOG(vbdev_compress, "spdk_json_decode_object failed\n"); 18562b3b171Spaul luse spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_PARSE_ERROR, 18607fe6a43SSeth Howell "spdk_json_decode_object failed"); 18707fe6a43SSeth Howell goto cleanup; 18807fe6a43SSeth Howell } 18907fe6a43SSeth Howell 190*ddd4603cSYankun Li rc = create_compress_bdev(req->base_bdev_name, req->pm_path, req->lb_size, req->comp_algo, 191*ddd4603cSYankun Li req->comp_level, rpc_bdev_compress_create_cb, ctx); 19207fe6a43SSeth Howell if (rc != 0) { 19389ee5a13Spaul luse if (rc == -EBUSY) { 19489ee5a13Spaul luse spdk_jsonrpc_send_error_response(request, rc, "Base bdev already in use for compression."); 19589ee5a13Spaul luse } else { 19607fe6a43SSeth Howell spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 19789ee5a13Spaul luse } 19807fe6a43SSeth Howell goto cleanup; 19907fe6a43SSeth Howell } 20007fe6a43SSeth Howell 201f3cda926SYankun Li ctx->request = request; 202f3cda926SYankun Li return; 20307fe6a43SSeth Howell 20407fe6a43SSeth Howell cleanup: 205f3cda926SYankun Li free_rpc_construct_compress(ctx); 20607fe6a43SSeth Howell } 207347499e7SSeth Howell SPDK_RPC_REGISTER("bdev_compress_create", rpc_bdev_compress_create, SPDK_RPC_RUNTIME) 20807fe6a43SSeth Howell 20907fe6a43SSeth Howell struct rpc_delete_compress { 21007fe6a43SSeth Howell char *name; 21107fe6a43SSeth Howell }; 21207fe6a43SSeth Howell 21307fe6a43SSeth Howell static void 21407fe6a43SSeth Howell free_rpc_delete_compress(struct rpc_delete_compress *req) 21507fe6a43SSeth Howell { 21607fe6a43SSeth Howell free(req->name); 21707fe6a43SSeth Howell } 21807fe6a43SSeth Howell 21907fe6a43SSeth Howell static const struct spdk_json_object_decoder rpc_delete_compress_decoders[] = { 22007fe6a43SSeth Howell {"name", offsetof(struct rpc_delete_compress, name), spdk_json_decode_string}, 22107fe6a43SSeth Howell }; 22207fe6a43SSeth Howell 22307fe6a43SSeth Howell static void 224347499e7SSeth Howell _rpc_bdev_compress_delete_cb(void *cb_arg, int bdeverrno) 22507fe6a43SSeth Howell { 22607fe6a43SSeth Howell struct spdk_jsonrpc_request *request = cb_arg; 22707fe6a43SSeth Howell 228c77bc554SShuhei Matsumoto if (bdeverrno == 0) { 229c77bc554SShuhei Matsumoto spdk_jsonrpc_send_bool_response(request, true); 230c77bc554SShuhei Matsumoto } else { 231c77bc554SShuhei Matsumoto spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno)); 232c77bc554SShuhei Matsumoto } 23307fe6a43SSeth Howell } 23407fe6a43SSeth Howell 23507fe6a43SSeth Howell static void 236347499e7SSeth Howell rpc_bdev_compress_delete(struct spdk_jsonrpc_request *request, 23707fe6a43SSeth Howell const struct spdk_json_val *params) 23807fe6a43SSeth Howell { 23907fe6a43SSeth Howell struct rpc_delete_compress req = {NULL}; 24007fe6a43SSeth Howell 24107fe6a43SSeth Howell if (spdk_json_decode_object(params, rpc_delete_compress_decoders, 24207fe6a43SSeth Howell SPDK_COUNTOF(rpc_delete_compress_decoders), 24307fe6a43SSeth Howell &req)) { 24407fe6a43SSeth Howell spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 24507fe6a43SSeth Howell "spdk_json_decode_object failed"); 24607fe6a43SSeth Howell } else { 247347499e7SSeth Howell bdev_compress_delete(req.name, _rpc_bdev_compress_delete_cb, request); 24807fe6a43SSeth Howell } 24907fe6a43SSeth Howell 25007fe6a43SSeth Howell free_rpc_delete_compress(&req); 25107fe6a43SSeth Howell } 252347499e7SSeth Howell SPDK_RPC_REGISTER("bdev_compress_delete", rpc_bdev_compress_delete, SPDK_RPC_RUNTIME) 253