]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/lib/lvol/lvol.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / lib / lvol / lvol.c
CommitLineData
11fdf7f2
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_internal/lvolstore.h"
35#include "spdk_internal/log.h"
36#include "spdk/string.h"
37#include "spdk/thread.h"
38#include "spdk/blob_bdev.h"
39#include "spdk/util.h"
40
41/* Default blob channel opts for lvol */
42#define SPDK_LVOL_BLOB_OPTS_CHANNEL_OPS 512
43
44#define LVOL_NAME "name"
45
46SPDK_LOG_REGISTER_COMPONENT("lvol", SPDK_LOG_LVOL)
47
48static TAILQ_HEAD(, spdk_lvol_store) g_lvol_stores = TAILQ_HEAD_INITIALIZER(g_lvol_stores);
49static pthread_mutex_t g_lvol_stores_mutex = PTHREAD_MUTEX_INITIALIZER;
50
11fdf7f2
TL
51static int
52_spdk_add_lvs_to_list(struct spdk_lvol_store *lvs)
53{
54 struct spdk_lvol_store *tmp;
55 bool name_conflict = false;
56
57 pthread_mutex_lock(&g_lvol_stores_mutex);
58 TAILQ_FOREACH(tmp, &g_lvol_stores, link) {
59 if (!strncmp(lvs->name, tmp->name, SPDK_LVS_NAME_MAX)) {
60 name_conflict = true;
61 break;
62 }
63 }
64 if (!name_conflict) {
65 lvs->on_list = true;
66 TAILQ_INSERT_TAIL(&g_lvol_stores, lvs, link);
67 }
68 pthread_mutex_unlock(&g_lvol_stores_mutex);
69
70 return name_conflict ? -1 : 0;
71}
72
73static void
74_spdk_lvs_free(struct spdk_lvol_store *lvs)
75{
9f95a23c 76 pthread_mutex_lock(&g_lvol_stores_mutex);
11fdf7f2
TL
77 if (lvs->on_list) {
78 TAILQ_REMOVE(&g_lvol_stores, lvs, link);
79 }
9f95a23c
TL
80 pthread_mutex_unlock(&g_lvol_stores_mutex);
81
11fdf7f2
TL
82 free(lvs);
83}
84
85static void
86_spdk_lvol_free(struct spdk_lvol *lvol)
87{
11fdf7f2
TL
88 free(lvol);
89}
90
91static void
92_spdk_lvol_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
93{
94 struct spdk_lvol_with_handle_req *req = cb_arg;
95 struct spdk_lvol *lvol = req->lvol;
96
97 if (lvolerrno != 0) {
98 SPDK_INFOLOG(SPDK_LOG_LVOL, "Failed to open lvol %s\n", lvol->unique_id);
99 goto end;
100 }
101
102 lvol->ref_count++;
103 lvol->blob = blob;
104end:
105 req->cb_fn(req->cb_arg, lvol, lvolerrno);
106 free(req);
107}
108
109void
110spdk_lvol_open(struct spdk_lvol *lvol, spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
111{
112 struct spdk_lvol_with_handle_req *req;
9f95a23c 113 struct spdk_blob_open_opts opts;
11fdf7f2
TL
114
115 assert(cb_fn != NULL);
116
117 if (lvol == NULL) {
118 SPDK_ERRLOG("lvol does not exist\n");
119 cb_fn(cb_arg, NULL, -ENODEV);
120 return;
121 }
122
123 if (lvol->action_in_progress == true) {
124 SPDK_ERRLOG("Cannot open lvol - operations on lvol pending\n");
125 cb_fn(cb_arg, lvol, -EBUSY);
126 return;
127 }
128
129 if (lvol->ref_count > 0) {
130 lvol->ref_count++;
131 cb_fn(cb_arg, lvol, 0);
132 return;
133 }
134
135 req = calloc(1, sizeof(*req));
136 if (req == NULL) {
137 SPDK_ERRLOG("Cannot alloc memory for request structure\n");
138 cb_fn(cb_arg, NULL, -ENOMEM);
139 return;
140 }
141
142 req->cb_fn = cb_fn;
143 req->cb_arg = cb_arg;
144 req->lvol = lvol;
145
9f95a23c
TL
146 spdk_blob_open_opts_init(&opts);
147 opts.clear_method = lvol->clear_method;
148
149 spdk_bs_open_blob_ext(lvol->lvol_store->blobstore, lvol->blob_id, &opts, _spdk_lvol_open_cb, req);
11fdf7f2
TL
150}
151
152static void
153_spdk_bs_unload_with_error_cb(void *cb_arg, int lvolerrno)
154{
155 struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)cb_arg;
156
157 req->cb_fn(req->cb_arg, NULL, req->lvserrno);
158 free(req);
159}
160
161static void
162_spdk_load_next_lvol(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
163{
164 struct spdk_lvs_with_handle_req *req = cb_arg;
165 struct spdk_lvol_store *lvs = req->lvol_store;
166 struct spdk_blob_store *bs = lvs->blobstore;
167 struct spdk_lvol *lvol, *tmp;
168 spdk_blob_id blob_id;
11fdf7f2 169 const char *attr;
9f95a23c 170 const enum blob_clear_method *clear_method;
11fdf7f2
TL
171 size_t value_len;
172 int rc;
173
174 if (lvolerrno == -ENOENT) {
175 /* Finished iterating */
176 req->cb_fn(req->cb_arg, lvs, 0);
177 free(req);
178 return;
179 } else if (lvolerrno < 0) {
180 SPDK_ERRLOG("Failed to fetch blobs list\n");
181 req->lvserrno = lvolerrno;
182 goto invalid;
183 }
184
185 blob_id = spdk_blob_get_id(blob);
186
187 if (blob_id == lvs->super_blob_id) {
188 SPDK_INFOLOG(SPDK_LOG_LVOL, "found superblob %"PRIu64"\n", (uint64_t)blob_id);
189 spdk_bs_iter_next(bs, blob, _spdk_load_next_lvol, req);
190 return;
191 }
192
193 lvol = calloc(1, sizeof(*lvol));
194 if (!lvol) {
195 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
196 req->lvserrno = -ENOMEM;
197 goto invalid;
198 }
199
200 lvol->blob = blob;
201 lvol->blob_id = blob_id;
202 lvol->lvol_store = lvs;
203
204 rc = spdk_blob_get_xattr_value(blob, "uuid", (const void **)&attr, &value_len);
205 if (rc != 0 || value_len != SPDK_UUID_STRING_LEN || attr[SPDK_UUID_STRING_LEN - 1] != '\0' ||
206 spdk_uuid_parse(&lvol->uuid, attr) != 0) {
207 SPDK_INFOLOG(SPDK_LOG_LVOL, "Missing or corrupt lvol uuid\n");
208 memset(&lvol->uuid, 0, sizeof(lvol->uuid));
209 }
210 spdk_uuid_fmt_lower(lvol->uuid_str, sizeof(lvol->uuid_str), &lvol->uuid);
211
212 if (!spdk_mem_all_zero(&lvol->uuid, sizeof(lvol->uuid))) {
9f95a23c 213 snprintf(lvol->unique_id, sizeof(lvol->unique_id), "%s", lvol->uuid_str);
11fdf7f2 214 } else {
9f95a23c
TL
215 spdk_uuid_fmt_lower(lvol->unique_id, sizeof(lvol->unique_id), &lvol->lvol_store->uuid);
216 value_len = strlen(lvol->unique_id);
217 snprintf(lvol->unique_id + value_len, sizeof(lvol->unique_id) - value_len, "_%"PRIu64,
218 (uint64_t)blob_id);
11fdf7f2
TL
219 }
220
221 rc = spdk_blob_get_xattr_value(blob, "name", (const void **)&attr, &value_len);
222 if (rc != 0 || value_len > SPDK_LVOL_NAME_MAX) {
223 SPDK_ERRLOG("Cannot assign lvol name\n");
224 _spdk_lvol_free(lvol);
225 req->lvserrno = -EINVAL;
226 goto invalid;
227 }
228
9f95a23c
TL
229 rc = spdk_blob_get_xattr_value(blob, "clear_method", (const void **)&clear_method, &value_len);
230 if (rc != 0) {
231 lvol->clear_method = BLOB_CLEAR_WITH_DEFAULT;
232 } else {
233 lvol->clear_method = *clear_method;
234 }
235
11fdf7f2
TL
236 snprintf(lvol->name, sizeof(lvol->name), "%s", attr);
237
238 TAILQ_INSERT_TAIL(&lvs->lvols, lvol, link);
239
240 lvs->lvol_count++;
241
242 SPDK_INFOLOG(SPDK_LOG_LVOL, "added lvol %s (%s)\n", lvol->unique_id, lvol->uuid_str);
243
244 spdk_bs_iter_next(bs, blob, _spdk_load_next_lvol, req);
245
246 return;
247
248invalid:
249 TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
250 TAILQ_REMOVE(&lvs->lvols, lvol, link);
11fdf7f2
TL
251 free(lvol);
252 }
253
254 _spdk_lvs_free(lvs);
255 spdk_bs_unload(bs, _spdk_bs_unload_with_error_cb, req);
256}
257
258static void
259_spdk_close_super_cb(void *cb_arg, int lvolerrno)
260{
261 struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)cb_arg;
262 struct spdk_lvol_store *lvs = req->lvol_store;
263 struct spdk_blob_store *bs = lvs->blobstore;
264
265 if (lvolerrno != 0) {
266 SPDK_INFOLOG(SPDK_LOG_LVOL, "Could not close super blob\n");
267 _spdk_lvs_free(lvs);
268 req->lvserrno = -ENODEV;
269 spdk_bs_unload(bs, _spdk_bs_unload_with_error_cb, req);
270 return;
271 }
272
273 /* Start loading lvols */
274 spdk_bs_iter_first(lvs->blobstore, _spdk_load_next_lvol, req);
275}
276
277static void
278_spdk_close_super_blob_with_error_cb(void *cb_arg, int lvolerrno)
279{
280 struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)cb_arg;
281 struct spdk_lvol_store *lvs = req->lvol_store;
282 struct spdk_blob_store *bs = lvs->blobstore;
283
284 _spdk_lvs_free(lvs);
285
286 spdk_bs_unload(bs, _spdk_bs_unload_with_error_cb, req);
287}
288
289static void
290_spdk_lvs_read_uuid(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
291{
292 struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)cb_arg;
293 struct spdk_lvol_store *lvs = req->lvol_store;
294 struct spdk_blob_store *bs = lvs->blobstore;
295 const char *attr;
296 size_t value_len;
297 int rc;
298
299 if (lvolerrno != 0) {
300 SPDK_INFOLOG(SPDK_LOG_LVOL, "Could not open super blob\n");
301 _spdk_lvs_free(lvs);
302 req->lvserrno = -ENODEV;
303 spdk_bs_unload(bs, _spdk_bs_unload_with_error_cb, req);
304 return;
305 }
306
307 rc = spdk_blob_get_xattr_value(blob, "uuid", (const void **)&attr, &value_len);
308 if (rc != 0 || value_len != SPDK_UUID_STRING_LEN || attr[SPDK_UUID_STRING_LEN - 1] != '\0') {
309 SPDK_INFOLOG(SPDK_LOG_LVOL, "missing or incorrect UUID\n");
310 req->lvserrno = -EINVAL;
311 spdk_blob_close(blob, _spdk_close_super_blob_with_error_cb, req);
312 return;
313 }
314
315 if (spdk_uuid_parse(&lvs->uuid, attr)) {
316 SPDK_INFOLOG(SPDK_LOG_LVOL, "incorrect UUID '%s'\n", attr);
317 req->lvserrno = -EINVAL;
318 spdk_blob_close(blob, _spdk_close_super_blob_with_error_cb, req);
319 return;
320 }
321
322 rc = spdk_blob_get_xattr_value(blob, "name", (const void **)&attr, &value_len);
323 if (rc != 0 || value_len > SPDK_LVS_NAME_MAX) {
324 SPDK_INFOLOG(SPDK_LOG_LVOL, "missing or invalid name\n");
325 req->lvserrno = -EINVAL;
326 spdk_blob_close(blob, _spdk_close_super_blob_with_error_cb, req);
327 return;
328 }
329
330 snprintf(lvs->name, sizeof(lvs->name), "%s", attr);
331
332 rc = _spdk_add_lvs_to_list(lvs);
333 if (rc) {
334 SPDK_INFOLOG(SPDK_LOG_LVOL, "lvolstore with name %s already exists\n", lvs->name);
335 req->lvserrno = -EEXIST;
336 spdk_blob_close(blob, _spdk_close_super_blob_with_error_cb, req);
337 return;
338 }
339
340 lvs->super_blob_id = spdk_blob_get_id(blob);
341
342 spdk_blob_close(blob, _spdk_close_super_cb, req);
343}
344
345static void
346_spdk_lvs_open_super(void *cb_arg, spdk_blob_id blobid, int lvolerrno)
347{
348 struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)cb_arg;
349 struct spdk_lvol_store *lvs = req->lvol_store;
350 struct spdk_blob_store *bs = lvs->blobstore;
351
352 if (lvolerrno != 0) {
353 SPDK_INFOLOG(SPDK_LOG_LVOL, "Super blob not found\n");
354 _spdk_lvs_free(lvs);
355 req->lvserrno = -ENODEV;
356 spdk_bs_unload(bs, _spdk_bs_unload_with_error_cb, req);
357 return;
358 }
359
360 spdk_bs_open_blob(bs, blobid, _spdk_lvs_read_uuid, req);
361}
362
363static void
364_spdk_lvs_load_cb(void *cb_arg, struct spdk_blob_store *bs, int lvolerrno)
365{
366 struct spdk_lvs_with_handle_req *req = (struct spdk_lvs_with_handle_req *)cb_arg;
367 struct spdk_lvol_store *lvs;
368
369 if (lvolerrno != 0) {
370 req->cb_fn(req->cb_arg, NULL, lvolerrno);
371 free(req);
372 return;
373 }
374
375 lvs = calloc(1, sizeof(*lvs));
376 if (lvs == NULL) {
377 SPDK_ERRLOG("Cannot alloc memory for lvol store\n");
378 spdk_bs_unload(bs, _spdk_bs_unload_with_error_cb, req);
379 return;
380 }
381
382 lvs->blobstore = bs;
383 lvs->bs_dev = req->bs_dev;
384 TAILQ_INIT(&lvs->lvols);
385 TAILQ_INIT(&lvs->pending_lvols);
386
387 req->lvol_store = lvs;
388
389 spdk_bs_get_super(bs, _spdk_lvs_open_super, req);
390}
391
392static void
393spdk_lvs_bs_opts_init(struct spdk_bs_opts *opts)
394{
395 spdk_bs_opts_init(opts);
396 opts->max_channel_ops = SPDK_LVOL_BLOB_OPTS_CHANNEL_OPS;
397}
398
399void
400spdk_lvs_load(struct spdk_bs_dev *bs_dev, spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
401{
402 struct spdk_lvs_with_handle_req *req;
403 struct spdk_bs_opts opts = {};
404
405 assert(cb_fn != NULL);
406
407 if (bs_dev == NULL) {
408 SPDK_ERRLOG("Blobstore device does not exist\n");
409 cb_fn(cb_arg, NULL, -ENODEV);
410 return;
411 }
412
413 req = calloc(1, sizeof(*req));
414 if (req == NULL) {
415 SPDK_ERRLOG("Cannot alloc memory for request structure\n");
416 cb_fn(cb_arg, NULL, -ENOMEM);
417 return;
418 }
419
420 req->cb_fn = cb_fn;
421 req->cb_arg = cb_arg;
422 req->bs_dev = bs_dev;
423
424 spdk_lvs_bs_opts_init(&opts);
425 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "LVOLSTORE");
426
427 spdk_bs_load(bs_dev, &opts, _spdk_lvs_load_cb, req);
428}
429
430static void
431_spdk_super_create_close_cb(void *cb_arg, int lvolerrno)
432{
433 struct spdk_lvs_with_handle_req *req = cb_arg;
434 struct spdk_lvol_store *lvs = req->lvol_store;
435
436 if (lvolerrno < 0) {
437 SPDK_ERRLOG("Lvol store init failed: could not close super blob\n");
438 req->cb_fn(req->cb_arg, NULL, lvolerrno);
439 _spdk_lvs_free(lvs);
440 free(req);
441 return;
442 }
443
444 req->cb_fn(req->cb_arg, lvs, lvolerrno);
445 free(req);
446}
447
448static void
449_spdk_super_blob_set_cb(void *cb_arg, int lvolerrno)
450{
451 struct spdk_lvs_with_handle_req *req = cb_arg;
452 struct spdk_lvol_store *lvs = req->lvol_store;
453 struct spdk_blob *blob = lvs->super_blob;
454
455 if (lvolerrno < 0) {
456 req->cb_fn(req->cb_arg, NULL, lvolerrno);
457 SPDK_ERRLOG("Lvol store init failed: could not set uuid for super blob\n");
458 _spdk_lvs_free(lvs);
459 free(req);
460 return;
461 }
462
463 spdk_blob_close(blob, _spdk_super_create_close_cb, req);
464}
465
466static void
467_spdk_super_blob_init_cb(void *cb_arg, int lvolerrno)
468{
469 struct spdk_lvs_with_handle_req *req = cb_arg;
470 struct spdk_lvol_store *lvs = req->lvol_store;
471 struct spdk_blob *blob = lvs->super_blob;
472 char uuid[SPDK_UUID_STRING_LEN];
473
474 if (lvolerrno < 0) {
475 req->cb_fn(req->cb_arg, NULL, lvolerrno);
476 SPDK_ERRLOG("Lvol store init failed: could not set super blob\n");
477 _spdk_lvs_free(lvs);
478 free(req);
479 return;
480 }
481
482 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &lvs->uuid);
483
484 spdk_blob_set_xattr(blob, "uuid", uuid, sizeof(uuid));
485 spdk_blob_set_xattr(blob, "name", lvs->name, strnlen(lvs->name, SPDK_LVS_NAME_MAX) + 1);
486 spdk_blob_sync_md(blob, _spdk_super_blob_set_cb, req);
487}
488
489static void
490_spdk_super_blob_create_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
491{
492 struct spdk_lvs_with_handle_req *req = cb_arg;
493 struct spdk_lvol_store *lvs = req->lvol_store;
494
495 if (lvolerrno < 0) {
496 req->cb_fn(req->cb_arg, NULL, lvolerrno);
497 SPDK_ERRLOG("Lvol store init failed: could not open super blob\n");
498 _spdk_lvs_free(lvs);
499 free(req);
500 return;
501 }
502
503 lvs->super_blob = blob;
504 lvs->super_blob_id = spdk_blob_get_id(blob);
505
506 spdk_bs_set_super(lvs->blobstore, lvs->super_blob_id, _spdk_super_blob_init_cb, req);
507}
508
509static void
510_spdk_super_blob_create_cb(void *cb_arg, spdk_blob_id blobid, int lvolerrno)
511{
512 struct spdk_lvs_with_handle_req *req = cb_arg;
513 struct spdk_lvol_store *lvs = req->lvol_store;
514 struct spdk_blob_store *bs;
515
516 if (lvolerrno < 0) {
517 req->cb_fn(req->cb_arg, NULL, lvolerrno);
518 SPDK_ERRLOG("Lvol store init failed: could not create super blob\n");
519 _spdk_lvs_free(lvs);
520 free(req);
521 return;
522 }
523
524 bs = req->lvol_store->blobstore;
525
526 spdk_bs_open_blob(bs, blobid, _spdk_super_blob_create_open_cb, req);
527}
528
529static void
530_spdk_lvs_init_cb(void *cb_arg, struct spdk_blob_store *bs, int lvserrno)
531{
532 struct spdk_lvs_with_handle_req *lvs_req = cb_arg;
533 struct spdk_lvol_store *lvs = lvs_req->lvol_store;
534
535 if (lvserrno != 0) {
536 assert(bs == NULL);
537 lvs_req->cb_fn(lvs_req->cb_arg, NULL, lvserrno);
538 SPDK_ERRLOG("Lvol store init failed: could not initialize blobstore\n");
539 _spdk_lvs_free(lvs);
540 free(lvs_req);
541 return;
542 }
543
544 assert(bs != NULL);
545 lvs->blobstore = bs;
546 TAILQ_INIT(&lvs->lvols);
547 TAILQ_INIT(&lvs->pending_lvols);
548
549 SPDK_INFOLOG(SPDK_LOG_LVOL, "Lvol store initialized\n");
550
551 /* create super blob */
552 spdk_bs_create_blob(lvs->blobstore, _spdk_super_blob_create_cb, lvs_req);
553}
554
555void
556spdk_lvs_opts_init(struct spdk_lvs_opts *o)
557{
558 o->cluster_sz = SPDK_LVS_OPTS_CLUSTER_SZ;
9f95a23c 559 o->clear_method = LVS_CLEAR_WITH_UNMAP;
11fdf7f2
TL
560 memset(o->name, 0, sizeof(o->name));
561}
562
563static void
564_spdk_setup_lvs_opts(struct spdk_bs_opts *bs_opts, struct spdk_lvs_opts *o)
565{
566 assert(o != NULL);
567 spdk_lvs_bs_opts_init(bs_opts);
568 bs_opts->cluster_sz = o->cluster_sz;
9f95a23c 569 bs_opts->clear_method = (enum bs_clear_method)o->clear_method;
11fdf7f2
TL
570}
571
572int
573spdk_lvs_init(struct spdk_bs_dev *bs_dev, struct spdk_lvs_opts *o,
574 spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg)
575{
576 struct spdk_lvol_store *lvs;
577 struct spdk_lvs_with_handle_req *lvs_req;
578 struct spdk_bs_opts opts = {};
579 int rc;
580
581 if (bs_dev == NULL) {
582 SPDK_ERRLOG("Blobstore device does not exist\n");
583 return -ENODEV;
584 }
585
586 if (o == NULL) {
587 SPDK_ERRLOG("spdk_lvs_opts not specified\n");
588 return -EINVAL;
589 }
590
591 _spdk_setup_lvs_opts(&opts, o);
592
593 if (strnlen(o->name, SPDK_LVS_NAME_MAX) == SPDK_LVS_NAME_MAX) {
594 SPDK_ERRLOG("Name has no null terminator.\n");
595 return -EINVAL;
596 }
597
598 if (strnlen(o->name, SPDK_LVS_NAME_MAX) == 0) {
599 SPDK_ERRLOG("No name specified.\n");
600 return -EINVAL;
601 }
602
603 lvs = calloc(1, sizeof(*lvs));
604 if (!lvs) {
605 SPDK_ERRLOG("Cannot alloc memory for lvol store base pointer\n");
606 return -ENOMEM;
607 }
608
609 spdk_uuid_generate(&lvs->uuid);
610 snprintf(lvs->name, sizeof(lvs->name), "%s", o->name);
611
612 rc = _spdk_add_lvs_to_list(lvs);
613 if (rc) {
614 SPDK_ERRLOG("lvolstore with name %s already exists\n", lvs->name);
615 _spdk_lvs_free(lvs);
616 return -EEXIST;
617 }
618
619 lvs_req = calloc(1, sizeof(*lvs_req));
620 if (!lvs_req) {
621 _spdk_lvs_free(lvs);
622 SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n");
623 return -ENOMEM;
624 }
625
626 assert(cb_fn != NULL);
627 lvs_req->cb_fn = cb_fn;
628 lvs_req->cb_arg = cb_arg;
629 lvs_req->lvol_store = lvs;
630 lvs->bs_dev = bs_dev;
631 lvs->destruct = false;
632
633 snprintf(opts.bstype.bstype, sizeof(opts.bstype.bstype), "LVOLSTORE");
634
635 SPDK_INFOLOG(SPDK_LOG_LVOL, "Initializing lvol store\n");
636 spdk_bs_init(bs_dev, &opts, _spdk_lvs_init_cb, lvs_req);
637
638 return 0;
639}
640
641static void
642_spdk_lvs_rename_cb(void *cb_arg, int lvolerrno)
643{
644 struct spdk_lvs_req *req = cb_arg;
645
646 if (lvolerrno != 0) {
647 req->lvserrno = lvolerrno;
648 }
649 if (req->lvserrno != 0) {
650 SPDK_ERRLOG("Lvol store rename operation failed\n");
651 /* Lvs renaming failed, so we should 'clear' new_name.
652 * Otherwise it could cause a failure on the next attepmt to change the name to 'new_name' */
653 snprintf(req->lvol_store->new_name,
654 sizeof(req->lvol_store->new_name),
655 "%s", req->lvol_store->name);
656 } else {
657 /* Update lvs name with new_name */
658 snprintf(req->lvol_store->name,
659 sizeof(req->lvol_store->name),
660 "%s", req->lvol_store->new_name);
661 }
662
663 req->cb_fn(req->cb_arg, req->lvserrno);
664 free(req);
665}
666
667static void
668_spdk_lvs_rename_sync_cb(void *cb_arg, int lvolerrno)
669{
670 struct spdk_lvs_req *req = cb_arg;
671 struct spdk_blob *blob = req->lvol_store->super_blob;
672
673 if (lvolerrno < 0) {
674 req->lvserrno = lvolerrno;
675 }
676
677 spdk_blob_close(blob, _spdk_lvs_rename_cb, req);
678}
679
680static void
681_spdk_lvs_rename_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
682{
683 struct spdk_lvs_req *req = cb_arg;
684 int rc;
685
686 if (lvolerrno < 0) {
687 _spdk_lvs_rename_cb(cb_arg, lvolerrno);
688 return;
689 }
690
691 rc = spdk_blob_set_xattr(blob, "name", req->lvol_store->new_name,
692 strlen(req->lvol_store->new_name) + 1);
693 if (rc < 0) {
694 req->lvserrno = rc;
695 _spdk_lvs_rename_sync_cb(req, rc);
696 return;
697 }
698
699 req->lvol_store->super_blob = blob;
700
701 spdk_blob_sync_md(blob, _spdk_lvs_rename_sync_cb, req);
702}
703
704void
705spdk_lvs_rename(struct spdk_lvol_store *lvs, const char *new_name,
706 spdk_lvs_op_complete cb_fn, void *cb_arg)
707{
708 struct spdk_lvs_req *req;
709 struct spdk_lvol_store *tmp;
710
711 /* Check if new name is current lvs name.
712 * If so, return success immediately */
713 if (strncmp(lvs->name, new_name, SPDK_LVS_NAME_MAX) == 0) {
714 cb_fn(cb_arg, 0);
715 return;
716 }
717
718 /* Check if new or new_name is already used in other lvs */
9f95a23c 719 pthread_mutex_lock(&g_lvol_stores_mutex);
11fdf7f2
TL
720 TAILQ_FOREACH(tmp, &g_lvol_stores, link) {
721 if (!strncmp(new_name, tmp->name, SPDK_LVS_NAME_MAX) ||
722 !strncmp(new_name, tmp->new_name, SPDK_LVS_NAME_MAX)) {
9f95a23c 723 pthread_mutex_unlock(&g_lvol_stores_mutex);
11fdf7f2
TL
724 cb_fn(cb_arg, -EEXIST);
725 return;
726 }
727 }
9f95a23c 728 pthread_mutex_unlock(&g_lvol_stores_mutex);
11fdf7f2
TL
729
730 req = calloc(1, sizeof(*req));
731 if (!req) {
732 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
733 cb_fn(cb_arg, -ENOMEM);
734 return;
735 }
736 snprintf(lvs->new_name, sizeof(lvs->new_name), "%s", new_name);
737 req->lvol_store = lvs;
738 req->cb_fn = cb_fn;
739 req->cb_arg = cb_arg;
740
741 spdk_bs_open_blob(lvs->blobstore, lvs->super_blob_id, _spdk_lvs_rename_open_cb, req);
742}
743
744static void
745_lvs_unload_cb(void *cb_arg, int lvserrno)
746{
747 struct spdk_lvs_req *lvs_req = cb_arg;
748
749 SPDK_INFOLOG(SPDK_LOG_LVOL, "Lvol store unloaded\n");
750 assert(lvs_req->cb_fn != NULL);
751 lvs_req->cb_fn(lvs_req->cb_arg, lvserrno);
752 free(lvs_req);
753}
754
755int
756spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
757 void *cb_arg)
758{
759 struct spdk_lvs_req *lvs_req;
760 struct spdk_lvol *lvol, *tmp;
761
762 if (lvs == NULL) {
763 SPDK_ERRLOG("Lvol store is NULL\n");
764 return -ENODEV;
765 }
766
767 TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
768 if (lvol->action_in_progress == true) {
769 SPDK_ERRLOG("Cannot unload lvol store - operations on lvols pending\n");
770 cb_fn(cb_arg, -EBUSY);
771 return -EBUSY;
772 } else if (lvol->ref_count != 0) {
773 SPDK_ERRLOG("Lvols still open on lvol store\n");
774 cb_fn(cb_arg, -EBUSY);
775 return -EBUSY;
776 }
777 }
778
779 TAILQ_FOREACH_SAFE(lvol, &lvs->lvols, link, tmp) {
780 TAILQ_REMOVE(&lvs->lvols, lvol, link);
781 _spdk_lvol_free(lvol);
782 }
783
784 lvs_req = calloc(1, sizeof(*lvs_req));
785 if (!lvs_req) {
786 SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n");
787 return -ENOMEM;
788 }
789
790 lvs_req->cb_fn = cb_fn;
791 lvs_req->cb_arg = cb_arg;
792
793 SPDK_INFOLOG(SPDK_LOG_LVOL, "Unloading lvol store\n");
794 spdk_bs_unload(lvs->blobstore, _lvs_unload_cb, lvs_req);
795 _spdk_lvs_free(lvs);
796
797 return 0;
798}
799
800static void
801_lvs_destroy_cb(void *cb_arg, int lvserrno)
802{
803 struct spdk_lvs_destroy_req *lvs_req = cb_arg;
804
805 SPDK_INFOLOG(SPDK_LOG_LVOL, "Lvol store destroyed\n");
806 assert(lvs_req->cb_fn != NULL);
807 lvs_req->cb_fn(lvs_req->cb_arg, lvserrno);
808 free(lvs_req);
809}
810
811static void
812_lvs_destroy_super_cb(void *cb_arg, int bserrno)
813{
814 struct spdk_lvs_destroy_req *lvs_req = cb_arg;
815 struct spdk_lvol_store *lvs = lvs_req->lvs;
816
817 assert(lvs != NULL);
818
819 SPDK_INFOLOG(SPDK_LOG_LVOL, "Destroying lvol store\n");
820 spdk_bs_destroy(lvs->blobstore, _lvs_destroy_cb, lvs_req);
821 _spdk_lvs_free(lvs);
822}
823
824int
825spdk_lvs_destroy(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn,
826 void *cb_arg)
827{
828 struct spdk_lvs_destroy_req *lvs_req;
829 struct spdk_lvol *iter_lvol, *tmp;
830
831 if (lvs == NULL) {
832 SPDK_ERRLOG("Lvol store is NULL\n");
833 return -ENODEV;
834 }
835
836 TAILQ_FOREACH_SAFE(iter_lvol, &lvs->lvols, link, tmp) {
837 if (iter_lvol->action_in_progress == true) {
838 SPDK_ERRLOG("Cannot destroy lvol store - operations on lvols pending\n");
839 cb_fn(cb_arg, -EBUSY);
840 return -EBUSY;
841 } else if (iter_lvol->ref_count != 0) {
842 SPDK_ERRLOG("Lvols still open on lvol store\n");
843 cb_fn(cb_arg, -EBUSY);
844 return -EBUSY;
845 }
846 }
847
848 TAILQ_FOREACH_SAFE(iter_lvol, &lvs->lvols, link, tmp) {
11fdf7f2
TL
849 free(iter_lvol);
850 }
851
852 lvs_req = calloc(1, sizeof(*lvs_req));
853 if (!lvs_req) {
854 SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n");
855 return -ENOMEM;
856 }
857
858 lvs_req->cb_fn = cb_fn;
859 lvs_req->cb_arg = cb_arg;
860 lvs_req->lvs = lvs;
861
862 SPDK_INFOLOG(SPDK_LOG_LVOL, "Deleting super blob\n");
863 spdk_bs_delete_blob(lvs->blobstore, lvs->super_blob_id, _lvs_destroy_super_cb, lvs_req);
864
865 return 0;
866}
867
868static void
869_spdk_lvol_close_blob_cb(void *cb_arg, int lvolerrno)
870{
871 struct spdk_lvol_req *req = cb_arg;
872 struct spdk_lvol *lvol = req->lvol;
873
874 if (lvolerrno < 0) {
875 SPDK_ERRLOG("Could not close blob on lvol\n");
876 _spdk_lvol_free(lvol);
877 goto end;
878 }
879
880 lvol->ref_count--;
881 lvol->action_in_progress = false;
882 SPDK_INFOLOG(SPDK_LOG_LVOL, "Lvol %s closed\n", lvol->unique_id);
883
884end:
885 req->cb_fn(req->cb_arg, lvolerrno);
886 free(req);
887}
888
889bool
890spdk_lvol_deletable(struct spdk_lvol *lvol)
891{
892 size_t count;
893
894 spdk_blob_get_clones(lvol->lvol_store->blobstore, lvol->blob_id, NULL, &count);
895 return (count == 0);
896}
897
898static void
899_spdk_lvol_delete_blob_cb(void *cb_arg, int lvolerrno)
900{
901 struct spdk_lvol_req *req = cb_arg;
902 struct spdk_lvol *lvol = req->lvol;
903
904 if (lvolerrno < 0) {
9f95a23c
TL
905 SPDK_ERRLOG("Could not remove blob on lvol gracefully - forced removal\n");
906 } else {
907 SPDK_INFOLOG(SPDK_LOG_LVOL, "Lvol %s deleted\n", lvol->unique_id);
11fdf7f2
TL
908 }
909
910 TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link);
11fdf7f2
TL
911 _spdk_lvol_free(lvol);
912 req->cb_fn(req->cb_arg, lvolerrno);
913 free(req);
914}
915
11fdf7f2
TL
916static void
917_spdk_lvol_create_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno)
918{
919 struct spdk_lvol_with_handle_req *req = cb_arg;
920 spdk_blob_id blob_id = spdk_blob_get_id(blob);
921 struct spdk_lvol *lvol = req->lvol;
922
923 TAILQ_REMOVE(&req->lvol->lvol_store->pending_lvols, req->lvol, link);
924
925 if (lvolerrno < 0) {
926 free(lvol);
927 req->cb_fn(req->cb_arg, NULL, lvolerrno);
928 free(req);
929 return;
930 }
931
932 lvol->blob = blob;
933 lvol->blob_id = blob_id;
934
935 TAILQ_INSERT_TAIL(&lvol->lvol_store->lvols, lvol, link);
936
9f95a23c 937 snprintf(lvol->unique_id, sizeof(lvol->unique_id), "%s", lvol->uuid_str);
11fdf7f2
TL
938 lvol->ref_count++;
939
940 assert(req->cb_fn != NULL);
941 req->cb_fn(req->cb_arg, req->lvol, lvolerrno);
942 free(req);
943}
944
945static void
946_spdk_lvol_create_cb(void *cb_arg, spdk_blob_id blobid, int lvolerrno)
947{
948 struct spdk_lvol_with_handle_req *req = cb_arg;
949 struct spdk_blob_store *bs;
9f95a23c 950 struct spdk_blob_open_opts opts;
11fdf7f2
TL
951
952 if (lvolerrno < 0) {
953 TAILQ_REMOVE(&req->lvol->lvol_store->pending_lvols, req->lvol, link);
954 free(req->lvol);
955 assert(req->cb_fn != NULL);
956 req->cb_fn(req->cb_arg, NULL, lvolerrno);
957 free(req);
958 return;
959 }
960
9f95a23c
TL
961 spdk_blob_open_opts_init(&opts);
962 opts.clear_method = req->lvol->clear_method;
11fdf7f2
TL
963 bs = req->lvol->lvol_store->blobstore;
964
9f95a23c 965 spdk_bs_open_blob_ext(bs, blobid, &opts, _spdk_lvol_create_open_cb, req);
11fdf7f2
TL
966}
967
968static void
969spdk_lvol_get_xattr_value(void *xattr_ctx, const char *name,
970 const void **value, size_t *value_len)
971{
972 struct spdk_lvol *lvol = xattr_ctx;
973
974 if (!strcmp(LVOL_NAME, name)) {
975 *value = lvol->name;
976 *value_len = SPDK_LVOL_NAME_MAX;
977 } else if (!strcmp("uuid", name)) {
978 *value = lvol->uuid_str;
979 *value_len = sizeof(lvol->uuid_str);
9f95a23c
TL
980 } else if (!strcmp("clear_method", name)) {
981 *value = &lvol->clear_method;
982 *value_len = sizeof(int);
11fdf7f2
TL
983 }
984}
985
986static int
987_spdk_lvs_verify_lvol_name(struct spdk_lvol_store *lvs, const char *name)
988{
989 struct spdk_lvol *tmp;
990
991 if (name == NULL || strnlen(name, SPDK_LVOL_NAME_MAX) == 0) {
992 SPDK_INFOLOG(SPDK_LOG_LVOL, "lvol name not provided.\n");
993 return -EINVAL;
994 }
995
996 if (strnlen(name, SPDK_LVOL_NAME_MAX) == SPDK_LVOL_NAME_MAX) {
997 SPDK_ERRLOG("Name has no null terminator.\n");
998 return -EINVAL;
999 }
1000
1001 TAILQ_FOREACH(tmp, &lvs->lvols, link) {
1002 if (!strncmp(name, tmp->name, SPDK_LVOL_NAME_MAX)) {
1003 SPDK_ERRLOG("lvol with name %s already exists\n", name);
1004 return -EEXIST;
1005 }
1006 }
1007
1008 TAILQ_FOREACH(tmp, &lvs->pending_lvols, link) {
1009 if (!strncmp(name, tmp->name, SPDK_LVOL_NAME_MAX)) {
1010 SPDK_ERRLOG("lvol with name %s is being already created\n", name);
1011 return -EEXIST;
1012 }
1013 }
1014
1015 return 0;
1016}
1017
1018int
1019spdk_lvol_create(struct spdk_lvol_store *lvs, const char *name, uint64_t sz,
9f95a23c
TL
1020 bool thin_provision, enum lvol_clear_method clear_method, spdk_lvol_op_with_handle_complete cb_fn,
1021 void *cb_arg)
11fdf7f2
TL
1022{
1023 struct spdk_lvol_with_handle_req *req;
1024 struct spdk_blob_store *bs;
1025 struct spdk_lvol *lvol;
1026 struct spdk_blob_opts opts;
1027 uint64_t num_clusters;
9f95a23c 1028 char *xattr_names[] = {LVOL_NAME, "uuid", "clear_method"};
11fdf7f2
TL
1029 int rc;
1030
1031 if (lvs == NULL) {
1032 SPDK_ERRLOG("lvol store does not exist\n");
1033 return -EINVAL;
1034 }
1035
1036 rc = _spdk_lvs_verify_lvol_name(lvs, name);
1037 if (rc < 0) {
1038 return rc;
1039 }
1040
1041 bs = lvs->blobstore;
1042
1043 req = calloc(1, sizeof(*req));
1044 if (!req) {
1045 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
1046 return -ENOMEM;
1047 }
1048 req->cb_fn = cb_fn;
1049 req->cb_arg = cb_arg;
1050
1051 lvol = calloc(1, sizeof(*lvol));
1052 if (!lvol) {
1053 free(req);
1054 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
1055 return -ENOMEM;
1056 }
1057 lvol->lvol_store = lvs;
9f95a23c 1058 num_clusters = spdk_divide_round_up(sz, spdk_bs_get_cluster_size(bs));
11fdf7f2 1059 lvol->thin_provision = thin_provision;
9f95a23c 1060 lvol->clear_method = (enum blob_clear_method)clear_method;
11fdf7f2
TL
1061 snprintf(lvol->name, sizeof(lvol->name), "%s", name);
1062 TAILQ_INSERT_TAIL(&lvol->lvol_store->pending_lvols, lvol, link);
1063 spdk_uuid_generate(&lvol->uuid);
1064 spdk_uuid_fmt_lower(lvol->uuid_str, sizeof(lvol->uuid_str), &lvol->uuid);
1065 req->lvol = lvol;
1066
1067 spdk_blob_opts_init(&opts);
1068 opts.thin_provision = thin_provision;
1069 opts.num_clusters = num_clusters;
1070 opts.xattrs.count = SPDK_COUNTOF(xattr_names);
1071 opts.xattrs.names = xattr_names;
1072 opts.xattrs.ctx = lvol;
1073 opts.xattrs.get_value = spdk_lvol_get_xattr_value;
1074
1075 spdk_bs_create_blob_ext(lvs->blobstore, &opts, _spdk_lvol_create_cb, req);
1076
1077 return 0;
1078}
1079
1080void
1081spdk_lvol_create_snapshot(struct spdk_lvol *origlvol, const char *snapshot_name,
1082 spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
1083{
1084 struct spdk_lvol_store *lvs;
1085 struct spdk_lvol *newlvol;
1086 struct spdk_blob *origblob;
1087 struct spdk_lvol_with_handle_req *req;
1088 struct spdk_blob_xattr_opts snapshot_xattrs;
1089 char *xattr_names[] = {LVOL_NAME, "uuid"};
1090 int rc;
1091
1092 if (origlvol == NULL) {
1093 SPDK_INFOLOG(SPDK_LOG_LVOL, "Lvol not provided.\n");
1094 cb_fn(cb_arg, NULL, -EINVAL);
1095 return;
1096 }
1097
1098 origblob = origlvol->blob;
1099 lvs = origlvol->lvol_store;
1100 if (lvs == NULL) {
1101 SPDK_ERRLOG("lvol store does not exist\n");
1102 cb_fn(cb_arg, NULL, -EINVAL);
1103 return;
1104 }
1105
1106 rc = _spdk_lvs_verify_lvol_name(lvs, snapshot_name);
1107 if (rc < 0) {
1108 cb_fn(cb_arg, NULL, rc);
1109 return;
1110 }
1111
1112 req = calloc(1, sizeof(*req));
1113 if (!req) {
1114 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
1115 cb_fn(cb_arg, NULL, -ENOMEM);
1116 return;
1117 }
1118
1119 newlvol = calloc(1, sizeof(*newlvol));
1120 if (!newlvol) {
1121 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
1122 free(req);
1123 cb_fn(cb_arg, NULL, -ENOMEM);
1124 return;
1125 }
1126
1127 newlvol->lvol_store = origlvol->lvol_store;
1128 snprintf(newlvol->name, sizeof(newlvol->name), "%s", snapshot_name);
1129 TAILQ_INSERT_TAIL(&newlvol->lvol_store->pending_lvols, newlvol, link);
1130 spdk_uuid_generate(&newlvol->uuid);
1131 spdk_uuid_fmt_lower(newlvol->uuid_str, sizeof(newlvol->uuid_str), &newlvol->uuid);
1132 snapshot_xattrs.count = SPDK_COUNTOF(xattr_names);
1133 snapshot_xattrs.ctx = newlvol;
1134 snapshot_xattrs.names = xattr_names;
1135 snapshot_xattrs.get_value = spdk_lvol_get_xattr_value;
1136 req->lvol = newlvol;
1137 req->cb_fn = cb_fn;
1138 req->cb_arg = cb_arg;
1139
1140 spdk_bs_create_snapshot(lvs->blobstore, spdk_blob_get_id(origblob), &snapshot_xattrs,
1141 _spdk_lvol_create_cb, req);
1142}
1143
1144void
1145spdk_lvol_create_clone(struct spdk_lvol *origlvol, const char *clone_name,
1146 spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg)
1147{
1148 struct spdk_lvol *newlvol;
1149 struct spdk_lvol_with_handle_req *req;
1150 struct spdk_lvol_store *lvs;
1151 struct spdk_blob *origblob;
1152 struct spdk_blob_xattr_opts clone_xattrs;
1153 char *xattr_names[] = {LVOL_NAME, "uuid"};
1154 int rc;
1155
1156 if (origlvol == NULL) {
1157 SPDK_INFOLOG(SPDK_LOG_LVOL, "Lvol not provided.\n");
1158 cb_fn(cb_arg, NULL, -EINVAL);
1159 return;
1160 }
1161
1162 origblob = origlvol->blob;
1163 lvs = origlvol->lvol_store;
1164 if (lvs == NULL) {
1165 SPDK_ERRLOG("lvol store does not exist\n");
1166 cb_fn(cb_arg, NULL, -EINVAL);
1167 return;
1168 }
1169
1170 rc = _spdk_lvs_verify_lvol_name(lvs, clone_name);
1171 if (rc < 0) {
1172 cb_fn(cb_arg, NULL, rc);
1173 return;
1174 }
1175
1176 req = calloc(1, sizeof(*req));
1177 if (!req) {
1178 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
1179 cb_fn(cb_arg, NULL, -ENOMEM);
1180 return;
1181 }
1182
1183 newlvol = calloc(1, sizeof(*newlvol));
1184 if (!newlvol) {
1185 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n");
1186 free(req);
1187 cb_fn(cb_arg, NULL, -ENOMEM);
1188 return;
1189 }
1190
1191 newlvol->lvol_store = lvs;
1192 snprintf(newlvol->name, sizeof(newlvol->name), "%s", clone_name);
1193 TAILQ_INSERT_TAIL(&newlvol->lvol_store->pending_lvols, newlvol, link);
1194 spdk_uuid_generate(&newlvol->uuid);
1195 spdk_uuid_fmt_lower(newlvol->uuid_str, sizeof(newlvol->uuid_str), &newlvol->uuid);
1196 clone_xattrs.count = SPDK_COUNTOF(xattr_names);
1197 clone_xattrs.ctx = newlvol;
1198 clone_xattrs.names = xattr_names;
1199 clone_xattrs.get_value = spdk_lvol_get_xattr_value;
1200 req->lvol = newlvol;
1201 req->cb_fn = cb_fn;
1202 req->cb_arg = cb_arg;
1203
1204 spdk_bs_create_clone(lvs->blobstore, spdk_blob_get_id(origblob), &clone_xattrs,
1205 _spdk_lvol_create_cb,
1206 req);
1207}
1208
1209static void
1210_spdk_lvol_resize_done(void *cb_arg, int lvolerrno)
1211{
1212 struct spdk_lvol_req *req = cb_arg;
1213
1214 req->cb_fn(req->cb_arg, lvolerrno);
1215 free(req);
1216}
1217
1218static void
1219_spdk_lvol_blob_resize_cb(void *cb_arg, int bserrno)
1220{
1221 struct spdk_lvol_req *req = cb_arg;
1222 struct spdk_lvol *lvol = req->lvol;
1223
1224 if (bserrno != 0) {
1225 req->cb_fn(req->cb_arg, bserrno);
1226 free(req);
1227 return;
1228 }
1229
1230 spdk_blob_sync_md(lvol->blob, _spdk_lvol_resize_done, req);
1231}
1232
1233void
1234spdk_lvol_resize(struct spdk_lvol *lvol, uint64_t sz,
1235 spdk_lvol_op_complete cb_fn, void *cb_arg)
1236{
1237 struct spdk_blob *blob = lvol->blob;
1238 struct spdk_lvol_store *lvs = lvol->lvol_store;
1239 struct spdk_lvol_req *req;
9f95a23c 1240 uint64_t new_clusters = spdk_divide_round_up(sz, spdk_bs_get_cluster_size(lvs->blobstore));
11fdf7f2
TL
1241
1242 req = calloc(1, sizeof(*req));
1243 if (!req) {
1244 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
1245 cb_fn(cb_arg, -ENOMEM);
1246 return;
1247 }
1248 req->cb_fn = cb_fn;
1249 req->cb_arg = cb_arg;
1250 req->lvol = lvol;
1251
1252 spdk_blob_resize(blob, new_clusters, _spdk_lvol_blob_resize_cb, req);
1253}
1254
9f95a23c
TL
1255static void
1256_spdk_lvol_set_read_only_cb(void *cb_arg, int lvolerrno)
1257{
1258 struct spdk_lvol_req *req = cb_arg;
1259
1260 req->cb_fn(req->cb_arg, lvolerrno);
1261 free(req);
1262}
1263
1264void
1265spdk_lvol_set_read_only(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
1266{
1267 struct spdk_lvol_req *req;
1268
1269 req = calloc(1, sizeof(*req));
1270 if (!req) {
1271 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
1272 cb_fn(cb_arg, -ENOMEM);
1273 return;
1274 }
1275 req->cb_fn = cb_fn;
1276 req->cb_arg = cb_arg;
1277
1278 spdk_blob_set_read_only(lvol->blob);
1279 spdk_blob_sync_md(lvol->blob, _spdk_lvol_set_read_only_cb, req);
1280}
1281
11fdf7f2
TL
1282static void
1283_spdk_lvol_rename_cb(void *cb_arg, int lvolerrno)
1284{
1285 struct spdk_lvol_req *req = cb_arg;
1286
1287 if (lvolerrno != 0) {
1288 SPDK_ERRLOG("Lvol rename operation failed\n");
1289 } else {
1290 snprintf(req->lvol->name, sizeof(req->lvol->name), "%s", req->name);
1291 }
1292
1293 req->cb_fn(req->cb_arg, lvolerrno);
1294 free(req);
1295}
1296
1297void
1298spdk_lvol_rename(struct spdk_lvol *lvol, const char *new_name,
1299 spdk_lvol_op_complete cb_fn, void *cb_arg)
1300{
1301 struct spdk_lvol *tmp;
1302 struct spdk_blob *blob = lvol->blob;
1303 struct spdk_lvol_req *req;
1304 int rc;
1305
1306 /* Check if new name is current lvol name.
1307 * If so, return success immediately */
1308 if (strncmp(lvol->name, new_name, SPDK_LVOL_NAME_MAX) == 0) {
1309 cb_fn(cb_arg, 0);
1310 return;
1311 }
1312
1313 /* Check if lvol with 'new_name' already exists in lvolstore */
1314 TAILQ_FOREACH(tmp, &lvol->lvol_store->lvols, link) {
1315 if (strncmp(tmp->name, new_name, SPDK_LVOL_NAME_MAX) == 0) {
1316 SPDK_ERRLOG("Lvol %s already exists in lvol store %s\n", new_name, lvol->lvol_store->name);
1317 cb_fn(cb_arg, -EEXIST);
1318 return;
1319 }
1320 }
1321
1322 req = calloc(1, sizeof(*req));
1323 if (!req) {
1324 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
1325 cb_fn(cb_arg, -ENOMEM);
1326 return;
1327 }
1328 req->cb_fn = cb_fn;
1329 req->cb_arg = cb_arg;
1330 req->lvol = lvol;
1331 snprintf(req->name, sizeof(req->name), "%s", new_name);
1332
1333 rc = spdk_blob_set_xattr(blob, "name", new_name, strlen(new_name) + 1);
1334 if (rc < 0) {
1335 free(req);
1336 cb_fn(cb_arg, rc);
1337 return;
1338 }
1339
1340 spdk_blob_sync_md(blob, _spdk_lvol_rename_cb, req);
1341}
1342
1343void
1344spdk_lvol_destroy(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
1345{
1346 struct spdk_lvol_req *req;
9f95a23c 1347 struct spdk_blob_store *bs;
11fdf7f2
TL
1348
1349 assert(cb_fn != NULL);
1350
1351 if (lvol == NULL) {
1352 SPDK_ERRLOG("lvol does not exist\n");
1353 cb_fn(cb_arg, -ENODEV);
1354 return;
1355 }
1356
1357 if (lvol->ref_count != 0) {
1358 SPDK_ERRLOG("Cannot destroy lvol %s because it is still open\n", lvol->unique_id);
1359 cb_fn(cb_arg, -EBUSY);
1360 return;
1361 }
1362
1363 lvol->action_in_progress = true;
1364
1365 req = calloc(1, sizeof(*req));
1366 if (!req) {
1367 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
1368 cb_fn(cb_arg, -ENOMEM);
1369 return;
1370 }
1371
1372 req->cb_fn = cb_fn;
1373 req->cb_arg = cb_arg;
1374 req->lvol = lvol;
9f95a23c 1375 bs = lvol->lvol_store->blobstore;
11fdf7f2
TL
1376
1377 spdk_bs_delete_blob(bs, lvol->blob_id, _spdk_lvol_delete_blob_cb, req);
1378}
1379
1380void
1381spdk_lvol_close(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
1382{
1383 struct spdk_lvol_req *req;
1384
1385 assert(cb_fn != NULL);
1386
1387 if (lvol == NULL) {
1388 SPDK_ERRLOG("lvol does not exist\n");
1389 cb_fn(cb_arg, -ENODEV);
1390 return;
1391 }
1392
1393 if (lvol->ref_count > 1) {
1394 lvol->ref_count--;
1395 cb_fn(cb_arg, 0);
1396 return;
1397 } else if (lvol->ref_count == 0) {
1398 cb_fn(cb_arg, -EINVAL);
1399 return;
1400 }
1401
1402 lvol->action_in_progress = true;
1403
1404 req = calloc(1, sizeof(*req));
1405 if (!req) {
1406 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
1407 cb_fn(cb_arg, -ENOMEM);
1408 return;
1409 }
1410
1411 req->cb_fn = cb_fn;
1412 req->cb_arg = cb_arg;
1413 req->lvol = lvol;
1414
1415 spdk_blob_close(lvol->blob, _spdk_lvol_close_blob_cb, req);
1416}
1417
1418struct spdk_io_channel *
1419spdk_lvol_get_io_channel(struct spdk_lvol *lvol)
1420{
1421 return spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
1422}
1423
1424static void
1425_spdk_lvol_inflate_cb(void *cb_arg, int lvolerrno)
1426{
1427 struct spdk_lvol_req *req = cb_arg;
1428
1429 spdk_bs_free_io_channel(req->channel);
1430
1431 if (lvolerrno < 0) {
1432 SPDK_ERRLOG("Could not inflate lvol\n");
1433 }
1434
1435 req->cb_fn(req->cb_arg, lvolerrno);
1436 free(req);
1437}
1438
1439void
1440spdk_lvol_inflate(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
1441{
1442 struct spdk_lvol_req *req;
9f95a23c 1443 spdk_blob_id blob_id;
11fdf7f2
TL
1444
1445 assert(cb_fn != NULL);
1446
1447 if (lvol == NULL) {
1448 SPDK_ERRLOG("Lvol does not exist\n");
1449 cb_fn(cb_arg, -ENODEV);
1450 return;
1451 }
1452
1453 req = calloc(1, sizeof(*req));
1454 if (!req) {
1455 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
1456 cb_fn(cb_arg, -ENOMEM);
1457 return;
1458 }
1459
1460 req->cb_fn = cb_fn;
1461 req->cb_arg = cb_arg;
1462 req->channel = spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
1463 if (req->channel == NULL) {
1464 SPDK_ERRLOG("Cannot alloc io channel for lvol inflate request\n");
1465 free(req);
1466 cb_fn(cb_arg, -ENOMEM);
1467 return;
1468 }
1469
9f95a23c 1470 blob_id = spdk_blob_get_id(lvol->blob);
11fdf7f2
TL
1471 spdk_bs_inflate_blob(lvol->lvol_store->blobstore, req->channel, blob_id, _spdk_lvol_inflate_cb,
1472 req);
1473}
1474
1475void
1476spdk_lvol_decouple_parent(struct spdk_lvol *lvol, spdk_lvol_op_complete cb_fn, void *cb_arg)
1477{
1478 struct spdk_lvol_req *req;
9f95a23c 1479 spdk_blob_id blob_id;
11fdf7f2
TL
1480
1481 assert(cb_fn != NULL);
1482
1483 if (lvol == NULL) {
1484 SPDK_ERRLOG("Lvol does not exist\n");
1485 cb_fn(cb_arg, -ENODEV);
1486 return;
1487 }
1488
1489 req = calloc(1, sizeof(*req));
1490 if (!req) {
1491 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n");
1492 cb_fn(cb_arg, -ENOMEM);
1493 return;
1494 }
1495
1496 req->cb_fn = cb_fn;
1497 req->cb_arg = cb_arg;
1498 req->channel = spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore);
1499 if (req->channel == NULL) {
1500 SPDK_ERRLOG("Cannot alloc io channel for lvol inflate request\n");
1501 free(req);
1502 cb_fn(cb_arg, -ENOMEM);
1503 return;
1504 }
1505
9f95a23c 1506 blob_id = spdk_blob_get_id(lvol->blob);
11fdf7f2
TL
1507 spdk_bs_blob_decouple_parent(lvol->lvol_store->blobstore, req->channel, blob_id,
1508 _spdk_lvol_inflate_cb, req);
1509}