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