1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2017 Intel Corporation. All rights reserved. 3 * Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved. 4 */ 5 6 #include "spdk/rpc.h" 7 #include "spdk/util.h" 8 #include "spdk/string.h" 9 #include "spdk/bdev_module.h" 10 #include "spdk/log.h" 11 12 #include "bdev_null.h" 13 14 struct rpc_construct_null { 15 char *name; 16 char *uuid; 17 uint64_t num_blocks; 18 uint32_t block_size; 19 uint32_t md_size; 20 int32_t dif_type; 21 bool dif_is_head_of_md; 22 }; 23 24 static void 25 free_rpc_construct_null(struct rpc_construct_null *req) 26 { 27 free(req->name); 28 free(req->uuid); 29 } 30 31 static const struct spdk_json_object_decoder rpc_construct_null_decoders[] = { 32 {"name", offsetof(struct rpc_construct_null, name), spdk_json_decode_string}, 33 {"uuid", offsetof(struct rpc_construct_null, uuid), spdk_json_decode_string, true}, 34 {"num_blocks", offsetof(struct rpc_construct_null, num_blocks), spdk_json_decode_uint64}, 35 {"block_size", offsetof(struct rpc_construct_null, block_size), spdk_json_decode_uint32}, 36 {"md_size", offsetof(struct rpc_construct_null, md_size), spdk_json_decode_uint32, true}, 37 {"dif_type", offsetof(struct rpc_construct_null, dif_type), spdk_json_decode_int32, true}, 38 {"dif_is_head_of_md", offsetof(struct rpc_construct_null, dif_is_head_of_md), spdk_json_decode_bool, true}, 39 }; 40 41 static void 42 rpc_bdev_null_create(struct spdk_jsonrpc_request *request, 43 const struct spdk_json_val *params) 44 { 45 struct rpc_construct_null req = {}; 46 struct spdk_json_write_ctx *w; 47 struct spdk_uuid *uuid = NULL; 48 struct spdk_uuid decoded_uuid; 49 struct spdk_bdev *bdev; 50 struct spdk_null_bdev_opts opts = {}; 51 uint32_t data_block_size; 52 int rc = 0; 53 54 if (spdk_json_decode_object(params, rpc_construct_null_decoders, 55 SPDK_COUNTOF(rpc_construct_null_decoders), 56 &req)) { 57 SPDK_DEBUGLOG(bdev_null, "spdk_json_decode_object failed\n"); 58 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 59 "spdk_json_decode_object failed"); 60 goto cleanup; 61 } 62 63 if (req.block_size < req.md_size) { 64 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, 65 "Interleaved metadata size can not be greater than block size"); 66 goto cleanup; 67 } 68 data_block_size = req.block_size - req.md_size; 69 if (data_block_size % 512 != 0) { 70 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, 71 "Data block size %u is not a multiple of 512", req.block_size); 72 goto cleanup; 73 } 74 75 if (req.num_blocks == 0) { 76 spdk_jsonrpc_send_error_response(request, -EINVAL, 77 "Disk num_blocks must be greater than 0"); 78 goto cleanup; 79 } 80 81 if (req.uuid) { 82 if (spdk_uuid_parse(&decoded_uuid, req.uuid)) { 83 spdk_jsonrpc_send_error_response(request, -EINVAL, 84 "Failed to parse bdev UUID"); 85 goto cleanup; 86 } 87 uuid = &decoded_uuid; 88 } 89 90 if (req.dif_type < SPDK_DIF_DISABLE || req.dif_type > SPDK_DIF_TYPE3) { 91 spdk_jsonrpc_send_error_response(request, -EINVAL, "Invalid protection information type"); 92 goto cleanup; 93 } 94 95 if (req.dif_type != SPDK_DIF_DISABLE && !req.md_size) { 96 spdk_jsonrpc_send_error_response(request, -EINVAL, 97 "Interleaved metadata size should be set for DIF"); 98 goto cleanup; 99 } 100 101 opts.name = req.name; 102 opts.uuid = uuid; 103 opts.num_blocks = req.num_blocks; 104 opts.block_size = req.block_size; 105 opts.md_size = req.md_size; 106 opts.md_interleave = true; 107 opts.dif_type = req.dif_type; 108 opts.dif_is_head_of_md = req.dif_is_head_of_md; 109 rc = bdev_null_create(&bdev, &opts); 110 if (rc) { 111 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 112 goto cleanup; 113 } 114 115 w = spdk_jsonrpc_begin_result(request); 116 spdk_json_write_string(w, bdev->name); 117 spdk_jsonrpc_end_result(request, w); 118 free_rpc_construct_null(&req); 119 return; 120 121 cleanup: 122 free_rpc_construct_null(&req); 123 } 124 SPDK_RPC_REGISTER("bdev_null_create", rpc_bdev_null_create, SPDK_RPC_RUNTIME) 125 126 struct rpc_delete_null { 127 char *name; 128 }; 129 130 static void 131 free_rpc_delete_null(struct rpc_delete_null *req) 132 { 133 free(req->name); 134 } 135 136 static const struct spdk_json_object_decoder rpc_delete_null_decoders[] = { 137 {"name", offsetof(struct rpc_delete_null, name), spdk_json_decode_string}, 138 }; 139 140 static void 141 rpc_bdev_null_delete_cb(void *cb_arg, int bdeverrno) 142 { 143 struct spdk_jsonrpc_request *request = cb_arg; 144 145 if (bdeverrno == 0) { 146 spdk_jsonrpc_send_bool_response(request, true); 147 } else { 148 spdk_jsonrpc_send_error_response(request, bdeverrno, spdk_strerror(-bdeverrno)); 149 } 150 } 151 152 static void 153 rpc_bdev_null_delete(struct spdk_jsonrpc_request *request, 154 const struct spdk_json_val *params) 155 { 156 struct rpc_delete_null req = {NULL}; 157 158 if (spdk_json_decode_object(params, rpc_delete_null_decoders, 159 SPDK_COUNTOF(rpc_delete_null_decoders), 160 &req)) { 161 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 162 "spdk_json_decode_object failed"); 163 goto cleanup; 164 } 165 166 bdev_null_delete(req.name, rpc_bdev_null_delete_cb, request); 167 168 free_rpc_delete_null(&req); 169 170 return; 171 172 cleanup: 173 free_rpc_delete_null(&req); 174 } 175 SPDK_RPC_REGISTER("bdev_null_delete", rpc_bdev_null_delete, SPDK_RPC_RUNTIME) 176 177 struct rpc_bdev_null_resize { 178 char *name; 179 uint64_t new_size; 180 }; 181 182 static const struct spdk_json_object_decoder rpc_bdev_null_resize_decoders[] = { 183 {"name", offsetof(struct rpc_bdev_null_resize, name), spdk_json_decode_string}, 184 {"new_size", offsetof(struct rpc_bdev_null_resize, new_size), spdk_json_decode_uint64} 185 }; 186 187 static void 188 free_rpc_bdev_null_resize(struct rpc_bdev_null_resize *req) 189 { 190 free(req->name); 191 } 192 193 static void 194 spdk_rpc_bdev_null_resize(struct spdk_jsonrpc_request *request, 195 const struct spdk_json_val *params) 196 { 197 struct rpc_bdev_null_resize req = {}; 198 int rc; 199 200 if (spdk_json_decode_object(params, rpc_bdev_null_resize_decoders, 201 SPDK_COUNTOF(rpc_bdev_null_resize_decoders), 202 &req)) { 203 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 204 "spdk_json_decode_object failed"); 205 goto cleanup; 206 } 207 208 rc = bdev_null_resize(req.name, req.new_size); 209 if (rc) { 210 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 211 goto cleanup; 212 } 213 214 spdk_jsonrpc_send_bool_response(request, true); 215 cleanup: 216 free_rpc_bdev_null_resize(&req); 217 } 218 SPDK_RPC_REGISTER("bdev_null_resize", spdk_rpc_bdev_null_resize, SPDK_RPC_RUNTIME) 219