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/io_channel.h" 38 39 /* Length of string returned from uuid_unparse() */ 40 #define UUID_STRING_LEN 37 41 42 SPDK_LOG_REGISTER_TRACE_FLAG("lvol", SPDK_TRACE_LVOL) 43 44 static inline size_t 45 divide_round_up(size_t num, size_t divisor) 46 { 47 return (num + divisor - 1) / divisor; 48 } 49 50 static void 51 _spdk_super_create_close_cb(void *cb_arg, int lvolerrno) 52 { 53 struct spdk_lvs_with_handle_req *req = cb_arg; 54 struct spdk_lvol_store *lvs = req->lvol_store; 55 56 if (lvolerrno < 0) { 57 SPDK_ERRLOG("Lvol store init failed: could not close super blob\n"); 58 req->cb_fn(req->cb_arg, NULL, lvolerrno); 59 free(lvs); 60 free(req); 61 return; 62 } 63 64 req->cb_fn(req->cb_arg, lvs, lvolerrno); 65 free(req); 66 } 67 68 static void 69 _spdk_super_blob_set_cb(void *cb_arg, int lvolerrno) 70 { 71 struct spdk_lvs_with_handle_req *req = cb_arg; 72 struct spdk_lvol_store *lvs = req->lvol_store; 73 struct spdk_blob *blob = lvs->super_blob; 74 75 if (lvolerrno < 0) { 76 req->cb_fn(req->cb_arg, NULL, lvolerrno); 77 SPDK_ERRLOG("Lvol store init failed: could not set uuid for super blob\n"); 78 free(lvs); 79 free(req); 80 return; 81 } 82 83 spdk_bs_md_close_blob(&blob, _spdk_super_create_close_cb, req); 84 } 85 86 static void 87 _spdk_super_blob_init_cb(void *cb_arg, int lvolerrno) 88 { 89 struct spdk_lvs_with_handle_req *req = cb_arg; 90 struct spdk_lvol_store *lvs = req->lvol_store; 91 struct spdk_blob *blob = lvs->super_blob; 92 char uuid[UUID_STRING_LEN]; 93 94 if (lvolerrno < 0) { 95 req->cb_fn(req->cb_arg, NULL, lvolerrno); 96 SPDK_ERRLOG("Lvol store init failed: could not set super blob\n"); 97 free(lvs); 98 free(req); 99 return; 100 } 101 102 uuid_unparse(lvs->uuid, uuid); 103 104 spdk_blob_md_set_xattr(blob, "uuid", uuid, UUID_STRING_LEN); 105 spdk_bs_md_sync_blob(blob, _spdk_super_blob_set_cb, req); 106 } 107 108 static void 109 _spdk_super_blob_create_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno) 110 { 111 struct spdk_lvs_with_handle_req *req = cb_arg; 112 struct spdk_lvol_store *lvs = req->lvol_store; 113 114 if (lvolerrno < 0) { 115 req->cb_fn(req->cb_arg, NULL, lvolerrno); 116 SPDK_ERRLOG("Lvol store init failed: could not open super blob\n"); 117 free(lvs); 118 free(req); 119 return; 120 } 121 122 lvs->super_blob = blob; 123 lvs->super_blob_id = spdk_blob_get_id(blob); 124 125 spdk_bs_set_super(lvs->blobstore, lvs->super_blob_id, _spdk_super_blob_init_cb, req); 126 } 127 128 static void 129 _spdk_super_blob_create_cb(void *cb_arg, spdk_blob_id blobid, int lvolerrno) 130 { 131 struct spdk_lvs_with_handle_req *req = cb_arg; 132 struct spdk_lvol_store *lvs = req->lvol_store; 133 struct spdk_blob_store *bs; 134 135 if (lvolerrno < 0) { 136 req->cb_fn(req->cb_arg, NULL, lvolerrno); 137 SPDK_ERRLOG("Lvol store init failed: could not create super blob\n"); 138 free(lvs); 139 free(req); 140 return; 141 } 142 143 bs = req->lvol_store->blobstore; 144 145 spdk_bs_md_open_blob(bs, blobid, _spdk_super_blob_create_open_cb, req); 146 } 147 148 static void 149 _spdk_lvs_init_cb(void *cb_arg, struct spdk_blob_store *bs, int lvserrno) 150 { 151 struct spdk_lvs_with_handle_req *lvs_req = cb_arg; 152 struct spdk_lvol_store *lvs = lvs_req->lvol_store; 153 154 if (lvserrno != 0) { 155 assert(bs == NULL); 156 lvs_req->cb_fn(lvs_req->cb_arg, NULL, lvserrno); 157 SPDK_ERRLOG("Lvol store init failed: could not initialize blobstore\n"); 158 free(lvs); 159 free(lvs_req); 160 return; 161 } 162 163 assert(bs != NULL); 164 lvs->blobstore = bs; 165 TAILQ_INIT(&lvs->lvols); 166 lvs->total_blocks = (spdk_bs_get_cluster_size(bs) * spdk_bs_free_cluster_count( 167 bs)) / spdk_bs_get_page_size(bs); 168 169 SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol store initialized\n"); 170 171 /* create super blob */ 172 spdk_bs_md_create_blob(lvs->blobstore, _spdk_super_blob_create_cb, lvs_req); 173 } 174 175 static void 176 spdk_setup_lvs_opts(struct spdk_bs_opts *bs_opts, struct spdk_lvs_opts *o) 177 { 178 spdk_bs_opts_init(bs_opts); 179 if (o) { 180 bs_opts->cluster_sz = o->cluster_sz; 181 } else { 182 bs_opts->cluster_sz = SPDK_LVS_OPTS_CLUSTER_SZ; 183 } 184 } 185 186 int 187 spdk_lvs_init(struct spdk_bs_dev *bs_dev, struct spdk_lvs_opts *o, 188 spdk_lvs_op_with_handle_complete cb_fn, void *cb_arg) 189 { 190 struct spdk_lvol_store *lvs; 191 struct spdk_lvs_with_handle_req *lvs_req; 192 struct spdk_bs_opts opts; 193 194 if (bs_dev == NULL) { 195 SPDK_ERRLOG("Blobstore device does not exist\n"); 196 return -ENODEV; 197 } 198 199 spdk_setup_lvs_opts(&opts, o); 200 201 lvs = calloc(1, sizeof(*lvs)); 202 if (!lvs) { 203 SPDK_ERRLOG("Cannot alloc memory for lvol store base pointer\n"); 204 return -ENOMEM; 205 } 206 207 uuid_generate_time(lvs->uuid); 208 209 lvs_req = calloc(1, sizeof(*lvs_req)); 210 if (!lvs_req) { 211 free(lvs); 212 SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n"); 213 return -ENOMEM; 214 } 215 216 assert(cb_fn != NULL); 217 lvs_req->cb_fn = cb_fn; 218 lvs_req->cb_arg = cb_arg; 219 lvs_req->lvol_store = lvs; 220 lvs->bs_dev = bs_dev; 221 222 SPDK_INFOLOG(SPDK_TRACE_LVOL, "Initializing lvol store\n"); 223 spdk_bs_init(bs_dev, &opts, _spdk_lvs_init_cb, lvs_req); 224 225 return 0; 226 } 227 228 static void 229 _lvs_unload_cb(void *cb_arg, int lvserrno) 230 { 231 struct spdk_lvs_req *lvs_req = cb_arg; 232 233 SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol store unloaded\n"); 234 assert(lvs_req->cb_fn != NULL); 235 lvs_req->cb_fn(lvs_req->cb_arg, lvserrno); 236 free(lvs_req); 237 } 238 239 int 240 spdk_lvs_unload(struct spdk_lvol_store *lvs, spdk_lvs_op_complete cb_fn, 241 void *cb_arg) 242 { 243 struct spdk_lvs_req *lvs_req; 244 245 if (lvs == NULL) { 246 SPDK_ERRLOG("Lvol store is NULL\n"); 247 return -ENODEV; 248 } 249 250 if (!TAILQ_EMPTY(&lvs->lvols)) { 251 SPDK_ERRLOG("Lvols still open on lvol store\n"); 252 return -EBUSY; 253 } 254 255 lvs_req = calloc(1, sizeof(*lvs_req)); 256 if (!lvs_req) { 257 SPDK_ERRLOG("Cannot alloc memory for lvol store request pointer\n"); 258 return -ENOMEM; 259 } 260 261 lvs_req->cb_fn = cb_fn; 262 lvs_req->cb_arg = cb_arg; 263 264 SPDK_INFOLOG(SPDK_TRACE_LVOL, "Unloading lvol store\n"); 265 spdk_bs_unload(lvs->blobstore, _lvs_unload_cb, lvs_req); 266 free(lvs); 267 268 return 0; 269 } 270 271 static void 272 _spdk_lvol_return_to_caller(void *cb_arg, int lvolerrno) 273 { 274 struct spdk_lvol_with_handle_req *req = cb_arg; 275 276 assert(req->cb_fn != NULL); 277 req->cb_fn(req->cb_arg, req->lvol, lvolerrno); 278 free(req); 279 } 280 281 static void 282 _spdk_lvs_destruct_cb(void *cb_arg, int lvserrno) 283 { 284 struct spdk_lvs_req *req = cb_arg; 285 286 SPDK_INFOLOG(SPDK_TRACE_LVOL, "Lvol store bdev deleted\n"); 287 288 if (req->cb_fn != NULL) 289 req->cb_fn(req->cb_arg, lvserrno); 290 free(req); 291 } 292 293 static void 294 _spdk_lvol_close_blob_cb(void *cb_arg, int lvolerrno) 295 { 296 struct spdk_lvol *lvol = cb_arg; 297 298 if (lvolerrno < 0) { 299 SPDK_ERRLOG("Could not close blob on lvol\n"); 300 free(lvol->name); 301 free(lvol); 302 return; 303 } 304 305 if (lvol->lvol_store->destruct_req && TAILQ_EMPTY(&lvol->lvol_store->lvols)) { 306 spdk_lvs_unload(lvol->lvol_store, _spdk_lvs_destruct_cb, lvol->lvol_store->destruct_req); 307 } 308 309 free(lvol->name); 310 free(lvol); 311 312 SPDK_INFOLOG(SPDK_TRACE_LVOL, "Blob closed on lvol\n"); 313 } 314 315 static void 316 _spdk_lvol_delete_blob_cb(void *cb_arg, int lvolerrno) 317 { 318 struct spdk_lvol *lvol = cb_arg; 319 struct spdk_blob_store *bs = lvol->lvol_store->blobstore; 320 321 if (lvolerrno < 0) { 322 SPDK_ERRLOG("Could not delete blob on lvol\n"); 323 free(lvol->name); 324 free(lvol); 325 return; 326 } 327 SPDK_INFOLOG(SPDK_TRACE_LVOL, "Blob closed on lvol\n"); 328 spdk_bs_md_delete_blob(bs, lvol->blob_id, _spdk_lvol_close_blob_cb, lvol); 329 } 330 331 static void 332 _spdk_lvol_create_open_cb(void *cb_arg, struct spdk_blob *blob, int lvolerrno) 333 { 334 struct spdk_lvol_with_handle_req *req = cb_arg; 335 spdk_blob_id blob_id = spdk_blob_get_id(blob); 336 struct spdk_lvol *lvol = req->lvol; 337 char uuid[UUID_STRING_LEN]; 338 339 if (lvolerrno < 0) { 340 free(lvol); 341 goto invalid; 342 } 343 344 lvol->blob = blob; 345 lvol->blob_id = blob_id; 346 347 uuid_unparse(lvol->lvol_store->uuid, uuid); 348 lvol->name = spdk_sprintf_alloc("%s_%"PRIu64, uuid, (uint64_t)blob_id); 349 if (!lvol->name) { 350 spdk_bs_md_close_blob(&blob, _spdk_lvol_delete_blob_cb, lvol); 351 SPDK_ERRLOG("Cannot alloc memory for lvol name\n"); 352 lvolerrno = -ENOMEM; 353 goto invalid; 354 } 355 356 lvolerrno = spdk_bs_md_resize_blob(blob, lvol->num_clusters); 357 if (lvolerrno < 0) { 358 spdk_bs_md_close_blob(&blob, _spdk_lvol_delete_blob_cb, lvol); 359 goto invalid; 360 } 361 362 TAILQ_INSERT_TAIL(&lvol->lvol_store->lvols, lvol, link); 363 364 spdk_bs_md_sync_blob(blob, _spdk_lvol_return_to_caller, req); 365 366 return; 367 368 invalid: 369 assert(req->cb_fn != NULL); 370 req->cb_fn(req->cb_arg, NULL, lvolerrno); 371 free(req); 372 } 373 374 static void 375 _spdk_lvol_create_cb(void *cb_arg, spdk_blob_id blobid, int lvolerrno) 376 { 377 struct spdk_lvol_with_handle_req *req = cb_arg; 378 struct spdk_blob_store *bs; 379 380 if (lvolerrno < 0) { 381 free(req->lvol); 382 assert(req->cb_fn != NULL); 383 req->cb_fn(req->cb_arg, NULL, lvolerrno); 384 free(req); 385 return; 386 } 387 388 bs = req->lvol->lvol_store->blobstore; 389 390 spdk_bs_md_open_blob(bs, blobid, _spdk_lvol_create_open_cb, req); 391 } 392 393 int 394 spdk_lvol_create(struct spdk_lvol_store *lvs, uint64_t sz, 395 spdk_lvol_op_with_handle_complete cb_fn, void *cb_arg) 396 { 397 struct spdk_lvol_with_handle_req *req; 398 struct spdk_blob_store *bs; 399 struct spdk_lvol *lvol; 400 uint64_t num_clusters, free_clusters; 401 402 if (lvs == NULL) { 403 SPDK_ERRLOG("lvol store does not exist\n"); 404 return -ENODEV; 405 } 406 bs = lvs->blobstore; 407 408 num_clusters = divide_round_up(sz, spdk_bs_get_cluster_size(bs)); 409 free_clusters = spdk_bs_free_cluster_count(bs); 410 if (num_clusters > free_clusters) { 411 SPDK_ERRLOG("Not enough free clusters left (%zu) on lvol store to add lvol %zu clusters\n", 412 free_clusters, num_clusters); 413 return -ENOMEM; 414 } 415 416 req = calloc(1, sizeof(*req)); 417 if (!req) { 418 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n"); 419 return -ENOMEM; 420 } 421 req->cb_fn = cb_fn; 422 req->cb_arg = cb_arg; 423 424 lvol = calloc(1, sizeof(*lvol)); 425 if (!lvol) { 426 free(req); 427 SPDK_ERRLOG("Cannot alloc memory for lvol base pointer\n"); 428 return -ENOMEM; 429 } 430 431 lvol->lvol_store = lvs; 432 lvol->num_clusters = num_clusters; 433 lvol->close_only = false; 434 req->lvol = lvol; 435 436 spdk_bs_md_create_blob(lvs->blobstore, _spdk_lvol_create_cb, req); 437 438 return 0; 439 } 440 441 static void 442 _spdk_lvol_resize_cb(void *cb_arg, int lvolerrno) 443 { 444 struct spdk_lvol_req *req = cb_arg; 445 446 req->cb_fn(req->cb_arg, lvolerrno); 447 free(req); 448 } 449 450 int 451 spdk_lvol_resize(struct spdk_lvol *lvol, uint64_t sz, 452 spdk_lvol_op_complete cb_fn, void *cb_arg) 453 { 454 int rc; 455 struct spdk_blob *blob = lvol->blob; 456 struct spdk_lvol_store *lvs = lvol->lvol_store; 457 struct spdk_lvol_req *req; 458 uint64_t free_clusters = spdk_bs_free_cluster_count(lvs->blobstore); 459 uint64_t used_clusters = lvol->num_clusters; 460 uint64_t new_clusters = divide_round_up(sz, spdk_bs_get_cluster_size(lvs->blobstore)); 461 462 /* Check if size of lvol increasing */ 463 if (new_clusters > used_clusters) { 464 /* Check if there is enough clusters left to resize */ 465 if (new_clusters - used_clusters > free_clusters) { 466 SPDK_ERRLOG("Not enough free clusters left on lvol store to resize lvol to %zu clusters\n", sz); 467 return -ENOMEM; 468 } 469 } 470 471 req = calloc(1, sizeof(*req)); 472 if (!req) { 473 SPDK_ERRLOG("Cannot alloc memory for lvol request pointer\n"); 474 return -ENOMEM; 475 } 476 req->cb_fn = cb_fn; 477 req->cb_arg = cb_arg; 478 479 rc = spdk_bs_md_resize_blob(blob, sz); 480 if (rc < 0) { 481 goto invalid; 482 } 483 484 lvol->num_clusters = new_clusters; 485 486 spdk_blob_md_set_xattr(blob, "length", &sz, sizeof(sz)); 487 488 spdk_bs_md_sync_blob(blob, _spdk_lvol_resize_cb, req); 489 490 return rc; 491 492 invalid: 493 req->cb_fn(req->cb_arg, rc); 494 free(req); 495 return rc; 496 } 497 498 void 499 spdk_lvol_destroy(struct spdk_lvol *lvol) 500 { 501 if (lvol == NULL) { 502 SPDK_ERRLOG("lvol does not exist\n"); 503 return; 504 } 505 506 TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link); 507 spdk_bs_md_close_blob(&(lvol->blob), _spdk_lvol_delete_blob_cb, lvol); 508 } 509 510 void 511 spdk_lvol_close(struct spdk_lvol *lvol) 512 { 513 if (lvol == NULL) { 514 SPDK_ERRLOG("lvol does not exist\n"); 515 return; 516 } 517 518 TAILQ_REMOVE(&lvol->lvol_store->lvols, lvol, link); 519 spdk_bs_md_close_blob(&(lvol->blob), _spdk_lvol_close_blob_cb, lvol); 520 } 521 522 struct spdk_io_channel * 523 spdk_lvol_get_io_channel(struct spdk_lvol *lvol) 524 { 525 return spdk_bs_alloc_io_channel(lvol->lvol_store->blobstore); 526 } 527