]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/module/blobfs/bdev/blobfs_bdev.c
update source to Ceph Pacific 16.2.2
[ceph.git] / ceph / src / spdk / module / blobfs / bdev / blobfs_bdev.c
CommitLineData
f67539c2
TL
1/*-
2 * BSD LICENSE
3 *
4 * Copyright (c) Intel Corporation.
5 * 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/stdinc.h"
35#include "spdk/blobfs.h"
36#include "spdk/bdev.h"
37#include "spdk/bdev_module.h"
38#include "spdk/event.h"
39#include "spdk/blob_bdev.h"
40#include "spdk/blobfs_bdev.h"
41#include "spdk/log.h"
42#include "spdk/string.h"
43#include "spdk/rpc.h"
44#include "spdk/util.h"
45
46#include "spdk_internal/log.h"
47
48#include "blobfs_fuse.h"
49
50/* Dummy bdev module used to to claim bdevs. */
51static struct spdk_bdev_module blobfs_bdev_module = {
52 .name = "blobfs",
53};
54
55static void
56blobfs_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
57 void *event_ctx)
58{
59 SPDK_WARNLOG("Async event(%d) is triggered in bdev %s\n", type, spdk_bdev_get_name(bdev));
60}
61
62struct blobfs_bdev_operation_ctx {
63 const char *bdev_name;
64 struct spdk_filesystem *fs;
65
66 /* If cb_fn is already called in other function, not _blobfs_bdev_unload_cb.
67 * cb_fn should be set NULL after its being called, in order to avoid repeated
68 * calling in _blobfs_bdev_unload_cb.
69 */
70 spdk_blobfs_bdev_op_complete cb_fn;
71 void *cb_arg;
72
73 /* Variables for mount operation */
74 const char *mountpoint;
75 struct spdk_thread *fs_loading_thread;
76
77 /* Used in bdev_event_cb to do some proper operations on blobfs_fuse for
78 * asynchronous event of the backend bdev.
79 */
80 struct spdk_blobfs_fuse *bfuse;
81};
82
83static void
84_blobfs_bdev_unload_cb(void *_ctx, int fserrno)
85{
86 struct blobfs_bdev_operation_ctx *ctx = _ctx;
87
88 if (fserrno) {
89 SPDK_ERRLOG("Failed to unload blobfs on bdev %s: errno %d\n", ctx->bdev_name, fserrno);
90 }
91
92 if (ctx->cb_fn) {
93 ctx->cb_fn(ctx->cb_arg, fserrno);
94 }
95
96 free(ctx);
97}
98
99static void
100blobfs_bdev_unload(void *_ctx)
101{
102 struct blobfs_bdev_operation_ctx *ctx = _ctx;
103
104 spdk_fs_unload(ctx->fs, _blobfs_bdev_unload_cb, ctx);
105}
106
107static void
108blobfs_bdev_load_cb_to_unload(void *_ctx, struct spdk_filesystem *fs, int fserrno)
109{
110 struct blobfs_bdev_operation_ctx *ctx = _ctx;
111
112 if (fserrno) {
113 ctx->cb_fn(ctx->cb_arg, fserrno);
114 free(ctx);
115 return;
116 }
117
118 ctx->fs = fs;
119 spdk_thread_send_msg(spdk_get_thread(), blobfs_bdev_unload, ctx);
120}
121
122void
123spdk_blobfs_bdev_detect(const char *bdev_name,
124 spdk_blobfs_bdev_op_complete cb_fn, void *cb_arg)
125{
126 struct blobfs_bdev_operation_ctx *ctx;
127 struct spdk_bs_dev *bs_dev;
128 struct spdk_bdev_desc *desc;
129 int rc;
130
131 ctx = calloc(1, sizeof(*ctx));
132 if (ctx == NULL) {
133 SPDK_ERRLOG("Failed to allocate ctx.\n");
134 cb_fn(cb_arg, -ENOMEM);
135
136 return;
137 }
138
139 ctx->bdev_name = bdev_name;
140 ctx->cb_fn = cb_fn;
141 ctx->cb_arg = cb_arg;
142
143 rc = spdk_bdev_open_ext(bdev_name, true, blobfs_bdev_event_cb, NULL, &desc);
144 if (rc != 0) {
145 SPDK_INFOLOG(SPDK_LOG_BLOBFS_BDEV, "Failed to open bdev(%s): %s\n", ctx->bdev_name,
146 spdk_strerror(rc));
147
148 goto invalid;
149 }
150
151 bs_dev = spdk_bdev_create_bs_dev_from_desc(desc);
152 if (bs_dev == NULL) {
153 SPDK_INFOLOG(SPDK_LOG_BLOBFS_BDEV, "Failed to create a blobstore block device from bdev desc");
154 rc = -ENOMEM;
155 spdk_bdev_close(desc);
156
157 goto invalid;
158 }
159
160 spdk_fs_load(bs_dev, NULL, blobfs_bdev_load_cb_to_unload, ctx);
161
162 return;
163
164invalid:
165 free(ctx);
166
167 cb_fn(cb_arg, rc);
168}
169
170void
171spdk_blobfs_bdev_create(const char *bdev_name, uint32_t cluster_sz,
172 spdk_blobfs_bdev_op_complete cb_fn, void *cb_arg)
173{
174 struct blobfs_bdev_operation_ctx *ctx;
175 struct spdk_blobfs_opts blobfs_opt;
176 struct spdk_bs_dev *bs_dev;
177 struct spdk_bdev_desc *desc;
178 int rc;
179
180 ctx = calloc(1, sizeof(*ctx));
181 if (ctx == NULL) {
182 SPDK_ERRLOG("Failed to allocate ctx.\n");
183 cb_fn(cb_arg, -ENOMEM);
184
185 return;
186 }
187
188 ctx->bdev_name = bdev_name;
189 ctx->cb_fn = cb_fn;
190 ctx->cb_arg = cb_arg;
191
192 /* Creation requires WRITE operation */
193 rc = spdk_bdev_open_ext(bdev_name, true, blobfs_bdev_event_cb, NULL, &desc);
194 if (rc != 0) {
195 SPDK_INFOLOG(SPDK_LOG_BLOBFS_BDEV, "Failed to open bdev(%s): %s\n", ctx->bdev_name,
196 spdk_strerror(rc));
197
198 goto invalid;
199 }
200
201 bs_dev = spdk_bdev_create_bs_dev_from_desc(desc);
202 if (bs_dev == NULL) {
203 SPDK_INFOLOG(SPDK_LOG_BLOBFS_BDEV, "Failed to create a blobstore block device from bdev desc\n");
204 rc = -ENOMEM;
205 spdk_bdev_close(desc);
206
207 goto invalid;
208 }
209
210 rc = spdk_bs_bdev_claim(bs_dev, &blobfs_bdev_module);
211 if (rc) {
212 SPDK_INFOLOG(SPDK_LOG_BLOBFS_BDEV, "Blobfs base bdev already claimed by another bdev\n");
213 bs_dev->destroy(bs_dev);
214
215 goto invalid;
216 }
217
218 spdk_fs_opts_init(&blobfs_opt);
219 if (cluster_sz) {
220 blobfs_opt.cluster_sz = cluster_sz;
221 }
222
223 spdk_fs_init(bs_dev, &blobfs_opt, NULL, blobfs_bdev_load_cb_to_unload, ctx);
224
225 return;
226
227invalid:
228 free(ctx);
229
230 cb_fn(cb_arg, rc);
231}
232SPDK_LOG_REGISTER_COMPONENT("blobfs_bdev", SPDK_LOG_BLOBFS_BDEV)
233#ifdef SPDK_CONFIG_FUSE
234
235static void
236blobfs_bdev_unmount(void *arg)
237{
238 struct blobfs_bdev_operation_ctx *ctx = arg;
239
240 /* Keep blobfs unloaded in a same spdk thread with spdk_fs_load */
241 spdk_thread_send_msg(ctx->fs_loading_thread, blobfs_bdev_unload, ctx);
242}
243
244static void
245_blobfs_bdev_mount_fuse_start(void *_ctx)
246{
247 struct blobfs_bdev_operation_ctx *ctx = _ctx;
248 spdk_blobfs_bdev_op_complete cb_fn = ctx->cb_fn;
249 int rc;
250
251 /* Since function of ctx->cb_fn will be called in this function, set
252 * ctx->cb_fn to be NULL, in order to avoid repeated calling in unload_cb.
253 */
254 ctx->cb_fn = NULL;
255
256 rc = blobfs_fuse_start(ctx->bdev_name, ctx->mountpoint, ctx->fs,
257 blobfs_bdev_unmount, ctx, &ctx->bfuse);
258 if (rc != 0) {
259 SPDK_ERRLOG("Failed to mount blobfs on bdev %s to %s\n", ctx->bdev_name, ctx->mountpoint);
260
261 /* Return failure state back */
262 cb_fn(ctx->cb_arg, rc);
263
264 blobfs_bdev_unmount(ctx);
265
266 return;
267 }
268
269 cb_fn(ctx->cb_arg, 0);
270}
271
272static void
273_blobfs_bdev_mount_load_cb(void *_ctx, struct spdk_filesystem *fs, int fserrno)
274{
275 struct blobfs_bdev_operation_ctx *ctx = _ctx;
276
277 if (fserrno) {
278 SPDK_ERRLOG("Failed to load blobfs on bdev %s: errno %d\n", ctx->bdev_name, fserrno);
279
280 ctx->cb_fn(ctx->cb_arg, fserrno);
281 free(ctx);
282 return;
283 }
284
285 ctx->fs = fs;
286 ctx->fs_loading_thread = spdk_get_thread();
287
288 spdk_thread_send_msg(spdk_get_thread(), _blobfs_bdev_mount_fuse_start, ctx);
289}
290
291static void
292blobfs_bdev_fuse_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev,
293 void *event_ctx)
294{
295 struct blobfs_bdev_operation_ctx *ctx = event_ctx;
296
297 SPDK_WARNLOG("Async event(%d) is triggered in bdev %s\n", type, spdk_bdev_get_name(bdev));
298
299 if (type == SPDK_BDEV_EVENT_REMOVE) {
300 blobfs_fuse_stop(ctx->bfuse);
301 }
302}
303
304void
305spdk_blobfs_bdev_mount(const char *bdev_name, const char *mountpoint,
306 spdk_blobfs_bdev_op_complete cb_fn, void *cb_arg)
307{
308 struct blobfs_bdev_operation_ctx *ctx;
309 struct spdk_bs_dev *bs_dev;
310 struct spdk_bdev_desc *desc;
311 int rc;
312
313 ctx = calloc(1, sizeof(*ctx));
314 if (ctx == NULL) {
315 SPDK_ERRLOG("Failed to allocate ctx.\n");
316 cb_fn(cb_arg, -ENOMEM);
317
318 return;
319 }
320
321 ctx->bdev_name = bdev_name;
322 ctx->mountpoint = mountpoint;
323 ctx->cb_fn = cb_fn;
324 ctx->cb_arg = cb_arg;
325
326 rc = spdk_bdev_open_ext(bdev_name, true, blobfs_bdev_fuse_event_cb, ctx, &desc);
327 if (rc != 0) {
328 SPDK_INFOLOG(SPDK_LOG_BLOBFS_BDEV, "Failed to open bdev(%s): %s\n", ctx->bdev_name,
329 spdk_strerror(rc));
330
331 goto invalid;
332 }
333
334 bs_dev = spdk_bdev_create_bs_dev_from_desc(desc);
335 if (bs_dev == NULL) {
336 SPDK_INFOLOG(SPDK_LOG_BLOBFS_BDEV, "Failed to create a blobstore block device from bdev desc");
337 rc = -ENOMEM;
338 spdk_bdev_close(desc);
339
340 goto invalid;
341 }
342
343 rc = spdk_bs_bdev_claim(bs_dev, &blobfs_bdev_module);
344 if (rc != 0) {
345 SPDK_INFOLOG(SPDK_LOG_BLOBFS_BDEV, "Blobfs base bdev already claimed by another bdev\n");
346 bs_dev->destroy(bs_dev);
347
348 goto invalid;
349 }
350
351 spdk_fs_load(bs_dev, blobfs_fuse_send_request, _blobfs_bdev_mount_load_cb, ctx);
352
353 return;
354
355invalid:
356 free(ctx);
357
358 cb_fn(cb_arg, rc);
359}
360
361#endif