1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2019 Intel Corporation. 3 * Copyright (c) 2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved. 4 * All rights reserved. 5 */ 6 7 #include "spdk/stdinc.h" 8 #include "spdk/blobfs.h" 9 #include "spdk/bdev.h" 10 #include "spdk/event.h" 11 #include "spdk/blob_bdev.h" 12 #include "spdk/blobfs_bdev.h" 13 #include "spdk/log.h" 14 #include "spdk/string.h" 15 #include "spdk/rpc.h" 16 #include "spdk/util.h" 17 18 #ifndef PAGE_SIZE 19 #define PAGE_SIZE 4096 20 #endif 21 22 #define MIN_CLUSTER_SZ (1024 * 1024) 23 24 struct rpc_blobfs_set_cache_size { 25 uint64_t size_in_mb; 26 }; 27 28 static const struct spdk_json_object_decoder rpc_blobfs_set_cache_size_decoders[] = { 29 {"size_in_mb", offsetof(struct rpc_blobfs_set_cache_size, size_in_mb), spdk_json_decode_uint64}, 30 }; 31 32 static void 33 rpc_blobfs_set_cache_size(struct spdk_jsonrpc_request *request, 34 const struct spdk_json_val *params) 35 { 36 struct rpc_blobfs_set_cache_size req; 37 int rc; 38 39 if (spdk_json_decode_object(params, rpc_blobfs_set_cache_size_decoders, 40 SPDK_COUNTOF(rpc_blobfs_set_cache_size_decoders), 41 &req)) { 42 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 43 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 44 "spdk_json_decode_object failed"); 45 46 return; 47 } 48 49 if (req.size_in_mb == 0) { 50 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 51 "spdk_json_decode_object failed"); 52 53 return; 54 } 55 56 rc = spdk_fs_set_cache_size(req.size_in_mb); 57 58 if (rc == 0) { 59 spdk_jsonrpc_send_bool_response(request, true); 60 } else { 61 spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc)); 62 } 63 } 64 65 SPDK_RPC_REGISTER("blobfs_set_cache_size", rpc_blobfs_set_cache_size, 66 SPDK_RPC_STARTUP | SPDK_RPC_RUNTIME) 67 68 struct rpc_blobfs_detect { 69 char *bdev_name; 70 71 struct spdk_jsonrpc_request *request; 72 }; 73 74 static void 75 free_rpc_blobfs_detect(struct rpc_blobfs_detect *req) 76 { 77 free(req->bdev_name); 78 free(req); 79 } 80 81 static const struct spdk_json_object_decoder rpc_blobfs_detect_decoders[] = { 82 {"bdev_name", offsetof(struct rpc_blobfs_detect, bdev_name), spdk_json_decode_string}, 83 }; 84 85 static void 86 _rpc_blobfs_detect_done(void *cb_arg, int fserrno) 87 { 88 struct rpc_blobfs_detect *req = cb_arg; 89 bool existed = true; 90 91 if (fserrno == -EILSEQ) { 92 /* There is no blobfs existing on bdev */ 93 existed = false; 94 } else if (fserrno != 0) { 95 spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 96 spdk_strerror(-fserrno)); 97 free_rpc_blobfs_detect(req); 98 return; 99 } 100 101 spdk_jsonrpc_send_bool_response(req->request, existed); 102 103 free_rpc_blobfs_detect(req); 104 } 105 106 static void 107 rpc_blobfs_detect(struct spdk_jsonrpc_request *request, 108 const struct spdk_json_val *params) 109 { 110 struct rpc_blobfs_detect *req; 111 112 req = calloc(1, sizeof(*req)); 113 if (req == NULL) { 114 SPDK_ERRLOG("could not allocate rpc_blobfs_detect request.\n"); 115 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 116 return; 117 } 118 119 if (spdk_json_decode_object(params, rpc_blobfs_detect_decoders, 120 SPDK_COUNTOF(rpc_blobfs_detect_decoders), 121 req)) { 122 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 123 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 124 "spdk_json_decode_object failed"); 125 126 free_rpc_blobfs_detect(req); 127 128 return; 129 } 130 131 req->request = request; 132 spdk_blobfs_bdev_detect(req->bdev_name, _rpc_blobfs_detect_done, req); 133 } 134 135 SPDK_RPC_REGISTER("blobfs_detect", rpc_blobfs_detect, SPDK_RPC_RUNTIME) 136 137 struct rpc_blobfs_create { 138 char *bdev_name; 139 uint64_t cluster_sz; 140 141 struct spdk_jsonrpc_request *request; 142 }; 143 144 static void 145 free_rpc_blobfs_create(struct rpc_blobfs_create *req) 146 { 147 free(req->bdev_name); 148 free(req); 149 } 150 151 static int 152 rpc_decode_cluster_sz(const struct spdk_json_val *val, void *out) 153 { 154 uint64_t *cluster_sz = out; 155 char *sz_str = NULL; 156 bool has_prefix; 157 int rc; 158 159 rc = spdk_json_decode_string(val, &sz_str); 160 if (rc) { 161 SPDK_NOTICELOG("Invalid parameter value: cluster_sz\n"); 162 return -EINVAL; 163 } 164 165 rc = spdk_parse_capacity(sz_str, cluster_sz, &has_prefix); 166 free(sz_str); 167 168 if (rc || *cluster_sz % PAGE_SIZE != 0 || *cluster_sz < MIN_CLUSTER_SZ) { 169 SPDK_NOTICELOG("Invalid parameter value: cluster_sz\n"); 170 return -EINVAL; 171 } 172 173 SPDK_DEBUGLOG(blobfs_bdev_rpc, "cluster_sz of blobfs: %" PRId64 "\n", *cluster_sz); 174 return 0; 175 } 176 177 static const struct spdk_json_object_decoder rpc_blobfs_create_decoders[] = { 178 {"bdev_name", offsetof(struct rpc_blobfs_create, bdev_name), spdk_json_decode_string}, 179 {"cluster_sz", offsetof(struct rpc_blobfs_create, cluster_sz), rpc_decode_cluster_sz, true}, 180 }; 181 182 static void 183 _rpc_blobfs_create_done(void *cb_arg, int fserrno) 184 { 185 struct rpc_blobfs_create *req = cb_arg; 186 187 if (fserrno != 0) { 188 spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 189 spdk_strerror(-fserrno)); 190 191 return; 192 } 193 194 spdk_jsonrpc_send_bool_response(req->request, true); 195 196 free_rpc_blobfs_create(req); 197 } 198 199 static void 200 rpc_blobfs_create(struct spdk_jsonrpc_request *request, 201 const struct spdk_json_val *params) 202 { 203 struct rpc_blobfs_create *req; 204 205 req = calloc(1, sizeof(*req)); 206 if (req == NULL) { 207 SPDK_ERRLOG("could not allocate rpc_blobfs_create request.\n"); 208 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 209 return; 210 } 211 212 if (spdk_json_decode_object(params, rpc_blobfs_create_decoders, 213 SPDK_COUNTOF(rpc_blobfs_create_decoders), 214 req)) { 215 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 216 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 217 "spdk_json_decode_object failed"); 218 219 free_rpc_blobfs_create(req); 220 221 return; 222 } 223 224 req->request = request; 225 spdk_blobfs_bdev_create(req->bdev_name, req->cluster_sz, _rpc_blobfs_create_done, req); 226 } 227 228 SPDK_RPC_REGISTER("blobfs_create", rpc_blobfs_create, SPDK_RPC_RUNTIME) 229 230 SPDK_LOG_REGISTER_COMPONENT(blobfs_bdev_rpc) 231 #ifdef SPDK_CONFIG_FUSE 232 233 struct rpc_blobfs_mount { 234 char *bdev_name; 235 char *mountpoint; 236 237 struct spdk_jsonrpc_request *request; 238 }; 239 240 static void 241 free_rpc_blobfs_mount(struct rpc_blobfs_mount *req) 242 { 243 free(req->bdev_name); 244 free(req->mountpoint); 245 free(req); 246 } 247 248 static const struct spdk_json_object_decoder rpc_blobfs_mount_decoders[] = { 249 {"bdev_name", offsetof(struct rpc_blobfs_mount, bdev_name), spdk_json_decode_string}, 250 {"mountpoint", offsetof(struct rpc_blobfs_mount, mountpoint), spdk_json_decode_string}, 251 }; 252 253 static void 254 _rpc_blobfs_mount_done(void *cb_arg, int fserrno) 255 { 256 struct rpc_blobfs_mount *req = cb_arg; 257 258 if (fserrno == -EILSEQ) { 259 /* There is no blobfs existing on bdev */ 260 spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 261 "No blobfs detected on given bdev"); 262 263 return; 264 } else if (fserrno != 0) { 265 spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, 266 spdk_strerror(-fserrno)); 267 268 return; 269 } 270 271 spdk_jsonrpc_send_bool_response(req->request, true); 272 273 free_rpc_blobfs_mount(req); 274 } 275 276 static void 277 rpc_blobfs_mount(struct spdk_jsonrpc_request *request, 278 const struct spdk_json_val *params) 279 { 280 struct rpc_blobfs_mount *req; 281 282 req = calloc(1, sizeof(*req)); 283 if (req == NULL) { 284 SPDK_ERRLOG("could not allocate rpc_blobfs_mount request.\n"); 285 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory"); 286 return; 287 } 288 289 if (spdk_json_decode_object(params, rpc_blobfs_mount_decoders, 290 SPDK_COUNTOF(rpc_blobfs_mount_decoders), 291 req)) { 292 SPDK_ERRLOG("spdk_json_decode_object failed\n"); 293 spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS, 294 "spdk_json_decode_object failed"); 295 296 free_rpc_blobfs_mount(req); 297 298 return; 299 } 300 301 req->request = request; 302 spdk_blobfs_bdev_mount(req->bdev_name, req->mountpoint, _rpc_blobfs_mount_done, req); 303 } 304 305 SPDK_RPC_REGISTER("blobfs_mount", rpc_blobfs_mount, SPDK_RPC_RUNTIME) 306 307 #endif 308