1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. All rights reserved. 5 * Copyright (c) 2019 Mellanox Technologies LTD. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include "spdk/rpc.h" 35 #include "spdk/util.h" 36 #include "spdk/string.h" 37 #include "spdk/bdev_module.h" 38 #include "spdk_internal/log.h" 39 40 #include "bdev_null.h" 41 42 struct rpc_construct_null { 43 char *name; 44 char *uuid; 45 uint64_t num_blocks; 46 uint32_t block_size; 47 }; 48 49 static void 50 free_rpc_construct_null(struct rpc_construct_null *req) 51 { 52 free(req->name); 53 free(req->uuid); 54 } 55 56 static const struct spdk_json_object_decoder rpc_construct_null_decoders[] = { 57 {"name", offsetof(struct rpc_construct_null, name), spdk_json_decode_string}, 58 {"uuid", offsetof(struct rpc_construct_null, uuid), spdk_json_decode_string, true}, 59 {"num_blocks", offsetof(struct rpc_construct_null, num_blocks), spdk_json_decode_uint64}, 60 {"block_size", offsetof(struct rpc_construct_null, block_size), spdk_json_decode_uint32}, 61 }; 62 63 static void 64 spdk_rpc_construct_null_bdev(struct spdk_jsonrpc_request *request, 65 const struct spdk_json_val *params) 66 { 67 struct rpc_construct_null req = {}; 68 struct spdk_json_write_ctx *w; 69 struct spdk_uuid *uuid = NULL; 70 struct spdk_uuid decoded_uuid; 71 struct spdk_bdev *bdev; 72 struct spdk_null_bdev_opts opts = {}; 73 int rc = 0; 74 75 if (spdk_json_decode_object(params, rpc_construct_null_decoders, 76 SPDK_COUNTOF(rpc_construct_null_decoders), 77 &req)) { 78 SPDK_DEBUGLOG(SPDK_LOG_BDEV_NULL, "spdk_json_decode_object failed\n"); 79 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 80 "spdk_json_decode_object failed"); 81 goto cleanup; 82 } 83 84 if (req.block_size % 512 != 0) { 85 spdk_jsonrpc_send_error_response_fmt(request, -EINVAL, 86 "Block size %u is not a multiple of 512", req.block_size); 87 goto cleanup; 88 } 89 90 if (req.num_blocks == 0) { 91 spdk_jsonrpc_send_error_response(request, -EINVAL, 92 "Disk num_blocks must be greater than 0"); 93 goto cleanup; 94 } 95 96 if (req.uuid) { 97 if (spdk_uuid_parse(&decoded_uuid, req.uuid)) { 98 spdk_jsonrpc_send_error_response(request, -EINVAL, 99 "Failed to parse bdev UUID"); 100 goto cleanup; 101 } 102 uuid = &decoded_uuid; 103 } 104 105 opts.name = req.name; 106 opts.uuid = uuid; 107 opts.num_blocks = req.num_blocks; 108 opts.block_size = req.block_size; 109 rc = create_null_bdev(&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("construct_null_bdev", spdk_rpc_construct_null_bdev, 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 _spdk_rpc_delete_null_bdev_cb(void *cb_arg, int bdeverrno) 142 { 143 struct spdk_jsonrpc_request *request = cb_arg; 144 struct spdk_json_write_ctx *w = spdk_jsonrpc_begin_result(request); 145 146 spdk_json_write_bool(w, bdeverrno == 0); 147 spdk_jsonrpc_end_result(request, w); 148 } 149 150 static void 151 spdk_rpc_delete_null_bdev(struct spdk_jsonrpc_request *request, 152 const struct spdk_json_val *params) 153 { 154 struct rpc_delete_null req = {NULL}; 155 struct spdk_bdev *bdev; 156 157 if (spdk_json_decode_object(params, rpc_delete_null_decoders, 158 SPDK_COUNTOF(rpc_delete_null_decoders), 159 &req)) { 160 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 161 "spdk_json_decode_object failed"); 162 goto cleanup; 163 } 164 165 bdev = spdk_bdev_get_by_name(req.name); 166 if (bdev == NULL) { 167 spdk_jsonrpc_send_error_response(request, -ENODEV, spdk_strerror(ENODEV)); 168 goto cleanup; 169 } 170 171 delete_null_bdev(bdev, _spdk_rpc_delete_null_bdev_cb, request); 172 173 free_rpc_delete_null(&req); 174 175 return; 176 177 cleanup: 178 free_rpc_delete_null(&req); 179 } 180 SPDK_RPC_REGISTER("delete_null_bdev", spdk_rpc_delete_null_bdev, SPDK_RPC_RUNTIME) 181