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