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
rpc_blobfs_set_cache_size(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)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
free_rpc_blobfs_detect(struct rpc_blobfs_detect * req)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
_rpc_blobfs_detect_done(void * cb_arg,int fserrno)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
rpc_blobfs_detect(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)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
free_rpc_blobfs_create(struct rpc_blobfs_create * req)145 free_rpc_blobfs_create(struct rpc_blobfs_create *req)
146 {
147 free(req->bdev_name);
148 free(req);
149 }
150
151 static int
rpc_decode_cluster_sz(const struct spdk_json_val * val,void * out)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
_rpc_blobfs_create_done(void * cb_arg,int fserrno)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
rpc_blobfs_create(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)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
free_rpc_blobfs_mount(struct rpc_blobfs_mount * req)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
_rpc_blobfs_mount_done(void * cb_arg,int fserrno)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
rpc_blobfs_mount(struct spdk_jsonrpc_request * request,const struct spdk_json_val * params)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