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