Line data Source code
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 0 : rpc_blobfs_set_cache_size(struct spdk_jsonrpc_request *request,
34 : const struct spdk_json_val *params)
35 : {
36 0 : struct rpc_blobfs_set_cache_size req;
37 : int rc;
38 :
39 0 : if (spdk_json_decode_object(params, rpc_blobfs_set_cache_size_decoders,
40 : SPDK_COUNTOF(rpc_blobfs_set_cache_size_decoders),
41 : &req)) {
42 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
43 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
44 : "spdk_json_decode_object failed");
45 :
46 0 : return;
47 : }
48 :
49 0 : if (req.size_in_mb == 0) {
50 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
51 : "spdk_json_decode_object failed");
52 :
53 0 : return;
54 : }
55 :
56 0 : rc = spdk_fs_set_cache_size(req.size_in_mb);
57 :
58 0 : if (rc == 0) {
59 0 : spdk_jsonrpc_send_bool_response(request, true);
60 : } else {
61 0 : spdk_jsonrpc_send_error_response(request, rc, spdk_strerror(-rc));
62 : }
63 : }
64 :
65 0 : 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 0 : free_rpc_blobfs_detect(struct rpc_blobfs_detect *req)
76 : {
77 0 : free(req->bdev_name);
78 0 : free(req);
79 0 : }
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 0 : _rpc_blobfs_detect_done(void *cb_arg, int fserrno)
87 : {
88 0 : struct rpc_blobfs_detect *req = cb_arg;
89 0 : bool existed = true;
90 :
91 0 : if (fserrno == -EILSEQ) {
92 : /* There is no blobfs existing on bdev */
93 0 : existed = false;
94 0 : } else if (fserrno != 0) {
95 0 : spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
96 : spdk_strerror(-fserrno));
97 0 : free_rpc_blobfs_detect(req);
98 0 : return;
99 : }
100 :
101 0 : spdk_jsonrpc_send_bool_response(req->request, existed);
102 :
103 0 : free_rpc_blobfs_detect(req);
104 : }
105 :
106 : static void
107 0 : rpc_blobfs_detect(struct spdk_jsonrpc_request *request,
108 : const struct spdk_json_val *params)
109 : {
110 : struct rpc_blobfs_detect *req;
111 :
112 0 : req = calloc(1, sizeof(*req));
113 0 : if (req == NULL) {
114 0 : SPDK_ERRLOG("could not allocate rpc_blobfs_detect request.\n");
115 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
116 0 : return;
117 : }
118 :
119 0 : if (spdk_json_decode_object(params, rpc_blobfs_detect_decoders,
120 : SPDK_COUNTOF(rpc_blobfs_detect_decoders),
121 : req)) {
122 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
123 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
124 : "spdk_json_decode_object failed");
125 :
126 0 : free_rpc_blobfs_detect(req);
127 :
128 0 : return;
129 : }
130 :
131 0 : req->request = request;
132 0 : spdk_blobfs_bdev_detect(req->bdev_name, _rpc_blobfs_detect_done, req);
133 : }
134 :
135 0 : 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 0 : free_rpc_blobfs_create(struct rpc_blobfs_create *req)
146 : {
147 0 : free(req->bdev_name);
148 0 : free(req);
149 0 : }
150 :
151 : static int
152 0 : rpc_decode_cluster_sz(const struct spdk_json_val *val, void *out)
153 : {
154 0 : uint64_t *cluster_sz = out;
155 0 : char *sz_str = NULL;
156 0 : bool has_prefix;
157 : int rc;
158 :
159 0 : rc = spdk_json_decode_string(val, &sz_str);
160 0 : if (rc) {
161 0 : SPDK_NOTICELOG("Invalid parameter value: cluster_sz\n");
162 0 : return -EINVAL;
163 : }
164 :
165 0 : rc = spdk_parse_capacity(sz_str, cluster_sz, &has_prefix);
166 0 : free(sz_str);
167 :
168 0 : if (rc || *cluster_sz % PAGE_SIZE != 0 || *cluster_sz < MIN_CLUSTER_SZ) {
169 0 : SPDK_NOTICELOG("Invalid parameter value: cluster_sz\n");
170 0 : return -EINVAL;
171 : }
172 :
173 0 : SPDK_DEBUGLOG(blobfs_bdev_rpc, "cluster_sz of blobfs: %" PRId64 "\n", *cluster_sz);
174 0 : 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 0 : _rpc_blobfs_create_done(void *cb_arg, int fserrno)
184 : {
185 0 : struct rpc_blobfs_create *req = cb_arg;
186 :
187 0 : if (fserrno != 0) {
188 0 : spdk_jsonrpc_send_error_response(req->request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR,
189 : spdk_strerror(-fserrno));
190 :
191 0 : return;
192 : }
193 :
194 0 : spdk_jsonrpc_send_bool_response(req->request, true);
195 :
196 0 : free_rpc_blobfs_create(req);
197 : }
198 :
199 : static void
200 0 : rpc_blobfs_create(struct spdk_jsonrpc_request *request,
201 : const struct spdk_json_val *params)
202 : {
203 : struct rpc_blobfs_create *req;
204 :
205 0 : req = calloc(1, sizeof(*req));
206 0 : if (req == NULL) {
207 0 : SPDK_ERRLOG("could not allocate rpc_blobfs_create request.\n");
208 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INTERNAL_ERROR, "Out of memory");
209 0 : return;
210 : }
211 :
212 0 : if (spdk_json_decode_object(params, rpc_blobfs_create_decoders,
213 : SPDK_COUNTOF(rpc_blobfs_create_decoders),
214 : req)) {
215 0 : SPDK_ERRLOG("spdk_json_decode_object failed\n");
216 0 : spdk_jsonrpc_send_error_response(request, SPDK_JSONRPC_ERROR_INVALID_PARAMS,
217 : "spdk_json_decode_object failed");
218 :
219 0 : free_rpc_blobfs_create(req);
220 :
221 0 : return;
222 : }
223 :
224 0 : req->request = request;
225 0 : spdk_blobfs_bdev_create(req->bdev_name, req->cluster_sz, _rpc_blobfs_create_done, req);
226 : }
227 :
228 0 : SPDK_RPC_REGISTER("blobfs_create", rpc_blobfs_create, SPDK_RPC_RUNTIME)
229 :
230 0 : 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
|